fix client stay in room and add Room.Send

- fix client stay in room:
  - replace Client.JoinRoom and Client.LeaveRoom by Client.SetRoom
  - do not call Client.LeaveRoom / Client.SetRoom(null) for SheduleDisconnect cases
    (only quietly remove client from room and the rest do in disconnect realisation)
- add Room.Send for send message to all clients in room
  - replace Room.Client sending loops by calls Room.Send
This commit is contained in:
Robert Paciorek 2024-03-24 21:29:57 +00:00
parent fa0870784a
commit 82e83722da
16 changed files with 81 additions and 127 deletions

View File

@ -35,11 +35,7 @@ class ChatMessageHandler : ICommandHandler {
cmd.Add("p", data);
NetworkPacket packet = NetworkObject.WrapObject(1, 13, cmd).Serialize();
foreach (var roomClient in client.Room.Clients) {
if (roomClient != client) {
roomClient.Send(packet);
}
}
client.Room.Send(packet, client);
cmd = new();
data = new();

View File

@ -7,6 +7,6 @@ namespace sodoffmmo.CommandHandlers;
[CommandHandler(26)]
class ExitHandler : ICommandHandler {
public void Handle(Client client, NetworkObject receivedObject) {
client.LeaveRoom();
client.SetRoom(null);
}
}

View File

@ -39,10 +39,7 @@ class GauntletPlayAgainHandler : ICommandHandler
client.PlayerData.Uid
}, "msg", room.Id);
foreach (var roomClient in room.Clients) {
if (roomClient != client)
roomClient.Send(packet);
}
room.Send(packet, client);
room.SendPA(client);
}
}
@ -61,9 +58,7 @@ class GauntletLobbyUserReadyHandler : ICommandHandler
client.PlayerData.Uid
}, "msg", room.Id);
foreach (var roomClient in room.Clients) {
roomClient.Send(packet);
}
room.Send(packet);
if (room.GetReadyCount() > 1) {
packet = Utils.ArrNetworkPacket(new string[] {
@ -72,9 +67,7 @@ class GauntletLobbyUserReadyHandler : ICommandHandler
client.PlayerData.Uid
}, "msg", room.Id);
foreach (var roomClient in room.Clients) {
roomClient.Send(packet);
}
room.Send(packet);
}
}
}
@ -93,9 +86,7 @@ class GauntletLobbyUserNotReadyHandler : ICommandHandler
client.PlayerData.Uid
}, "msg", room.Id);
foreach (var roomClient in room.Clients) {
roomClient.Send(packet);
}
room.Send(packet);
}
}
@ -114,10 +105,7 @@ class GauntletLevelLoadHandler : ICommandHandler
p.Get<string>("1"),
p.Get<string>("2") // TODO use size of p.fields - 1
}, "msg", room.Id);
foreach (var roomClient in room.Clients) {
roomClient.Send(packet);
}
room.Send(packet);
}
}
@ -139,9 +127,7 @@ class GauntletLevelLoadedHandler : ICommandHandler
room.Id.ToString(),
(--counter).ToString()
}, "msg", room.Id);
foreach (var roomClient in room.Clients) {
roomClient.Send(packet);
}
room.Send(packet);
timer = new System.Timers.Timer(1500);
timer.AutoReset = true;
@ -169,9 +155,7 @@ class GauntletLevelLoadedHandler : ICommandHandler
timer!.Close();
timer = null;
}
foreach (var roomClient in room.Clients) {
roomClient.Send(packet);
}
room.Send(packet);
}
}
@ -191,10 +175,7 @@ class GauntletRelayGameDataHandler : ICommandHandler
p.Get<string>("0"),
p.Get<string>("1")
}, "msg", room.Id);
foreach (var roomClient in room.Clients) {
if (roomClient != client)
roomClient.Send(packet);
}
room.Send(packet, client);
}
}

View File

@ -8,7 +8,6 @@ namespace sodoffmmo.CommandHandlers;
class GenericMessageHandler : ICommandHandler {
public void Handle(Client client, NetworkObject receivedObject) {
NetworkPacket packet = NetworkObject.WrapObject(0, 7, receivedObject).Serialize();
foreach (var roomClient in client.Room.Clients)
roomClient.Send(packet);
client.Room.Send(packet);
}
}

