using System; namespace XWorld.Framework.Protocol { public static class DevDiscovery { public const int Port = 48923; public const uint ProtoVersion = 1; public static readonly byte[] Magic = { 0x58, 0x57, 0x44, 0x4C }; public const byte TypeQuery = 1; public const byte TypeReply = 2; } public struct DevDiscoveryQuery { public uint ProtoVersion; public uint Nonce; public string Token; } public struct DevDiscoveryReply { public uint ProtoVersion; public uint Nonce; public string ServerName; public string GatewayUrl; public string ResourceBaseUrl; public string Token; } public static class DevDiscoveryCodec { public static byte[] EncodeQuery(DevDiscoveryQuery q) { var w = new PacketWriter(32); WriteHeader(w, DevDiscovery.TypeQuery); w.WriteVarUInt(q.ProtoVersion); w.WriteVarUInt(q.Nonce); w.WriteString(q.Token); return w.ToArray(); } public static byte[] EncodeReply(DevDiscoveryReply r) { var w = new PacketWriter(96); WriteHeader(w, DevDiscovery.TypeReply); w.WriteVarUInt(r.ProtoVersion); w.WriteVarUInt(r.Nonce); w.WriteString(r.ServerName); w.WriteString(r.GatewayUrl); w.WriteString(r.ResourceBaseUrl); w.WriteString(r.Token); return w.ToArray(); } public static bool TryDecodeQuery(byte[] data, out DevDiscoveryQuery q) { q = default; try { var r = new PacketReader(data); if (!ReadAndCheckHeader(r, DevDiscovery.TypeQuery)) return false; q.ProtoVersion = r.ReadVarUInt(); q.Nonce = r.ReadVarUInt(); q.Token = r.ReadString(); return true; } catch (FormatException) { return false; } } public static bool TryDecodeReply(byte[] data, out DevDiscoveryReply reply) { reply = default; try { var r = new PacketReader(data); if (!ReadAndCheckHeader(r, DevDiscovery.TypeReply)) return false; reply.ProtoVersion = r.ReadVarUInt(); reply.Nonce = r.ReadVarUInt(); reply.ServerName = r.ReadString(); reply.GatewayUrl = r.ReadString(); reply.ResourceBaseUrl = r.ReadString(); reply.Token = r.ReadString(); return true; } catch (FormatException) { return false; } } private static void WriteHeader(PacketWriter w, byte type) { for (int i = 0; i < DevDiscovery.Magic.Length; i++) { w.WriteByte(DevDiscovery.Magic[i]); } w.WriteByte(type); } private static bool ReadAndCheckHeader(PacketReader r, byte expectedType) { for (int i = 0; i < DevDiscovery.Magic.Length; i++) { if (r.ReadByte() != DevDiscovery.Magic[i]) return false; } return r.ReadByte() == expectedType; } } }