use async handlers, add delay in PingHandler

client do NOT like ping < 16ms (considers it to be zero and this disables updates to other players' positions) ... so add some delay in PNG handler
This commit is contained in:
Robert Paciorek 2024-04-02 13:08:09 +00:00 committed by Spirtix
parent 04b906b21c
commit d0c1839b11
21 changed files with 145 additions and 94 deletions

View File

@ -5,13 +5,14 @@ using sodoffmmo.Data;
namespace sodoffmmo.CommandHandlers; namespace sodoffmmo.CommandHandlers;
[ExtensionCommandHandler("SCM")] [ExtensionCommandHandler("SCM")]
class ChatMessageHandler : ICommandHandler { class ChatMessageHandler : CommandHandler {
public void Handle(Client client, NetworkObject receivedObject) { public override Task Handle(Client client, NetworkObject receivedObject) {
if (!Configuration.ServerConfiguration.EnableChat) { if (!Configuration.ServerConfiguration.EnableChat) {
ChatDisabled(client, receivedObject); ChatDisabled(client, receivedObject);
return; } else {
Chat(client, receivedObject);
} }
Chat(client, receivedObject); return Task.CompletedTask;
} }
public void ChatDisabled(Client client, NetworkObject receivedObject) { public void ChatDisabled(Client client, NetworkObject receivedObject) {

View File

@ -5,13 +5,14 @@ using sodoffmmo.Data;
namespace sodoffmmo.CommandHandlers; namespace sodoffmmo.CommandHandlers;
[ExtensionCommandHandler("DT")] [ExtensionCommandHandler("DT")]
class DateTimeHandler : ICommandHandler { class DateTimeHandler : CommandHandler {
public void Handle(Client client, NetworkObject receivedObject) { public override Task Handle(Client client, NetworkObject receivedObject) {
NetworkObject cmd = new(); NetworkObject cmd = new();
NetworkObject obj = new(); NetworkObject obj = new();
obj.Add("arr", new string[] { "DT", DateTime.UtcNow.ToString("MM/dd/yyyy HH:mm:ss") }); obj.Add("arr", new string[] { "DT", DateTime.UtcNow.ToString("MM/dd/yyyy HH:mm:ss") });
cmd.Add("c", "DT"); cmd.Add("c", "DT");
cmd.Add("p", obj); cmd.Add("p", obj);
client.Send(NetworkObject.WrapObject(1, 13, cmd).Serialize()); client.Send(NetworkObject.WrapObject(1, 13, cmd).Serialize());
return Task.CompletedTask;
} }
} }

View File

@ -5,8 +5,9 @@ using sodoffmmo.Data;
namespace sodoffmmo.CommandHandlers; namespace sodoffmmo.CommandHandlers;
[CommandHandler(26)] [CommandHandler(26)]
class ExitHandler : ICommandHandler { class ExitHandler : CommandHandler {
public void Handle(Client client, NetworkObject receivedObject) { public override Task Handle(Client client, NetworkObject receivedObject) {
client.SetRoom(null); client.SetRoom(null);
return Task.CompletedTask;
} }
} }

View File

@ -9,27 +9,29 @@ namespace sodoffmmo.CommandHandlers;
// Host Room For Any // Host Room For Any
[ExtensionCommandHandler("gs.HRFA")] [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); GauntletRoom.Join(client);
return Task.CompletedTask;
} }
} }
// Join Any Room // Join Any Room
[ExtensionCommandHandler("gs.JAR")] [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); GauntletRoom.Join(client);
return Task.CompletedTask;
} }
} }
// Play Again // Play Again
[ExtensionCommandHandler("gs.PA")] [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)!; GauntletRoom room = (client.Room as GauntletRoom)!;
room.SetPlayerReady(client, false); room.SetPlayerReady(client, false);
@ -41,14 +43,15 @@ class GauntletPlayAgainHandler : ICommandHandler
room.Send(packet, client); room.Send(packet, client);
room.SendPA(client); room.SendPA(client);
return Task.CompletedTask;
} }
} }
// Lobby User Ready // Lobby User Ready
[ExtensionCommandHandler("gs.LUR")] [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)!; GauntletRoom room = (client.Room as GauntletRoom)!;
room.SetPlayerReady(client); room.SetPlayerReady(client);
@ -69,14 +72,15 @@ class GauntletLobbyUserReadyHandler : ICommandHandler
room.Send(packet); room.Send(packet);
} }
return Task.CompletedTask;
} }
} }
// Lobby User Not Ready // Lobby User Not Ready
[ExtensionCommandHandler("gs.LUNR")] [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)!; GauntletRoom room = (client.Room as GauntletRoom)!;
room.SetPlayerReady(client, false); room.SetPlayerReady(client, false);
@ -87,14 +91,15 @@ class GauntletLobbyUserNotReadyHandler : ICommandHandler
}, "msg", room.Id); }, "msg", room.Id);
room.Send(packet); room.Send(packet);
return Task.CompletedTask;
} }
} }
// Game Level Load // Game Level Load
[ExtensionCommandHandler("gs.GLL")] [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)!; GauntletRoom room = (client.Room as GauntletRoom)!;
NetworkObject p = receivedObject.Get<NetworkObject>("p"); NetworkObject p = receivedObject.Get<NetworkObject>("p");
@ -106,18 +111,19 @@ class GauntletLevelLoadHandler : ICommandHandler
p.Get<string>("2") // TODO use size of p.fields - 1 p.Get<string>("2") // TODO use size of p.fields - 1
}, "msg", room.Id); }, "msg", room.Id);
room.Send(packet); room.Send(packet);
return Task.CompletedTask;
} }
} }
// Game Level Loaded // Game Level Loaded
[ExtensionCommandHandler("gs.GLLD")] [ExtensionCommandHandler("gs.GLLD")]
class GauntletLevelLoadedHandler : ICommandHandler class GauntletLevelLoadedHandler : CommandHandler
{ {
private System.Timers.Timer? timer = null; private System.Timers.Timer? timer = null;
private int counter; private int counter;
private GauntletRoom room; private GauntletRoom room;
public void Handle(Client client, NetworkObject receivedObject) { public override Task Handle(Client client, NetworkObject receivedObject) {
room = (client.Room as GauntletRoom)!; room = (client.Room as GauntletRoom)!;
counter = 5; counter = 5;
@ -133,6 +139,7 @@ class GauntletLevelLoadedHandler : ICommandHandler
timer.AutoReset = true; timer.AutoReset = true;
timer.Enabled = true; timer.Enabled = true;
timer.Elapsed += OnTick; timer.Elapsed += OnTick;
return Task.CompletedTask;
} }
private void OnTick(Object? source, ElapsedEventArgs e) { private void OnTick(Object? source, ElapsedEventArgs e) {
@ -161,9 +168,9 @@ class GauntletLevelLoadedHandler : ICommandHandler
// Relay Game Data // Relay Game Data
[ExtensionCommandHandler("gs.RGD")] [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)!; GauntletRoom room = (client.Room as GauntletRoom)!;
NetworkObject p = receivedObject.Get<NetworkObject>("p"); NetworkObject p = receivedObject.Get<NetworkObject>("p");
@ -176,19 +183,21 @@ class GauntletRelayGameDataHandler : ICommandHandler
p.Get<string>("1") p.Get<string>("1")
}, "msg", room.Id); }, "msg", room.Id);
room.Send(packet, client); room.Send(packet, client);
return Task.CompletedTask;
} }
} }
// Game Complete // Game Complete
[ExtensionCommandHandler("gs.GC")] [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)!; GauntletRoom room = (client.Room as GauntletRoom)!;
NetworkObject p = receivedObject.Get<NetworkObject>("p"); NetworkObject p = receivedObject.Get<NetworkObject>("p");
room.ProcessResult(client, p.Get<string>("0"), p.Get<string>("1")); room.ProcessResult(client, p.Get<string>("0"), p.Get<string>("1"));
return Task.CompletedTask;
} }
} }

