From bbb11895697d22a72beb34b9ed0600f5d7f61cde Mon Sep 17 00:00:00 2001 From: AS <56699741+AlchlcDvl@users.noreply.github.com> Date: Wed, 26 Feb 2025 14:42:21 -0500 Subject: [PATCH 01/17] Update ExtraMessageExtensions.cs Added enum methods --- .../Extensions/ExtraMessageExtensions.cs | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs index f124fa0..fba6b03 100644 --- a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs +++ b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs @@ -32,6 +32,44 @@ public static void Write(this MessageWriter writer, Vector2 value) writer.Write(y); } + /// + /// Writes an Enum value to the . + /// + /// The to write to. + /// The to write. + public static void Write(this MessageWriter, Enum value) + { + var enumType = value.GetType(); + var underlyingType = enumType.GetEnumUnderlyingType(); + + if (underlyingType == typeof(byte)) + writer.Write(Convert.ToByte(enumVal)); + else if (underlyingType == typeof(sbyte)) + writer.Write(Convert.ToSByte(enumVal)); + else if (underlyingType == typeof(short)) + writer.Write(Convert.ToInt16(enumVal)); + else if (underlyingType == typeof(ushort)) + writer.Write(Convert.ToUInt16(enumVal)); + else if (underlyingType == typeof(long)) + writer.Write(Convert.ToInt64(enumVal)); + else if (underlyingType == typeof(ulong)) + writer.Write(Convert.ToUInt64(enumVal)); + else if (underlyingType == typeof(uint)) + writer.WritePacked(Convert.ToUInt32(enumVal)); + else if (underlyingType == typeof(int)) + writer.WritePacked(Convert.ToInt32(enumVal)); + else + throw new ArgumentException("Unknown underlying type for " + enumType.Name); + } + + /// + /// Writes a generic Enum value to the . + /// + /// The to write to. + /// The to write. + /// Enum type to write + public static void Write(this MessageWriter writer, T value) where T : struct, Enum => writer.Write((Enum)value); + /// /// Reads a from the . /// @@ -45,6 +83,81 @@ public static Vector2 ReadVector2(this MessageReader reader) return new Vector2(Mathf.Lerp(MIN, MAX, x), Mathf.Lerp(MIN, MAX, y)); } + /// + /// Reads and converts an enum value from a network message. + /// + /// The to read from. + /// Enum type to convert to + /// An from the . + /// Read value as a specified enum type + public static T ReadEnum(this MessageReader reader) where T : struct, Enum + { + var enumType = typeof(T); + var underlyingType = enumType.GetEnumUnderlyingType(); + + if (underlyingType == typeof(byte)) + return (T)(object)reader.ReadByte(); + + if (underlyingType == typeof(sbyte)) + return (T)(object)reader.ReadSByte(); + + if (underlyingType == typeof(short)) + return (T)(object)reader.ReadInt16(); + + if (underlyingType == typeof(ushort)) + return (T)(object)reader.ReadUInt16(); + + if (underlyingType == typeof(long)) + return (T)(object)reader.ReadInt64(); + + if (underlyingType == typeof(ulong)) + return (T)(object)reader.ReadUInt64(); + + if (underlyingType == typeof(uint)) + return (T)(object)reader.ReadPackedUInt32(); + + if (underlyingType == typeof(int)) + return (T)(object)reader.ReadPackedInt32(); + + throw new ArgumentException("Unknown underlying type for " + enumType.Name); + } + + /// + /// Reads an enum value from a network message. + /// + /// The to read from. + /// The resulting enum value + public static object ReadEnum(this MessageReader reader, Type enumType) + { + var underlyingType = enumType.GetEnumUnderlyingType(); + + if (underlyingType == typeof(byte)) + return Enum.Parse(enumType, reader.ReadByte().ToString()); + + if (underlyingType == typeof(sbyte)) + return Enum.Parse(enumType, reader.ReadSByte().ToString()); + + if (underlyingType == typeof(short)) + return Enum.Parse(enumType, reader.ReadInt16().ToString()); + + if (underlyingType == typeof(ushort)) + return Enum.Parse(enumType, reader.ReadUInt16().ToString()); + + if (underlyingType == typeof(long)) + return Enum.Parse(enumType, reader.ReadInt64().ToString()); + + if (underlyingType == typeof(ulong)) + return Enum.Parse(enumType, reader.ReadUInt64().ToString()); + + if (underlyingType == typeof(uint)) + return Enum.Parse(enumType, reader.ReadPackedUInt32().ToString()); + + if (underlyingType == typeof(int)) + return Enum.Parse(enumType, reader.ReadPackedInt32().ToString()); + + throw new ArgumentException("Unknown underlying type for " + enumType.Name); + } + /// /// Sends a message on the with an . /// From 4bd657269a4253a4378f2ac28a0a1691767162ec Mon Sep 17 00:00:00 2001 From: AS <56699741+AlchlcDvl@users.noreply.github.com> Date: Wed, 26 Feb 2025 14:48:53 -0500 Subject: [PATCH 02/17] Update MessageSerializer.cs Add enum serialisation --- Reactor/Networking/Serialization/MessageSerializer.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Reactor/Networking/Serialization/MessageSerializer.cs b/Reactor/Networking/Serialization/MessageSerializer.cs index 3f92591..d98d376 100644 --- a/Reactor/Networking/Serialization/MessageSerializer.cs +++ b/Reactor/Networking/Serialization/MessageSerializer.cs @@ -93,6 +93,9 @@ public static void Serialize(this MessageWriter writer, object @object) case string i: writer.Write(i); break; + case Enum i: + writer.Write(i); + break; default: var converter = FindConverter(@object.GetType()); if (converter != null) @@ -158,6 +161,11 @@ public static object Deserialize(this MessageReader reader, Type objectType) return reader.ReadString(); } + if (typeof(Enum).IsAssignableFrom(objectType)) + { + return reader.ReadEnum(objectType); + } + var converter = FindConverter(objectType); if (converter != null) { From aa564c0b73c3a6bd05a6b796bcda960bdb9062b4 Mon Sep 17 00:00:00 2001 From: AS <56699741+AlchlcDvl@users.noreply.github.com> Date: Wed, 26 Feb 2025 14:52:26 -0500 Subject: [PATCH 03/17] Oops documentation fix --- Reactor/Networking/Extensions/ExtraMessageExtensions.cs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs index fba6b03..e8d703a 100644 --- a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs +++ b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs @@ -67,7 +67,7 @@ public static void Write(this MessageWriter, Enum value) /// /// The to write to. /// The to write. - /// Enum type to write + /// Enum type to write. public static void Write(this MessageWriter writer, T value) where T : struct, Enum => writer.Write((Enum)value); /// @@ -87,9 +87,8 @@ public static Vector2 ReadVector2(this MessageReader reader) /// Reads and converts an enum value from a network message. /// /// The to read from. - /// Enum type to convert to - /// An from the . - /// Read value as a specified enum type + /// The type to convert to. + /// An value from the . public static T ReadEnum(this MessageReader reader) where T : struct, Enum { var enumType = typeof(T); @@ -126,7 +125,7 @@ public static T ReadEnum(this MessageReader reader) where T : struct, Enum /// Reads an enum value from a network message. /// /// The to read from. - /// The resulting enum value + /// The resulting enum value from the . public static object ReadEnum(this MessageReader reader, Type enumType) { var underlyingType = enumType.GetEnumUnderlyingType(); From d80903de221a320769897963f2727c8c14c5a519 Mon Sep 17 00:00:00 2001 From: AlchlcDvl <56699741+AlchlcDvl@users.noreply.github.com> Date: Wed, 26 Feb 2025 15:08:13 -0500 Subject: [PATCH 04/17] Fix errors + add long serialisation --- .../Extensions/ExtraMessageExtensions.cs | 63 ++++++++++--------- .../Serialization/MessageSerializer.cs | 8 +++ 2 files changed, 41 insertions(+), 30 deletions(-) diff --git a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs index e8d703a..711d8d6 100644 --- a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs +++ b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs @@ -1,3 +1,5 @@ +#pragma warning disable CA1305 // Specify IFormatProvider + using System; using Hazel; using Hazel.Udp; @@ -37,27 +39,27 @@ public static void Write(this MessageWriter writer, Vector2 value) /// /// The to write to. /// The to write. - public static void Write(this MessageWriter, Enum value) + public static void Write(this MessageWriter writer, Enum value) { var enumType = value.GetType(); var underlyingType = enumType.GetEnumUnderlyingType(); if (underlyingType == typeof(byte)) - writer.Write(Convert.ToByte(enumVal)); + writer.Write(Convert.ToByte(value)); else if (underlyingType == typeof(sbyte)) - writer.Write(Convert.ToSByte(enumVal)); + writer.Write(Convert.ToSByte(value)); else if (underlyingType == typeof(short)) - writer.Write(Convert.ToInt16(enumVal)); + writer.Write(Convert.ToInt16(value)); else if (underlyingType == typeof(ushort)) - writer.Write(Convert.ToUInt16(enumVal)); + writer.Write(Convert.ToUInt16(value)); else if (underlyingType == typeof(long)) - writer.Write(Convert.ToInt64(enumVal)); + writer.Write(Convert.ToInt64(value)); else if (underlyingType == typeof(ulong)) - writer.Write(Convert.ToUInt64(enumVal)); + writer.Write(Convert.ToUInt64(value)); else if (underlyingType == typeof(uint)) - writer.WritePacked(Convert.ToUInt32(enumVal)); + writer.WritePacked(Convert.ToUInt32(value)); else if (underlyingType == typeof(int)) - writer.WritePacked(Convert.ToInt32(enumVal)); + writer.WritePacked(Convert.ToInt32(value)); else throw new ArgumentException("Unknown underlying type for " + enumType.Name); } @@ -68,7 +70,7 @@ public static void Write(this MessageWriter, Enum value) /// The to write to. /// The to write. /// Enum type to write. - public static void Write(this MessageWriter writer, T value) where T : struct, Enum => writer.Write((Enum)value); + public static void Write(this MessageWriter writer, T value) where T : struct, Enum => writer.Write((Enum) value); /// /// Reads a from the . @@ -95,28 +97,28 @@ public static T ReadEnum(this MessageReader reader) where T : struct, Enum var underlyingType = enumType.GetEnumUnderlyingType(); if (underlyingType == typeof(byte)) - return (T)(object)reader.ReadByte(); + return (T) (object) reader.ReadByte(); if (underlyingType == typeof(sbyte)) - return (T)(object)reader.ReadSByte(); + return (T) (object) reader.ReadSByte(); if (underlyingType == typeof(short)) - return (T)(object)reader.ReadInt16(); + return (T) (object) reader.ReadInt16(); if (underlyingType == typeof(ushort)) - return (T)(object)reader.ReadUInt16(); - - if (underlyingType == typeof(long)) - return (T)(object)reader.ReadInt64(); + return (T) (object) reader.ReadUInt16(); if (underlyingType == typeof(ulong)) - return (T)(object)reader.ReadUInt64(); + return (T) (object) reader.ReadUInt64(); if (underlyingType == typeof(uint)) - return (T)(object)reader.ReadPackedUInt32(); + return (T) (object) reader.ReadPackedUInt32(); if (underlyingType == typeof(int)) - return (T)(object)reader.ReadPackedInt32(); + return (T) (object) reader.ReadPackedInt32(); + + if (underlyingType == typeof(long)) + throw new NotSupportedException("long enum types are not supported at the moment."); throw new ArgumentException("Unknown underlying type for " + enumType.Name); } @@ -125,34 +127,35 @@ public static T ReadEnum(this MessageReader reader) where T : struct, Enum /// Reads an enum value from a network message. /// /// The to read from. + /// The type of the enum. /// The resulting enum value from the . public static object ReadEnum(this MessageReader reader, Type enumType) { var underlyingType = enumType.GetEnumUnderlyingType(); if (underlyingType == typeof(byte)) - return Enum.Parse(enumType, reader.ReadByte().ToString()); + return Enum.Parse(enumType, $"{reader.ReadByte()}"); if (underlyingType == typeof(sbyte)) - return Enum.Parse(enumType, reader.ReadSByte().ToString()); + return Enum.Parse(enumType, $"{reader.ReadSByte()}"); if (underlyingType == typeof(short)) - return Enum.Parse(enumType, reader.ReadInt16().ToString()); + return Enum.Parse(enumType, $"{reader.ReadInt16()}"); if (underlyingType == typeof(ushort)) - return Enum.Parse(enumType, reader.ReadUInt16().ToString()); - - if (underlyingType == typeof(long)) - return Enum.Parse(enumType, reader.ReadInt64().ToString()); + return Enum.Parse(enumType, $"{reader.ReadUInt16()}"); if (underlyingType == typeof(ulong)) - return Enum.Parse(enumType, reader.ReadUInt64().ToString()); + return Enum.Parse(enumType, $"{reader.ReadUInt64()}"); if (underlyingType == typeof(uint)) - return Enum.Parse(enumType, reader.ReadPackedUInt32().ToString()); + return Enum.Parse(enumType, $"{reader.ReadPackedUInt32()}"); if (underlyingType == typeof(int)) - return Enum.Parse(enumType, reader.ReadPackedInt32().ToString()); + return Enum.Parse(enumType, $"{reader.ReadPackedInt32()}"); + + if (underlyingType == typeof(long)) + throw new NotSupportedException("long enum types are not supported at the moment."); throw new ArgumentException("Unknown underlying type for " + enumType.Name); } diff --git a/Reactor/Networking/Serialization/MessageSerializer.cs b/Reactor/Networking/Serialization/MessageSerializer.cs index d98d376..11db5ac 100644 --- a/Reactor/Networking/Serialization/MessageSerializer.cs +++ b/Reactor/Networking/Serialization/MessageSerializer.cs @@ -87,6 +87,9 @@ public static void Serialize(this MessageWriter writer, object @object) case bool i: writer.Write(i); break; + case ulong i: + writer.Write(i); + break; case Vector2 i: writer.Write(i); break; @@ -161,6 +164,11 @@ public static object Deserialize(this MessageReader reader, Type objectType) return reader.ReadString(); } + if (objectType == typeof(ulong)) + { + return reader.ReadUInt64(); + } + if (typeof(Enum).IsAssignableFrom(objectType)) { return reader.ReadEnum(objectType); From 82391065d6773020c89ddfcca39cd9edf0724a1b Mon Sep 17 00:00:00 2001 From: AlchlcDvl <56699741+AlchlcDvl@users.noreply.github.com> Date: Wed, 26 Feb 2025 15:09:10 -0500 Subject: [PATCH 05/17] Correction: ulong not long --- Reactor/Networking/Extensions/ExtraMessageExtensions.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs index 711d8d6..59ee64d 100644 --- a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs +++ b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs @@ -52,14 +52,14 @@ public static void Write(this MessageWriter writer, Enum value) writer.Write(Convert.ToInt16(value)); else if (underlyingType == typeof(ushort)) writer.Write(Convert.ToUInt16(value)); - else if (underlyingType == typeof(long)) - writer.Write(Convert.ToInt64(value)); else if (underlyingType == typeof(ulong)) writer.Write(Convert.ToUInt64(value)); else if (underlyingType == typeof(uint)) writer.WritePacked(Convert.ToUInt32(value)); else if (underlyingType == typeof(int)) writer.WritePacked(Convert.ToInt32(value)); + else if (underlyingType == typeof(long)) + throw new NotSupportedException("long enum types are not supported at the moment."); else throw new ArgumentException("Unknown underlying type for " + enumType.Name); } From f130f4495900ac4e0c166fd19e42d73a04d48022 Mon Sep 17 00:00:00 2001 From: AlchlcDvl <56699741+AlchlcDvl@users.noreply.github.com> Date: Sun, 23 Mar 2025 16:57:21 -0400 Subject: [PATCH 06/17] Specify format --- .gitignore | 3 ++- .../Extensions/ExtraMessageExtensions.cs | 17 ++++++++--------- .../Serialization/MessageSerializer.cs | 4 ++-- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index f04d691..ca04d7a 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ riderModule.iml .idea /tools .vscode -*.DotSettings.user \ No newline at end of file +*.DotSettings.user +.qodo diff --git a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs index 59ee64d..55f86fb 100644 --- a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs +++ b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs @@ -1,6 +1,5 @@ -#pragma warning disable CA1305 // Specify IFormatProvider - using System; +using System.Globalization; using Hazel; using Hazel.Udp; using UnityEngine; @@ -45,19 +44,19 @@ public static void Write(this MessageWriter writer, Enum value) var underlyingType = enumType.GetEnumUnderlyingType(); if (underlyingType == typeof(byte)) - writer.Write(Convert.ToByte(value)); + writer.Write(Convert.ToByte(value, NumberFormatInfo.InvariantInfo)); else if (underlyingType == typeof(sbyte)) - writer.Write(Convert.ToSByte(value)); + writer.Write(Convert.ToSByte(value, NumberFormatInfo.InvariantInfo)); else if (underlyingType == typeof(short)) - writer.Write(Convert.ToInt16(value)); + writer.Write(Convert.ToInt16(value, NumberFormatInfo.InvariantInfo)); else if (underlyingType == typeof(ushort)) - writer.Write(Convert.ToUInt16(value)); + writer.Write(Convert.ToUInt16(value, NumberFormatInfo.InvariantInfo)); else if (underlyingType == typeof(ulong)) - writer.Write(Convert.ToUInt64(value)); + writer.Write(Convert.ToUInt64(value, NumberFormatInfo.InvariantInfo)); else if (underlyingType == typeof(uint)) - writer.WritePacked(Convert.ToUInt32(value)); + writer.WritePacked(Convert.ToUInt32(value, NumberFormatInfo.InvariantInfo)); else if (underlyingType == typeof(int)) - writer.WritePacked(Convert.ToInt32(value)); + writer.WritePacked(Convert.ToInt32(value, NumberFormatInfo.InvariantInfo)); else if (underlyingType == typeof(long)) throw new NotSupportedException("long enum types are not supported at the moment."); else diff --git a/Reactor/Networking/Serialization/MessageSerializer.cs b/Reactor/Networking/Serialization/MessageSerializer.cs index 11db5ac..463c5ac 100644 --- a/Reactor/Networking/Serialization/MessageSerializer.cs +++ b/Reactor/Networking/Serialization/MessageSerializer.cs @@ -30,7 +30,7 @@ public static void Register(UnsafeMessageConverter messageConverter) /// Finds a MessageConverter for the specified . /// /// The type of an object. - /// A MessageConverted that can convert the specified . + /// A MessageConverter that can convert the specified . public static UnsafeMessageConverter? FindConverter(Type type) { if (MessageConverterMap.TryGetValue(type, out var value)) @@ -169,7 +169,7 @@ public static object Deserialize(this MessageReader reader, Type objectType) return reader.ReadUInt64(); } - if (typeof(Enum).IsAssignableFrom(objectType)) + if (objectType.IsEnum) { return reader.ReadEnum(objectType); } From 1431a9d4655543378046bc8bb12f1f8587ffcaa7 Mon Sep 17 00:00:00 2001 From: AlchlcDvl <56699741+AlchlcDvl@users.noreply.github.com> Date: Sun, 23 Mar 2025 17:46:20 -0400 Subject: [PATCH 07/17] Add long serialisation + improve enum serialisation --- .../Extensions/ExtraMessageExtensions.cs | 102 ++++-------------- .../Serialization/MessageSerializer.cs | 8 ++ 2 files changed, 26 insertions(+), 84 deletions(-) diff --git a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs index 55f86fb..dd8341c 100644 --- a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs +++ b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs @@ -2,6 +2,7 @@ using System.Globalization; using Hazel; using Hazel.Udp; +using Reactor.Networking.Serialization; using UnityEngine; namespace Reactor.Networking.Extensions; @@ -38,30 +39,7 @@ public static void Write(this MessageWriter writer, Vector2 value) /// /// The to write to. /// The to write. - public static void Write(this MessageWriter writer, Enum value) - { - var enumType = value.GetType(); - var underlyingType = enumType.GetEnumUnderlyingType(); - - if (underlyingType == typeof(byte)) - writer.Write(Convert.ToByte(value, NumberFormatInfo.InvariantInfo)); - else if (underlyingType == typeof(sbyte)) - writer.Write(Convert.ToSByte(value, NumberFormatInfo.InvariantInfo)); - else if (underlyingType == typeof(short)) - writer.Write(Convert.ToInt16(value, NumberFormatInfo.InvariantInfo)); - else if (underlyingType == typeof(ushort)) - writer.Write(Convert.ToUInt16(value, NumberFormatInfo.InvariantInfo)); - else if (underlyingType == typeof(ulong)) - writer.Write(Convert.ToUInt64(value, NumberFormatInfo.InvariantInfo)); - else if (underlyingType == typeof(uint)) - writer.WritePacked(Convert.ToUInt32(value, NumberFormatInfo.InvariantInfo)); - else if (underlyingType == typeof(int)) - writer.WritePacked(Convert.ToInt32(value, NumberFormatInfo.InvariantInfo)); - else if (underlyingType == typeof(long)) - throw new NotSupportedException("long enum types are not supported at the moment."); - else - throw new ArgumentException("Unknown underlying type for " + enumType.Name); - } + public static void Write(this MessageWriter writer, Enum value) => writer.Serialize(Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType()), CultureInfo.InvariantCulture)); /// /// Writes a generic Enum value to the . @@ -71,6 +49,14 @@ public static void Write(this MessageWriter writer, Enum value) /// Enum type to write. public static void Write(this MessageWriter writer, T value) where T : struct, Enum => writer.Write((Enum) value); + /// + /// Writes a long value to the . + /// + /// The to write to. + /// The to write. + public static void Write(this MessageWriter writer, long value) => writer.Write(unchecked(value + long.MaxValue)); + // Someone please give me a better way to do this that does not involve shifting values please + /// /// Reads a from the . /// @@ -90,37 +76,7 @@ public static Vector2 ReadVector2(this MessageReader reader) /// The to read from. /// The type to convert to. /// An value from the . - public static T ReadEnum(this MessageReader reader) where T : struct, Enum - { - var enumType = typeof(T); - var underlyingType = enumType.GetEnumUnderlyingType(); - - if (underlyingType == typeof(byte)) - return (T) (object) reader.ReadByte(); - - if (underlyingType == typeof(sbyte)) - return (T) (object) reader.ReadSByte(); - - if (underlyingType == typeof(short)) - return (T) (object) reader.ReadInt16(); - - if (underlyingType == typeof(ushort)) - return (T) (object) reader.ReadUInt16(); - - if (underlyingType == typeof(ulong)) - return (T) (object) reader.ReadUInt64(); - - if (underlyingType == typeof(uint)) - return (T) (object) reader.ReadPackedUInt32(); - - if (underlyingType == typeof(int)) - return (T) (object) reader.ReadPackedInt32(); - - if (underlyingType == typeof(long)) - throw new NotSupportedException("long enum types are not supported at the moment."); - - throw new ArgumentException("Unknown underlying type for " + enumType.Name); - } + public static T ReadEnum(this MessageReader reader) where T : struct, Enum => (T) reader.ReadEnum(typeof(T)); /// /// Reads an enum value from a network message. @@ -128,36 +84,14 @@ public static T ReadEnum(this MessageReader reader) where T : struct, Enum /// The to read from. /// The type of the enum. /// The resulting enum value from the . - public static object ReadEnum(this MessageReader reader, Type enumType) - { - var underlyingType = enumType.GetEnumUnderlyingType(); - - if (underlyingType == typeof(byte)) - return Enum.Parse(enumType, $"{reader.ReadByte()}"); - - if (underlyingType == typeof(sbyte)) - return Enum.Parse(enumType, $"{reader.ReadSByte()}"); - - if (underlyingType == typeof(short)) - return Enum.Parse(enumType, $"{reader.ReadInt16()}"); - - if (underlyingType == typeof(ushort)) - return Enum.Parse(enumType, $"{reader.ReadUInt16()}"); - - if (underlyingType == typeof(ulong)) - return Enum.Parse(enumType, $"{reader.ReadUInt64()}"); + public static object ReadEnum(this MessageReader reader, Type enumType) => reader.Deserialize(Enum.GetUnderlyingType(enumType)); - if (underlyingType == typeof(uint)) - return Enum.Parse(enumType, $"{reader.ReadPackedUInt32()}"); - - if (underlyingType == typeof(int)) - return Enum.Parse(enumType, $"{reader.ReadPackedInt32()}"); - - if (underlyingType == typeof(long)) - throw new NotSupportedException("long enum types are not supported at the moment."); - - throw new ArgumentException("Unknown underlying type for " + enumType.Name); - } + /// + /// Reads a long value from a network message. + /// + /// The to read from. + /// The resulting long value from the . + public static long ReadInt64(this MessageReader reader) => (long) unchecked(reader.ReadUInt64() - long.MaxValue); /// /// Sends a message on the with an . diff --git a/Reactor/Networking/Serialization/MessageSerializer.cs b/Reactor/Networking/Serialization/MessageSerializer.cs index 463c5ac..2297b9c 100644 --- a/Reactor/Networking/Serialization/MessageSerializer.cs +++ b/Reactor/Networking/Serialization/MessageSerializer.cs @@ -90,6 +90,9 @@ public static void Serialize(this MessageWriter writer, object @object) case ulong i: writer.Write(i); break; + case long i: + ExtraMessageExtensions.Write(writer, i); // For some reason this insists on referring the to float write method, so this is me taking precautions + break; case Vector2 i: writer.Write(i); break; @@ -169,6 +172,11 @@ public static object Deserialize(this MessageReader reader, Type objectType) return reader.ReadUInt64(); } + if (objectType == typeof(long)) + { + return reader.ReadInt64(); + } + if (objectType.IsEnum) { return reader.ReadEnum(objectType); From 44ea7d2cc3984b47e40ce3de4e105135f8edaa2d Mon Sep 17 00:00:00 2001 From: AlchlcDvl <56699741+AlchlcDvl@users.noreply.github.com> Date: Sun, 23 Mar 2025 18:20:25 -0400 Subject: [PATCH 08/17] Add a shorthand method --- Reactor/Networking/Serialization/MessageSerializer.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Reactor/Networking/Serialization/MessageSerializer.cs b/Reactor/Networking/Serialization/MessageSerializer.cs index 2297b9c..b38b8bd 100644 --- a/Reactor/Networking/Serialization/MessageSerializer.cs +++ b/Reactor/Networking/Serialization/MessageSerializer.cs @@ -114,6 +114,14 @@ public static void Serialize(this MessageWriter writer, object @object) } } + /// + /// Deserializes a generic value from the . + /// + /// The to read from. + /// The type to be read. + /// A generic value from the . + public static T Deserialize(this MessageReader reader) => (T) reader.Deserialize(typeof(T)); + /// /// Deserializes an of from the . /// From c146282303c00433b6383be0c6647ad323b60b0b Mon Sep 17 00:00:00 2001 From: AlchlcDvl <56699741+AlchlcDvl@users.noreply.github.com> Date: Thu, 27 Mar 2025 14:40:44 -0400 Subject: [PATCH 09/17] Removed generic enum write and fix long write --- .../Networking/Extensions/ExtraMessageExtensions.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs index dd8341c..6c002d5 100644 --- a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs +++ b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs @@ -41,20 +41,12 @@ public static void Write(this MessageWriter writer, Vector2 value) /// The to write. public static void Write(this MessageWriter writer, Enum value) => writer.Serialize(Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType()), CultureInfo.InvariantCulture)); - /// - /// Writes a generic Enum value to the . - /// - /// The to write to. - /// The to write. - /// Enum type to write. - public static void Write(this MessageWriter writer, T value) where T : struct, Enum => writer.Write((Enum) value); - /// /// Writes a long value to the . /// /// The to write to. /// The to write. - public static void Write(this MessageWriter writer, long value) => writer.Write(unchecked(value + long.MaxValue)); + public static void Write(this MessageWriter writer, long value) => writer.Write((ulong) unchecked(value + long.MaxValue)); // Someone please give me a better way to do this that does not involve shifting values please /// From 3efa22c77302650895d549e7c365bf3f3ed19898 Mon Sep 17 00:00:00 2001 From: AlchlcDvl <56699741+AlchlcDvl@users.noreply.github.com> Date: Fri, 28 Mar 2025 00:48:28 -0400 Subject: [PATCH 10/17] Add generic converter support + read enum improvement --- .../Attributes/MessageConverterAttribute.cs | 4 +- .../Extensions/ExtraMessageExtensions.cs | 2 +- .../Serialization/MessageSerializer.cs | 86 +++++++++++++++---- 3 files changed, 73 insertions(+), 19 deletions(-) diff --git a/Reactor/Networking/Attributes/MessageConverterAttribute.cs b/Reactor/Networking/Attributes/MessageConverterAttribute.cs index e3515be..3efd3b9 100644 --- a/Reactor/Networking/Attributes/MessageConverterAttribute.cs +++ b/Reactor/Networking/Attributes/MessageConverterAttribute.cs @@ -38,8 +38,7 @@ public static void Register(Assembly assembly) try { - var messageConverter = (UnsafeMessageConverter) Activator.CreateInstance(type)!; - MessageSerializer.Register(messageConverter); + MessageSerializer.Register(type); } catch (Exception e) { @@ -52,5 +51,6 @@ public static void Register(Assembly assembly) internal static void Initialize() { IL2CPPChainloader.Instance.PluginLoad += (_, assembly, _) => Register(assembly); + IL2CPPChainloader.Instance.Finished += MessageSerializer.ClearMaps; } } diff --git a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs index 6c002d5..e9db3d8 100644 --- a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs +++ b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs @@ -76,7 +76,7 @@ public static Vector2 ReadVector2(this MessageReader reader) /// The to read from. /// The type of the enum. /// The resulting enum value from the . - public static object ReadEnum(this MessageReader reader, Type enumType) => reader.Deserialize(Enum.GetUnderlyingType(enumType)); + public static object ReadEnum(this MessageReader reader, Type enumType) => Enum.ToObject(enumType, reader.Deserialize(Enum.GetUnderlyingType(enumType))); /// /// Reads a long value from a network message. diff --git a/Reactor/Networking/Serialization/MessageSerializer.cs b/Reactor/Networking/Serialization/MessageSerializer.cs index b38b8bd..bf22524 100644 --- a/Reactor/Networking/Serialization/MessageSerializer.cs +++ b/Reactor/Networking/Serialization/MessageSerializer.cs @@ -12,18 +12,41 @@ namespace Reactor.Networking.Serialization; /// public static class MessageSerializer { + internal record class GenericTypeHolder(Type Type, Type Arg); + private static List MessageConverters { get; } = new(); private static Dictionary MessageConverterMap { get; } = new(); + private static Dictionary GenericConvertersMap { get; } = new(); + + internal static void ClearMaps() + { + MessageConverterMap.Clear(); + } /// /// Registers a MessageConverter. /// - /// The MessageConverter to be registered. - public static void Register(UnsafeMessageConverter messageConverter) + /// The Type of the MessageConverter to be registered. + public static void Register(Type type) { - MessageConverters.Add(messageConverter); - MessageConverterMap.Clear(); + if (type.IsGenericTypeDefinition) + { + var baseType = type.BaseType!; + + if (!baseType.Name.Contains("MessageConverter")) + throw new InvalidOperationException($"{type.Name} should directly inherit from MessageConverter"); + + var generics = baseType.GetGenericArguments(); + var param = generics[0]; + + GenericConvertersMap.Add(param.GetGenericTypeDefinition(), type); + } + else + { + var messageConverter = (UnsafeMessageConverter) Activator.CreateInstance(type)!; + MessageConverters.Add(messageConverter); + } } /// @@ -33,15 +56,44 @@ public static void Register(UnsafeMessageConverter messageConverter) /// A MessageConverter that can convert the specified . public static UnsafeMessageConverter? FindConverter(Type type) { - if (MessageConverterMap.TryGetValue(type, out var value)) + if (!MessageConverterMap.TryGetValue(type, out var value)) { - return value; + value = MessageConverters.SingleOrDefault(x => x.CanConvert(type)); + + if (value == null) + return null; + + MessageConverterMap.Add(type, value); } - var converter = MessageConverters.SingleOrDefault(x => x.CanConvert(type)); - MessageConverterMap.Add(type, converter); + return value; + } + + /// + /// Finds and builds a MessageConverter for the specified using a registered generic converter. + /// + /// The type of an object. + /// A MessageConverter that can convert the specified . + public static UnsafeMessageConverter? FindGenericConverter(Type type) + { + if (MessageConverterMap.TryGetValue(type, out var value)) + return value; - return converter; + if (!type.IsGenericType) + return null; + + var typeDef = type.GetGenericTypeDefinition(); + + if (!GenericConvertersMap.TryGetValue(typeDef, out var builder)) + return null; + + var generic = builder.MakeGenericType(type.GetGenericArguments()); + value = (UnsafeMessageConverter) Activator.CreateInstance(generic)!; + + MessageConverters.Add(value); + MessageConverterMap.Add(type, value); + + return value; } /// @@ -49,7 +101,7 @@ public static void Register(UnsafeMessageConverter messageConverter) /// /// The to write to. /// The args to be written. - public static void Serialize(MessageWriter writer, object[] args) + public static void Serialize(this MessageWriter writer, params object[] args) { foreach (var arg in args) { @@ -103,14 +155,15 @@ public static void Serialize(this MessageWriter writer, object @object) writer.Write(i); break; default: - var converter = FindConverter(@object.GetType()); + var type = @object.GetType(); + var converter = FindGenericConverter(type) ?? FindConverter(type); + if (converter != null) - { converter.UnsafeWrite(writer, @object); - break; - } + else + throw new NotSupportedException("Couldn't serialize " + type.Name); - throw new NotSupportedException("Couldn't serialize " + @object.GetType()); + break; } } @@ -190,7 +243,8 @@ public static object Deserialize(this MessageReader reader, Type objectType) return reader.ReadEnum(objectType); } - var converter = FindConverter(objectType); + var converter = FindGenericConverter(objectType) ?? FindConverter(objectType); + if (converter != null) { return converter.UnsafeRead(reader, objectType); From 814376094ea3b0f2ee1a829f08d8c4512fae2224 Mon Sep 17 00:00:00 2001 From: AlchlcDvl <56699741+AlchlcDvl@users.noreply.github.com> Date: Fri, 28 Mar 2025 00:49:08 -0400 Subject: [PATCH 11/17] Remove leftover code --- Reactor/Networking/Serialization/MessageSerializer.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Reactor/Networking/Serialization/MessageSerializer.cs b/Reactor/Networking/Serialization/MessageSerializer.cs index bf22524..9e982d5 100644 --- a/Reactor/Networking/Serialization/MessageSerializer.cs +++ b/Reactor/Networking/Serialization/MessageSerializer.cs @@ -12,8 +12,6 @@ namespace Reactor.Networking.Serialization; /// public static class MessageSerializer { - internal record class GenericTypeHolder(Type Type, Type Arg); - private static List MessageConverters { get; } = new(); private static Dictionary MessageConverterMap { get; } = new(); From 0b9cfa816910255f8ded7ecc2c2ee7f6c085553c Mon Sep 17 00:00:00 2001 From: AlchlcDvl <56699741+AlchlcDvl@users.noreply.github.com> Date: Thu, 3 Apr 2025 14:50:09 -0400 Subject: [PATCH 12/17] Better long serialisation --- .../Networking/Extensions/ExtraMessageExtensions.cs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs index e9db3d8..19bbdaa 100644 --- a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs +++ b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs @@ -46,8 +46,12 @@ public static void Write(this MessageWriter writer, Vector2 value) /// /// The to write to. /// The to write. - public static void Write(this MessageWriter writer, long value) => writer.Write((ulong) unchecked(value + long.MaxValue)); - // Someone please give me a better way to do this that does not involve shifting values please + public static void Write(this MessageWriter writer, long value) + { + var array = BitConverter.GetBytes(value); + foreach (var i in array) + writer.Write(i); + } /// /// Reads a from the . @@ -83,7 +87,7 @@ public static Vector2 ReadVector2(this MessageReader reader) /// /// The to read from. /// The resulting long value from the . - public static long ReadInt64(this MessageReader reader) => (long) unchecked(reader.ReadUInt64() - long.MaxValue); + public static long ReadInt64(this MessageReader reader) => BitConverter.ToInt64(reader.ReadBytes(8), 0); /// /// Sends a message on the with an . From ff8c3c67cf97c1042ae98dfc128468b06a4c5a41 Mon Sep 17 00:00:00 2001 From: AlchlcDvl <56699741+AlchlcDvl@users.noreply.github.com> Date: Wed, 9 Apr 2025 14:52:42 -0400 Subject: [PATCH 13/17] Serialise the array directly --- Reactor/Networking/Extensions/ExtraMessageExtensions.cs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs index 19bbdaa..273db97 100644 --- a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs +++ b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs @@ -46,12 +46,7 @@ public static void Write(this MessageWriter writer, Vector2 value) /// /// The to write to. /// The to write. - public static void Write(this MessageWriter writer, long value) - { - var array = BitConverter.GetBytes(value); - foreach (var i in array) - writer.Write(i); - } + public static void Write(this MessageWriter writer, long value) => writer.Write(BitConverter.GetBytes(value)); /// /// Reads a from the . From d2364602256a52cb512006ef946fbd05fa8f8ae5 Mon Sep 17 00:00:00 2001 From: AlchlcDvl <56699741+AlchlcDvl@users.noreply.github.com> Date: Sun, 18 May 2025 20:13:37 -0400 Subject: [PATCH 14/17] Allow serialising color values --- .../Extensions/ExtraMessageExtensions.cs | 45 ++++++++++++++++++- .../Serialization/MessageSerializer.cs | 16 +++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs index 273db97..0fc4f93 100644 --- a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs +++ b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs @@ -14,10 +14,11 @@ public static class ExtraMessageExtensions { private const float MIN = -50f; private const float MAX = 50f; + private const float DIFF = MAX - MIN; private static float ReverseLerp(float t) { - return Mathf.Clamp((t - MIN) / (MAX - MIN), 0f, 1f); + return Mathf.Clamp01((t - MIN) / DIFF); } /// @@ -48,6 +49,32 @@ public static void Write(this MessageWriter writer, Vector2 value) /// The to write. public static void Write(this MessageWriter writer, long value) => writer.Write(BitConverter.GetBytes(value)); + /// + /// Writes a color value to the . + /// + /// The to write to. + /// The to write. + public static void Write(this MessageWriter writer, Color32 value) + { + writer.Write(value.r); + writer.Write(value.g); + writer.Write(value.b); + writer.Write(value.a); + } + + /// + /// Writes a color value to the . + /// + /// The to write to. + /// The to write. + public static void Write(this MessageWriter writer, Color value) + { + writer.Write(value.r); + writer.Write(value.g); + writer.Write(value.b); + writer.Write(value.a); + } + /// /// Reads a from the . /// @@ -62,7 +89,7 @@ public static Vector2 ReadVector2(this MessageReader reader) } /// - /// Reads and converts an enum value from a network message. + /// Reads an enum value and casts it to the specified type from a network message. /// /// The to read from. /// The type to convert to. @@ -84,6 +111,20 @@ public static Vector2 ReadVector2(this MessageReader reader) /// The resulting long value from the . public static long ReadInt64(this MessageReader reader) => BitConverter.ToInt64(reader.ReadBytes(8), 0); + /// + /// Reads a color value from a network message. + /// + /// The to read from. + /// The resulting Color32 value from the . + public static Color32 ReadColor32(this MessageReader reader) => new(reader.ReadByte(), reader.ReadByte(), reader.ReadByte(), reader.ReadByte()); + + /// + /// Reads a color value from a network message. + /// + /// The to read from. + /// The resulting Color value from the . + public static Color ReadColor(this MessageReader reader) => new(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); + /// /// Sends a message on the with an . /// diff --git a/Reactor/Networking/Serialization/MessageSerializer.cs b/Reactor/Networking/Serialization/MessageSerializer.cs index 9e982d5..5a1236c 100644 --- a/Reactor/Networking/Serialization/MessageSerializer.cs +++ b/Reactor/Networking/Serialization/MessageSerializer.cs @@ -149,6 +149,12 @@ public static void Serialize(this MessageWriter writer, object @object) case string i: writer.Write(i); break; + case Color i: + writer.Write(i); + break; + case Color32 i: + writer.Write(i); + break; case Enum i: writer.Write(i); break; @@ -236,6 +242,16 @@ public static object Deserialize(this MessageReader reader, Type objectType) return reader.ReadInt64(); } + if (objectType == typeof(Color)) + { + return reader.ReadColor(); + } + + if (objectType == typeof(Color32)) + { + return reader.ReadColor32(); + } + if (objectType.IsEnum) { return reader.ReadEnum(objectType); From ef66b54c0348da5f899911f8b8082c8e4f9f5a64 Mon Sep 17 00:00:00 2001 From: AS <56699741+AlchlcDvl@users.noreply.github.com> Date: Mon, 2 Jun 2025 18:23:38 -0400 Subject: [PATCH 15/17] Update .gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index ca04d7a..369166a 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,3 @@ riderModule.iml /tools .vscode *.DotSettings.user -.qodo From 22fac617c3eaa9767aabfaa2da4e736f077092fe Mon Sep 17 00:00:00 2001 From: AS <56699741+AlchlcDvl@users.noreply.github.com> Date: Mon, 2 Jun 2025 18:24:14 -0400 Subject: [PATCH 16/17] Update ExtraMessageExtensions.cs --- .../Networking/Extensions/ExtraMessageExtensions.cs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs index 0fc4f93..439cf42 100644 --- a/Reactor/Networking/Extensions/ExtraMessageExtensions.cs +++ b/Reactor/Networking/Extensions/ExtraMessageExtensions.cs @@ -62,19 +62,6 @@ public static void Write(this MessageWriter writer, Color32 value) writer.Write(value.a); } - /// - /// Writes a color value to the . - /// - /// The to write to. - /// The to write. - public static void Write(this MessageWriter writer, Color value) - { - writer.Write(value.r); - writer.Write(value.g); - writer.Write(value.b); - writer.Write(value.a); - } - /// /// Reads a from the . /// From 3beb5e732b67b62a0d76ef29860ede2478649030 Mon Sep 17 00:00:00 2001 From: AS <56699741+AlchlcDvl@users.noreply.github.com> Date: Thu, 5 Jun 2025 00:47:17 -0400 Subject: [PATCH 17/17] Discard changes to .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 369166a..f04d691 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,4 @@ riderModule.iml .idea /tools .vscode -*.DotSettings.user +*.DotSettings.user \ No newline at end of file