using System; using System.Collections.Generic; using UnityEngine; namespace Jovian.InGameLogging { public sealed class GameLogStore : IGameLogStore { private readonly LogEntry[] buffer; private readonly HashSet disabledChannels = new(); private int head; private int count; public int Count => count; public int Capacity => buffer.Length; public event Action OnEntryAdded; public event Action OnCleared; public GameLogStore(int capacity = 500) { buffer = new LogEntry[capacity]; head = 0; count = 0; } public void Add(LogChannel channel, string message) { if(disabledChannels.Contains(channel)) { return; } var entry = new LogEntry(message, channel, Time.time); buffer[head] = entry; head = (head + 1) % buffer.Length; if(count < buffer.Length) { count++; } OnEntryAdded?.Invoke(entry); } public void EnableChannel(LogChannel channel) { disabledChannels.Remove(channel); } public void DisableChannel(LogChannel channel) { disabledChannels.Add(channel); } public bool IsChannelEnabled(LogChannel channel) { return !disabledChannels.Contains(channel); } public void Clear() { head = 0; count = 0; OnCleared?.Invoke(); } public void Clear(LogChannel channel) { var kept = new List(count); var entries = GetEntries(); for(var i = 0; i < entries.Length; i++) { if(entries[i].channel != channel) { kept.Add(entries[i]); } } head = 0; count = 0; for(var i = 0; i < kept.Count; i++) { buffer[i] = kept[i]; count++; } head = count % buffer.Length; OnCleared?.Invoke(); } public ReadOnlySpan GetEntries() { if(count < buffer.Length) { return new ReadOnlySpan(buffer, 0, count); } var result = new LogEntry[count]; var start = head; for(var i = 0; i < count; i++) { result[i] = buffer[(start + i) % buffer.Length]; } return result; } public int GetEntries(LogChannel channel, List results) { results.Clear(); var entries = GetEntries(); for(var i = 0; i < entries.Length; i++) { if(entries[i].channel == channel) { results.Add(entries[i]); } } return results.Count; } public GameLogSaveData GetSaveData() { var entries = GetEntries(); var list = new List(entries.Length); foreach(var t in entries) { list.Add(t); } return new GameLogSaveData(list); } public void RestoreFromSaveData(GameLogSaveData data) { head = 0; count = 0; if(data?.entries == null) { OnCleared?.Invoke(); return; } var startIndex = Math.Max(0, data.entries.Count - buffer.Length); for(var i = startIndex; i < data.entries.Count; i++) { buffer[count] = data.entries[i]; count++; } head = count % buffer.Length; OnCleared?.Invoke(); } } }