View File

@ -5,9 +5,10 @@ using sodoffmmo.Data;
namespace sodoffmmo.CommandHandlers; namespace sodoffmmo.CommandHandlers;
[CommandHandler(7)] [CommandHandler(7)]
class GenericMessageHandler : ICommandHandler { class GenericMessageHandler : CommandHandler {
public void Handle(Client client, NetworkObject receivedObject) { public override Task Handle(Client client, NetworkObject receivedObject) {
NetworkPacket packet = NetworkObject.WrapObject(0, 7, receivedObject).Serialize(); NetworkPacket packet = NetworkObject.WrapObject(0, 7, receivedObject).Serialize();
client.Room.Send(packet); client.Room.Send(packet);
return Task.CompletedTask;
} }
} }

View File

@ -7,14 +7,14 @@ using System;
namespace sodoffmmo.CommandHandlers; namespace sodoffmmo.CommandHandlers;
[CommandHandler(0)] [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<string>("rt"); string? token = receivedObject.Get<string>("rt");
if (token != null) { if (token != null) {
client.Send(NetworkObject.WrapObject(0, 1006, new NetworkObject()).Serialize()); client.Send(NetworkObject.WrapObject(0, 1006, new NetworkObject()).Serialize());
return; return Task.CompletedTask;
} }
NetworkObject obj = new(); NetworkObject obj = new();
@ -24,6 +24,7 @@ class HandshakeHandler : ICommandHandler
obj.Add("ms", 1000000); obj.Add("ms", 1000000);
client.Send(NetworkObject.WrapObject(0, 0, obj).Serialize()); client.Send(NetworkObject.WrapObject(0, 0, obj).Serialize());
return Task.CompletedTask;
} }
private string RandomString(int length) { private string RandomString(int length) {

View File

@ -5,13 +5,14 @@ using sodoffmmo.Data;
namespace sodoffmmo.CommandHandlers; namespace sodoffmmo.CommandHandlers;
[ExtensionCommandHandler("JO")] [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<NetworkObject>("p"); var p = receivedObject.Get<NetworkObject>("p");
string roomName = p.Get<string>("rn") + "_" + p.Get<string>("0"); string roomName = p.Get<string>("rn") + "_" + p.Get<string>("0");
Room room = Room.GetOrAdd(roomName, autoRemove: true); Room room = Room.GetOrAdd(roomName, autoRemove: true);
client.SetRoom(room); client.SetRoom(room);
return Task.CompletedTask;
} }
} }

