diff --git a/src/CommandHandlers/ChatMessageHandler.cs b/src/CommandHandlers/ChatMessageHandler.cs index 313f359..e20f690 100644 --- a/src/CommandHandlers/ChatMessageHandler.cs +++ b/src/CommandHandlers/ChatMessageHandler.cs @@ -5,13 +5,14 @@ using sodoffmmo.Data; namespace sodoffmmo.CommandHandlers; [ExtensionCommandHandler("SCM")] -class ChatMessageHandler : ICommandHandler { - public void Handle(Client client, NetworkObject receivedObject) { +class ChatMessageHandler : CommandHandler { + public override Task Handle(Client client, NetworkObject receivedObject) { if (!Configuration.ServerConfiguration.EnableChat) { ChatDisabled(client, receivedObject); - return; + } else { + Chat(client, receivedObject); } - Chat(client, receivedObject); + return Task.CompletedTask; } public void ChatDisabled(Client client, NetworkObject receivedObject) { diff --git a/src/CommandHandlers/DateTimeHandler.cs b/src/CommandHandlers/DateTimeHandler.cs index 753d459..5bdf459 100644 --- a/src/CommandHandlers/DateTimeHandler.cs +++ b/src/CommandHandlers/DateTimeHandler.cs @@ -5,13 +5,14 @@ using sodoffmmo.Data; namespace sodoffmmo.CommandHandlers; [ExtensionCommandHandler("DT")] -class DateTimeHandler : ICommandHandler { - public void Handle(Client client, NetworkObject receivedObject) { +class DateTimeHandler : CommandHandler { + public override Task Handle(Client client, NetworkObject receivedObject) { NetworkObject cmd = new(); NetworkObject obj = new(); obj.Add("arr", new string[] { "DT", DateTime.UtcNow.ToString("MM/dd/yyyy HH:mm:ss") }); cmd.Add("c", "DT"); cmd.Add("p", obj); client.Send(NetworkObject.WrapObject(1, 13, cmd).Serialize()); + return Task.CompletedTask; } } diff --git a/src/CommandHandlers/ExitHandler.cs b/src/CommandHandlers/ExitHandler.cs index caee1f7..1154345 100644 --- a/src/CommandHandlers/ExitHandler.cs +++ b/src/CommandHandlers/ExitHandler.cs @@ -5,8 +5,9 @@ using sodoffmmo.Data; namespace sodoffmmo.CommandHandlers; [CommandHandler(26)] -class ExitHandler : ICommandHandler { - public void Handle(Client client, NetworkObject receivedObject) { +class ExitHandler : CommandHandler { + public override Task Handle(Client client, NetworkObject receivedObject) { client.SetRoom(null); + return Task.CompletedTask; } } diff --git a/src/CommandHandlers/GauntletHandlers.cs b/src/CommandHandlers/GauntletHandlers.cs index c90a583..118756c 100644 --- a/src/CommandHandlers/GauntletHandlers.cs +++ b/src/CommandHandlers/GauntletHandlers.cs @@ -9,27 +9,29 @@ namespace sodoffmmo.CommandHandlers; // Host Room For Any [ExtensionCommandHandler("gs.HRFA")] -class GauntletCreateRoomHandler : ICommandHandler +class GauntletCreateRoomHandler : CommandHandler { - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { GauntletRoom.Join(client); + return Task.CompletedTask; } } // Join Any Room [ExtensionCommandHandler("gs.JAR")] -class GauntletJoinRoomHandler : ICommandHandler +class GauntletJoinRoomHandler : CommandHandler { - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { GauntletRoom.Join(client); + return Task.CompletedTask; } } // Play Again [ExtensionCommandHandler("gs.PA")] -class GauntletPlayAgainHandler : ICommandHandler +class GauntletPlayAgainHandler : CommandHandler { - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { GauntletRoom room = (client.Room as GauntletRoom)!; room.SetPlayerReady(client, false); @@ -41,14 +43,15 @@ class GauntletPlayAgainHandler : ICommandHandler room.Send(packet, client); room.SendPA(client); + return Task.CompletedTask; } } // Lobby User Ready [ExtensionCommandHandler("gs.LUR")] -class GauntletLobbyUserReadyHandler : ICommandHandler +class GauntletLobbyUserReadyHandler : CommandHandler { - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { GauntletRoom room = (client.Room as GauntletRoom)!; room.SetPlayerReady(client); @@ -69,14 +72,15 @@ class GauntletLobbyUserReadyHandler : ICommandHandler room.Send(packet); } + return Task.CompletedTask; } } // Lobby User Not Ready [ExtensionCommandHandler("gs.LUNR")] -class GauntletLobbyUserNotReadyHandler : ICommandHandler +class GauntletLobbyUserNotReadyHandler : CommandHandler { - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { GauntletRoom room = (client.Room as GauntletRoom)!; room.SetPlayerReady(client, false); @@ -87,14 +91,15 @@ class GauntletLobbyUserNotReadyHandler : ICommandHandler }, "msg", room.Id); room.Send(packet); + return Task.CompletedTask; } } // Game Level Load [ExtensionCommandHandler("gs.GLL")] -class GauntletLevelLoadHandler : ICommandHandler +class GauntletLevelLoadHandler : CommandHandler { - 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}} + public override Task 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"); @@ -106,18 +111,19 @@ class GauntletLevelLoadHandler : ICommandHandler p.Get("2") // TODO use size of p.fields - 1 }, "msg", room.Id); room.Send(packet); + return Task.CompletedTask; } } // Game Level Loaded [ExtensionCommandHandler("gs.GLLD")] -class GauntletLevelLoadedHandler : ICommandHandler +class GauntletLevelLoadedHandler : CommandHandler { private System.Timers.Timer? timer = null; private int counter; private GauntletRoom room; - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { room = (client.Room as GauntletRoom)!; counter = 5; @@ -133,6 +139,7 @@ class GauntletLevelLoadedHandler : ICommandHandler timer.AutoReset = true; timer.Enabled = true; timer.Elapsed += OnTick; + return Task.CompletedTask; } private void OnTick(Object? source, ElapsedEventArgs e) { @@ -161,9 +168,9 @@ class GauntletLevelLoadedHandler : ICommandHandler // Relay Game Data [ExtensionCommandHandler("gs.RGD")] -class GauntletRelayGameDataHandler : ICommandHandler +class GauntletRelayGameDataHandler : CommandHandler { - public void Handle(Client client, NetworkObject receivedObject) // {"a":13,"c":1,"p":{"c":"gs.RGD","p":{"0":"2700","1":"78","en":"GauntletGameExtension"},"r":4}} + public override Task 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"); @@ -176,19 +183,21 @@ class GauntletRelayGameDataHandler : ICommandHandler p.Get("1") }, "msg", room.Id); room.Send(packet, client); + return Task.CompletedTask; } } // Game Complete [ExtensionCommandHandler("gs.GC")] -class GauntletGameCompleteHandler : ICommandHandler +class GauntletGameCompleteHandler : CommandHandler { - public void Handle(Client client, NetworkObject receivedObject) // {"a":13,"c":1,"p":{"c":"gs.GC","p":{"0":"1550","1":"84","en":"GauntletGameExtension"},"r":4}} + public override Task 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")); + return Task.CompletedTask; } } diff --git a/src/CommandHandlers/GenericMessageHandler.cs b/src/CommandHandlers/GenericMessageHandler.cs index bb6c41f..cd7fb60 100644 --- a/src/CommandHandlers/GenericMessageHandler.cs +++ b/src/CommandHandlers/GenericMessageHandler.cs @@ -5,9 +5,10 @@ using sodoffmmo.Data; namespace sodoffmmo.CommandHandlers; [CommandHandler(7)] -class GenericMessageHandler : ICommandHandler { - public void Handle(Client client, NetworkObject receivedObject) { +class GenericMessageHandler : CommandHandler { + public override Task Handle(Client client, NetworkObject receivedObject) { NetworkPacket packet = NetworkObject.WrapObject(0, 7, receivedObject).Serialize(); client.Room.Send(packet); + return Task.CompletedTask; } } diff --git a/src/CommandHandlers/HandshakeHandler.cs b/src/CommandHandlers/HandshakeHandler.cs index 2eea93f..18a56b2 100644 --- a/src/CommandHandlers/HandshakeHandler.cs +++ b/src/CommandHandlers/HandshakeHandler.cs @@ -7,14 +7,14 @@ using System; namespace sodoffmmo.CommandHandlers; [CommandHandler(0)] -class HandshakeHandler : ICommandHandler +class HandshakeHandler : CommandHandler { - public void Handle(Client client, NetworkObject receivedObject) + public override Task Handle(Client client, NetworkObject receivedObject) { string? token = receivedObject.Get("rt"); if (token != null) { client.Send(NetworkObject.WrapObject(0, 1006, new NetworkObject()).Serialize()); - return; + return Task.CompletedTask; } NetworkObject obj = new(); @@ -24,6 +24,7 @@ class HandshakeHandler : ICommandHandler obj.Add("ms", 1000000); client.Send(NetworkObject.WrapObject(0, 0, obj).Serialize()); + return Task.CompletedTask; } private string RandomString(int length) { @@ -38,4 +39,4 @@ class HandshakeHandler : ICommandHandler return builder.ToString(); } -} \ No newline at end of file +} diff --git a/src/CommandHandlers/JoinPrivateRoomHandler.cs b/src/CommandHandlers/JoinPrivateRoomHandler.cs index 3e91fa3..bd9d5cb 100644 --- a/src/CommandHandlers/JoinPrivateRoomHandler.cs +++ b/src/CommandHandlers/JoinPrivateRoomHandler.cs @@ -5,13 +5,14 @@ using sodoffmmo.Data; namespace sodoffmmo.CommandHandlers; [ExtensionCommandHandler("JO")] -class JoinPrivateRoomHandler : ICommandHandler +class JoinPrivateRoomHandler : CommandHandler { - public void Handle(Client client, NetworkObject receivedObject) + public override Task Handle(Client client, NetworkObject receivedObject) { var p = receivedObject.Get("p"); string roomName = p.Get("rn") + "_" + p.Get("0"); Room room = Room.GetOrAdd(roomName, autoRemove: true); client.SetRoom(room); + return Task.CompletedTask; } } diff --git a/src/CommandHandlers/JoinRoomHandler.cs b/src/CommandHandlers/JoinRoomHandler.cs index b9f7ab0..3277809 100644 --- a/src/CommandHandlers/JoinRoomHandler.cs +++ b/src/CommandHandlers/JoinRoomHandler.cs @@ -5,12 +5,13 @@ using sodoffmmo.Data; namespace sodoffmmo.CommandHandlers; [ExtensionCommandHandler("JA")] -class JoinRoomHandler : ICommandHandler +class JoinRoomHandler : CommandHandler { - public void Handle(Client client, NetworkObject receivedObject) + public override Task Handle(Client client, NetworkObject receivedObject) { string roomName = receivedObject.Get("p").Get("rn"); Room room = Room.GetOrAdd(roomName); client.SetRoom(room); + return Task.CompletedTask; } } diff --git a/src/CommandHandlers/LoginHandler.cs b/src/CommandHandlers/LoginHandler.cs index c4a311a..2af9a57 100644 --- a/src/CommandHandlers/LoginHandler.cs +++ b/src/CommandHandlers/LoginHandler.cs @@ -6,9 +6,9 @@ using sodoffmmo.Management; namespace sodoffmmo.CommandHandlers; [CommandHandler(1)] -class LoginHandler : ICommandHandler +class LoginHandler : CommandHandler { - public void Handle(Client client, NetworkObject receivedObject) + public override Task Handle(Client client, NetworkObject receivedObject) { client.PlayerData.UNToken = receivedObject.Get("un"); if (!ValidToken(client)) { @@ -16,7 +16,7 @@ class LoginHandler : ICommandHandler obj.Add("dr", (byte)1); client.Send(NetworkObject.WrapObject(0, 1005, obj).Serialize()); client.ScheduleDisconnect(); - return; + return Task.CompletedTask; } NetworkArray rl = new(); @@ -68,6 +68,7 @@ class LoginHandler : ICommandHandler content.Add("pi", (short)1); client.Send(NetworkObject.WrapObject(0, 1, content).Serialize()); + return Task.CompletedTask; } private bool ValidToken(Client client) { diff --git a/src/CommandHandlers/PingHandler.cs b/src/CommandHandlers/PingHandler.cs index b5d3478..cfc665a 100644 --- a/src/CommandHandlers/PingHandler.cs +++ b/src/CommandHandlers/PingHandler.cs @@ -5,8 +5,13 @@ using sodoffmmo.Data; namespace sodoffmmo.CommandHandlers; [ExtensionCommandHandler("PNG")] -class PingHandler : ICommandHandler { - public void Handle(Client client, NetworkObject receivedObject) { +class PingHandler : CommandHandler { + public bool RunInBackground { get; } = true; + + public override async Task Handle(Client client, NetworkObject receivedObject) { + if (Configuration.ServerConfiguration.PingDelay > 0) { + await Task.Delay(Configuration.ServerConfiguration.PingDelay); + } NetworkObject cmd = new(); NetworkObject obj = new(); obj.Add("arr", new string[] { "PNG", DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString() }); diff --git a/src/CommandHandlers/PublicMessageHandlers.cs b/src/CommandHandlers/PublicMessageHandlers.cs index 86f1257..80266f1 100644 --- a/src/CommandHandlers/PublicMessageHandlers.cs +++ b/src/CommandHandlers/PublicMessageHandlers.cs @@ -5,10 +5,10 @@ using sodoffmmo.Data; namespace sodoffmmo.CommandHandlers; [ExtensionCommandHandler("PM")] -class RacingPMHandler : ICommandHandler +class RacingPMHandler : CommandHandler { // rec: {"a":13,"c":1,"p":{"c":"PM","p":{"M":"DT:c4647597-a72a-4f34-973c-5a10218d9a64:1000","en":"we"},"r":-1}} - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { // send: {"a":13,"c":1,"p":{"c":"PM","p":{"arr":[{"M":["DT:f05fc387-7358-4bff-be04-7c316f0a8de8:1000"],"MID":3529441}]}}} NetworkObject cmd = new(); NetworkObject p = new(); @@ -25,5 +25,6 @@ class RacingPMHandler : ICommandHandler NetworkPacket packet = NetworkObject.WrapObject(1, 13, cmd).Serialize(); client.Room.Send(packet); + return Task.CompletedTask; } } diff --git a/src/CommandHandlers/RacingHandlers.cs b/src/CommandHandlers/RacingHandlers.cs index d0ee9e3..57a1d89 100644 --- a/src/CommandHandlers/RacingHandlers.cs +++ b/src/CommandHandlers/RacingHandlers.cs @@ -8,9 +8,9 @@ namespace sodoffmmo.CommandHandlers; // Set Player Ready [ExtensionCommandHandler("dr.PR")] -class RacingPlayerReadyHandler : ICommandHandler +class RacingPlayerReadyHandler : CommandHandler { - public void Handle(Client client, NetworkObject receivedObject) { // {"a":13,"c":1,"p":{"c":"dr.PR","p":{"IMR":"True","en":""},"r":-1}} + public override Task Handle(Client client, NetworkObject receivedObject) { // {"a":13,"c":1,"p":{"c":"dr.PR","p":{"IMR":"True","en":""},"r":-1}} NetworkObject p = receivedObject.Get("p"); RacingPlayerState ready = p.Get("IMR") == "True" ? RacingPlayerState.Ready : RacingPlayerState.NotReady; @@ -26,33 +26,37 @@ class RacingPlayerReadyHandler : ICommandHandler RacingLobby.Lobby.SetPlayerState(client, ready); Console.WriteLine($"IMR: {client.ClientID} {ready}"); } + + return Task.CompletedTask; } } // Player Status Request [ExtensionCommandHandler("dr.PS")] -class RacingPlayerStatusHandler : ICommandHandler +class RacingPlayerStatusHandler : CommandHandler { - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { client.Send(RacingLobby.Lobby.GetPS()); + return Task.CompletedTask; } } // User Ready ACK [ExtensionCommandHandler("dr.UACK")] -class RacingUACKHandler : ICommandHandler +class RacingUACKHandler : CommandHandler { - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { RacingRoom room = (client.Room as RacingRoom)!; room.SetPlayerState(client, RacingPlayerState.RaceReady1); + return Task.CompletedTask; } } // All Ready ACK [ExtensionCommandHandler("dr.ARACK")] -class RacingARACKHandler : ICommandHandler +class RacingARACKHandler : CommandHandler { - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { RacingRoom room = (client.Room as RacingRoom)!; room.SetPlayerState(client, RacingPlayerState.RaceReady2); @@ -61,17 +65,19 @@ class RacingARACKHandler : ICommandHandler room.Send(packet); Console.WriteLine($"STA"); } + return Task.CompletedTask; } } [ExtensionCommandHandler("dr.AR")] -class RacingARHandler : ICommandHandler +class RacingARHandler : CommandHandler { - public void Handle(Client client, NetworkObject receivedObject) { // {"a":13,"c":1,"p":{"c":"dr.AR","p":{"CT":"112.1268","FD":"3008.283","LC":"3","UN":"scourgexxwulf","en":""},"r":412467}} + public override Task Handle(Client client, NetworkObject receivedObject) { // {"a":13,"c":1,"p":{"c":"dr.AR","p":{"CT":"112.1268","FD":"3008.283","LC":"3","UN":"scourgexxwulf","en":""},"r":412467}} RacingRoom room = (client.Room as RacingRoom)!; NetworkObject p = receivedObject.Get("p"); room.SetResults(client, p.Get("UN"), p.Get("CT"), p.Get("LC")); room.SendResults(); + return Task.CompletedTask; } } diff --git a/src/CommandHandlers/SetPositionVariablesHandler.cs b/src/CommandHandlers/SetPositionVariablesHandler.cs index b24f6b3..772c9e4 100644 --- a/src/CommandHandlers/SetPositionVariablesHandler.cs +++ b/src/CommandHandlers/SetPositionVariablesHandler.cs @@ -5,20 +5,22 @@ using sodoffmmo.Data; namespace sodoffmmo.CommandHandlers; [ExtensionCommandHandler("SPV")] -class SetPositionVariablesHandler : ICommandHandler { +class SetPositionVariablesHandler : CommandHandler { Client client; NetworkObject spvData; - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { if (client.Room == null) { Console.WriteLine($"SPV Missing Room IID: {client.ClientID}"); client.Send(NetworkObject.WrapObject(0, 1006, new NetworkObject()).Serialize()); client.ScheduleDisconnect(); - return; + return Task.CompletedTask; } this.client = client; spvData = receivedObject; UpdatePositionVariables(); SendSPVCommand(); + + return Task.CompletedTask; } private void UpdatePositionVariables() { diff --git a/src/CommandHandlers/SetUserVariablesHandler.cs b/src/CommandHandlers/SetUserVariablesHandler.cs index 12a8d4b..5a57ced 100644 --- a/src/CommandHandlers/SetUserVariablesHandler.cs +++ b/src/CommandHandlers/SetUserVariablesHandler.cs @@ -6,16 +6,16 @@ using System.Globalization; namespace sodoffmmo.CommandHandlers; [ExtensionCommandHandler("SUV")] -class SetUserVariablesHandler : ICommandHandler { +class SetUserVariablesHandler : CommandHandler { NetworkObject suvData; Client client; string? uid; - public void Handle(Client client, NetworkObject receivedObject) { + public override Task 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.ScheduleDisconnect(); - return; + return Task.CompletedTask; } this.client = client; suvData = receivedObject.Get("p"); @@ -27,6 +27,7 @@ class SetUserVariablesHandler : ICommandHandler { else UpdateVars(); + return Task.CompletedTask; } private void ProcessPlayerData() { diff --git a/src/CommandHandlers/WorldEventHandlers.cs b/src/CommandHandlers/WorldEventHandlers.cs index 88fe73e..86ef5b6 100644 --- a/src/CommandHandlers/WorldEventHandlers.cs +++ b/src/CommandHandlers/WorldEventHandlers.cs @@ -6,20 +6,21 @@ using sodoffmmo.Data; namespace sodoffmmo.CommandHandlers; [ExtensionCommandHandler("wex.WES")] // event status request -class WorldEventStatusHandler : ICommandHandler { - public void Handle(Client client, NetworkObject receivedObject) { +class WorldEventStatusHandler : CommandHandler { + public override Task Handle(Client client, NetworkObject receivedObject) { client.Send(Utils.ArrNetworkPacket( new string[] { "WESR", "WE_ScoutAttack|" + WorldEvent.Get().EventInfo(), "EvEnd|" + WorldEvent.Get().GetLastResults() })); + return Task.CompletedTask; } } [ExtensionCommandHandler("wex.OV")] -class WorldEventHealthHandler : ICommandHandler { +class WorldEventHealthHandler : CommandHandler { // rec: {"a":13,"c":1,"p":{"c":"wex.OV","p":{"en":"","event":"ScoutAttack","eventUID":"ZydLUmCC","oh":"0.003444444","uid":"ZydLUmCC1"},"r":-1}} - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { // NOTE: this should be process on event in any state - we use it to make event active NetworkObject p = receivedObject.Get("p"); float healthUpdateVal = float.Parse( @@ -39,15 +40,16 @@ class WorldEventHealthHandler : ICommandHandler { ); WorldEvent.Get().GetRoom().Send(packet); } + return Task.CompletedTask; } } [ExtensionCommandHandler("wex.OVF")] // flare info from ship AI -> resend as WEF_ -class WorldEventFlareHandler : ICommandHandler { +class WorldEventFlareHandler : CommandHandler { // rec: {"a":13,"c":1,"p":{"c":"wex.OVF","p":{"en":"","fuid":"WpnpDyJ51,14,0","oh":"0","ts":"6/29/2023 3:03:18 AM"},"r":-1}} - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { if (!WorldEvent.Get().IsActive()) - return; + return Task.CompletedTask; NetworkObject p = receivedObject.Get("p"); @@ -58,15 +60,17 @@ class WorldEventFlareHandler : ICommandHandler { WorldEvent.Get().GetRoom().Id ); WorldEvent.Get().GetRoom().Send(packet); + + return Task.CompletedTask; } } [ExtensionCommandHandler("wex.ST")] // missile info from ship AI -> resend as WA -class WorldEventMissileHandler : ICommandHandler { +class WorldEventMissileHandler : CommandHandler { // rec: {"a":13,"c":1,"p":{"c":"wex.ST","p":{"en":"","objID":"-4X_gWAo1","tID":"f5b6254a-df78-4e24-aa9d-7e14539fb858","uID":"1f8eeb6b-753f-4e7f-af13-42cdd69d14e7","wID":"5"},"r":-1}} - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { if (!WorldEvent.Get().IsActive()) - return; + return Task.CompletedTask; NetworkObject p = receivedObject.Get("p"); @@ -79,45 +83,52 @@ class WorldEventMissileHandler : ICommandHandler { p.Get("objID") }); WorldEvent.Get().GetRoom().Send(packet); + + return Task.CompletedTask; } } [ExtensionCommandHandler("wex.PS")] -class WorldEventScoreHandler : ICommandHandler { +class WorldEventScoreHandler : CommandHandler { // rec: {"a":13,"c":1,"p":{"c":"wex.PS","p":{"ScoreData":"Datashyo/10","en":"","id":"ScoutAttack"},"r":-1}} - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { if (!WorldEvent.Get().IsActive()) - return; + return Task.CompletedTask; string scoreData = receivedObject.Get("p").Get("ScoreData"); string[] keyValPair = scoreData.Split('/'); WorldEvent.Get().UpdateScore(keyValPair[0], keyValPair[1]); + + return Task.CompletedTask; } } [ExtensionCommandHandler("wex.AIACK")] // AI ack -class WorldEventAIACKHandler : ICommandHandler { +class WorldEventAIACKHandler : CommandHandler { // rec: {"a":13,"c":1,"p":{"c":"wex.AIACK","p":{"en":"","id":"f322dd98-e9fb-4b2d-a5e0-1c98680517b5","uid":"SoDOff1"},"r":-1}} - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { WorldEvent.Get().UpdateAI(client); + return Task.CompletedTask; } } [ExtensionCommandHandler("wex.AIP")] // AI ping -class WorldEventAIPingHandler : ICommandHandler { +class WorldEventAIPingHandler : CommandHandler { // rec: {"a":13,"c":1,"p":{"c":"wex.AIP","p":{"en":""},"r":-1}} - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { WorldEvent.Get().UpdateAI(client); + return Task.CompletedTask; } } [ExtensionCommandHandler("wex.ETS")] // time span -class WorldEventTimeSpanHandler : ICommandHandler { +class WorldEventTimeSpanHandler : CommandHandler { // rec: {"a":13,"c":1,"p":{"c":"wex.ETS","p":{"en":"","timeSpan":"300"},"r":-1}} - public void Handle(Client client, NetworkObject receivedObject) { + public override Task Handle(Client client, NetworkObject receivedObject) { float timeSpan = float.Parse( receivedObject.Get("p").Get("timeSpan"), System.Globalization.CultureInfo.InvariantCulture ); WorldEvent.Get().SetTimeSpan(client, timeSpan); + return Task.CompletedTask; } } diff --git a/src/Core/CommandHandler.cs b/src/Core/CommandHandler.cs new file mode 100644 index 0000000..5d6b7a1 --- /dev/null +++ b/src/Core/CommandHandler.cs @@ -0,0 +1,8 @@ +using sodoffmmo.Data; + +namespace sodoffmmo.Core; +public abstract class CommandHandler { + public bool RunInBackground { get; } + + public abstract Task Handle(Client client, NetworkObject receivedObject); +} diff --git a/src/Core/Configuration.cs b/src/Core/Configuration.cs index 65ec472..e99cbf1 100644 --- a/src/Core/Configuration.cs +++ b/src/Core/Configuration.cs @@ -34,6 +34,7 @@ internal sealed class ServerConfiguration { public int RacingMaxPlayers { get; set; } = 6; public int RacingMinPlayers { get; set; } = 2; public int RacingMainLobbyTimer { get; set; } = 15; + public int PingDelay { get; set; } = 17; public bool EnableChat { get; set; } = true; public bool AllowChaos { get; set; } = false; public bool Authentication { get; set; } = false; diff --git a/src/Core/ICommandHandler.cs b/src/Core/ICommandHandler.cs deleted file mode 100644 index e4c0b34..0000000 --- a/src/Core/ICommandHandler.cs +++ /dev/null @@ -1,6 +0,0 @@ -using sodoffmmo.Data; - -namespace sodoffmmo.Core; -public interface ICommandHandler { - public void Handle(Client client, NetworkObject receivedObject); -} diff --git a/src/Core/ModuleManager.cs b/src/Core/ModuleManager.cs index d83ec98..a4c31ad 100644 --- a/src/Core/ModuleManager.cs +++ b/src/Core/ModuleManager.cs @@ -12,22 +12,22 @@ class ModuleManager { RegisterExtensionHandlers(); } - public ICommandHandler GetCommandHandler(int id) { + public CommandHandler GetCommandHandler(int id) { if (handlers.TryGetValue(id, out Type? handler)) - return (ICommandHandler)Activator.CreateInstance(handler)!; + return (CommandHandler)Activator.CreateInstance(handler)!; throw new Exception($"Command handler with ID {id} not found!"); } - public ICommandHandler GetCommandHandler(string name) { + public CommandHandler GetCommandHandler(string name) { if (extHandlers.TryGetValue(name, out Type? handler)) - return (ICommandHandler)Activator.CreateInstance(handler)!; + return (CommandHandler)Activator.CreateInstance(handler)!; throw new Exception($"Command handler with name \"{name}\" not found!"); } private void RegisterHandlers() { handlers.Clear(); var handlerTypes = Assembly.GetExecutingAssembly().GetTypes() - .Where(type => typeof(ICommandHandler).IsAssignableFrom(type)) + .Where(type => typeof(CommandHandler).IsAssignableFrom(type)) .Where(type => type.GetCustomAttribute() != null); foreach (var handlerType in handlerTypes) { @@ -39,7 +39,7 @@ class ModuleManager { private void RegisterExtensionHandlers() { extHandlers.Clear(); var extHandlerTypes = Assembly.GetExecutingAssembly().GetTypes() - .Where(type => typeof(ICommandHandler).IsAssignableFrom(type)) + .Where(type => typeof(CommandHandler).IsAssignableFrom(type)) .Where(type => type.GetCustomAttribute() != null); foreach (var extHandlerType in extHandlerTypes) { diff --git a/src/Server.cs b/src/Server.cs index 0d7a1dd..911ee28 100644 --- a/src/Server.cs +++ b/src/Server.cs @@ -49,7 +49,7 @@ public class Server { while (client.TryGetNextPacket(out NetworkPacket packet)) networkObjects.Add(packet.GetObject()); - HandleObjects(networkObjects, client); + await HandleObjects(networkObjects, client); } } finally { try { @@ -60,18 +60,20 @@ public class Server { } } - private void HandleObjects(List networkObjects, Client client) { + private async Task HandleObjects(List networkObjects, Client client) { foreach (var obj in networkObjects) { try { short commandId = obj.Get("a"); - ICommandHandler handler; + CommandHandler handler; if (commandId != 13) { if (commandId == 0 || commandId == 1) Console.WriteLine($"System command: {commandId} IID: {client.ClientID}"); handler = moduleManager.GetCommandHandler(commandId); } else handler = moduleManager.GetCommandHandler(obj.Get("p").Get("c")); - handler.Handle(client, obj.Get("p")); + Task task = handler.Handle(client, obj.Get("p")); + if (!handler.RunInBackground) + await task; } catch (Exception ex) { Console.WriteLine($"Exception IID: {client.ClientID} - {ex}"); } diff --git a/src/appsettings.json b/src/appsettings.json index 86fb74e..959be1f 100644 --- a/src/appsettings.json +++ b/src/appsettings.json @@ -6,6 +6,9 @@ "// Port": "Listening port number for the MMO server", "Port": 9933, + "// PingDelay": "delay (in milliseconds) for PNG response", + "PingDelay": 17, + "// EnableChat": "When true, in-game chat will be enabled", "EnableChat": true,