diff --git a/Server/Server.cs b/Server/Server.cs index a51e0c9..2691259 100644 --- a/Server/Server.cs +++ b/Server/Server.cs @@ -11,7 +11,6 @@ public class Server { private readonly MemoryPool memoryPool = MemoryPool.Shared; public readonly List Clients = new List(); public readonly Logger Logger = new Logger("Server"); - private static int HeaderSize => Marshal.SizeOf(); public async Task Listen(ushort port) { TcpListener listener = TcpListener.Create(port); @@ -34,12 +33,12 @@ public class Server { Span data = memory.Span; MemoryMarshal.Write(data, ref header); - MemoryMarshal.Write(data[HeaderSize..], ref packet); + MemoryMarshal.Write(data[Constants.HeaderSize..], ref packet); } // broadcast packets to all clients public async void Broadcast(T packet, Client? sender = null) where T : unmanaged, IPacket { - IMemoryOwner memory = memoryPool.Rent(Marshal.SizeOf() + HeaderSize); + IMemoryOwner memory = memoryPool.Rent(Marshal.SizeOf() + Constants.HeaderSize); PacketHeader header = new PacketHeader { Id = sender?.Id ?? Guid.Empty, @@ -97,7 +96,7 @@ public class Server { throw new Exception($"First packet was not init, instead it was {header.Type}"); } - ConnectPacket connect = MemoryMarshal.Read(memory.Memory.Span[HeaderSize..size]); + ConnectPacket connect = MemoryMarshal.Read(memory.Memory.Span[Constants.HeaderSize..size]); lock (Clients) { switch (connect.ConnectionType) { case ConnectionTypes.FirstConnection: { @@ -136,7 +135,10 @@ public class Server { // todo support variable length packets when they show up - if (header.Sender == PacketSender.Client) await Broadcast(memory, client); + if (header.Sender == PacketSender.Client) { + Logger.Warn($"broadcasting {header.Type}"); + await Broadcast(memory, client); + } else { //todo handle server packets :) } diff --git a/Shared/Constants.cs b/Shared/Constants.cs index 7dcd911..b1a8545 100644 --- a/Shared/Constants.cs +++ b/Shared/Constants.cs @@ -1,4 +1,5 @@ using System.Reflection; +using System.Runtime.InteropServices; using Shared.Packet; using Shared.Packet.Packets; @@ -7,6 +8,7 @@ namespace Shared; public static class Constants { public const int MaxPacketSize = 256; public const int MaxClients = 4; + public static int HeaderSize => Marshal.SizeOf(); // dictionary of packet types to packet public static readonly Dictionary Packets = Assembly diff --git a/Shared/Packet/Packets/CommandPacket.cs b/Shared/Packet/Packets/CommandPacket.cs index 23a7174..00f6116 100644 --- a/Shared/Packet/Packets/CommandPacket.cs +++ b/Shared/Packet/Packets/CommandPacket.cs @@ -2,4 +2,11 @@ [Packet(PacketType.Command)] public struct CommandPacket : IPacket { + public void Serialize(Span data) { + + } + + public void Deserialize(Span data) { + + } } \ No newline at end of file diff --git a/Shared/Packet/Packets/ConnectPacket.cs b/Shared/Packet/Packets/ConnectPacket.cs index e02d78b..3d154af 100644 --- a/Shared/Packet/Packets/ConnectPacket.cs +++ b/Shared/Packet/Packets/ConnectPacket.cs @@ -1,6 +1,15 @@ -namespace Shared.Packet.Packets; +using System.Runtime.InteropServices; + +namespace Shared.Packet.Packets; [Packet(PacketType.Connect)] public struct ConnectPacket : IPacket { public ConnectionTypes ConnectionType; + public void Serialize(Span data) { + MemoryMarshal.Write(data, ref ConnectionType); + } + + public void Deserialize(Span data) { + ConnectionType = MemoryMarshal.Read(data); + } } \ No newline at end of file diff --git a/Shared/Packet/Packets/CostumePacket.cs b/Shared/Packet/Packets/CostumePacket.cs index 2080999..8a63f49 100644 --- a/Shared/Packet/Packets/CostumePacket.cs +++ b/Shared/Packet/Packets/CostumePacket.cs @@ -6,8 +6,17 @@ namespace Shared.Packet.Packets; public struct CostumePacket : IPacket { public const int CostumeNameSize = 0x20; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CostumeNameSize)] public string BodyName; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CostumeNameSize)] public string CapName; + public void Serialize(Span data) { + Span strData = MemoryMarshal.Cast(data); + BodyName.CopyTo(strData[..CostumeNameSize]); + CapName.CopyTo(strData[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')); + } } \ No newline at end of file diff --git a/Shared/Packet/Packets/DisconnectPacket.cs b/Shared/Packet/Packets/DisconnectPacket.cs index a266d2d..abbeeb7 100644 --- a/Shared/Packet/Packets/DisconnectPacket.cs +++ b/Shared/Packet/Packets/DisconnectPacket.cs @@ -2,4 +2,11 @@ [Packet(PacketType.Disconnect)] public struct DisconnectPacket : IPacket { + public void Serialize(Span data) { + + } + + public void Deserialize(Span data) { + + } } \ No newline at end of file diff --git a/Shared/Packet/Packets/IPacket.cs b/Shared/Packet/Packets/IPacket.cs index 7e12b64..2badf31 100644 --- a/Shared/Packet/Packets/IPacket.cs +++ b/Shared/Packet/Packets/IPacket.cs @@ -2,4 +2,6 @@ // Packet interface for type safety public interface IPacket { + void Serialize(Span data); + void Deserialize(Span data); } \ No newline at end of file diff --git a/Shared/Packet/Packets/PlayerPacket.cs b/Shared/Packet/Packets/PlayerPacket.cs index 16ac10a..a9662d6 100644 --- a/Shared/Packet/Packets/PlayerPacket.cs +++ b/Shared/Packet/Packets/PlayerPacket.cs @@ -1,7 +1,7 @@ using System.Numerics; using System.Runtime.InteropServices; -namespace Shared.Packet.Packets; +namespace Shared.Packet.Packets; [Packet(PacketType.Player)] public struct PlayerPacket : IPacket { @@ -9,17 +9,52 @@ public struct PlayerPacket : IPacket { public Vector3 Position; public Quaternion Rotation; - [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)] public float[] AnimationBlendWeights; public float AnimationRate; public bool Flat; public bool ThrowingCap; public bool Seeker; public int ScenarioNum; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NameSize)] public string Stage; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NameSize)] public string Act; - [MarshalAs(UnmanagedType.ByValTStr, SizeConst = NameSize)] public string SubAct; + + public void Serialize(Span data) { + int offset = 0; + MemoryMarshal.Write(data, ref Position); + offset += Marshal.SizeOf(); + MemoryMarshal.Write(data[offset..], ref Rotation); + offset += Marshal.SizeOf(); + AnimationBlendWeights.CopyTo(MemoryMarshal.Cast(data[offset..(offset += 4 * 6)])); + MemoryMarshal.Write(data[(offset += 4)..], ref AnimationRate); + offset += 4; + MemoryMarshal.Write(data[offset++..], ref Flat); + MemoryMarshal.Write(data[offset++..], ref ThrowingCap); + MemoryMarshal.Write(data[offset++..], ref Seeker); + MemoryMarshal.Write(data[(offset += 4)..], ref ScenarioNum); + Span strData = MemoryMarshal.Cast(data[offset..]); + Stage.CopyTo(strData[..NameSize]); + Act.CopyTo(strData[NameSize..(2 * NameSize)]); + SubAct.CopyTo(strData[(2 * NameSize)..(3 * NameSize)]); + } + + public void Deserialize(Span data) { + int offset = 0; + Position = MemoryMarshal.Read(data); + offset += Marshal.SizeOf(); + Rotation = MemoryMarshal.Read(data[offset..]); + offset += Marshal.SizeOf(); + AnimationBlendWeights = MemoryMarshal.Cast(data[offset..(offset + 4 * 6)]).ToArray(); + offset += 4 * 6; + AnimationRate = MemoryMarshal.Read(data[(offset += 4)..]); + offset += 4; + Flat = MemoryMarshal.Read(data[offset++..]); + ThrowingCap = MemoryMarshal.Read(data[offset++..]); + Seeker = MemoryMarshal.Read(data[offset++..]); + ScenarioNum = MemoryMarshal.Read(data[(offset += 4)..]); + Span strData = MemoryMarshal.Cast(data[offset..]); + Stage = new string(strData[..NameSize].TrimEnd('\0')); + Act = new string(strData[NameSize..(2 * NameSize)].TrimEnd('\0')); + SubAct = new string(strData[(2 * NameSize)..(3 * NameSize)].TrimEnd('\0')); + } } \ No newline at end of file diff --git a/Shared/Packet/Packets/ShinePacket.cs b/Shared/Packet/Packets/ShinePacket.cs index 9dab7fe..353a1de 100644 --- a/Shared/Packet/Packets/ShinePacket.cs +++ b/Shared/Packet/Packets/ShinePacket.cs @@ -1,6 +1,15 @@ -namespace Shared.Packet.Packets; +using System.Runtime.InteropServices; + +namespace Shared.Packet.Packets; [Packet(PacketType.Shine)] public struct ShinePacket : IPacket { public int ShineId; + public void Serialize(Span data) { + MemoryMarshal.Write(data, ref ShineId); + } + + public void Deserialize(Span data) { + ShineId = MemoryMarshal.Read(data); + } } \ No newline at end of file diff --git a/TestClient/Program.cs b/TestClient/Program.cs index e9f86e2..a748574 100644 --- a/TestClient/Program.cs +++ b/TestClient/Program.cs @@ -1,4 +1,7 @@ -using System.Net.Sockets; +using System.Buffers; +using System.Net.Sockets; +using System.Numerics; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using Shared; using Shared.Packet; @@ -8,9 +11,53 @@ TcpClient client = new TcpClient("127.0.0.1", 1027); Guid ownId = new Guid(); Logger logger = new Logger("Client"); NetworkStream stream = client.GetStream(); +PacketHeader coolHeader = new PacketHeader { + Type = PacketType.Connect, + Sender = PacketSender.Client, + Id = Guid.Empty +}; +int e = 0; +double d = 0; -// void WritePacket(Span data, IPacket packet) { -// MemoryMarshal.Write(); -// } -// stream.Write(); \ No newline at end of file +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 (e++ != 0) { + e %= 3; + continue; + } + + d += Math.PI; + for (int i = 0; i < 1; i++) { + unsafe { + coolHeader.Id = new Guid(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, (byte)i); + MemoryMarshal.Write(owner.Memory.Span, ref coolHeader); + // unbelievably shitty way to marshal playerpacket + fixed (byte* basePtr = owner.Memory.Span) { + byte* dataPtr = basePtr + Constants.HeaderSize; + Vector3 pos = Unsafe.Read(dataPtr); + pos.X += 1000f * (float)Math.Cos(d); + pos.Z += 1000f * (float)Math.Sin(d); + Unsafe.Write(dataPtr, pos); + } + } + // Console.WriteLine($"aargh {coolHeader.Id} {owner.Memory.Span.Hex()}"); + await stream.WriteAsync(owner.Memory); + } + } + } +} +IMemoryOwner owner = MemoryPool.Shared.Rent(256); +MemoryMarshal.Write(owner.Memory.Span[..], ref coolHeader); +ConnectPacket connect = new ConnectPacket { + ConnectionType = ConnectionTypes.FirstConnection +}; +MemoryMarshal.Write(owner.Memory.Span[Constants.HeaderSize..256], ref connect); +await stream.WriteAsync(owner.Memory); +coolHeader.Type = PacketType.Player; +MemoryMarshal.Write(owner.Memory.Span[..], ref coolHeader); +await S(); \ No newline at end of file diff --git a/TestClient/TestClient.csproj b/TestClient/TestClient.csproj index 7d518c2..ee81c78 100644 --- a/TestClient/TestClient.csproj +++ b/TestClient/TestClient.csproj @@ -5,6 +5,7 @@ net6.0 enable enable + true