View File

@ -5,12 +5,13 @@ using sodoffmmo.Data;
namespace sodoffmmo.CommandHandlers; namespace sodoffmmo.CommandHandlers;
[ExtensionCommandHandler("JA")] [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<NetworkObject>("p").Get<string>("rn"); string roomName = receivedObject.Get<NetworkObject>("p").Get<string>("rn");
Room room = Room.GetOrAdd(roomName); Room room = Room.GetOrAdd(roomName);
client.SetRoom(room); client.SetRoom(room);
return Task.CompletedTask;
} }
} }

View File

@ -6,9 +6,9 @@ using sodoffmmo.Management;
namespace sodoffmmo.CommandHandlers; namespace sodoffmmo.CommandHandlers;
[CommandHandler(1)] [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<string>("un"); client.PlayerData.UNToken = receivedObject.Get<string>("un");
if (!ValidToken(client)) { if (!ValidToken(client)) {
@ -16,7 +16,7 @@ class LoginHandler : ICommandHandler
obj.Add("dr", (byte)1); obj.Add("dr", (byte)1);
client.Send(NetworkObject.WrapObject(0, 1005, obj).Serialize()); client.Send(NetworkObject.WrapObject(0, 1005, obj).Serialize());
client.ScheduleDisconnect(); client.ScheduleDisconnect();
return; return Task.CompletedTask;
} }
NetworkArray rl = new(); NetworkArray rl = new();
@ -68,6 +68,7 @@ class LoginHandler : ICommandHandler
content.Add("pi", (short)1); content.Add("pi", (short)1);
client.Send(NetworkObject.WrapObject(0, 1, content).Serialize()); client.Send(NetworkObject.WrapObject(0, 1, content).Serialize());
return Task.CompletedTask;
} }
private bool ValidToken(Client client) { private bool ValidToken(Client client) {

View File

@ -5,8 +5,13 @@ using sodoffmmo.Data;
namespace sodoffmmo.CommandHandlers; namespace sodoffmmo.CommandHandlers;
[ExtensionCommandHandler("PNG")] [ExtensionCommandHandler("PNG")]
class PingHandler : ICommandHandler { class PingHandler : CommandHandler {
public void Handle(Client client, NetworkObject receivedObject) { 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 cmd = new();
NetworkObject obj = new(); NetworkObject obj = new();
obj.Add("arr", new string[] { "PNG", DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString() }); obj.Add("arr", new string[] { "PNG", DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString() });

View File

@ -5,10 +5,10 @@ using sodoffmmo.Data;
namespace sodoffmmo.CommandHandlers; namespace sodoffmmo.CommandHandlers;
[ExtensionCommandHandler("PM")] [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}} // 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}]}}} // send: {"a":13,"c":1,"p":{"c":"PM","p":{"arr":[{"M":["DT:f05fc387-7358-4bff-be04-7c316f0a8de8:1000"],"MID":3529441}]}}}
NetworkObject cmd = new(); NetworkObject cmd = new();
NetworkObject p = new(); NetworkObject p = new();
@ -25,5 +25,6 @@ class RacingPMHandler : ICommandHandler
NetworkPacket packet = NetworkObject.WrapObject(1, 13, cmd).Serialize(); NetworkPacket packet = NetworkObject.WrapObject(1, 13, cmd).Serialize();
client.Room.Send(packet); client.Room.Send(packet);
return Task.CompletedTask;
} }
} }