View File

@ -11,7 +11,6 @@ class JoinRoomHandler : ICommandHandler
{
string roomName = receivedObject.Get<NetworkObject>("p").Get<string>("rn");
Room room = Room.GetOrAdd(roomName);
Console.WriteLine($"Join Room: {roomName} RoomID: {room.Id} IID: {client.ClientID}");
client.JoinRoom(room);
client.SetRoom(room);
}
}

View File

@ -24,8 +24,6 @@ class RacingPMHandler : ICommandHandler
cmd.Add("p", p);
NetworkPacket packet = NetworkObject.WrapObject(1, 13, cmd).Serialize();
foreach (var roomClient in client.Room.Clients) {
roomClient.Send(packet);
}
client.Room.Send(packet);
}
}

View File

@ -58,9 +58,7 @@ class RacingARACKHandler : ICommandHandler
if (room.GetPlayersCount(RacingPlayerState.RaceReady2) == room.ClientsCount) {
NetworkPacket packet = room.GetSTAPacket();
foreach (var roomClient in room.Clients) {
roomClient.Send(packet);
}
room.Send(packet);
Console.WriteLine($"STA");
}
}

View File

@ -59,11 +59,7 @@ class SetPositionVariablesHandler : ICommandHandler {
cmd.Add("c", "SPV");
cmd.Add("p", obj);
NetworkPacket packet = NetworkObject.WrapObject(1, 13, cmd).Serialize();
foreach (var roomClient in client.Room.Clients) {
if (roomClient != client)
roomClient.Send(packet);
}
client.Room.Send(packet, client);
}
}

View File

@ -11,6 +11,12 @@ class SetUserVariablesHandler : ICommandHandler {
Client client;
string? uid;
public void Handle(Client client, NetworkObject receivedObject) {
if (client.Room == null) {
Console.WriteLine($"SUV Missing Room IID: {client.ClientID}");
client.Send(NetworkObject.WrapObject(0, 1006, new NetworkObject()).Serialize());
client.SheduleDisconnect();
return;
}
this.client = client;
suvData = receivedObject.Get<NetworkObject>("p");
uid = suvData.Get<string>("UID");
@ -90,8 +96,7 @@ class SetUserVariablesHandler : ICommandHandler {
data.Add("vl", vl);
NetworkPacket packet = NetworkObject.WrapObject(0, 12, data).Serialize();
foreach (var roomClient in client.Room.Clients)
roomClient.Send(packet);
client.Room.Send(packet);
NetworkObject cmd = new();
cmd.Add("c", "SUV");
@ -105,10 +110,7 @@ class SetUserVariablesHandler : ICommandHandler {
container.Add("arr", arr);
cmd.Add("p", container);
packet = NetworkObject.WrapObject(1, 13, cmd).Serialize();
foreach (var roomClient in client.Room.Clients) {
if (roomClient != client)
roomClient.Send(packet);
}
client.Room.Send(packet, client);
}
private void UpdatePlayersInRoom() {
@ -129,10 +131,7 @@ class SetUserVariablesHandler : ICommandHandler {
NetworkPacket packet = NetworkObject.WrapObject(0, 1000, data).Serialize();
packet.Compress();
foreach (var roomClient in client.Room.Clients) {
if (roomClient != client)
roomClient.Send(packet);
}
client.Room.Send(packet, client);
}
private void SendSUVToPlayerInRoom() {
@ -144,9 +143,6 @@ class SetUserVariablesHandler : ICommandHandler {
cmd.Add("p", obj);
NetworkPacket packet = NetworkObject.WrapObject(1, 13, cmd).Serialize();
foreach (var roomClient in client.Room.Clients) {
if (roomClient != client)
roomClient.Send(packet);
}
client.Room.Send(packet, client);
}
}

View File

@ -37,9 +37,7 @@ class WorldEventHealthHandler : ICommandHandler {
health.ToString("0.0#####", CultureInfo.GetCultureInfo("en-US")) + "," + DateTime.UtcNow.ToString("ddd MMM dd HH:mm:ss UTC yyyy", CultureInfo.GetCultureInfo("en-US")),
WorldEvent.Get().GetRoom().Id
);
foreach (var roomClient in WorldEvent.Get().GetRoom().Clients) {
roomClient.Send(packet);
}
WorldEvent.Get().GetRoom().Send(packet);
}
}
}
@ -59,9 +57,7 @@ class WorldEventFlareHandler : ICommandHandler {
p.Get<string>("oh") + "," + p.Get<string>("ts"),
WorldEvent.Get().GetRoom().Id
);
foreach (var roomClient in WorldEvent.Get().GetRoom().Clients) {
roomClient.Send(packet);
}
WorldEvent.Get().GetRoom().Send(packet);
}
}
@ -82,9 +78,7 @@ class WorldEventMissileHandler : ICommandHandler {
p.Get<string>("tID"),
p.Get<string>("objID")
});
foreach (var roomClient in WorldEvent.Get().GetRoom().Clients) {
roomClient.Send(packet);
}
WorldEvent.Get().GetRoom().Send(packet);
}
}

