diff --git a/src/CommandHandlers/HandshakeHandler.cs b/src/CommandHandlers/HandshakeHandler.cs index 18a56b2..ab34487 100644 --- a/src/CommandHandlers/HandshakeHandler.cs +++ b/src/CommandHandlers/HandshakeHandler.cs @@ -17,6 +17,11 @@ class HandshakeHandler : CommandHandler return Task.CompletedTask; } + string? api = receivedObject.Get("api"); + if (api != null && api[0] == '0') { + client.OldApi = true; + } + NetworkObject obj = new(); obj.Add("tk", RandomString(32)); diff --git a/src/CommandHandlers/JoinRoomHandler.cs b/src/CommandHandlers/JoinRoomHandler.cs index 3277809..e633ae4 100644 --- a/src/CommandHandlers/JoinRoomHandler.cs +++ b/src/CommandHandlers/JoinRoomHandler.cs @@ -10,6 +10,9 @@ class JoinRoomHandler : CommandHandler public override Task Handle(Client client, NetworkObject receivedObject) { string roomName = receivedObject.Get("p").Get("rn"); + if (roomName is null) { + roomName = client.PlayerData.ZoneName; + } Room room = Room.GetOrAdd(roomName); client.SetRoom(room); return Task.CompletedTask; diff --git a/src/CommandHandlers/LoginHandler.cs b/src/CommandHandlers/LoginHandler.cs index 3eceffa..0c6eacf 100644 --- a/src/CommandHandlers/LoginHandler.cs +++ b/src/CommandHandlers/LoginHandler.cs @@ -11,6 +11,8 @@ class LoginHandler : CommandHandler public override Task Handle(Client client, NetworkObject receivedObject) { client.PlayerData.UNToken = receivedObject.Get("un"); + client.PlayerData.ZoneName = receivedObject.Get("zn"); + if (!ValidToken(client)) { NetworkObject obj = new(); obj.Add("dr", (byte)1); @@ -61,7 +63,7 @@ class LoginHandler : CommandHandler NetworkObject content = new(); content.Add("rl", rl); - content.Add("zn", "JumpStart"); + content.Add("zn", client.PlayerData.ZoneName); content.Add("rs", (short)5); content.Add("un", client.PlayerData.UNToken); content.Add("id", client.ClientID); diff --git a/src/CommandHandlers/LogoutHandler.cs b/src/CommandHandlers/LogoutHandler.cs new file mode 100644 index 0000000..85180f2 --- /dev/null +++ b/src/CommandHandlers/LogoutHandler.cs @@ -0,0 +1,22 @@ +using sodoffmmo.Attributes; +using sodoffmmo.Core; +using sodoffmmo.Data; + +namespace sodoffmmo.CommandHandlers; + +[CommandHandler(2)] +class LogoutHandler : CommandHandler +{ + public override Task Handle(Client client, NetworkObject receivedObject) + { + client.SetRoom(null); + client.PlayerData.UNToken = null; + client.PlayerData.ZoneName = null; + + NetworkObject content = new(); + content.Add("zn", ""); + + client.Send(NetworkObject.WrapObject(0, 2, content).Serialize()); + return Task.CompletedTask; + } +} diff --git a/src/CommandHandlers/SetUserVariablesHandler.cs b/src/CommandHandlers/SetUserVariablesHandler.cs index 16b146c..878a32a 100644 --- a/src/CommandHandlers/SetUserVariablesHandler.cs +++ b/src/CommandHandlers/SetUserVariablesHandler.cs @@ -62,7 +62,12 @@ class SetUserVariablesHandler : CommandHandler { NetworkObject cmd = new(); cmd.Add("c", "SUV"); NetworkArray arr = new(); - data.Add("MID", client.ClientID); + if (client.OldApi) { + data.Add("MID", client.ClientID.ToString()); + } else { + data.Add("MID", client.ClientID); + } + data.Add("RID", client.Room.Id.ToString()); arr.Add(data); NetworkObject container = new(); container.Add("arr", arr); @@ -97,7 +102,11 @@ class SetUserVariablesHandler : CommandHandler { NetworkObject obj = new(); cmd.Add("c", "SUV"); - obj.Add("MID", client.ClientID); + if (client.OldApi) { + obj.Add("MID", client.ClientID.ToString()); + } else { + obj.Add("MID", client.ClientID); + } cmd.Add("p", obj); NetworkPacket packet = NetworkObject.WrapObject(1, 13, cmd).Serialize(); diff --git a/src/Core/Client.cs b/src/Core/Client.cs index 6a1e277..455a6a3 100644 --- a/src/Core/Client.cs +++ b/src/Core/Client.cs @@ -11,6 +11,7 @@ public class Client { public int ClientID { get; private set; } public PlayerData PlayerData { get; set; } = new(); public Room? Room { get; private set; } + public bool OldApi { get; set; } = false; public bool TempMuted { get; set; } = false; private readonly Socket socket; @@ -78,7 +79,11 @@ public class Client { NetworkObject cmd = new(); NetworkObject obj = new(); cmd.Add("c", "SUV"); - obj.Add("MID", c.ClientID); + if (OldApi) { + obj.Add("MID", c.ClientID.ToString()); + } else { + obj.Add("MID", c.ClientID); + } cmd.Add("p", obj); Send(NetworkObject.WrapObject(1, 13, cmd).Serialize()); } diff --git a/src/Data/PlayerData.cs b/src/Data/PlayerData.cs index 8479c61..7b56583 100644 --- a/src/Data/PlayerData.cs +++ b/src/Data/PlayerData.cs @@ -11,6 +11,8 @@ public class PlayerData { public string Uid { get; set; } = ""; // client token public string UNToken { get; set; } = ""; + // client zone + public string ZoneName { get; set; } = ""; // rotation (eulerAngles.y) public float R { get; set; } @@ -28,7 +30,7 @@ public class PlayerData { public float P3 { get; set; } // max speed public float Mx { get; set; } = 6; - // flags (?) + // flags public int F { get; set; } // animation bitfield (animations used by avatar, e.g. mounted, swim, ...) public int Mbf { get; set; } @@ -51,7 +53,10 @@ public class PlayerData { "CU", // country id (int) (for flag?) "J", // join allowed "BU", // busy (?) - "M" // membership status (bool) + "M", // membership status (bool) + "P", // position vector (older games) + "R", // rotation (older games - updated via SUV, not SPV) + "F", // flags (older games - updated via SUV, not SPV) }; // other variables (set and updated via SUV command) @@ -62,29 +67,47 @@ public class PlayerData { } public void SetVariable(string varName, string value) { - if (varName == "UID") + // do not store in variables directory + if (varName == "UID") { return; - if (varName == "FP") + } + if (varName == "R") { + R = float.Parse(value, CultureInfo.InvariantCulture); + return; + } + if (varName == "F") { + F = unchecked((int)Convert.ToUInt32(value, 16)); + return; + } + + // fix variable value before store + if (varName == "FP") { value = FixMountState(value); + } + + // store in directory variables[varName] = value; } public void InitFromNetworkData(NetworkObject suvData) { // set initial state for SPV data R = float.Parse(suvData.Get("R"), CultureInfo.InvariantCulture); - P1 = float.Parse(suvData.Get("P1"), CultureInfo.InvariantCulture); - P2 = float.Parse(suvData.Get("P2"), CultureInfo.InvariantCulture); - P3 = float.Parse(suvData.Get("P3"), CultureInfo.InvariantCulture); - R1 = float.Parse(suvData.Get("R1"), CultureInfo.InvariantCulture); - R2 = float.Parse(suvData.Get("R2"), CultureInfo.InvariantCulture); - R3 = float.Parse(suvData.Get("R3"), CultureInfo.InvariantCulture); + string? p1 = suvData.Get("P1"); + if (p1 != null) { + P1 = float.Parse(p1, CultureInfo.InvariantCulture); + P2 = float.Parse(suvData.Get("P2"), CultureInfo.InvariantCulture); + P3 = float.Parse(suvData.Get("P3"), CultureInfo.InvariantCulture); + R1 = float.Parse(suvData.Get("R1"), CultureInfo.InvariantCulture); + R2 = float.Parse(suvData.Get("R2"), CultureInfo.InvariantCulture); + R3 = float.Parse(suvData.Get("R3"), CultureInfo.InvariantCulture); + } string? mbf = suvData.Get("MBF"); if (mbf != null) Mbf = int.Parse(mbf); F = int.Parse(suvData.Get("F")); // reset all variables values - variables.Clear(); + // variables.Clear(); // set initial state for SUV data foreach (string varName in SupportedVariables) {