View File

@ -8,9 +8,9 @@ namespace sodoffmmo.CommandHandlers;
// Set Player Ready // Set Player Ready
[ExtensionCommandHandler("dr.PR")] [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<NetworkObject>("p"); NetworkObject p = receivedObject.Get<NetworkObject>("p");
RacingPlayerState ready = p.Get<string>("IMR") == "True" ? RacingPlayerState.Ready : RacingPlayerState.NotReady; RacingPlayerState ready = p.Get<string>("IMR") == "True" ? RacingPlayerState.Ready : RacingPlayerState.NotReady;
@ -26,33 +26,37 @@ class RacingPlayerReadyHandler : ICommandHandler
RacingLobby.Lobby.SetPlayerState(client, ready); RacingLobby.Lobby.SetPlayerState(client, ready);
Console.WriteLine($"IMR: {client.ClientID} {ready}"); Console.WriteLine($"IMR: {client.ClientID} {ready}");
} }
return Task.CompletedTask;
} }
} }
// Player Status Request // Player Status Request
[ExtensionCommandHandler("dr.PS")] [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()); client.Send(RacingLobby.Lobby.GetPS());
return Task.CompletedTask;
} }
} }
// User Ready ACK // User Ready ACK
[ExtensionCommandHandler("dr.UACK")] [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)!; RacingRoom room = (client.Room as RacingRoom)!;
room.SetPlayerState(client, RacingPlayerState.RaceReady1); room.SetPlayerState(client, RacingPlayerState.RaceReady1);
return Task.CompletedTask;
} }
} }
// All Ready ACK // All Ready ACK
[ExtensionCommandHandler("dr.ARACK")] [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)!; RacingRoom room = (client.Room as RacingRoom)!;
room.SetPlayerState(client, RacingPlayerState.RaceReady2); room.SetPlayerState(client, RacingPlayerState.RaceReady2);
@ -61,17 +65,19 @@ class RacingARACKHandler : ICommandHandler
room.Send(packet); room.Send(packet);
Console.WriteLine($"STA"); Console.WriteLine($"STA");
} }
return Task.CompletedTask;
} }
} }
[ExtensionCommandHandler("dr.AR")] [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)!; RacingRoom room = (client.Room as RacingRoom)!;
NetworkObject p = receivedObject.Get<NetworkObject>("p"); NetworkObject p = receivedObject.Get<NetworkObject>("p");
room.SetResults(client, p.Get<string>("UN"), p.Get<string>("CT"), p.Get<string>("LC")); room.SetResults(client, p.Get<string>("UN"), p.Get<string>("CT"), p.Get<string>("LC"));
room.SendResults(); room.SendResults();
return Task.CompletedTask;
} }
} }

View File

