0
0
Fork 0
mirror of https://github.com/Sanae6/SmoOnlineServer.git synced 2024-11-25 04:35:18 +00:00

Catch up with crafty's current protocol

This commit is contained in:
Sanae 2022-02-08 10:15:31 -06:00
parent de16e4a787
commit aa119c0b2f
12 changed files with 100 additions and 51 deletions

View file

@ -151,16 +151,15 @@ public class Server {
Logger.Info($"Client {socket.RemoteEndPoint} disconnected from the server"); Logger.Info($"Client {socket.RemoteEndPoint} disconnected from the server");
} else { } else {
Logger.Error($"Exception on socket {socket.RemoteEndPoint}, disconnecting for: {e}"); Logger.Error($"Exception on socket {socket.RemoteEndPoint}, disconnecting for: {e}");
await socket.DisconnectAsync(false); Task.Run(() => socket.DisconnectAsync(false));
} }
memory?.Dispose(); memory?.Dispose();
} }
Clients.Remove(client); Clients.Remove(client);
Broadcast(new DisconnectPacket(), client).ContinueWith(_ => { client.Dispose();
client.Dispose(); Task.Run(() => Broadcast(new DisconnectPacket(), client));
});
} }
private static PacketHeader GetHeader(Span<byte> data) { private static PacketHeader GetHeader(Span<byte> data) {

View file

@ -9,6 +9,7 @@ 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 { get; } = Marshal.SizeOf<PacketHeader>(); public static int HeaderSize { get; } = Marshal.SizeOf<PacketHeader>();
public const int CostumeNameSize = 0x20;
// 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

@ -8,4 +8,12 @@ public static class Extensions {
} }
public static string Hex(this IEnumerable<byte> array) => string.Join(' ', array.ToArray().Select(x => x.ToString("X2"))); public static string Hex(this IEnumerable<byte> array) => string.Join(' ', array.ToArray().Select(x => x.ToString("X2")));
public static unsafe byte* Ptr(this Span<byte> span) {
fixed (byte* data = span) return data;
}
public static string TrimNullTerm(this string text) {
return text.Split('\0').FirstOrDefault() ?? "";
}
} }

View file

@ -0,0 +1,23 @@
using System.Numerics;
using System.Runtime.InteropServices;
using System.Text;
namespace Shared.Packet.Packets;
public class CapPacket : IPacket {
public const int NameSize = 0x30;
public Vector3 Position;
public Quaternion Rotation;
public string CapAnim;
public void Serialize(Span<byte> data) {
MemoryMarshal.Write(data, ref Position);
MemoryMarshal.Write(data[12..], ref Position);
Encoding.UTF8.GetBytes(CapAnim).CopyTo(data[28..]);
}
public void Deserialize(Span<byte> data) {
Position = MemoryMarshal.Read<Vector3>(data);
Rotation = MemoryMarshal.Read<Quaternion>(data[12..]);
CapAnim = Encoding.UTF8.GetString(data[28..]).TrimEnd('\0');
}
}

View file

@ -0,0 +1,19 @@
using System.Runtime.InteropServices;
using System.Text;
namespace Shared.Packet.Packets;
public class CapturePacket : IPacket {
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.CostumeNameSize)]
public string ModelName;
public bool IsCaptured;
public void Serialize(Span<byte> data) {
Encoding.UTF8.GetBytes(ModelName).CopyTo(data[..Constants.CostumeNameSize]);
MemoryMarshal.Write(data[Constants.CostumeNameSize..], ref IsCaptured);
}
public void Deserialize(Span<byte> data) {
ModelName = Encoding.UTF8.GetString(data[..Constants.CostumeNameSize]).TrimNullTerm();
IsCaptured = MemoryMarshal.Read<bool>(data[Constants.CostumeNameSize..]);
}
}

View file

