diff --git a/Server/Server.cs b/Server/Server.cs index 6724ad3..5517c38 100644 --- a/Server/Server.cs +++ b/Server/Server.cs @@ -151,16 +151,15 @@ public class Server { Logger.Info($"Client {socket.RemoteEndPoint} disconnected from the server"); } else { Logger.Error($"Exception on socket {socket.RemoteEndPoint}, disconnecting for: {e}"); - await socket.DisconnectAsync(false); + Task.Run(() => socket.DisconnectAsync(false)); } memory?.Dispose(); } Clients.Remove(client); - Broadcast(new DisconnectPacket(), client).ContinueWith(_ => { - client.Dispose(); - }); + client.Dispose(); + Task.Run(() => Broadcast(new DisconnectPacket(), client)); } private static PacketHeader GetHeader(Span data) { diff --git a/Shared/Constants.cs b/Shared/Constants.cs index 5cfbdd1..8506fdf 100644 --- a/Shared/Constants.cs +++ b/Shared/Constants.cs @@ -9,6 +9,7 @@ public static class Constants { public const int MaxPacketSize = 256; public const int MaxClients = 4; public static int HeaderSize { get; } = Marshal.SizeOf(); + public const int CostumeNameSize = 0x20; // dictionary of packet types to packet public static readonly Dictionary Packets = Assembly diff --git a/Shared/Extensions.cs b/Shared/Extensions.cs index 09e7351..0438bb5 100644 --- a/Shared/Extensions.cs +++ b/Shared/Extensions.cs @@ -8,4 +8,12 @@ public static class Extensions { } public static string Hex(this IEnumerable array) => string.Join(' ', array.ToArray().Select(x => x.ToString("X2"))); + + public static unsafe byte* Ptr(this Span span) { + fixed (byte* data = span) return data; + } + + public static string TrimNullTerm(this string text) { + return text.Split('\0').FirstOrDefault() ?? ""; + } } \ No newline at end of file diff --git a/Shared/Packet/Packets/CapPacket.cs b/Shared/Packet/Packets/CapPacket.cs new file mode 100644 index 0000000..1601733 --- /dev/null +++ b/Shared/Packet/Packets/CapPacket.cs @@ -0,0 +1,23 @@ +using System.Numerics; +using System.Runtime.InteropServices; +using System.Text; + +namespace Shared.Packet.Packets; + +public class CapPacket : IPacket { + public const int NameSize = 0x30; + public Vector3 Position; + public Quaternion Rotation; + public string CapAnim; + public void Serialize(Span data) { + MemoryMarshal.Write(data, ref Position); + MemoryMarshal.Write(data[12..], ref Position); + Encoding.UTF8.GetBytes(CapAnim).CopyTo(data[28..]); + } + + public void Deserialize(Span data) { + Position = MemoryMarshal.Read(data); + Rotation = MemoryMarshal.Read(data[12..]); + CapAnim = Encoding.UTF8.GetString(data[28..]).TrimEnd('\0'); + } +} \ No newline at end of file diff --git a/Shared/Packet/Packets/CapturePacket.cs b/Shared/Packet/Packets/CapturePacket.cs new file mode 100644 index 0000000..b51aace --- /dev/null +++ b/Shared/Packet/Packets/CapturePacket.cs @@ -0,0 +1,19 @@ +using System.Runtime.InteropServices; +using System.Text; + +namespace Shared.Packet.Packets; + +public class CapturePacket : IPacket { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.CostumeNameSize)] + public string ModelName; + public bool IsCaptured; + public void Serialize(Span data) { + Encoding.UTF8.GetBytes(ModelName).CopyTo(data[..Constants.CostumeNameSize]); + MemoryMarshal.Write(data[Constants.CostumeNameSize..], ref IsCaptured); + } + + public void Deserialize(Span data) { + ModelName = Encoding.UTF8.GetString(data[..Constants.CostumeNameSize]).TrimNullTerm(); + IsCaptured = MemoryMarshal.Read(data[Constants.CostumeNameSize..]); + } +} \ No newline at end of file diff --git a/Shared/Packet/Packets/CostumePacket.cs b/Shared/Packet/Packets/CostumePacket.cs index 0d39727..fa62643 100644 --- a/Shared/Packet/Packets/CostumePacket.cs +++ b/Shared/Packet/Packets/CostumePacket.cs @@ -1,24 +1,21 @@ using System.Runtime.InteropServices; +using System.Text; namespace Shared.Packet.Packets; [Packet(PacketType.Costume)] public struct CostumePacket : IPacket { - public const int CostumeNameSize = 0x20; - - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CostumeNameSize)] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.CostumeNameSize)] public string BodyName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CostumeNameSize)] + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.CostumeNameSize)] public string CapName; public void Serialize(Span data) { - Span strData = MemoryMarshal.Cast(data); - BodyName.CopyTo(strData[..CostumeNameSize]); - CapName.CopyTo(strData[CostumeNameSize..]); + Encoding.UTF8.GetBytes(BodyName).CopyTo(data[..Constants.CostumeNameSize]); + Encoding.UTF8.GetBytes(CapName).CopyTo(data[Constants.CostumeNameSize..]); } public void Deserialize(Span data) { - Span strData = MemoryMarshal.Cast(data); - BodyName = new string(strData[..CostumeNameSize].TrimEnd('\0')); - CapName = new string(strData[CostumeNameSize..].TrimEnd('\0')); + BodyName = Encoding.UTF8.GetString(data[..Constants.CostumeNameSize]).TrimNullTerm(); + CapName = Encoding.UTF8.GetString(data[Constants.CostumeNameSize..]).TrimNullTerm(); } } \ No newline at end of file diff --git a/Shared/Packet/Packets/GamePacket.cs b/Shared/Packet/Packets/GamePacket.cs deleted file mode 100644 index d65eac4..0000000 --- a/Shared/Packet/Packets/GamePacket.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Runtime.InteropServices; - -namespace Shared.Packet.Packets; - -public class GamePacket : IPacket { - public int ScenarioNum; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = PlayerPacket.NameSize)] - public string Stage; - - public void Serialize(Span data) { - MemoryMarshal.Write(data, ref ScenarioNum); - Stage.CopyTo(MemoryMarshal.Cast(data[4..])); - } - - public void Deserialize(Span data) { - ScenarioNum = MemoryMarshal.Read(data); - Stage = new string(MemoryMarshal.Cast(data[4..])); - } -} \ No newline at end of file diff --git a/Shared/Packet/Packets/PlayerPacket.cs b/Shared/Packet/Packets/PlayerPacket.cs index 73a2ece..dbaf859 100644 --- a/Shared/Packet/Packets/PlayerPacket.cs +++ b/Shared/Packet/Packets/PlayerPacket.cs @@ -1,4 +1,5 @@ using System.Numerics; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; @@ -38,7 +39,6 @@ public struct PlayerPacket : IPacket { MemoryMarshal.Write(data[offset++..], ref IsIt); MemoryMarshal.Write(data[offset..], ref ScenarioNum); offset += 5; - // Span strData = MemoryMarshal.Cast(data[offset..]); Encoding.UTF8.GetBytes(Stage).CopyTo(data[offset..(offset + NameSize)]); offset += NameSize; Encoding.UTF8.GetBytes(Act).CopyTo(data[offset..(offset + NameSize)]); @@ -60,10 +60,10 @@ public struct PlayerPacket : IPacket { // offset++; // padding ScenarioNum = MemoryMarshal.Read(data[offset..]); offset += 5; - Stage = new string(Encoding.UTF8.GetString(data[offset..(offset + NameSize)]).TrimEnd('\0')); + Stage = Encoding.UTF8.GetString(data[offset..(offset + NameSize)]).TrimEnd('\0'); offset += NameSize; - Act = new string(Encoding.UTF8.GetString(data[offset..(offset + NameSize)]).TrimEnd('\0')); + Act = Encoding.UTF8.GetString(data[offset..(offset + NameSize)]).TrimEnd('\0'); offset += NameSize; - SubAct = new string(Encoding.UTF8.GetString(data[offset..(offset + NameSize)]).TrimEnd('\0')); + SubAct = Encoding.UTF8.GetString(data[offset..(offset + NameSize)]).TrimEnd('\0'); } } \ No newline at end of file diff --git a/Shared/Packet/Packets/ShinePacket.cs b/Shared/Packet/Packets/ShinePacket.cs index 353a1de..072bc00 100644 --- a/Shared/Packet/Packets/ShinePacket.cs +++ b/Shared/Packet/Packets/ShinePacket.cs @@ -5,11 +5,14 @@ namespace Shared.Packet.Packets; [Packet(PacketType.Shine)] public struct ShinePacket : IPacket { public int ShineId; + public bool IsGrand; public void Serialize(Span data) { MemoryMarshal.Write(data, ref ShineId); + MemoryMarshal.Write(data, ref IsGrand); } public void Deserialize(Span data) { ShineId = MemoryMarshal.Read(data); + IsGrand = MemoryMarshal.Read(data); } } \ No newline at end of file diff --git a/Shared/Packet/Packets/TagPacket.cs b/Shared/Packet/Packets/TagPacket.cs new file mode 100644 index 0000000..b94fbf4 --- /dev/null +++ b/Shared/Packet/Packets/TagPacket.cs @@ -0,0 +1,14 @@ +using System.Runtime.InteropServices; + +namespace Shared.Packet.Packets; + +public class TagPacket : IPacket { + public bool IsIt = false; + public void Serialize(Span data) { + MemoryMarshal.Write(data, ref IsIt); + } + + public void Deserialize(Span data) { + IsIt = MemoryMarshal.Read(data); + } +} \ No newline at end of file diff --git a/Shared/Shared.csproj b/Shared/Shared.csproj index b0d75bf..94fa761 100644 --- a/Shared/Shared.csproj +++ b/Shared/Shared.csproj @@ -4,6 +4,7 @@ net6.0 enable enable + true diff --git a/TestClient/Program.cs b/TestClient/Program.cs index a9ec173..30af137 100644 --- a/TestClient/Program.cs +++ b/TestClient/Program.cs @@ -32,7 +32,7 @@ async void Funny() { while (true) { d += Math.PI / 32; if (playerPacket == null) { - // logger.Warn($"Waiting..."); + // wait until valid player packet has arrived await Task.Delay(300); continue; } @@ -55,27 +55,30 @@ async Task S() { IMemoryOwner owner = MemoryPool.Shared.Rent(256); while (true) { await stream.ReadAsync(owner.Memory); - PacketHeader header = MemoryMarshal.Read(owner.Memory.Span); - if (header.Type == PacketType.Player) { - if (otherId == Guid.Empty) otherId = header.Id; - if (otherId != header.Id) continue; - if (e++ != 0) { - e %= 3; - continue; - } + unsafe { + + PacketHeader header = MemoryMarshal.Read(owner.Memory.Span); + if (header.Type == PacketType.Player) { + if (otherId == Guid.Empty) otherId = header.Id; + if (otherId != header.Id) continue; + if (e++ != 0) { + e %= 3; + continue; + } - header.Id = ownId; - MemoryMarshal.Write(owner.Memory.Span, ref header); - unsafe { + header.Id = ownId; + MemoryMarshal.Write(owner.Memory.Span, ref header); fixed (byte* data = owner.Memory.Span[Constants.HeaderSize..]) { logger.Error($"{Marshal.OffsetOf(nameof(PlayerPacket.AnimationBlendWeights))} {Marshal.OffsetOf(nameof(PlayerPacket.AnimationRate))}"); PlayerPacket packet = Marshal.PtrToStructure((IntPtr) data); playerPacket = packet; basePoint = packet.Position; } - } - // packet.SubAct = ""; + // packet.SubAct = ""; + } else if (header.Type == PacketType.Cap) { + + } } } }