From 0fd5044a71baeafb4927a18b7bcb1c49fdf86742 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Thu, 11 Feb 2021 10:32:09 -0500 Subject: [PATCH] Core/Maps: Fixes player not being removed from map/server when they close the client without using logout/exitgame --- Source/Framework/Collections/MultiMap.cs | 1 - Source/Game/Networking/WorldSocket.cs | 75 +++++++++++++++--------- Source/Game/Server/WorldSession.cs | 3 + 3 files changed, 51 insertions(+), 28 deletions(-) diff --git a/Source/Framework/Collections/MultiMap.cs b/Source/Framework/Collections/MultiMap.cs index 7b8d092f6..4af610d5b 100644 --- a/Source/Framework/Collections/MultiMap.cs +++ b/Source/Framework/Collections/MultiMap.cs @@ -87,7 +87,6 @@ namespace System.Collections.Generic return false; bool val = _interalStorage[key].Remove(value); - if (!val) return false; diff --git a/Source/Game/Networking/WorldSocket.cs b/Source/Game/Networking/WorldSocket.cs index 0abfd70fb..6626964e8 100644 --- a/Source/Game/Networking/WorldSocket.cs +++ b/Source/Game/Networking/WorldSocket.cs @@ -52,6 +52,7 @@ namespace Game.Networking long _LastPingTime; uint _OverSpeedPings; + object _worldSessionLock = new object(); WorldSession _worldSession; ZLib.z_stream _compressionStream; @@ -324,23 +325,26 @@ namespace Game.Networking HandleEnterEncryptedModeAck(); break; default: - if (_worldSession == null) + lock (_worldSessionLock) { - Log.outError(LogFilter.Network, $"ProcessIncoming: Client not authed opcode = {opcode}"); - return ReadDataHandlerResult.Error; + if (_worldSession == null) + { + Log.outError(LogFilter.Network, $"ProcessIncoming: Client not authed opcode = {opcode}"); + return ReadDataHandlerResult.Error; + } + + if (!PacketManager.ContainsHandler(opcode)) + { + Log.outError(LogFilter.Network, $"No defined handler for opcode {opcode} sent by {_worldSession.GetPlayerInfo()}"); + break; + } + + // Our Idle timer will reset on any non PING opcodes on login screen, allowing us to catch people idling. + _worldSession.ResetTimeOutTime(false); + + // Copy the packet to the heap before enqueuing + _worldSession.QueuePacket(packet); } - - if (!PacketManager.ContainsHandler(opcode)) - { - Log.outError(LogFilter.Network, $"No defined handler for opcode {opcode} sent by {_worldSession.GetPlayerInfo()}"); - break; - } - - // Our Idle timer will reset on any non PING opcodes on login screen, allowing us to catch people idling. - _worldSession.ResetTimeOutTime(false); - - // Copy the packet to the heap before enqueuing - _worldSession.QueuePacket(packet); break; } @@ -398,7 +402,8 @@ namespace Game.Networking public void SetWorldSession(WorldSession session) { - _worldSession = session; + lock (_worldSessionLock) + _worldSession = session; } public uint CompressPacket(byte[] data, ServerOpcodes opcode, out byte[] outData) @@ -436,6 +441,16 @@ namespace Game.Networking return true; } + public override void OnClose() + { + lock (_worldSessionLock) + { + _worldSession.Dispose(); + _worldSession = null; + } + base.OnClose(); + } + void HandleSendAuthSession() { AuthChallenge challenge = new AuthChallenge(); @@ -781,10 +796,13 @@ namespace Game.Networking uint maxAllowed = WorldConfig.GetUIntValue(WorldCfg.MaxOverspeedPings); if (maxAllowed != 0 && _OverSpeedPings > maxAllowed) { - if (_worldSession != null && !_worldSession.HasPermission(RBACPermissions.SkipCheckOverspeedPing)) + lock (_worldSessionLock) { - Log.outError(LogFilter.Network, "WorldSocket:HandlePing: {0} kicked for over-speed pings (address: {1})", _worldSession.GetPlayerInfo(), GetRemoteIpAddress()); - //return ReadDataHandlerResult.Error; + if (_worldSession != null && !_worldSession.HasPermission(RBACPermissions.SkipCheckOverspeedPing)) + { + Log.outError(LogFilter.Network, "WorldSocket:HandlePing: {0} kicked for over-speed pings (address: {1})", _worldSession.GetPlayerInfo(), GetRemoteIpAddress()); + //return ReadDataHandlerResult.Error; + } } } } @@ -792,15 +810,18 @@ namespace Game.Networking _OverSpeedPings = 0; } - if (_worldSession != null) + lock (_worldSessionLock) { - _worldSession.SetLatency(ping.Latency); - _worldSession.ResetClientTimeDelay(); - } - else - { - Log.outError(LogFilter.Network, "WorldSocket:HandlePing: peer sent CMSG_PING, but is not authenticated or got recently kicked, address = {0}", GetRemoteIpAddress()); - return false; + if (_worldSession != null) + { + _worldSession.SetLatency(ping.Latency); + _worldSession.ResetClientTimeDelay(); + } + else + { + Log.outError(LogFilter.Network, "WorldSocket:HandlePing: peer sent CMSG_PING, but is not authenticated or got recently kicked, address = {0}", GetRemoteIpAddress()); + return false; + } } SendPacket(new Pong(ping.Serial)); diff --git a/Source/Game/Server/WorldSession.cs b/Source/Game/Server/WorldSession.cs index 6a7a8fc8c..1056367e7 100644 --- a/Source/Game/Server/WorldSession.cs +++ b/Source/Game/Server/WorldSession.cs @@ -86,6 +86,9 @@ namespace Game public void LogoutPlayer(bool save) { + if (m_playerLogout) + return; + // finish pending transfers before starting the logout while (_player && _player.IsBeingTeleportedFar()) HandleMoveWorldportAck();