namespace Supercell.Laser.Server.Logic.Game { using Supercell.Laser.Logic.Battle; using System; using System.Collections.Concurrent; using System.IO; using System.Linq; using System.Text; using System.Threading; public static class Battles { private static long m_battleIdCounter; private static ConcurrentDictionary m_battles; public static void Init() { m_battles = new ConcurrentDictionary(); m_battleIdCounter = 0; new Thread(Update) { IsBackground = true }.Start(); } public static void Update() { while (true) { try { foreach (BattleMode battle in m_battles.Values.ToArray()) { try { if (battle == null) continue; if (battle.IsGameOver) { if (m_battles.TryRemove(battle.Id, out _)) { // Освобождаем UDP-сокеты этого боя. Без этого словарь // Sockets в UDPGateway рос бы бессрочно (утечка). foreach (long sessionId in battle.GetAllSessionIds()) Networking.UDPGateway.RemoveSocket(sessionId); Log($"Battle removed (GameOver): {battle.Id}"); } } } catch (Exception ex) { HandleBattleError(battle, ex); } } } catch (Exception ex) { HandleGlobalError(ex); } Thread.Sleep(1000); } } public static int GetBattlesCount() { return m_battles?.Count ?? 0; } public static long Add(BattleMode battle) { try { long id = Interlocked.Increment(ref m_battleIdCounter); battle.Id = id; m_battles[id] = battle; Log($"Battle added: {id}"); return id; } catch (Exception ex) { Logger.Error("[Battles.Add ERROR] " + ex); throw; } } public static BattleMode Get(long id) { try { m_battles.TryGetValue(id, out var battle); return battle; } catch (Exception ex) { Logger.Error("[Battles.Get ERROR] " + ex); return null; } } private static void HandleBattleError(BattleMode battle, Exception ex) { string msg = $"[BATTLE ERROR] BattleId={battle?.Id} | {ex}"; // Fix 6: Logger.Error — без Console-лока. Logger.Error(msg); WriteLog("battle_errors.log", msg); } private static void HandleGlobalError(Exception ex) { string msg = $"[GLOBAL BATTLES ERROR] {ex}"; Logger.Error(msg); WriteLog("global_battles_errors.log", msg); } private static void Log(string msg) { Logger.WriteServerLog("[Battles] " + msg); } private static void WriteLog(string file, string msg) { try { Directory.CreateDirectory("logs"); File.AppendAllText( Path.Combine("logs", file), $"[{DateTime.UtcNow:yyyy-MM-dd HH:mm:ss}] {msg}{Environment.NewLine}" ); } catch { // не ломаем сервер из-за логов } } } }