Fix rooms not being closed when last game is closed.

This commit is contained in:
Ray Koopa 2020-07-11 01:50:25 +02:00
parent 20d7c3c743
commit 0cfbc5b675

View File

@ -128,57 +128,31 @@ namespace Syroot.Worms.Worms2.GameServer
} }
} }
private void LeaveGame(User fromUser) private void LeaveRoom(Room? room, int leftID)
{
// 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)
{ {
// Close an abandoned room. // Close an abandoned room.
bool roomClosed = fromUser.RoomID != 0 bool roomClosed = room != null
&& !_users.Any(x => x != fromUser && x.RoomID == fromUser.RoomID) && !_users.Any(x => x.ID != leftID && x.RoomID == room.ID)
&& !_games.Any(x => x.RoomID == fromUser.RoomID); && !_games.Any(x => x.ID != leftID && x.RoomID == room.ID);
if (roomClosed) if (roomClosed)
_rooms.Remove(_rooms.Single(x => x.ID == fromUser.RoomID)); _rooms.Remove(room!);
// Notify other users. // 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. // Notify room leave, if any.
if (fromUser.RoomID != 0) if (room != null)
{ {
SendPacket(user.Connection, new Packet(PacketCode.Leave, SendPacket(user.Connection, new Packet(PacketCode.Leave,
value2: fromUser.RoomID, value2: room.ID,
value10: fromUser.ID)); value10: leftID));
} }
// Notify room close, if any. // Notify room close, if any.
if (roomClosed) if (roomClosed)
{ SendPacket(user.Connection, new Packet(PacketCode.Close, value10: room!.ID));
SendPacket(user.Connection, new Packet(PacketCode.Close,
value10: fromUser.RoomID));
} }
} }
// Update user room.
fromUser.RoomID = 0;
}
// ---- Handlers ---- // ---- Handlers ----
private void OnListRooms(PacketConnection connection, Packet packet) private void OnListRooms(PacketConnection connection, Packet packet)
@ -349,16 +323,16 @@ namespace Syroot.Worms.Worms2.GameServer
// Require valid room ID (never sent for games, users disconnect if leaving a game). // Require valid room ID (never sent for games, users disconnect if leaving a game).
if (packet.Value2 == fromUser.RoomID) if (packet.Value2 == fromUser.RoomID)
{ {
LeaveRoom(fromUser); LeaveRoom(_rooms.FirstOrDefault(x => x.ID == fromUser.RoomID), fromUser.ID);
fromUser.RoomID = 0;
// Reply to leaver. // Reply to leaver.
SendPacket(connection, new Packet(PacketCode.LeaveReply, SendPacket(connection, new Packet(PacketCode.LeaveReply, error: 0));
error: 0));
} }
else else
{ {
// Reply to leaver. // Reply to leaver.
SendPacket(connection, new Packet(PacketCode.LeaveReply, SendPacket(connection, new Packet(PacketCode.LeaveReply, error: 1));
error: 1));
} }
} }
@ -368,10 +342,27 @@ namespace Syroot.Worms.Worms2.GameServer
if (fromUser == null) if (fromUser == null)
return; return;
int roomID = fromUser.RoomID;
int leftID = fromUser.ID;
_users.Remove(fromUser); _users.Remove(fromUser);
LeaveGame(fromUser); // Close an abandoned game.
LeaveRoom(fromUser); 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. // Notify user disconnect.
foreach (User user in _users) foreach (User user in _users)
@ -395,12 +386,12 @@ namespace Syroot.Worms.Worms2.GameServer
private void OnCreateGame(PacketConnection connection, Packet packet) private void OnCreateGame(PacketConnection connection, Packet packet)
{ {
User? fromUser = GetUser(connection); 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) || packet.Data == null || packet.Name == null || packet.Session == null)
return; return;
// Require valid room ID. // Require valid room ID and IP.
if (packet.Value2 == fromUser.RoomID) if (connection.RemoteEndPoint.Address.Equals(IPAddress.Parse(packet.Data)))
{ {
Game newGame = new Game(++_lastID, fromUser.Name, fromUser.Session.Nation, fromUser.RoomID, 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 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. // Send reply to host.
SendPacket(connection, new Packet(PacketCode.CreateGameReply, SendPacket(connection, new Packet(PacketCode.CreateGameReply, value1: newGame.ID, error: 0));
value1: newGame.ID,
error: 0));
} }
else else
{ {
SendPacket(connection, new Packet(PacketCode.CreateGameReply, SendPacket(connection, new Packet(PacketCode.CreateGameReply, value1: 0, error: 2));
value1: 0,
error: 1));
} }
} }