102 lines
2.8 KiB
C
102 lines
2.8 KiB
C
// Server-owned audit stream. The file contains every event; chat reads a bounded
|
|
// recent-history window with explicit gap notices for clients that fall behind.
|
|
class ERR_HQJournal
|
|
{
|
|
protected ref array<string> m_Recent = {};
|
|
protected ref array<string> m_Pending = {};
|
|
protected int m_Sequence;
|
|
protected int m_Message;
|
|
protected static int s_Part;
|
|
protected static int s_Session;
|
|
protected string m_Session;
|
|
|
|
void ERR_HQJournal()
|
|
{
|
|
s_Session++;
|
|
m_Session = string.Format("%1-%2", System.GetUnixTime(), s_Session);
|
|
}
|
|
protected float m_RetryAt;
|
|
protected int m_Lost;
|
|
|
|
string Path()
|
|
{
|
|
if (s_Part == 0)
|
|
return "$logs:rereintroduced-hq.log";
|
|
return "$logs:rereintroduced-hq-" + s_Part.ToString() + ".log";
|
|
}
|
|
|
|
int Message()
|
|
{
|
|
return ++m_Message;
|
|
}
|
|
|
|
int Sequence()
|
|
{
|
|
return m_Sequence;
|
|
}
|
|
|
|
void Write(string kind, string message, int messageId = 0)
|
|
{
|
|
if (!Replication.IsServer())
|
|
return;
|
|
float seconds = GetGame().GetWorld().GetWorldTime() / 1000;
|
|
string line = string.Format("#%1 t=%2s M%3 %4 %5", ++m_Sequence, Math.Round(seconds * 10) / 10.0, messageId, kind, message) + " [session=" + m_Session + "]";
|
|
if (m_Recent.Count() >= 300)
|
|
m_Recent.Remove(0);
|
|
m_Recent.Insert(line);
|
|
if (m_Pending.Count() < 4096)
|
|
m_Pending.Insert(line);
|
|
else
|
|
m_Lost++;
|
|
}
|
|
|
|
void Read(int after, out array<string> lines, out int cursor, int limit = 8)
|
|
{
|
|
lines.Clear();
|
|
cursor = Math.Clamp(after, 0, m_Sequence);
|
|
int first = m_Sequence - m_Recent.Count();
|
|
if (cursor < first)
|
|
{
|
|
lines.Insert(string.Format("HQ log: %1 older entries are outside chat history; see %2", first - cursor, Path()));
|
|
cursor = first;
|
|
}
|
|
int characters;
|
|
for (int i = cursor - first; i < m_Recent.Count() && lines.Count() < Math.Clamp(limit, 1, 40); i++)
|
|
{
|
|
// Bound each menu RPC without skipping unread records. Chat still
|
|
// requests eight; the live menu can drain a busy journal faster.
|
|
if (characters + m_Recent[i].Length() > 16000 && !lines.IsEmpty())
|
|
break;
|
|
lines.Insert(m_Recent[i]);
|
|
characters += m_Recent[i].Length();
|
|
cursor++;
|
|
}
|
|
}
|
|
|
|
void Flush()
|
|
{
|
|
if (m_Pending.IsEmpty() || !Replication.IsServer())
|
|
return;
|
|
float now = GetGame().GetWorld().GetWorldTime();
|
|
if (now < m_RetryAt)
|
|
return;
|
|
FileHandle file = FileIO.OpenFile(Path(), FileMode.APPEND);
|
|
if (!file)
|
|
{
|
|
m_RetryAt = now + 30000;
|
|
PrintFormat("Escapists AI [HQ log]: cannot open %1; retry in 30s, chat history remains available", Path(), level: LogLevel.ERROR);
|
|
return;
|
|
}
|
|
foreach (string line : m_Pending)
|
|
file.WriteLine(line);
|
|
if (m_Lost > 0)
|
|
file.WriteLine(string.Format("HQ log: %1 entries lost while file was unavailable and buffer full", m_Lost));
|
|
bool rotate = file.GetLength() >= 5242880;
|
|
file.Close();
|
|
m_Pending.Clear();
|
|
m_Lost = 0;
|
|
if (rotate)
|
|
s_Part++;
|
|
}
|
|
}
|