Merge pull request #4 from VelocityRa/packing-fixes

This commit is contained in:
Sanae 2022-07-03 01:07:01 -06:00 committed by GitHub
commit e2f2f76669
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 86 additions and 17 deletions

View File

@ -1,8 +1,6 @@
using System.Buffers;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using Shared;
using Shared.Packet;
using Shared.Packet.Packets;
@ -50,6 +48,17 @@ public class Client : IDisposable {
Logger.Error(e);
}
#if DEBUG
Guid senderId = sender?.Id ?? Id;
string senderName = "?";
Client? client = Server.FindExistingClient(senderId);
if (client is not null) {
senderName = client.Name;
}
PacketUtils.LogPacket(packet, $"{senderName} -> (server)");
#endif
await Socket!.SendAsync(memory.Memory[..(Constants.HeaderSize + packet.Size)], SocketFlags.None);
memory.Dispose();
}

View File

@ -69,7 +69,6 @@ float MarioSize(bool is2d) => is2d ? 180 : 160;
server.PacketHandler = (c, p) => {
switch (p) {
case GamePacket gamePacket: {
c.Logger.Info($"Got game packet {gamePacket.Stage}->{gamePacket.ScenarioNum}");
c.Metadata["scenario"] = gamePacket.ScenarioNum;
c.Metadata["2d"] = gamePacket.Is2d;
c.Metadata["lastGamePacket"] = gamePacket;
@ -394,7 +393,7 @@ CommandHandler.RegisterCommand("maxplayers", args => {
});
CommandHandler.RegisterCommand("list",
_ => $"List: {string.Join("\n\t", server.Clients.Where(x => x.Connected).Select(x => $"{x.Name} ({x.Id})"))}");
_ => $"List: {string.Join("\n ", server.Clients.Where(x => x.Connected).Select(x => $"{x.Name} ({x.Id})"))}");
CommandHandler.RegisterCommand("flip", args => {
const string optionUsage =

View File

@ -1,7 +1,6 @@
using System.Buffers;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using Shared;
using Shared.Packet;
using Shared.Packet.Packets;
@ -79,10 +78,23 @@ public class Server {
PacketSize = packet.Size
};
FillPacket(header, packet, memory.Memory);
#if DEBUG
Guid senderId = sender?.Id ?? Guid.Empty;
string senderName = "?";
Client? client = FindExistingClient(senderId);
if (client != null)
senderName = client.Name;
PacketUtils.LogPacket(packet, $"{senderName} -> (all)");
#endif
await Broadcast(memory, sender);
}
public Task Broadcast<T>(T packet) where T : struct, IPacket {
#if DEBUG
PacketUtils.LogPacket(packet, "BRDC");
#endif
return Task.WhenAll(Clients.Where(c => c.Connected).Select(async client => {
IMemoryOwner<byte> memory = MemoryPool<byte>.Shared.RentZero(Constants.HeaderSize + packet.Size);
PacketHeader header = new PacketHeader {
@ -242,12 +254,18 @@ public class Server {
ClientName = other.Name
};
connectPacket.Serialize(tempBuffer.Memory.Span[Constants.HeaderSize..]);
#if DEBUG
PacketUtils.LogPacket(connectPacket, $"{client.Name} -> {other.Name}");
#endif
await client.Send(tempBuffer.Memory[..(Constants.HeaderSize + connect.Size)], null);
if (other.CurrentCostume.HasValue) {
connectHeader.Type = PacketType.Costume;
connectHeader.PacketSize = other.CurrentCostume.Value.Size;
connectHeader.Serialize(tempBuffer.Memory.Span[..Constants.HeaderSize]);
other.CurrentCostume.Value.Serialize(tempBuffer.Memory.Span[Constants.HeaderSize..(Constants.HeaderSize + connectHeader.PacketSize)]);
#if DEBUG
PacketUtils.LogPacket((CostumePacket)other.CurrentCostume, $"{client.Name} -> {other.Name}");
#endif
await client.Send(tempBuffer.Memory[..(Constants.HeaderSize + connectHeader.PacketSize)], null);
}
@ -256,7 +274,7 @@ public class Server {
Logger.Info($"Client {client.Name} ({client.Id}/{socket.RemoteEndPoint}) connected.");
} else if (header.Id != client.Id && client.Id != Guid.Empty) {
throw new Exception($"Client {client.Name} sent packet with invalid client id {header.Id} instead of {client.Id}");
throw new Exception($"Client {client.Name} sent packet {header.Type} with invalid client id {header.Id} instead of {client.Id}");
}
if (header.Type == PacketType.Costume) {
@ -270,6 +288,11 @@ public class Server {
try {
IPacket packet = (IPacket) Activator.CreateInstance(Constants.PacketIdMap[header.Type])!;
packet.Deserialize(memory.Memory.Span[Constants.HeaderSize..(Constants.HeaderSize + packet.Size)]);
#if DEBUG
PacketUtils.LogPacket(packet, $"{FindExistingClient(header.Id)!.Name} -> (server)");
#endif
if (PacketHandler?.Invoke(client, packet) is false) {
memory.Dispose();
continue;
@ -279,6 +302,12 @@ public class Server {
client.Logger.Error($"Packet handler warning: {e}");
}
#if DEBUG
if (header.Type is not (PacketType.Player or PacketType.Cap)) {
PacketUtils.LogPacketSame($"{client.Name} -> (all)");
}
#endif
Broadcast(memory, client);
}
}

View File

@ -9,9 +9,11 @@ public class Logger {
public string Name { get; set; }
public void Info(string text) => Handler?.Invoke(Name, "Info", text, ConsoleColor.White);
public void Debug(string text) => Handler?.Invoke(Name, "Debug", text, ConsoleColor.White);
public void Warn(string text) => Handler?.Invoke(Name, "Warn", text, ConsoleColor.Yellow);
public void Info(string text) => Handler?.Invoke(Name, "Info ", text, ConsoleColor.Cyan);
public void Warn(string text) => Handler?.Invoke(Name, "Warn ", text, ConsoleColor.Yellow);
public void Error(string text) => Handler?.Invoke(Name, "Error", text, ConsoleColor.Red);

View File

@ -1,4 +1,5 @@
using System.Runtime.InteropServices;
using System.Reflection;
using System.Runtime.InteropServices;
using Shared.Packet.Packets;
namespace Shared.Packet;
@ -18,4 +19,29 @@ public static class PacketUtils {
public static int SizeOf<T>() where T : struct, IPacket {
return Constants.HeaderSize + Marshal.SizeOf<T>();
}
public static void LogPacket<T>(T packet, string tag) where T : IPacket {
if (packet is PlayerPacket or CapPacket) // These are too spammy
return;
Type packetType = packet.GetType();
FieldInfo[] fields = packetType.GetFields();
string prefix = $"{{{DateTime.Now}}} Debug";
string msg = $"{prefix} [{tag}] {packetType.Name} {{\n";
foreach (FieldInfo field in fields)
{
msg += $"{prefix} {field.Name} = {field.GetValue(packet)}\n";
}
Console.ForegroundColor = ConsoleColor.White;
Console.Write(msg);
}
public static void LogPacketSame(string tag) {
string prefix = $"{{{DateTime.Now}}} Debug";
string msg = $"{prefix} [{tag}] {{same}}\n";
Console.ForegroundColor = ConsoleColor.White;
Console.Write(msg);
}
}

View File

@ -12,19 +12,19 @@ public struct CapPacket : IPacket {
public bool CapOut;
public string CapAnim;
public short Size => 0x50;
public short Size => 29 + NameSize;
public void Serialize(Span<byte> data) {
MemoryMarshal.Write(data, ref Position);
MemoryMarshal.Write(data[12..], ref Rotation);
MemoryMarshal.Write(data[28..], ref CapOut);
Encoding.UTF8.GetBytes(CapAnim).CopyTo(data[32..(32 + NameSize)]);
Encoding.UTF8.GetBytes(CapAnim).CopyTo(data[29..(29 + NameSize)]);
}
public void Deserialize(ReadOnlySpan<byte> data) {
Position = MemoryMarshal.Read<Vector3>(data);
Rotation = MemoryMarshal.Read<Quaternion>(data[12..]);
CapOut = MemoryMarshal.Read<bool>(data[28..]);
CapAnim = Encoding.UTF8.GetString(data[32..(32 + NameSize)]).TrimEnd('\0');
CapAnim = Encoding.UTF8.GetString(data[29..(29 + NameSize)]).TrimEnd('\0');
}
}

View File

@ -12,7 +12,8 @@ public struct GamePacket : IPacket {
public GamePacket() { }
public short Size => 0x42;
public short Size => 2 + StageSize;
public void Serialize(Span<byte> data) {
MemoryMarshal.Write(data, ref Is2d);
MemoryMarshal.Write(data[1..], ref ScenarioNum);

View File

@ -5,14 +5,17 @@ namespace Shared.Packet.Packets;
[Packet(PacketType.Shine)]
public struct ShinePacket : IPacket {
public int ShineId;
public bool IsGrand;
public short Size => 4;
public short Size => 5;
public void Serialize(Span<byte> data) {
MemoryMarshal.Write(data, ref ShineId);
MemoryMarshal.Write(data[1..], ref IsGrand);
}
public void Deserialize(ReadOnlySpan<byte> data) {
ShineId = MemoryMarshal.Read<int>(data);
IsGrand = MemoryMarshal.Read<bool>(data[1..]);
}
}

View File

@ -9,20 +9,20 @@ public struct TagPacket : IPacket {
public byte Seconds;
public ushort Minutes;
public short Size => 6;
public short Size => 5;
public void Serialize(Span<byte> data) {
MemoryMarshal.Write(data, ref UpdateType);
MemoryMarshal.Write(data[1..], ref IsIt);
MemoryMarshal.Write(data[2..], ref Seconds);
MemoryMarshal.Write(data[4..], ref Minutes);
MemoryMarshal.Write(data[3..], ref Minutes);
}
public void Deserialize(ReadOnlySpan<byte> data) {
UpdateType = MemoryMarshal.Read<TagUpdate>(data);
IsIt = MemoryMarshal.Read<bool>(data[1..]);
Seconds = MemoryMarshal.Read<byte>(data[2..]);
Minutes = MemoryMarshal.Read<ushort>(data[4..]);
Minutes = MemoryMarshal.Read<ushort>(data[3..]);
}
[Flags]