View File

@ -1,6 +1,7 @@
using sodoffmmo.Data;
using System;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
namespace sodoffmmo.Core;
public class Client {
@ -9,12 +10,12 @@ public class Client {
public int ClientID { get; private set; }
public PlayerData PlayerData { get; set; } = new();
public Room Room { get; private set; }
public Room? Room { get; private set; }
private readonly Socket socket;
SocketBuffer socketBuffer = new();
private volatile bool scheduledDisconnect = false;
private object ClientLock = new();
private readonly object clientLock = new();
public Client(Socket clientSocket) {
socket = clientSocket;
@ -39,36 +40,36 @@ public class Client {
try {
socket.Send(packet.SendData);
} catch (SocketException) {
LeaveRoom();
SheduleDisconnect();
}
}
public void LeaveRoom() {
if (Room != null) {
Console.WriteLine($"Leave room {Room.Name} IID: {ClientID}");
Room.RemoveClient(this);
NetworkObject data = new();
data.Add("r", Room.Id);
data.Add("u", ClientID);
NetworkPacket packet = NetworkObject.WrapObject(0, 1004, data).Serialize();
foreach (var roomClient in Room.Clients) {
roomClient.Send(packet);
}
Room = null;
}
}
public void JoinRoom(Room room) {
lock(ClientLock) {
LeaveRoom();
public void SetRoom(Room? room) {
lock(clientLock) {
// set variable player data as not valid, but do not reset all player data
PlayerData.IsValid = false;
if (Room != null) {
Console.WriteLine($"Leave room: {Room.Name} (id={Room.Id}, size={Room.ClientsCount}) IID: {ClientID}");
Room.RemoveClient(this);
NetworkObject data = new();
data.Add("r", Room.Id);
data.Add("u", ClientID);
Room.Send(NetworkObject.WrapObject(0, 1004, data).Serialize());
}
// set new room (null when SetRoom is used as LeaveRoom)
Room = room;
Room.AddClient(this);
if (Room != null) {
Console.WriteLine($"Join room: {Room.Name} RoomID (id={Room.Id}, size={Room.ClientsCount}) IID: {ClientID}");
Room.AddClient(this);
Send(Room.SubscribeRoom());
UpdatePlayerUserVariables();
}
}
Send(Room.SubscribeRoom());
UpdatePlayerUserVariables();
}
private void UpdatePlayerUserVariables() {
@ -91,6 +92,12 @@ public class Client {
}
public void SheduleDisconnect() {
if (Room != null) {
// quiet remove from room (to avoid issues in Room.Send)
// - do not change Room value here
// - full remove will be will take place Server.HandleClient (before real disconnected)
Room.RemoveClient(this);
}
scheduledDisconnect = true;
}

View File

@ -65,9 +65,7 @@ public class GauntletRoom : Room {
}
NetworkPacket packet = Utils.ArrNetworkPacket(info.ToArray(), "msg", base.Id);
foreach(var player in players) {
player.Key.Send(packet);
}
Send(packet);
}
public void SendPA(Client client) {
@ -112,10 +110,7 @@ public class GauntletRoom : Room {
}
NetworkPacket packet = Utils.ArrNetworkPacket(info.ToArray(), "msg", base.Id);
foreach(var player in players) {
player.Key.Send(packet);
}
Send(packet);
return true;
}
}
@ -127,8 +122,8 @@ public class GauntletRoom : Room {
if (room is null)
room = GauntletRoom.Get();
room.AddPlayer(client); // must be call before JoinRoom (before InvalidatePlayerData) - we need uid
client.JoinRoom(room);
client.SetRoom(room);
room.AddPlayer(client); // client will be not removed from GauntletRoom.players ... after remove all client from room whole GauntletRoom.players will be removed
room.SendUJR();
}
}

View File

@ -94,9 +94,7 @@ public class RacingRoom : Room {
}
NetworkPacket packet = Utils.ArrNetworkPacket(info.ToArray(), "", Id);
foreach (var roomClient in Clients) {
roomClient.Send(packet);
}
Send(packet);
}
}
@ -124,8 +122,7 @@ public class RacingRoom : Room {
private void SendJoin(Object? source, ElapsedEventArgs e) {
foreach(var player in players) {
Console.WriteLine($"Join Racing Room: {Name} RoomID: {Id} IID: {player.Key.ClientID}");
player.Key.JoinRoom(this);
player.Key.SetRoom(this);
}
SetTimer(1, CountDown, true);
}
@ -142,9 +139,7 @@ public class RacingRoom : Room {
"LT",
(--counter).ToString()
}, "", Id);
foreach (var roomClient in Clients) {
roomClient.Send(packet);
}
Send(packet);
}
}
}
@ -167,9 +162,7 @@ public class RacingRoom : Room {
"",
"ST"
}, "", Id);
foreach (var roomClient in Clients) {
roomClient.Send(packet);
}
Send(packet);
}
// TODO StratTimer → kick out to main lobby players without RacingPlayerState.RaceReady1 after timeout, next kick out players without RacingPlayerState.RaceReady2 after timeout2

