0
0
Fork 0
mirror of https://github.com/Sanae6/SmoOnlineServer.git synced 2024-11-28 14:13:05 +00:00

Update TestClient and add custom ser/deser for packets

This commit is contained in:
Sanae 2021-11-29 12:09:12 -06:00
parent 6afb232953
commit eaa03467e6
11 changed files with 149 additions and 19 deletions

View file

@ -11,7 +11,6 @@ public class Server {
private readonly MemoryPool<byte> memoryPool = MemoryPool<byte>.Shared; private readonly MemoryPool<byte> memoryPool = MemoryPool<byte>.Shared;
public readonly List<Client> Clients = new List<Client>(); public readonly List<Client> Clients = new List<Client>();
public readonly Logger Logger = new Logger("Server"); public readonly Logger Logger = new Logger("Server");
private static int HeaderSize => Marshal.SizeOf<PacketHeader>();
public async Task Listen(ushort port) { public async Task Listen(ushort port) {
TcpListener listener = TcpListener.Create(port); TcpListener listener = TcpListener.Create(port);
@ -34,12 +33,12 @@ public class Server {
Span<byte> data = memory.Span; Span<byte> data = memory.Span;
MemoryMarshal.Write(data, ref header); MemoryMarshal.Write(data, ref header);
MemoryMarshal.Write(data[HeaderSize..], ref packet); MemoryMarshal.Write(data[Constants.HeaderSize..], ref packet);
} }
// broadcast packets to all clients // broadcast packets to all clients
public async void Broadcast<T>(T packet, Client? sender = null) where T : unmanaged, IPacket { public async void Broadcast<T>(T packet, Client? sender = null) where T : unmanaged, IPacket {
IMemoryOwner<byte> memory = memoryPool.Rent(Marshal.SizeOf<T>() + HeaderSize); IMemoryOwner<byte> memory = memoryPool.Rent(Marshal.SizeOf<T>() + Constants.HeaderSize);
PacketHeader header = new PacketHeader { PacketHeader header = new PacketHeader {
Id = sender?.Id ?? Guid.Empty, 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}"); throw new Exception($"First packet was not init, instead it was {header.Type}");
} }
ConnectPacket connect = MemoryMarshal.Read<ConnectPacket>(memory.Memory.Span[HeaderSize..size]); ConnectPacket connect = MemoryMarshal.Read<ConnectPacket>(memory.Memory.Span[Constants.HeaderSize..size]);
lock (Clients) { lock (Clients) {
switch (connect.ConnectionType) { switch (connect.ConnectionType) {
case ConnectionTypes.FirstConnection: { case ConnectionTypes.FirstConnection: {
@ -136,7 +135,10 @@ public class Server {
// todo support variable length packets when they show up // 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 { else {
//todo handle server packets :) //todo handle server packets :)
} }

View file

@ -1,4 +1,5 @@
using System.Reflection; using System.Reflection;
using System.Runtime.InteropServices;
using Shared.Packet; using Shared.Packet;
using Shared.Packet.Packets; using Shared.Packet.Packets;
@ -7,6 +8,7 @@ namespace Shared;
public static class Constants { public static class Constants {
public const int MaxPacketSize = 256; public const int MaxPacketSize = 256;
public const int MaxClients = 4; public const int MaxClients = 4;
public static int HeaderSize => Marshal.SizeOf<PacketHeader>();
// dictionary of packet types to packet // dictionary of packet types to packet
public static readonly Dictionary<Type, PacketAttribute> Packets = Assembly public static readonly Dictionary<Type, PacketAttribute> Packets = Assembly

View file

@ -2,4 +2,11 @@
[Packet(PacketType.Command)] [Packet(PacketType.Command)]
public struct CommandPacket : IPacket { public struct CommandPacket : IPacket {
public void Serialize(Span<byte> data) {
}
public void Deserialize(Span<byte> data) {
}
} }

View file

@ -1,6 +1,15 @@
namespace Shared.Packet.Packets; using System.Runtime.InteropServices;
namespace Shared.Packet.Packets;
[Packet(PacketType.Connect)] [Packet(PacketType.Connect)]
public struct ConnectPacket : IPacket { public struct ConnectPacket : IPacket {
public ConnectionTypes ConnectionType; public ConnectionTypes ConnectionType;
public void Serialize(Span<byte> data) {
MemoryMarshal.Write(data, ref ConnectionType);
}
public void Deserialize(Span<byte> data) {
ConnectionType = MemoryMarshal.Read<ConnectionTypes>(data);
}
} }

View file

@ -6,8 +6,17 @@ namespace Shared.Packet.Packets;
public struct CostumePacket : IPacket { public struct CostumePacket : IPacket {
public const int CostumeNameSize = 0x20; public const int CostumeNameSize = 0x20;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CostumeNameSize)]
public string BodyName; public string BodyName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CostumeNameSize)]
public string CapName; public string CapName;
public void Serialize(Span<byte> data) {
Span<char> strData = MemoryMarshal.Cast<byte, char>(data);
BodyName.CopyTo(strData[..CostumeNameSize]);
CapName.CopyTo(strData[CostumeNameSize..]);
}
public void Deserialize(Span<byte> data) {
Span<char> strData = MemoryMarshal.Cast<byte, char>(data);
BodyName = new string(strData[..CostumeNameSize].TrimEnd('\0'));
CapName = new string(strData[CostumeNameSize..].TrimEnd('\0'));
}
} }

View file

@ -2,4 +2,11 @@
[Packet(PacketType.Disconnect)] [Packet(PacketType.Disconnect)]
public struct DisconnectPacket : IPacket { public struct DisconnectPacket : IPacket {
public void Serialize(Span<byte> data) {
}
public void Deserialize(Span<byte> data) {
}
} }

View file

@ -2,4 +2,6 @@
// Packet interface for type safety // Packet interface for type safety
public interface IPacket { public interface IPacket {
void Serialize(Span<byte> data);
void Deserialize(Span<byte> data);
} }

View file

@ -9,17 +9,52 @@ public struct PlayerPacket : IPacket {
public Vector3 Position; public Vector3 Position;
public Quaternion Rotation; public Quaternion Rotation;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public float[] AnimationBlendWeights; public float[] AnimationBlendWeights;
public float AnimationRate; public float AnimationRate;
public bool Flat; public bool Flat;
public bool ThrowingCap; public bool ThrowingCap;
public bool Seeker; public bool Seeker;
public int ScenarioNum; public int ScenarioNum;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = NameSize)]
public string Stage; public string Stage;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = NameSize)]
public string Act; public string Act;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = NameSize)]
public string SubAct; public string SubAct;
public void Serialize(Span<byte> data) {
int offset = 0;
MemoryMarshal.Write(data, ref Position);
offset += Marshal.SizeOf<Vector3>();
MemoryMarshal.Write(data[offset..], ref Rotation);
offset += Marshal.SizeOf<Quaternion>();
AnimationBlendWeights.CopyTo(MemoryMarshal.Cast<byte, float>(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<char> strData = MemoryMarshal.Cast<byte, char>(data[offset..]);
Stage.CopyTo(strData[..NameSize]);
Act.CopyTo(strData[NameSize..(2 * NameSize)]);
SubAct.CopyTo(strData[(2 * NameSize)..(3 * NameSize)]);
}
public void Deserialize(Span<byte> data) {
int offset = 0;
Position = MemoryMarshal.Read<Vector3>(data);
offset += Marshal.SizeOf<Vector3>();
Rotation = MemoryMarshal.Read<Quaternion>(data[offset..]);
offset += Marshal.SizeOf<Quaternion>();
AnimationBlendWeights = MemoryMarshal.Cast<byte, float>(data[offset..(offset + 4 * 6)]).ToArray();
offset += 4 * 6;
AnimationRate = MemoryMarshal.Read<float>(data[(offset += 4)..]);
offset += 4;
Flat = MemoryMarshal.Read<bool>(data[offset++..]);
ThrowingCap = MemoryMarshal.Read<bool>(data[offset++..]);
Seeker = MemoryMarshal.Read<bool>(data[offset++..]);
ScenarioNum = MemoryMarshal.Read<int>(data[(offset += 4)..]);
Span<char> strData = MemoryMarshal.Cast<byte, char>(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'));
}
} }

View file

@ -1,6 +1,15 @@
namespace Shared.Packet.Packets; using System.Runtime.InteropServices;
namespace Shared.Packet.Packets;
[Packet(PacketType.Shine)] [Packet(PacketType.Shine)]
public struct ShinePacket : IPacket { public struct ShinePacket : IPacket {
public int ShineId; public int ShineId;
public void Serialize(Span<byte> data) {
MemoryMarshal.Write(data, ref ShineId);
}
public void Deserialize(Span<byte> data) {
ShineId = MemoryMarshal.Read<int>(data);
}
} }

View file

@ -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 System.Runtime.InteropServices;
using Shared; using Shared;
using Shared.Packet; using Shared.Packet;
@ -8,9 +11,53 @@ TcpClient client = new TcpClient("127.0.0.1", 1027);
Guid ownId = new Guid(); Guid ownId = new Guid();
Logger logger = new Logger("Client"); Logger logger = new Logger("Client");
NetworkStream stream = client.GetStream(); 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<byte> data, IPacket packet) { async Task S() {
// MemoryMarshal.Write(); IMemoryOwner<byte> owner = MemoryPool<byte>.Shared.Rent(256);
// } while (true) {
// stream.Write(); await stream.ReadAsync(owner.Memory);
PacketHeader header = MemoryMarshal.Read<PacketHeader>(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<Vector3>(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<byte> owner = MemoryPool<byte>.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();

View file

@ -5,6 +5,7 @@
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable> <Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>