From 5a8d666a7b82772efef92323cb2562929c8bdc04 Mon Sep 17 00:00:00 2001 From: Robert Paciorek Date: Mon, 26 Feb 2024 01:34:27 +0000 Subject: [PATCH] support for Gauntlet (Fireball Frenzy) also move SubscribeRoom and RespondJoinRoom from JoinRoomHandler to Room class --- src/CommandHandlers/GauntletHandlers.cs | 213 ++++++++++++++++++++++++ src/CommandHandlers/JoinRoomHandler.cs | 70 +------- src/Core/GauntletRoom.cs | 137 +++++++++++++++ src/Core/Room.cs | 125 ++++++++++++-- src/Core/Utils.cs | 9 +- 5 files changed, 472 insertions(+), 82 deletions(-) create mode 100644 src/CommandHandlers/GauntletHandlers.cs create mode 100644 src/Core/GauntletRoom.cs diff --git a/src/CommandHandlers/GauntletHandlers.cs b/src/CommandHandlers/GauntletHandlers.cs new file mode 100644 index 0000000..7c4ea9a --- /dev/null +++ b/src/CommandHandlers/GauntletHandlers.cs @@ -0,0 +1,213 @@ +using sodoffmmo.Attributes; +using sodoffmmo.Core; +using sodoffmmo.Data; + +using System.Timers; + +namespace sodoffmmo.CommandHandlers; + + +// Host Room For Any +[ExtensionCommandHandler("gs.HRFA")] +class GauntletCreateRoomHandler : ICommandHandler +{ + public void Handle(Client client, NetworkObject receivedObject) { + GauntletRoom.Join(client); + } +} + +// Join Any Room +[ExtensionCommandHandler("gs.JAR")] +class GauntletJoinRoomHandler : ICommandHandler +{ + public void Handle(Client client, NetworkObject receivedObject) { + GauntletRoom.Join(client); + } +} + +// Play Again +[ExtensionCommandHandler("gs.PA")] +class GauntletPlayAgainHandler : ICommandHandler +{ + public void Handle(Client client, NetworkObject receivedObject) { + GauntletRoom room = client.Room as GauntletRoom; + room.SetPlayerReady(client, false); + + NetworkPacket packet = Utils.ArrNetworkPacket(new string[] { + "LUNR", + room.Id.ToString(), + client.PlayerData.Uid + }, "msg", room.Id); + + foreach (var roomClient in room.Clients) { + if (roomClient != client) + roomClient.Send(packet); + } + room.SendPA(client); + } +} + +// Lobby User Ready +[ExtensionCommandHandler("gs.LUR")] +class GauntletLobbyUserReadyHandler : ICommandHandler +{ + public void Handle(Client client, NetworkObject receivedObject) { + GauntletRoom room = client.Room as GauntletRoom; + room.SetPlayerReady(client); + + NetworkPacket packet = Utils.ArrNetworkPacket(new string[] { + "LUR", + room.Id.ToString(), + client.PlayerData.Uid + }, "msg", room.Id); + + foreach (var roomClient in room.Clients) { + roomClient.Send(packet); + } + + if (room.GetReadyCount() > 1) { + packet = Utils.ArrNetworkPacket(new string[] { + "LCDD", // Lobby CountDown Done + room.Id.ToString(), + client.PlayerData.Uid + }, "msg", room.Id); + + foreach (var roomClient in room.Clients) { + roomClient.Send(packet); + } + } + } +} + +// Lobby User Not Ready +[ExtensionCommandHandler("gs.LUNR")] +class GauntletLobbyUserNotReadyHandler : ICommandHandler +{ + public void Handle(Client client, NetworkObject receivedObject) { + GauntletRoom room = client.Room as GauntletRoom; + room.SetPlayerReady(client, false); + + NetworkPacket packet = Utils.ArrNetworkPacket(new string[] { + "LUNR", + room.Id.ToString(), + client.PlayerData.Uid + }, "msg", room.Id); + + foreach (var roomClient in room.Clients) { + roomClient.Send(packet); + } + } +} + +// Game Level Load +[ExtensionCommandHandler("gs.GLL")] +class GauntletLevelLoadHandler : ICommandHandler +{ + public void Handle(Client client, NetworkObject receivedObject) { // {"a":13,"c":1,"p":{"c":"gs.GLL","p":{"0":"0","1":"0","2":"5","en":"GauntletGameExtension"},"r":365587}} + GauntletRoom room = client.Room as GauntletRoom; + NetworkObject p = receivedObject.Get("p"); + + NetworkPacket packet = Utils.ArrNetworkPacket(new string[] { + "GLL", // Game CountDown Start + room.Id.ToString(), + p.Get("0"), + p.Get("1"), + p.Get("2") // TODO use size of p.fields - 1 + }, "msg", room.Id); + foreach (var roomClient in room.Clients) { + roomClient.Send(packet); + } + + } +} + +// Game Level Loaded +[ExtensionCommandHandler("gs.GLLD")] +class GauntletLevelLoadedHandler : ICommandHandler +{ + private System.Timers.Timer timer = null; + private int counter; + private GauntletRoom room; + + public void Handle(Client client, NetworkObject receivedObject) { + room = client.Room as GauntletRoom; + counter = 5; + + // {"a":13,"c":1,"p":{"c":"msg","p":{"arr":["GCDS","365587","4"]},"r":365587}} + NetworkPacket packet = Utils.ArrNetworkPacket(new string[] { + "GCDS", // Game CountDown Start + room.Id.ToString(), + (--counter).ToString() + }, "msg", room.Id); + foreach (var roomClient in room.Clients) { + roomClient.Send(packet); + } + + timer = new System.Timers.Timer(1500); + timer.AutoReset = true; + timer.Enabled = true; + timer.Elapsed += OnTick; + } + + private void OnTick(Object source, ElapsedEventArgs e) { + NetworkPacket packet; + if (--counter > 0) { + // {"a":13,"c":1,"p":{"c":"msg","p":{"arr":["GCDS","365587","4"]},"r":365587}} + packet = Utils.ArrNetworkPacket(new string[] { + "GCDU", // Game CountDown Update + room.Id.ToString(), + counter.ToString() + }, "msg", room.Id); + } else { + // {"a":13,"c":1,"p":{"c":"msg","p":{"arr":["GS","365587"]},"r":365587}} + packet = Utils.ArrNetworkPacket(new string[] { + "GS", // Game Start + room.Id.ToString() + }, "msg", room.Id); + + timer.Stop(); + timer.Close(); + timer = null; + } + foreach (var roomClient in room.Clients) { + roomClient.Send(packet); + } + } +} + +// Relay Game Data +[ExtensionCommandHandler("gs.RGD")] +class GauntletRelayGameDataHandler : ICommandHandler +{ + public void Handle(Client client, NetworkObject receivedObject) // {"a":13,"c":1,"p":{"c":"gs.RGD","p":{"0":"2700","1":"78","en":"GauntletGameExtension"},"r":4}} + { + GauntletRoom room = client.Room as GauntletRoom; + NetworkObject p = receivedObject.Get("p"); + + // {"a":13,"c":1,"p":{"c":"msg","p":{"arr":["RGD","365587","150","75"]},"r":365587}} + NetworkPacket packet = Utils.ArrNetworkPacket(new string[] { + "RGD", // Relay Game Data + room.Id.ToString(), + p.Get("0"), + p.Get("1") + }, "msg", room.Id); + foreach (var roomClient in room.Clients) { + if (roomClient != client) + roomClient.Send(packet); + } + } +} + +// Game Complete +[ExtensionCommandHandler("gs.GC")] +class GauntletGameCompleteHandler : ICommandHandler +{ + public void Handle(Client client, NetworkObject receivedObject) // {"a":13,"c":1,"p":{"c":"gs.GC","p":{"0":"1550","1":"84","en":"GauntletGameExtension"},"r":4}} + { + GauntletRoom room = client.Room as GauntletRoom; + NetworkObject p = receivedObject.Get("p"); + + room.ProcessResult(client, p.Get("0"), p.Get("1")); + } +} + diff --git a/src/CommandHandlers/JoinRoomHandler.cs b/src/CommandHandlers/JoinRoomHandler.cs index 60ca1af..8408f03 100644 --- a/src/CommandHandlers/JoinRoomHandler.cs +++ b/src/CommandHandlers/JoinRoomHandler.cs @@ -18,78 +18,12 @@ class JoinRoomHandler : ICommandHandler Console.WriteLine($"Join Room: {roomName} RoomID: {room.Id} IID: {client.ClientID}"); this.client = client; - RespondJoinRoom(); - SubscribeRoom(); + client.Send(room.RespondJoinRoom()); + client.Send(room.SubscribeRoom()); UpdatePlayerUserVariables(); client.Room = room; } - private void RespondJoinRoom() { - NetworkObject obj = new(); - NetworkArray roomInfo = new(); - roomInfo.Add(room.Id); - roomInfo.Add(room.Name); // Room Name - roomInfo.Add(room.Name); // Group Name - roomInfo.Add(true); - roomInfo.Add(false); - roomInfo.Add(false); - roomInfo.Add((short)24); - roomInfo.Add((short)27); - roomInfo.Add(new NetworkArray()); - roomInfo.Add((short)0); - roomInfo.Add((short)0); - - NetworkArray userList = new(); - foreach (Client player in room.Clients) { - userList.Add(player.PlayerData.GetNetworkData(player.ClientID)); - } - - obj.Add("r", roomInfo); - obj.Add("ul", userList); - - NetworkPacket packet = NetworkObject.WrapObject(0, 4, obj).Serialize(); - packet.Compress(); - client.Send(packet); - } - - private void SubscribeRoom() { - NetworkObject obj = new(); - NetworkArray list = new(); - - NetworkArray r1 = new(); - r1.Add(room.Id); - r1.Add(room.Name); // Room Name - r1.Add(room.Name); // Group Name - r1.Add(true); - r1.Add(false); - r1.Add(false); - r1.Add((short)24); - r1.Add((short)27); - r1.Add(new NetworkArray()); - r1.Add((short)0); - r1.Add((short)0); - - NetworkArray r2 = new(); - r2.Add(room.Id); - r2.Add(room.Name); // Room Name - r2.Add(room.Name); // Group Name - r2.Add(true); - r2.Add(false); - r2.Add(false); - r2.Add((short)7); - r2.Add((short)27); - r2.Add(new NetworkArray()); - r2.Add((short)0); - r2.Add((short)0); - - list.Add(r1); - list.Add(r2); - - obj.Add("rl", list); - obj.Add("g", room.Name); - client.Send(NetworkObject.WrapObject(0, 15, obj).Serialize()); - } - private void UpdatePlayerUserVariables() { foreach (Client c in room.Clients) { NetworkObject cmd = new(); diff --git a/src/Core/GauntletRoom.cs b/src/Core/GauntletRoom.cs new file mode 100644 index 0000000..e1114c2 --- /dev/null +++ b/src/Core/GauntletRoom.cs @@ -0,0 +1,137 @@ +using System; +using sodoffmmo.Data; + +namespace sodoffmmo.Core; +public class GauntletRoom : Room { + static List GauntletRooms = new(); + + public static GauntletRoom Get() { + foreach (var room in GauntletRooms) { + if (room.ClientsCount < 2) { + lock (room.roomLock) { + if (room.ClientsCount == 0) + room.players.Clear(); + } + return room; + } + } + var newroom = new GauntletRoom("GauntletDO" + "_" + GauntletRooms.Count.ToString()); + GauntletRooms.Add(newroom); + return newroom; + } + + public GauntletRoom(string name) : base (name, "GauntletDO", true) { } + + + class Status { + public string uid; + public bool isReady = false; + public string resultA = null; + public string resultB = null; + } + + private Dictionary players = new(); + + public void AddPlayer(Client client) { + players[client] = new Status { uid = client.PlayerData.Uid }; + } + + public void SetPlayerReady(Client client, bool status = true) { + players[client].isReady = status; + } + + public int GetReadyCount() { + int count = 0; + foreach(var player in players) { + if (player.Value.isReady) ++count; + } + return count; + } + + public void SendUJR() { + // {"a":13,"c":1,"p":{"c":"msg","p":{"arr":["UJR","287997","2","f66cc516-7ea3-40a5-9021-01ff8f290123","false","2","03a3ad99-87a5-4af4-8966-0b2733a05e0f","false","1"]},"r":287997}} + List info = new(); + info.Add("UJR"); // User Joined Room + info.Add(base.Id.ToString()); + info.Add("2"); + int i = 0; + foreach(var player in players) { + info.Add(player.Value.uid); + info.Add(player.Value.isReady.ToString()); + info.Add("1"); // TODO this should be player gender + } + NetworkPacket packet = Utils.ArrNetworkPacket(info.ToArray(), "msg", base.Id); + + foreach(var player in players) { + player.Key.Send(packet); + } + } + + public void SendPA(Client client) { + // {"a":13,"c":1,"p":{"c":"msg","p":{"arr":["UJR","287997","2","f66cc516-7ea3-40a5-9021-01ff8f290123","false","2","03a3ad99-87a5-4af4-8966-0b2733a05e0f","false","1"]},"r":287997}} + List info = new(); + info.Add("PA"); // Play Again + info.Add(base.Id.ToString()); + info.Add("1"); + int i = 0; + foreach(var player in players) { + info.Add(player.Value.uid); + info.Add(player.Value.isReady.ToString()); + info.Add("1"); // TODO this should be player gender + } + NetworkPacket packet = Utils.ArrNetworkPacket(info.ToArray(), "msg", base.Id); + + client.Send(packet); + } + + public bool ProcessResult(Client client, string resultA, string resultB) { + lock (base.roomLock) { + players[client].resultA = resultA; + players[client].resultB = resultB; + + int count = 0; + foreach(var player in players) { + if (player.Value.resultA != null) ++count; + } + if (count != 2) + return false; + + // {"a":13,"c":1,"p":{"c":"msg","p":{"arr":["GC","365587","03a3ad99-87a5-4af4-8966-0b2733a05e0f","10850","79","1","bff0c312-8763-497d-aa0c-a5dfc7d8b861","21050","73","1"]},"r":365587}} + List info = new(); + info.Add("GC"); + info.Add(base.Id.ToString()); + int i = 0; + foreach(var player in players) { + if (player.Value.resultA is null) + continue; + info.Add(player.Value.uid); + info.Add(player.Value.resultA); + info.Add(player.Value.resultB); + info.Add("1"); + } + NetworkPacket packet = Utils.ArrNetworkPacket(info.ToArray(), "msg", base.Id); + + foreach(var player in players) { + player.Key.Send(packet); + } + + return true; + } + } + + static public void Join(Client client, GauntletRoom room = null) { + if (room is null) + room = GauntletRoom.Get(); + + room.AddPlayer(client); // must be call before InvalidatePlayerData - we need uid + + client.LeaveRoom(); + client.InvalidatePlayerData(); + + client.Send(room.RespondJoinRoom()); + client.Send(room.SubscribeRoom()); + room.SendUJR(); + + client.Room = room; + } +} diff --git a/src/Core/Room.cs b/src/Core/Room.cs index fb20ef7..14509a4 100644 --- a/src/Core/Room.cs +++ b/src/Core/Room.cs @@ -1,20 +1,33 @@ using System; +using sodoffmmo.Data; namespace sodoffmmo.Core; public class Room { + static int id = 2; static Dictionary rooms = new(); - public object roomLock = new object(); List clients = new(); + public object roomLock = new object(); - public string Name { get; private set; } public int Id { get; private set; } + public string Name { get; private set; } + public string Group { get; private set; } + public bool IsRaceRoom { get; private set; } - public Room(int id, string name) { + public Room(string name, string group = null, bool isRaceRoom = false) { + Id = rooms.Count + 3; Name = name; - Id = id; + if (group is null) { + Group = name; + } else { + Group = group; + } + IsRaceRoom = isRaceRoom; + rooms.Add(Name, this); } + public int ClientsCount => clients.Count; + public IEnumerable Clients { get { List list; @@ -37,21 +50,111 @@ public class Room { } } + public static bool Exists(string name) => rooms.ContainsKey(name); + public static Room Get(string name) => rooms[name]; public static Room GetOrAdd(string name) { if (!Room.Exists(name)) - Room.Add(name); + return new Room(name); return rooms[name]; } - public static bool Exists(string name) => rooms.ContainsKey(name); - - public static void Add(string name) { - rooms[name] = new Room(rooms.Count + 3, name); - } - public static Room[] AllRooms() { return rooms.Values.ToArray(); } + + + public NetworkPacket RespondJoinRoom() { + NetworkObject obj = new(); + NetworkArray roomInfo = new(); + roomInfo.Add(Id); + roomInfo.Add(Name); // Room Name + roomInfo.Add(Group); // Group Name + roomInfo.Add(true); + roomInfo.Add(false); + roomInfo.Add(false); + if (IsRaceRoom) { + NetworkArray raceRoom = new(); + raceRoom.Add("IS_RACE_ROOM"); + raceRoom.Add((Byte)1); + raceRoom.Add(true); + raceRoom.Add(false); + raceRoom.Add(false); + + NetworkArray raceRoom2 = new(); + raceRoom2.Add(raceRoom); + + roomInfo.Add((short)1); + roomInfo.Add((short)2); + roomInfo.Add(raceRoom2); + } else { + roomInfo.Add((short)24); + roomInfo.Add((short)27); + roomInfo.Add(new NetworkArray()); + } + roomInfo.Add((short)0); + roomInfo.Add((short)0); + + NetworkArray userList = new(); + foreach (Client player in Clients) { + userList.Add(player.PlayerData.GetNetworkData(player.ClientID)); + } + + obj.Add("r", roomInfo); + obj.Add("ul", userList); + + NetworkPacket packet = NetworkObject.WrapObject(0, 4, obj).Serialize(); + packet.Compress(); + + return packet; + } + + public NetworkPacket SubscribeRoom() { + NetworkObject obj = new(); + NetworkArray list = new(); + + NetworkArray r1 = new(); + r1.Add(Id); + r1.Add(Name); // Room Name + r1.Add(Group); // Group Name + r1.Add(true); + r1.Add(false); + r1.Add(false); + if (IsRaceRoom) { + r1.Add((short)1); + r1.Add((short)2); + } else { + r1.Add((short)24); + r1.Add((short)27); + } + r1.Add(new NetworkArray()); + r1.Add((short)0); + r1.Add((short)0); + + NetworkArray r2 = new(); + r2.Add(Id); + r2.Add(Name); // Room Name + r2.Add(Group); // Group Name + r2.Add(true); + r2.Add(false); + r2.Add(false); + if (IsRaceRoom) { + r2.Add((short)1); + r2.Add((short)2); + } else { + r2.Add((short)7); + r2.Add((short)27); + } + r2.Add(new NetworkArray()); + r2.Add((short)0); + r2.Add((short)0); + + list.Add(r1); + list.Add(r2); + + obj.Add("rl", list); + obj.Add("g", Name); + return NetworkObject.WrapObject(0, 15, obj).Serialize(); + } } diff --git a/src/Core/Utils.cs b/src/Core/Utils.cs index 08d0cb3..df2471d 100644 --- a/src/Core/Utils.cs +++ b/src/Core/Utils.cs @@ -28,12 +28,15 @@ internal static class Utils { return VlNetworkPacket(vl, roomID); } - public static NetworkPacket ArrNetworkPacket(string[] data) { + public static NetworkPacket ArrNetworkPacket(string[] data, string c = "", int? roomID = null) { NetworkObject cmd = new(); NetworkObject obj = new(); obj.Add("arr", data); - cmd.Add("c", ""); + cmd.Add("c", c); cmd.Add("p", obj); - return NetworkObject.WrapObject(1, 13, cmd).Serialize(); + NetworkObject ret = NetworkObject.WrapObject(1, 13, cmd); + if (roomID != null) + ret.Add("r", (int)roomID); + return ret.Serialize(); } }