@ -5,20 +5,22 @@ using sodoffmmo.Data;
namespace sodoffmmo.CommandHandlers; namespace sodoffmmo.CommandHandlers;
[ExtensionCommandHandler("SPV")] [ExtensionCommandHandler("SPV")]
class SetPositionVariablesHandler : ICommandHandler { class SetPositionVariablesHandler : CommandHandler {
Client client; Client client;
NetworkObject spvData; NetworkObject spvData;
public void Handle(Client client, NetworkObject receivedObject) { public override Task Handle(Client client, NetworkObject receivedObject) {
if (client.Room == null) { if (client.Room == null) {
Console.WriteLine($"SPV Missing Room IID: {client.ClientID}"); Console.WriteLine($"SPV Missing Room IID: {client.ClientID}");
client.Send(NetworkObject.WrapObject(0, 1006, new NetworkObject()).Serialize()); client.Send(NetworkObject.WrapObject(0, 1006, new NetworkObject()).Serialize());
client.ScheduleDisconnect(); client.ScheduleDisconnect();
return; return Task.CompletedTask;
} }
this.client = client; this.client = client;
spvData = receivedObject; spvData = receivedObject;
UpdatePositionVariables(); UpdatePositionVariables();
SendSPVCommand(); SendSPVCommand();
return Task.CompletedTask;
} }
private void UpdatePositionVariables() { private void UpdatePositionVariables() {

View File

@ -6,16 +6,16 @@ using System.Globalization;
namespace sodoffmmo.CommandHandlers; namespace sodoffmmo.CommandHandlers;
[ExtensionCommandHandler("SUV")] [ExtensionCommandHandler("SUV")]
class SetUserVariablesHandler : ICommandHandler { class SetUserVariablesHandler : CommandHandler {
NetworkObject suvData; NetworkObject suvData;
Client client; Client client;
string? uid; string? uid;
public void Handle(Client client, NetworkObject receivedObject) { public override Task Handle(Client client, NetworkObject receivedObject) {
if (client.Room == null) { if (client.Room == null) {
Console.WriteLine($"SUV Missing Room IID: {client.ClientID}"); Console.WriteLine($"SUV Missing Room IID: {client.ClientID}");
client.Send(NetworkObject.WrapObject(0, 1006, new NetworkObject()).Serialize()); client.Send(NetworkObject.WrapObject(0, 1006, new NetworkObject()).Serialize());
client.ScheduleDisconnect(); client.ScheduleDisconnect();
return; return Task.CompletedTask;
} }
this.client = client; this.client = client;
suvData = receivedObject.Get<NetworkObject>("p"); suvData = receivedObject.Get<NetworkObject>("p");
@ -27,6 +27,7 @@ class SetUserVariablesHandler : ICommandHandler {
else else
UpdateVars(); UpdateVars();
return Task.CompletedTask;
} }
private void ProcessPlayerData() { private void ProcessPlayerData() {

View File

@ -6,20 +6,21 @@ using sodoffmmo.Data;
namespace sodoffmmo.CommandHandlers; namespace sodoffmmo.CommandHandlers;
[ExtensionCommandHandler("wex.WES")] // event status request [ExtensionCommandHandler("wex.WES")] // event status request
class WorldEventStatusHandler : ICommandHandler { class WorldEventStatusHandler : CommandHandler {
public void Handle(Client client, NetworkObject receivedObject) { public override Task Handle(Client client, NetworkObject receivedObject) {
client.Send(Utils.ArrNetworkPacket( new string[] { client.Send(Utils.ArrNetworkPacket( new string[] {
"WESR", "WESR",
"WE_ScoutAttack|" + WorldEvent.Get().EventInfo(), "WE_ScoutAttack|" + WorldEvent.Get().EventInfo(),
"EvEnd|" + WorldEvent.Get().GetLastResults() "EvEnd|" + WorldEvent.Get().GetLastResults()
})); }));
return Task.CompletedTask;
} }
} }
[ExtensionCommandHandler("wex.OV")] [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}} // 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 // NOTE: this should be process on event in any state - we use it to make event active
NetworkObject p = receivedObject.Get<NetworkObject>("p"); NetworkObject p = receivedObject.Get<NetworkObject>("p");
float healthUpdateVal = float.Parse( float healthUpdateVal = float.Parse(
@ -39,15 +40,16 @@ class WorldEventHealthHandler : ICommandHandler {
); );
WorldEvent.Get().GetRoom().Send(packet); WorldEvent.Get().GetRoom().Send(packet);
} }
return Task.CompletedTask;
} }
} }
[ExtensionCommandHandler("wex.OVF")] // flare info from ship AI -> resend as WEF_ [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}} // 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()) if (!WorldEvent.Get().IsActive())
return; return Task.CompletedTask;
NetworkObject p = receivedObject.Get<NetworkObject>("p"); NetworkObject p = receivedObject.Get<NetworkObject>("p");
@ -58,15 +60,17 @@ class WorldEventFlareHandler : ICommandHandler {
WorldEvent.Get().GetRoom().Id WorldEvent.Get().GetRoom().Id
); );
WorldEvent.Get().GetRoom().Send(packet); WorldEvent.Get().GetRoom().Send(packet);
return Task.CompletedTask;
} }
} }
[ExtensionCommandHandler("wex.ST")] // missile info from ship AI -> resend as WA [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}} // 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()) if (!WorldEvent.Get().IsActive())
return; return Task.CompletedTask;
NetworkObject p = receivedObject.Get<NetworkObject>("p"); NetworkObject p = receivedObject.Get<NetworkObject>("p");
@ -79,45 +83,52 @@ class WorldEventMissileHandler : ICommandHandler {
p.Get<string>("objID") p.Get<string>("objID")
}); });
WorldEvent.Get().GetRoom().Send(packet); WorldEvent.Get().GetRoom().Send(packet);
return Task.CompletedTask;
} }
} }
[ExtensionCommandHandler("wex.PS")] [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}} // 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()) if (!WorldEvent.Get().IsActive())
return; return Task.CompletedTask;
string scoreData = receivedObject.Get<NetworkObject>("p").Get<string>("ScoreData"); string scoreData = receivedObject.Get<NetworkObject>("p").Get<string>("ScoreData");
string[] keyValPair = scoreData.Split('/'); string[] keyValPair = scoreData.Split('/');
WorldEvent.Get().UpdateScore(keyValPair[0], keyValPair[1]); WorldEvent.Get().UpdateScore(keyValPair[0], keyValPair[1]);
return Task.CompletedTask;
} }
} }
[ExtensionCommandHandler("wex.AIACK")] // AI ack [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}} // 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); WorldEvent.Get().UpdateAI(client);
return Task.CompletedTask;
} }
} }
[ExtensionCommandHandler("wex.AIP")] // AI ping [ExtensionCommandHandler("wex.AIP")] // AI ping
class WorldEventAIPingHandler : ICommandHandler { class WorldEventAIPingHandler : CommandHandler {
// rec: {"a":13,"c":1,"p":{"c":"wex.AIP","p":{"en":""},"r":-1}} // 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); WorldEvent.Get().UpdateAI(client);
return Task.CompletedTask;
} }
} }
[ExtensionCommandHandler("wex.ETS")] // time span [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}} // 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( float timeSpan = float.Parse(
receivedObject.Get<NetworkObject>("p").Get<string>("timeSpan"), receivedObject.Get<NetworkObject>("p").Get<string>("timeSpan"),
System.Globalization.CultureInfo.InvariantCulture System.Globalization.CultureInfo.InvariantCulture
); );
WorldEvent.Get().SetTimeSpan(client, timeSpan); WorldEvent.Get().SetTimeSpan(client, timeSpan);
return Task.CompletedTask;
} }
} }