@ -1,24 +1,21 @@
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text;
namespace Shared.Packet.Packets; namespace Shared.Packet.Packets;
[Packet(PacketType.Costume)] [Packet(PacketType.Costume)]
public struct CostumePacket : IPacket { public struct CostumePacket : IPacket {
public const int CostumeNameSize = 0x20; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.CostumeNameSize)]
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CostumeNameSize)]
public string BodyName; public string BodyName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CostumeNameSize)] [MarshalAs(UnmanagedType.ByValTStr, SizeConst = Constants.CostumeNameSize)]
public string CapName; public string CapName;
public void Serialize(Span<byte> data) { public void Serialize(Span<byte> data) {
Span<char> strData = MemoryMarshal.Cast<byte, char>(data); Encoding.UTF8.GetBytes(BodyName).CopyTo(data[..Constants.CostumeNameSize]);
BodyName.CopyTo(strData[..CostumeNameSize]); Encoding.UTF8.GetBytes(CapName).CopyTo(data[Constants.CostumeNameSize..]);
CapName.CopyTo(strData[CostumeNameSize..]);
} }
public void Deserialize(Span<byte> data) { public void Deserialize(Span<byte> data) {
Span<char> strData = MemoryMarshal.Cast<byte, char>(data); BodyName = Encoding.UTF8.GetString(data[..Constants.CostumeNameSize]).TrimNullTerm();
BodyName = new string(strData[..CostumeNameSize].TrimEnd('\0')); CapName = Encoding.UTF8.GetString(data[Constants.CostumeNameSize..]).TrimNullTerm();
CapName = new string(strData[CostumeNameSize..].TrimEnd('\0'));
} }
} }

View file

@ -1,19 +0,0 @@
using System.Runtime.InteropServices;
namespace Shared.Packet.Packets;
public class GamePacket : IPacket {
public int ScenarioNum;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = PlayerPacket.NameSize)]
public string Stage;
public void Serialize(Span<byte> data) {
MemoryMarshal.Write(data, ref ScenarioNum);
Stage.CopyTo(MemoryMarshal.Cast<byte, char>(data[4..]));
}
public void Deserialize(Span<byte> data) {
ScenarioNum = MemoryMarshal.Read<int>(data);
Stage = new string(MemoryMarshal.Cast<byte, char>(data[4..]));
}
}

View file

@ -1,4 +1,5 @@
using System.Numerics; using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Text; using System.Text;
@ -38,7 +39,6 @@ public struct PlayerPacket : IPacket {
MemoryMarshal.Write(data[offset++..], ref IsIt); MemoryMarshal.Write(data[offset++..], ref IsIt);
MemoryMarshal.Write(data[offset..], ref ScenarioNum); MemoryMarshal.Write(data[offset..], ref ScenarioNum);
offset += 5; offset += 5;
// Span<char> strData = MemoryMarshal.Cast<byte, char>(data[offset..]);
Encoding.UTF8.GetBytes(Stage).CopyTo(data[offset..(offset + NameSize)]); Encoding.UTF8.GetBytes(Stage).CopyTo(data[offset..(offset + NameSize)]);
offset += NameSize; offset += NameSize;
Encoding.UTF8.GetBytes(Act).CopyTo(data[offset..(offset + NameSize)]); Encoding.UTF8.GetBytes(Act).CopyTo(data[offset..(offset + NameSize)]);
@ -60,10 +60,10 @@ public struct PlayerPacket : IPacket {
// offset++; // padding // offset++; // padding
ScenarioNum = MemoryMarshal.Read<int>(data[offset..]); ScenarioNum = MemoryMarshal.Read<int>(data[offset..]);
offset += 5; offset += 5;
Stage = new string(Encoding.UTF8.GetString(data[offset..(offset + NameSize)]).TrimEnd('\0')); Stage = Encoding.UTF8.GetString(data[offset..(offset + NameSize)]).TrimEnd('\0');
offset += NameSize; offset += NameSize;
Act = new string(Encoding.UTF8.GetString(data[offset..(offset + NameSize)]).TrimEnd('\0')); Act = Encoding.UTF8.GetString(data[offset..(offset + NameSize)]).TrimEnd('\0');
offset += NameSize; offset += NameSize;
SubAct = new string(Encoding.UTF8.GetString(data[offset..(offset + NameSize)]).TrimEnd('\0')); SubAct = Encoding.UTF8.GetString(data[offset..(offset + NameSize)]).TrimEnd('\0');
} }
} }

