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:
parent
de16e4a787
commit
aa119c0b2f
12 changed files with 100 additions and 51 deletions
|
@ -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) {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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() ?? "";
|
||||||
|
}
|
||||||
}
|
}
|
23
Shared/Packet/Packets/CapPacket.cs
Normal file
23
Shared/Packet/Packets/CapPacket.cs
Normal 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');
|
||||||
|
}
|
||||||
|
}
|
19
Shared/Packet/Packets/CapturePacket.cs
Normal file
19
Shared/Packet/Packets/CapturePacket.cs
Normal 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..]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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'));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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..]));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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');
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
14
Shared/Packet/Packets/TagPacket.cs
Normal file
14
Shared/Packet/Packets/TagPacket.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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>
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue