namespace Supercell.Laser.Server.Networking.Session { using Supercell.Laser.Logic.Avatar; using Supercell.Laser.Logic.Club; using Supercell.Laser.Logic.Friends; using Supercell.Laser.Logic.Home; using Supercell.Laser.Logic.Message.Club; using Supercell.Laser.Logic.Listener; using Supercell.Laser.Logic.Message.Account; using Supercell.Laser.Logic.Message.Account.Auth; using Supercell.Laser.Logic.Message.Friends; using Supercell.Laser.Server.Database; using Supercell.Laser.Server.Logic.Game; using System.Collections.Concurrent; public static class Sessions { public static bool Maintenance; private static ConcurrentDictionary ActiveSessions = new ConcurrentDictionary(); public static int Count { get { return ActiveSessions.Count; } } public static void Init() { ActiveSessions = new ConcurrentDictionary(); } public static void StartShutdown() { Maintenance = true; foreach (var session in ActiveSessions.Values.ToArray()) { session.Connection.Send(new ShutdownStartedMessage()); } Thread.Sleep(1000); foreach (var session in ActiveSessions.Values.ToArray()) { session.Connection.Send(new AuthenticationFailedMessage() { ErrorCode = 10, }); } } public static void RefreshFriendEntries(ClientAvatar avatar) { if (avatar == null) { return; } SendFriendListToPlayer(avatar.AccountId, avatar); FriendOnlineStatusEntryMessage statusMessage = new FriendOnlineStatusEntryMessage { AvatarId = avatar.AccountId, PlayerStatus = avatar.PlayerStatus }; foreach (Friend friend in avatar.Friends.ToArray()) { if (!IsSessionActive(friend.AccountId)) { continue; } LogicGameListener friendListener = LogicServerListener.Instance.GetGameListener(friend.AccountId); friendListener?.SendTCPMessage(statusMessage); ClientAvatar friendAvatar = LogicServerListener.Instance.GetAvatar(friend.AccountId); if (friendAvatar != null) { SendFriendListToPlayer(friendAvatar.AccountId, friendAvatar); } } } public static void RefreshAllianceEntries(ClientAvatar avatar) { if (avatar == null || avatar.AllianceId <= 0) { return; } Alliance alliance = Alliances.Load(avatar.AllianceId); if (alliance == null) { return; } foreach (AllianceMember member in alliance.Members.ToArray()) { if (!IsSessionActive(member.AccountId)) { continue; } LogicGameListener listener = LogicServerListener.Instance.GetGameListener(member.AccountId); if (listener == null) { continue; } listener.SendTCPMessage(new AllianceDataMessage { Alliance = alliance, IsMyAlliance = true }); ClientAvatar memberAvatar = LogicServerListener.Instance.GetAvatar(member.AccountId); if (memberAvatar != null) { listener.SendTCPMessage(new MyAllianceMessage { Role = memberAvatar.AllianceRole, OnlineMembers = alliance.OnlinePlayers, AllianceHeader = alliance.Header }); } } } private static void SendFriendListToPlayer(long accountId, ClientAvatar avatar) { if (avatar == null || !IsSessionActive(accountId)) { return; } LogicGameListener listener = LogicServerListener.Instance.GetGameListener(accountId); if (listener == null) { return; } listener.SendTCPMessage(new FriendListMessage { Friends = avatar.Friends.ToArray() }); } public static void Remove(long id) { if (ActiveSessions.ContainsKey(id)) { var avatar = ActiveSessions[id].Home.Avatar; Logger.Network($"{avatar.Name}#{id} disconnected — online={ActiveSessions.Count - 1}"); AuditLogger.Logout(id, avatar.Name, ActiveSessions[id].Connection?.RemoteIpAddress ?? "?"); avatar.LastOnline = DateTime.UtcNow; avatar.PlayerStatus = 0; RefreshFriendEntries(avatar); RefreshAllianceEntries(avatar); if (ActiveSessions[id].Home.Avatar.TeamId > 0) { var team = Teams.Get(ActiveSessions[id].Home.Avatar.TeamId); if (team != null) { var member = team.GetMember(id); if (member != null) { member.State = 0; team.TeamUpdated(); } } } } ActiveSessions.Remove(id, out _); } public static Session Create(HomeMode home, Connection connection) { if (ActiveSessions.ContainsKey(home.Avatar.AccountId)) { Session oldSession = ActiveSessions[home.Avatar.AccountId]; Logger.Warning($"Replacing duplicate session for {home.Avatar.Name}#{home.Avatar.AccountId}"); oldSession.Connection.Send(new DisconnectedMessage() { Reason = 1 }); Session s = new Session(home, connection); ActiveSessions[home.Avatar.AccountId] = s; return s; } Session session = new Session(home, connection); ActiveSessions[home.Avatar.AccountId] = session; Logger.Network($"{home.Avatar.Name}#{home.Avatar.AccountId} joined — online={ActiveSessions.Count}"); AuditLogger.Login(home.Avatar.AccountId, home.Avatar.Name, connection?.RemoteIpAddress ?? "?", home.Home.Device ?? "?"); // Подписываем аудит транзакций home.Avatar.OnBalanceChanged = (type, delta, reason, before, after) => { long id = home.Avatar.AccountId; string name = home.Avatar.Name; if (type == "gems") { if (delta < 0) AuditLogger.GemSpend(id, name, -delta, reason, before, after); else AuditLogger.GemGain(id, name, delta, reason, before, after); } else if (type == "gold") { if (delta < 0) AuditLogger.GoldSpend(id, name, -delta, reason, before, after); else AuditLogger.GoldGain(id, name, delta, reason, before, after); } else if (type == "starpoints") { if (delta < 0) AuditLogger.StarPointsSpend(id, name, -delta, reason); else AuditLogger.StarPointsGain(id, name, delta, reason); } }; RefreshFriendEntries(home.Avatar); RefreshAllianceEntries(home.Avatar); return session; } public static bool IsSessionActive(long id) { return ActiveSessions.ContainsKey(id); } public static Session GetSession(long id) { if (ActiveSessions.ContainsKey(id)) { return ActiveSessions[id]; } return null; } } }