View file

@ -5,11 +5,14 @@ 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 bool IsGrand;
public void Serialize(Span<byte> data) { public void Serialize(Span<byte> data) {
MemoryMarshal.Write(data, ref ShineId); MemoryMarshal.Write(data, ref ShineId);
MemoryMarshal.Write(data, ref IsGrand);
} }
public void Deserialize(Span<byte> data) { public void Deserialize(Span<byte> data) {
ShineId = MemoryMarshal.Read<int>(data); ShineId = MemoryMarshal.Read<int>(data);
IsGrand = MemoryMarshal.Read<bool>(data);
} }
} }

View file

@ -0,0 +1,14 @@
using System.Runtime.InteropServices;
namespace Shared.Packet.Packets;
public class TagPacket : IPacket {
public bool IsIt = false;
public void Serialize(Span<byte> data) {
MemoryMarshal.Write(data, ref IsIt);
}
public void Deserialize(Span<byte> data) {
IsIt = MemoryMarshal.Read<bool>(data);
}
}

View file

@ -4,6 +4,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>

View file

@ -32,7 +32,7 @@ async void Funny() {
while (true) { while (true) {
d += Math.PI / 32; d += Math.PI / 32;
if (playerPacket == null) { if (playerPacket == null) {
// logger.Warn($"Waiting..."); // wait until valid player packet has arrived
await Task.Delay(300); await Task.Delay(300);
continue; continue;
} }
@ -55,27 +55,30 @@ async Task S() {
IMemoryOwner<byte> owner = MemoryPool<byte>.Shared.Rent(256); IMemoryOwner<byte> owner = MemoryPool<byte>.Shared.Rent(256);
while (true) { while (true) {
await stream.ReadAsync(owner.Memory); await stream.ReadAsync(owner.Memory);
PacketHeader header = MemoryMarshal.Read<PacketHeader>(owner.Memory.Span); unsafe {
if (header.Type == PacketType.Player) {
if (otherId == Guid.Empty) otherId = header.Id;
if (otherId != header.Id) continue;
if (e++ != 0) {
e %= 3;
continue;
}
header.Id = ownId; PacketHeader header = MemoryMarshal.Read<PacketHeader>(owner.Memory.Span);
MemoryMarshal.Write(owner.Memory.Span, ref header); if (header.Type == PacketType.Player) {
unsafe { if (otherId == Guid.Empty) otherId = header.Id;
if (otherId != header.Id) continue;
if (e++ != 0) {
e %= 3;
continue;
}
header.Id = ownId;
MemoryMarshal.Write(owner.Memory.Span, ref header);
fixed (byte* data = owner.Memory.Span[Constants.HeaderSize..]) { fixed (byte* data = owner.Memory.Span[Constants.HeaderSize..]) {
logger.Error($"{Marshal.OffsetOf<PlayerPacket>(nameof(PlayerPacket.AnimationBlendWeights))} {Marshal.OffsetOf<PlayerPacket>(nameof(PlayerPacket.AnimationRate))}"); logger.Error($"{Marshal.OffsetOf<PlayerPacket>(nameof(PlayerPacket.AnimationBlendWeights))} {Marshal.OffsetOf<PlayerPacket>(nameof(PlayerPacket.AnimationRate))}");
PlayerPacket packet = Marshal.PtrToStructure<PlayerPacket>((IntPtr) data); PlayerPacket packet = Marshal.PtrToStructure<PlayerPacket>((IntPtr) data);
playerPacket = packet; playerPacket = packet;
basePoint = packet.Position; basePoint = packet.Position;
} }
}
// packet.SubAct = ""; // packet.SubAct = "";
} else if (header.Type == PacketType.Cap) {
}
} }
} }
} }