Tons of minor fixes
This commit is contained in:
1 parent
873a6fa455
commit
37a6b5d59b
12 files changed
+219
-147
No files matched your search
@@ -1,69 +1,81 @@
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using MessagePack;
|
||||
using Mistox.Attributes;
|
||||
|
||||
namespace Mistox {
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
||||
public struct DataPacketHeader {
|
||||
public byte Type { get; set; }
|
||||
public ushort DataLength { get; set; }
|
||||
}
|
||||
|
||||
public class DataPacket {
|
||||
|
||||
// The length of the packet header in bytes
|
||||
public static readonly int HeaderLength = 3;
|
||||
public static int HeaderLength => Unsafe.SizeOf<DataPacketHeader>();
|
||||
|
||||
// 8b. 16b. value of datalength
|
||||
// Data Packet [ Type | DataLength | Data ]
|
||||
|
||||
public DataPacketHeader Header { get; set; }
|
||||
public dynamic Data { get; set; }
|
||||
|
||||
// Helper classes
|
||||
public static byte[] Serialize<T>( T Object ) {
|
||||
|
||||
// Get your custom packet attribute to find the ID
|
||||
|
||||
// Get the attribute ID
|
||||
mPacket attribute = typeof(T).GetCustomAttribute<mPacket>(false);
|
||||
if (attribute == null) {
|
||||
throw new Exception($"The datastructure {typeof(T).Name} is not an mPacket");
|
||||
}
|
||||
|
||||
// Serialize the payload directly to a temporary byte array.
|
||||
byte[] payloadData = MessagePackSerializer.Serialize(Object);
|
||||
ushort dataLength = (ushort)payloadData.Length;
|
||||
// Use an expandable buffer writer from the system stack
|
||||
var writer = new ArrayBufferWriter<byte>(256);
|
||||
|
||||
// Allocate an array for the final output (1 byte Type + 2 bytes Length + Payload)
|
||||
byte[] finalPacket = new byte[HeaderLength + dataLength];
|
||||
// Advance the writer past the 3-byte header slot so MessagePack doesn't overwrite it
|
||||
writer.Advance(HeaderLength);
|
||||
|
||||
// Write the 3-byte header directly into the final array
|
||||
finalPacket[0] = attribute.ID;
|
||||
finalPacket[1] = (byte)((dataLength >> 8) & 0xFF); // High byte of ushort
|
||||
finalPacket[2] = (byte)(dataLength & 0xFF); // Low byte of ushort
|
||||
// Serialize the payload DIRECTLY into the final buffer memory
|
||||
MessagePackSerializer.Serialize(writer, Object);
|
||||
|
||||
// Copy the payload directly into the final array right after the header
|
||||
// This replaces all your .Join() allocations with a single ultra-fast CPU copy
|
||||
Buffer.BlockCopy(payloadData, 0, finalPacket, HeaderLength, dataLength);
|
||||
// Build our header struct on the stack
|
||||
DataPacketHeader header = new DataPacketHeader {
|
||||
Type = attribute.ID,
|
||||
DataLength = (ushort)(writer.WrittenCount - HeaderLength)
|
||||
};
|
||||
|
||||
return finalPacket;
|
||||
// Map the struct directly onto the 3-byte 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( byte PacketByte, ushort DataLength, ReadOnlyMemory<byte> Data ) {
|
||||
public static object Deserialize( DataPacketHeader Header, ReadOnlyMemory<byte> Data ) {
|
||||
|
||||
// Get the type from the tag
|
||||
if (!NetworkPacketDictionary.ServerToClientPackets.TryGetValue(PacketByte, out Type resolvedType)) {
|
||||
throw new Exception($"Unknown packet type ID: {PacketByte}");
|
||||
if (!NetworkPacketDictionary.ServerToClientPackets.TryGetValue(Header.Type, out Type resolvedType)) {
|
||||
throw new Exception($"Unknown packet type ID: {Header.Type}");
|
||||
}
|
||||
|
||||
// Sanity check: Ensure the packet we received actually has the payload bytes it claims to have
|
||||
if ( DataLength < Data.Length ) {
|
||||
// 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, DataLength);
|
||||
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
|
||||
dynamic obj = MessagePackSerializer.Deserialize( resolvedType, ref reader, MessagePackSerializerOptions.Standard );
|
||||
|
||||
return obj;
|
||||
return MessagePackSerializer.Deserialize( resolvedType, ref reader, MessagePackSerializerOptions.Standard );
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -5,21 +5,28 @@ using Mistox.Attributes;
|
||||
namespace Mistox.ResevedPackets {
|
||||
|
||||
[mPacket(0xFF)]
|
||||
public class EntityPacket {
|
||||
public ushort ObjectId { get; set; }
|
||||
public byte[] InnerPayload { get; set; }
|
||||
}
|
||||
|
||||
[mPacket(0xFE)]
|
||||
public class UserConnectedPacket {
|
||||
public string UserName { get; set; }
|
||||
public IPAddress ClientIPAddress { get; set; }
|
||||
public int ClientPort { get; set; }
|
||||
}
|
||||
|
||||
[mPacket(0xFE)]
|
||||
public class UserAuthPacket {
|
||||
public string UserName { get; set; } = "";
|
||||
public string ConnectionKey { get; set; } = "";
|
||||
public int AuthSuccessful { get; set; } = 0; // 0 is standard, -1 is auth failure, 1 is auth success
|
||||
}
|
||||
|
||||
[mPacket(0xFD)]
|
||||
public class EntityPacket {
|
||||
public ushort ObjectId { get; set; }
|
||||
public byte[] InnerPayload { get; set; }
|
||||
}
|
||||
|
||||
[mPacket(0xFC)]
|
||||
public class UserDisconnectedPacket {
|
||||
public UInt128 ConnectionKey { get; set; }
|
||||
public string UserName { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user