View File

@ -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);
}

View File

@ -34,6 +34,7 @@ internal sealed class ServerConfiguration {
public int RacingMaxPlayers { get; set; } = 6; public int RacingMaxPlayers { get; set; } = 6;
public int RacingMinPlayers { get; set; } = 2; public int RacingMinPlayers { get; set; } = 2;
public int RacingMainLobbyTimer { get; set; } = 15; public int RacingMainLobbyTimer { get; set; } = 15;
public int PingDelay { get; set; } = 17;
public bool EnableChat { get; set; } = true; public bool EnableChat { get; set; } = true;
public bool AllowChaos { get; set; } = false; public bool AllowChaos { get; set; } = false;
public bool Authentication { get; set; } = false; public bool Authentication { get; set; } = false;

View File

@ -1,6 +0,0 @@
using sodoffmmo.Data;
namespace sodoffmmo.Core;
public interface ICommandHandler {
public void Handle(Client client, NetworkObject receivedObject);
}

View File

@ -12,22 +12,22 @@ class ModuleManager {
RegisterExtensionHandlers(); RegisterExtensionHandlers();
} }
public ICommandHandler GetCommandHandler(int id) { public CommandHandler GetCommandHandler(int id) {
if (handlers.TryGetValue(id, out Type? handler)) 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!"); 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)) 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!"); throw new Exception($"Command handler with name \"{name}\" not found!");
} }
private void RegisterHandlers() { private void RegisterHandlers() {
handlers.Clear(); handlers.Clear();
var handlerTypes = Assembly.GetExecutingAssembly().GetTypes() var handlerTypes = Assembly.GetExecutingAssembly().GetTypes()
.Where(type => typeof(ICommandHandler).IsAssignableFrom(type)) .Where(type => typeof(CommandHandler).IsAssignableFrom(type))
.Where(type => type.GetCustomAttribute<CommandHandlerAttribute>() != null); .Where(type => type.GetCustomAttribute<CommandHandlerAttribute>() != null);
foreach (var handlerType in handlerTypes) { foreach (var handlerType in handlerTypes) {
@ -39,7 +39,7 @@ class ModuleManager {
private void RegisterExtensionHandlers() { private void RegisterExtensionHandlers() {
extHandlers.Clear(); extHandlers.Clear();
var extHandlerTypes = Assembly.GetExecutingAssembly().GetTypes() var extHandlerTypes = Assembly.GetExecutingAssembly().GetTypes()
.Where(type => typeof(ICommandHandler).IsAssignableFrom(type)) .Where(type => typeof(CommandHandler).IsAssignableFrom(type))
.Where(type => type.GetCustomAttribute<ExtensionCommandHandlerAttribute>() != null); .Where(type => type.GetCustomAttribute<ExtensionCommandHandlerAttribute>() != null);
foreach (var extHandlerType in extHandlerTypes) { foreach (var extHandlerType in extHandlerTypes) {

View File

@ -49,7 +49,7 @@ public class Server {
while (client.TryGetNextPacket(out NetworkPacket packet)) while (client.TryGetNextPacket(out NetworkPacket packet))
networkObjects.Add(packet.GetObject()); networkObjects.Add(packet.GetObject());
HandleObjects(networkObjects, client); await HandleObjects(networkObjects, client);
} }
} finally { } finally {
try { try {
@ -60,18 +60,20 @@ public class Server {
} }
} }
private void HandleObjects(List<NetworkObject> networkObjects, Client client) { private async Task HandleObjects(List<NetworkObject> networkObjects, Client client) {
foreach (var obj in networkObjects) { foreach (var obj in networkObjects) {
try { try {
short commandId = obj.Get<short>("a"); short commandId = obj.Get<short>("a");
ICommandHandler handler; CommandHandler handler;
if (commandId != 13) { if (commandId != 13) {
if (commandId == 0 || commandId == 1) if (commandId == 0 || commandId == 1)
Console.WriteLine($"System command: {commandId} IID: {client.ClientID}"); Console.WriteLine($"System command: {commandId} IID: {client.ClientID}");
handler = moduleManager.GetCommandHandler(commandId); handler = moduleManager.GetCommandHandler(commandId);
} else } else
handler = moduleManager.GetCommandHandler(obj.Get<NetworkObject>("p").Get<string>("c")); handler = moduleManager.GetCommandHandler(obj.Get<NetworkObject>("p").Get<string>("c"));
handler.Handle(client, obj.Get<NetworkObject>("p")); Task task = handler.Handle(client, obj.Get<NetworkObject>("p"));
if (!handler.RunInBackground)
await task;
} catch (Exception ex) { } catch (Exception ex) {
Console.WriteLine($"Exception IID: {client.ClientID} - {ex}"); Console.WriteLine($"Exception IID: {client.ClientID} - {ex}");
} }

View File

@ -6,6 +6,9 @@
"// Port": "Listening port number for the MMO server", "// Port": "Listening port number for the MMO server",
"Port": 9933, "Port": 9933,
"// PingDelay": "delay (in milliseconds) for PNG response",
"PingDelay": 17,
"// EnableChat": "When true, in-game chat will be enabled", "// EnableChat": "When true, in-game chat will be enabled",
"EnableChat": true, "EnableChat": true,