diff --git a/src/tool/Syroot.Worms.Worms2.GameServer/Server.cs b/src/tool/Syroot.Worms.Worms2.GameServer/Server.cs index 73d6e03..e2ff127 100644 --- a/src/tool/Syroot.Worms.Worms2.GameServer/Server.cs +++ b/src/tool/Syroot.Worms.Worms2.GameServer/Server.cs @@ -128,55 +128,29 @@ namespace Syroot.Worms.Worms2.GameServer } } - private void LeaveGame(User fromUser) - { - // Close an abandoned game. - Game? game = _games.SingleOrDefault(x => x.Name == fromUser.Name); - if (game == null) - return; - - _games.Remove(game); - - // Notify other users. - foreach (User user in _users.Where(x => x != fromUser)) - { - SendPacket(user.Connection, new Packet(PacketCode.Leave, - value2: game.ID, - value10: fromUser.ID)); - SendPacket(user.Connection, new Packet(PacketCode.Close, - value10: game.ID)); - } - } - - private void LeaveRoom(User fromUser) + private void LeaveRoom(Room? room, int leftID) { // Close an abandoned room. - bool roomClosed = fromUser.RoomID != 0 - && !_users.Any(x => x != fromUser && x.RoomID == fromUser.RoomID) - && !_games.Any(x => x.RoomID == fromUser.RoomID); + bool roomClosed = room != null + && !_users.Any(x => x.ID != leftID && x.RoomID == room.ID) + && !_games.Any(x => x.ID != leftID && x.RoomID == room.ID); if (roomClosed) - _rooms.Remove(_rooms.Single(x => x.ID == fromUser.RoomID)); + _rooms.Remove(room!); // Notify other users. - foreach (User user in _users.Where(x => x != fromUser)) + foreach (User user in _users.Where(x => x.ID != leftID)) { // Notify room leave, if any. - if (fromUser.RoomID != 0) + if (room != null) { SendPacket(user.Connection, new Packet(PacketCode.Leave, - value2: fromUser.RoomID, - value10: fromUser.ID)); + value2: room.ID, + value10: leftID)); } // Notify room close, if any. if (roomClosed) - { - SendPacket(user.Connection, new Packet(PacketCode.Close, - value10: fromUser.RoomID)); - } + SendPacket(user.Connection, new Packet(PacketCode.Close, value10: room!.ID)); } - - // Update user room. - fromUser.RoomID = 0; } // ---- Handlers ---- @@ -349,16 +323,16 @@ namespace Syroot.Worms.Worms2.GameServer // Require valid room ID (never sent for games, users disconnect if leaving a game). if (packet.Value2 == fromUser.RoomID) { - LeaveRoom(fromUser); + LeaveRoom(_rooms.FirstOrDefault(x => x.ID == fromUser.RoomID), fromUser.ID); + fromUser.RoomID = 0; + // Reply to leaver. - SendPacket(connection, new Packet(PacketCode.LeaveReply, - error: 0)); + SendPacket(connection, new Packet(PacketCode.LeaveReply, error: 0)); } else { // Reply to leaver. - SendPacket(connection, new Packet(PacketCode.LeaveReply, - error: 1)); + SendPacket(connection, new Packet(PacketCode.LeaveReply, error: 1)); } } @@ -368,10 +342,27 @@ namespace Syroot.Worms.Worms2.GameServer if (fromUser == null) return; + int roomID = fromUser.RoomID; + int leftID = fromUser.ID; _users.Remove(fromUser); - LeaveGame(fromUser); - LeaveRoom(fromUser); + // Close an abandoned game. + Game? game = _games.SingleOrDefault(x => x.Name == fromUser.Name); + if (game != null) + { + roomID = game.RoomID; + leftID = game.ID; + _games.Remove(game); + // Notify other users. + foreach (User user in _users.Where(x => x != fromUser)) + { + SendPacket(user.Connection, new Packet(PacketCode.Leave, value2: game.ID, value10: fromUser.ID)); + SendPacket(user.Connection, new Packet(PacketCode.Close, value10: game.ID)); + } + } + + // Close any abandoned room. + LeaveRoom(_rooms.FirstOrDefault(x => x.ID == roomID), leftID); // Notify user disconnect. foreach (User user in _users) @@ -395,12 +386,12 @@ namespace Syroot.Worms.Worms2.GameServer private void OnCreateGame(PacketConnection connection, Packet packet) { User? fromUser = GetUser(connection); - if (fromUser == null || packet.Value1 != 0 || packet.Value2 == null || packet.Value4 != 0x800 + if (fromUser == null || packet.Value1 != 0 || packet.Value2 != fromUser.RoomID || packet.Value4 != 0x800 || packet.Data == null || packet.Name == null || packet.Session == null) return; - // Require valid room ID. - if (packet.Value2 == fromUser.RoomID) + // Require valid room ID and IP. + if (connection.RemoteEndPoint.Address.Equals(IPAddress.Parse(packet.Data))) { Game newGame = new Game(++_lastID, fromUser.Name, fromUser.Session.Nation, fromUser.RoomID, connection.RemoteEndPoint.Address, // do not use bad NAT IP reported by users here @@ -420,15 +411,11 @@ namespace Syroot.Worms.Worms2.GameServer } // Send reply to host. - SendPacket(connection, new Packet(PacketCode.CreateGameReply, - value1: newGame.ID, - error: 0)); + SendPacket(connection, new Packet(PacketCode.CreateGameReply, value1: newGame.ID, error: 0)); } else { - SendPacket(connection, new Packet(PacketCode.CreateGameReply, - value1: 0, - error: 1)); + SendPacket(connection, new Packet(PacketCode.CreateGameReply, value1: 0, error: 2)); } }