Files
GameServer/MistoxServer/mPacket/DataPacket.cs
T
2026-08-04 07:56:25 -07:00

73 lines
2.8 KiB
C#

using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using MessagePack;
using Mistox.Attributes;
namespace Mistox {
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct DataPacketHeader {
public ushort Type { get; set; }
public ushort DataLength { get; set; }
}
public class DataPacket {
// The length of the packet header in bytes
public static int HeaderLength => Unsafe.SizeOf<DataPacketHeader>();
// Helper classes
public static byte[] Serialize<T>( T Object ) {
// Use an expandable buffer writer from the system stack
var writer = new ArrayBufferWriter<byte>(256);
// Advance the writer past the header slot so MessagePack doesn't overwrite it
writer.Advance(HeaderLength);
// Serialize the payload DIRECTLY into the final buffer memory
MessagePackSerializer.Serialize(writer, Object);
// Build our header struct on the stack
DataPacketHeader header = new DataPacketHeader {
Type = NetworkPacketDictionary.PacketIDTable[typeof(T)],
DataLength = (ushort)(writer.WrittenCount - HeaderLength)
};
// Map the struct directly onto the reservation we left at the front
writer.WrittenMemory.Slice(0, HeaderLength);
MemoryMarshal.Write(writer.GetSpan(HeaderLength).Slice(0, HeaderLength), in header);
// 7. Extract the finished byte array.
// Note: In a production socket pipeline, you would pass writer.WrittenMemory directly
// to the socket instead of converting it to an array here!
return writer.WrittenSpan.ToArray();
}
public static object Deserialize( DataPacketHeader Header, ReadOnlyMemory<byte> Data ) {
// Get the type from the tag
if (!NetworkPacketDictionary.PacketLookupTable.TryGetValue(Header.Type, out Type resolvedType)) {
throw new Exception($"Unknown packet type ID: {Header.Type}");
}
// Ensure the packet we received actually has the payload bytes it claims to have
if ( Header.DataLength < Data.Length ) {
throw new Exception("Malformed packet: Payload size mismatch.");
}
// Make sure the data is exactly the size requested
ReadOnlyMemory<byte> payloadSlice = Data.Slice(0, Header.DataLength);
// Create the low-level reader struct directly over the memory slice
var reader = new MessagePackReader(payloadSlice);
// Extract the object
return MessagePackSerializer.Deserialize( resolvedType, ref reader, MessagePackSerializerOptions.Standard );
}
}
}