View File

@ -66,6 +66,14 @@ public class Room {
}
}
public void Send(NetworkPacket packet, Client? skip = null) {
foreach (var roomClient in clients) {
if (roomClient != skip) {
roomClient.Send(packet);
}
}
}
public static bool Exists(string name) => rooms.ContainsKey(name);
public static Room Get(string name) => rooms[name];
@ -99,7 +107,7 @@ public class Room {
roomInfo.Add((short)0); // max spectator count
NetworkArray userList = new();
foreach (Client player in Clients) {
foreach (Client player in clients) {
if (player.PlayerData.Uid != "")
userList.Add(player.PlayerData.GetNetworkData(player.ClientID, out _));
}

View File

@ -160,9 +160,7 @@ class WorldEvent {
lastResults,
room.Id
);
foreach (var roomClient in room.Clients) {
roomClient.Send(packet);
}
room.Send(packet);
NetworkArray vl = new();
vl.Add(NetworkArray.VlElement("WE__AI", NetworkArray.NULL));
@ -171,9 +169,7 @@ class WorldEvent {
vl.Add(NetworkArray.VlElement("WEF_" + t.Key, NetworkArray.NULL));
}
packet = Utils.VlNetworkPacket(vl, room.Id);
foreach (var roomClient in room.Clients) {
roomClient.Send(packet);
}
room.Send(packet);
Console.WriteLine($"Event {uid} sent _End");
@ -206,9 +202,7 @@ class WorldEvent {
Console.WriteLine($"Event {uid} send event notification (WE_ = {(WE ? startTimeString : WE)} WEN_ = {(WEN ? nextStartTimeString : WEN)}, room = {room.Id}) to all clients");
NetworkPacket packet = Utils.VlNetworkPacket(EventInfoArray(WE, WEN), room.Id);
foreach (var r in Room.AllRooms()) {
foreach (var roomClient in r.Clients) {
roomClient.Send(packet);
}
r.Send(packet);
}
}

View File

@ -53,7 +53,7 @@ public class Server {
}
} finally {
try {
client.LeaveRoom();
client.SetRoom(null);
} catch (Exception) { }
client.Disconnect();
Console.WriteLine("Socket disconnected IID: " + client.ClientID);