diff --git a/src/CommandHandlers/SetPositionVariablesHandler.cs b/src/CommandHandlers/SetPositionVariablesHandler.cs index 772c9e4..54e7186 100644 --- a/src/CommandHandlers/SetPositionVariablesHandler.cs +++ b/src/CommandHandlers/SetPositionVariablesHandler.cs @@ -16,7 +16,7 @@ class SetPositionVariablesHandler : CommandHandler { return Task.CompletedTask; } this.client = client; - spvData = receivedObject; + spvData = receivedObject.Get("p"); UpdatePositionVariables(); SendSPVCommand(); @@ -24,18 +24,17 @@ class SetPositionVariablesHandler : CommandHandler { } private void UpdatePositionVariables() { - NetworkObject obj = spvData.Get("p"); - float[] pos = obj.Get("U"); - client.PlayerData.R = obj.Get("R"); + float[] pos = spvData.Get("U"); + client.PlayerData.R = spvData.Get("R"); client.PlayerData.P1 = pos[0]; client.PlayerData.P2 = pos[1]; client.PlayerData.P3 = pos[2]; client.PlayerData.R1 = pos[3]; client.PlayerData.R2 = pos[4]; client.PlayerData.R3 = pos[5]; - client.PlayerData.Mx = obj.Get("MX"); - client.PlayerData.F = obj.Get("F"); - client.PlayerData.Mbf = obj.Get("MBF"); + client.PlayerData.Mx = spvData.Get("MX"); + client.PlayerData.F = spvData.Get("F"); + client.PlayerData.Mbf = spvData.Get("MBF"); } private void SendSPVCommand() { @@ -43,18 +42,24 @@ class SetPositionVariablesHandler : CommandHandler { NetworkObject obj = new(); NetworkArray container = new(); NetworkObject vars = new(); - vars.Add("MX", (float)client.PlayerData.Mx); - vars.Add("ST", Runtime.CurrentRuntime); - vars.Add("NT", DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString()); - vars.Add("t", (int)(Runtime.CurrentRuntime / 1000)); + vars.Add("R", client.PlayerData.R); + vars.Add("U", new float[] { client.PlayerData.P1, client.PlayerData.P2, client.PlayerData.P3, client.PlayerData.R1, client.PlayerData.R2, client.PlayerData.R3 }); + vars.Add("MX", client.PlayerData.Mx); vars.Add("F", client.PlayerData.F); vars.Add("MBF", client.PlayerData.Mbf); - vars.Add("R", client.PlayerData.R); - vars.Add("U", new float[] { (float)client.PlayerData.P1, (float)client.PlayerData.P2, (float)client.PlayerData.P3, (float)client.PlayerData.R1, (float)client.PlayerData.R2, (float)client.PlayerData.R3 }); - vars.Add("MID", client.ClientID); - string? ue = spvData.Get("p").Get("UE"); + + // user event + string? ue = spvData.Get("UE"); if (ue != null) vars.Add("UE", ue); + // pitch + string? cup = spvData.Get("CUP"); + if (cup != null) + vars.Add("CUP", cup); + + vars.Add("NT", DateTimeOffset.UtcNow.ToUnixTimeMilliseconds().ToString()); + vars.Add("t", (int)(Runtime.CurrentRuntime / 1000)); + vars.Add("MID", client.ClientID); container.Add(vars); obj.Add("arr", container); diff --git a/src/CommandHandlers/SetUserVariablesHandler.cs b/src/CommandHandlers/SetUserVariablesHandler.cs index 5a57ced..16b146c 100644 --- a/src/CommandHandlers/SetUserVariablesHandler.cs +++ b/src/CommandHandlers/SetUserVariablesHandler.cs @@ -1,7 +1,6 @@ using sodoffmmo.Attributes; using sodoffmmo.Core; using sodoffmmo.Data; -using System.Globalization; namespace sodoffmmo.CommandHandlers; @@ -22,94 +21,50 @@ class SetUserVariablesHandler : CommandHandler { uid = suvData.Get("UID"); // TODO - if (uid != null && (client.PlayerData.Uid != uid || !client.PlayerData.IsValid)) - ProcessPlayerData(); - else + if (uid != null && (client.PlayerData.Uid != uid || !client.PlayerData.IsValid)) { + Console.WriteLine($"SUV {client.Room.Name} ({client.Room.ClientsCount}) IID: {client.ClientID} UID: {uid}"); + client.PlayerData.Uid = uid; + client.PlayerData.InitFromNetworkData(suvData); + UpdatePlayersInRoom(); + SendSUVToPlayerInRoom(); + } else { UpdateVars(); + } return Task.CompletedTask; } - private void ProcessPlayerData() { - client.PlayerData.Uid = uid; - client.PlayerData.A = suvData.Get("A"); - client.PlayerData.Cu = suvData.Get("CU"); - client.PlayerData.M = suvData.Get("M"); - client.PlayerData.L = suvData.Get("L"); - client.PlayerData.Ra = suvData.Get("RA"); - string? udt = suvData.Get("UDT"); - if (udt != null) - client.PlayerData.Udt = udt; - client.PlayerData.P1 = double.Parse(suvData.Get("P1"), CultureInfo.InvariantCulture); - client.PlayerData.P2 = double.Parse(suvData.Get("P2"), CultureInfo.InvariantCulture); - client.PlayerData.P3 = double.Parse(suvData.Get("P3"), CultureInfo.InvariantCulture); - client.PlayerData.R1 = double.Parse(suvData.Get("R1"), CultureInfo.InvariantCulture); - client.PlayerData.R2 = double.Parse(suvData.Get("R2"), CultureInfo.InvariantCulture); - client.PlayerData.R3 = double.Parse(suvData.Get("R3"), CultureInfo.InvariantCulture); - client.PlayerData.R = double.Parse(suvData.Get("R"), CultureInfo.InvariantCulture); - string? mbf = suvData.Get("MBF"); - if (mbf != null) - client.PlayerData.Mbf = int.Parse(mbf); - client.PlayerData.F = int.Parse(suvData.Get("F")); - client.PlayerData.J = suvData.Get("J"); - client.PlayerData.Bu = suvData.Get("BU"); - client.PlayerData.Fp = suvData.Get("FP"); - client.PlayerData.IsValid = true; - - Console.WriteLine($"SUV {client.Room.Name} ({client.Room.ClientsCount}) IID: {client.ClientID} UID: {uid}"); - - UpdatePlayersInRoom(); - SendSUVToPlayerInRoom(); - } - private void UpdateVars() { - string? FP = suvData.Get("FP"); - string? PU = suvData.Get("PU"); - string? A = suvData.Get("A"); - string? L = suvData.Get("L"); - if (FP is null && PU is null && A is null && L is null) { - return; // TODO - } - NetworkObject data = new(); - NetworkObject data2 = new(); - data.Add("u", client.ClientID); - + bool updated = false; NetworkArray vl = new(); - if (FP != null) { - client.PlayerData.Fp = FP; - data2.Add("FP", client.PlayerData.Fp); - vl.Add(NetworkArray.Param("FP", client.PlayerData.Fp)); - } - if (PU != null) { - client.PlayerData.Pu = PU; - data2.Add("PU", client.PlayerData.Pu); - vl.Add(NetworkArray.Param("PU", client.PlayerData.Pu)); - } - if (A != null) { - client.PlayerData.A = A; - data2.Add("A", client.PlayerData.A); - vl.Add(NetworkArray.Param("A", client.PlayerData.A)); - } - if (L != null) { - client.PlayerData.L = L; - data2.Add("L", client.PlayerData.L); - vl.Add(NetworkArray.Param("L", client.PlayerData.L)); + NetworkObject data = new(); + + foreach (string varName in PlayerData.SupportedVariables) { + string? value = suvData.Get(varName); + if (value != null) { + client.PlayerData.SetVariable(varName, value); + updated = true; + data.Add(varName, value); + vl.Add(NetworkArray.Param(varName, value)); + } } - data.Add("vl", vl); + if (!updated) { + return; + } - NetworkPacket packet = NetworkObject.WrapObject(0, 12, data).Serialize(); + NetworkObject data2 = new(); + data2.Add("u", client.ClientID); + data2.Add("vl", vl); + NetworkPacket packet = NetworkObject.WrapObject(0, 12, data2).Serialize(); client.Room.Send(packet); NetworkObject cmd = new(); cmd.Add("c", "SUV"); - - NetworkObject container = new(); - NetworkArray arr = new(); - data2.Add("RID", "1"); - data2.Add("MID", client.ClientID); - arr.Add(data2); + data.Add("MID", client.ClientID); + arr.Add(data); + NetworkObject container = new(); container.Add("arr", arr); cmd.Add("p", container); packet = NetworkObject.WrapObject(1, 13, cmd).Serialize(); diff --git a/src/Data/NetworkArray.cs b/src/Data/NetworkArray.cs index 89d7252..61992d8 100644 --- a/src/Data/NetworkArray.cs +++ b/src/Data/NetworkArray.cs @@ -114,6 +114,8 @@ public class NetworkArray { AddWithTypeObject(NetworkDataType.Int, 2, value); else if (typeof(T) == typeof(double)) AddWithTypeObject(NetworkDataType.Double, 3, value); + else if (typeof(T) == typeof(float)) + AddWithTypeObject(NetworkDataType.Float, 3, value); else if (typeof(T) == typeof(string)) AddWithTypeObject(NetworkDataType.String, 4, value); else @@ -121,7 +123,7 @@ public class NetworkArray { } private void AddWithTypeObject(NetworkDataType dataType, byte typeId, object? obj) { - Add(new DataWrapper(NetworkDataType.Byte,typeId)); + Add(new DataWrapper(NetworkDataType.Byte, typeId)); Add(new DataWrapper(dataType, obj)); } diff --git a/src/Data/PlayerData.cs b/src/Data/PlayerData.cs index 34b3c55..4e830b8 100644 --- a/src/Data/PlayerData.cs +++ b/src/Data/PlayerData.cs @@ -1,4 +1,5 @@ using System.Text.RegularExpressions; +using System.Globalization; using sodoffmmo.Core; using sodoffmmo.Management; @@ -10,56 +11,88 @@ public class PlayerData { public string Uid { get; set; } = ""; // client token public string UNToken { get; set; } = ""; - // avatar data - public string A { get; set; } = ""; - // (not raised) pet data - public string Pu { get; set; } = ""; - // raised pet data - public string Fp { - get { - return fp; - } - set { - fp = FixMountState(value); - } - } - private string fp = ""; // rotation (eulerAngles.y) - public double R { get; set; } + public float R { get; set; } // velocity x - public double R1 { get; set; } + public float R1 { get; set; } // velocity y - public double R2 { get; set; } + public float R2 { get; set; } // velocity z - public double R3 { get; set; } + public float R3 { get; set; } // position x - public double P1 { get; set; } + public float P1 { get; set; } // position y - public double P2 { get; set; } + public float P2 { get; set; } // position z - public double P3 { get; set; } - // animation bitfield (animations used by avatar, e.g. mounted, swim, ...) - public int Mbf { get; set; } + public float P3 { get; set; } // max speed - public double Mx { get; set; } = 6; + public float Mx { get; set; } = 6; // flags (?) public int F { get; set; } - // location (level) - public string L { get; set; } = ""; + // animation bitfield (animations used by avatar, e.g. mounted, swim, ...) + public int Mbf { get; set; } - // join allowed - public string J { get; set; } = "2"; - // busy (?) - public string Bu { get; set; } = "False"; - // UDT points - public string Udt { get; set; } = ""; - // XP rank (points and level) - public string Ra { get; set; } = ""; - // country info (for flag?) - public string Cu { get; set; } = "-1"; - // membership status - public string M { get; set; } = "True"; + public static readonly string[] SupportedVariables = { + "A", // avatar data + "FP", // raised pet data + "RA", // XP rank (points and level) + "UDT", // UDT points + "L", // location (level) + "PU", // (not raised) pet data + "RDE", // ride (int) + "MU", // mood + "MBR", // mount broom (bool) + "GU", // goggles (bool) + "LC", // livechat (int) + "CU", // country id (int) (for flag?) + "J", // join allowed + "BU", // busy (?) + "M" // membership status (bool) + }; + + // other variables (set and updated via SUV command) + private Dictionary variables = new(); + + public string GetVariable(string varName) { + return variables[varName]; + } + + public void SetVariable(string varName, string value) { + if (varName == "UID") + return; + if (varName == "FP") + value = FixMountState(value); + 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? mbf = suvData.Get("MBF"); + if (mbf != null) + Mbf = int.Parse(mbf); + F = int.Parse(suvData.Get("F")); + + // reset all variables values + variables.Clear(); + + // set initial state for SUV data + foreach (string varName in SupportedVariables) { + string? value = suvData.Get(varName); + if (value != null) { + SetVariable(varName, value); + } + } + + IsValid = true; + } public string DiplayName { get; set; } = ""; public Role Role { get; set; } = Role.User; @@ -72,13 +105,12 @@ public class PlayerData { arr.Add((short)clientID); paramArr = new(); - paramArr.Add(NetworkArray.Param("NT", (double)(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()))); // network time - paramArr.Add(NetworkArray.Param("t", (int)(Runtime.CurrentRuntime / 1000))); // timestamp + paramArr.Add(NetworkArray.Param("NT", (double)(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()))); // network time (like PNG) + paramArr.Add(NetworkArray.Param("t", (int)(Runtime.CurrentRuntime / 1000))); // timestamp (non-decreasing integer) paramArr.Add(NetworkArray.Param("UID", Uid)); - paramArr.Add(NetworkArray.Param("A", A)); - paramArr.Add(NetworkArray.Param("PU", Pu)); - paramArr.Add(NetworkArray.Param("FP", Fp)); + addVariableToArray(paramArr, "A"); + addVariableToArray(paramArr, "FP"); if (IsValid) { paramArr.Add(NetworkArray.Param("R", R)); @@ -91,20 +123,24 @@ public class PlayerData { paramArr.Add(NetworkArray.Param("MX", Mx)); paramArr.Add(NetworkArray.Param("F", F)); paramArr.Add(NetworkArray.Param("MBF", Mbf)); - paramArr.Add(NetworkArray.Param("L", L)); - - paramArr.Add(NetworkArray.Param("J", J)); - paramArr.Add(NetworkArray.Param("BU", Bu)); - paramArr.Add(NetworkArray.Param("UDT", Udt)); - paramArr.Add(NetworkArray.Param("RA", Ra)); - paramArr.Add(NetworkArray.Param("CU", Cu)); - paramArr.Add(NetworkArray.Param("M", M)); + + foreach (var v in variables) { + if (v.Value is null || v.Key == "A" || v.Key == "FP") + continue; + paramArr.Add(NetworkArray.Param(v.Key, v.Value)); + } } arr.Add(paramArr); return arr; } + private void addVariableToArray(NetworkArray paramArr, string varName) { + if (variables.TryGetValue (varName, out string tmp) && tmp != null) { + paramArr.Add(NetworkArray.Param(varName, tmp)); + } + } + private string FixMountState(string value) { // raised pet geometry - set from Fp PetGeometryType GeometryType = PetGeometryType.Default;