using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Numerics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Text.RegularExpressions; using BombRushMP.Common.Networking; using Microsoft.CodeAnalysis; using Newtonsoft.Json; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyVersion("0.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BombRushMP.Common { public static class AprilCommon { public const string Tag = "april"; } public class AuthUser { [JsonProperty("Description")] private string _description = ""; [JsonProperty("UserKind")] private string _userKind = UserKinds.Player.ToString(); public string[] Tags = Array.Empty(); public int[] Badges = Array.Empty(); [JsonIgnore] public bool CanLurk { get { if (!IsModerator) { return HasTag("elite"); } return true; } } [JsonIgnore] public bool IsAdmin => UserKind == UserKinds.Admin; [JsonIgnore] public bool IsModerator { get { if (UserKind != UserKinds.Mod) { return UserKind == UserKinds.Admin; } return true; } } [JsonIgnore] public UserKinds UserKind { get { if (Enum.TryParse(_userKind, out var result)) { return result; } return UserKinds.Player; } set { _userKind = value.ToString(); } } public AuthUser(UserKinds userKind = UserKinds.Player, string[] tags = null, int[] badges = null, string description = "") { UserKind = userKind; Tags = tags; if (Tags == null) { Tags = Array.Empty(); } Badges = badges; if (Badges == null) { Badges = Array.Empty(); } _description = description; } public AuthUser() { } public bool HasTag(string tag) { return Tags.Contains(tag); } public void Write(BinaryWriter writer) { writer.Write((int)UserKind); writer.Write(Tags.Length); string[] tags = Tags; foreach (string value in tags) { writer.Write(value); } writer.Write(Badges.Length); int[] badges = Badges; foreach (int value2 in badges) { writer.Write(value2); } } public void Read(BinaryReader reader) { UserKind = (UserKinds)reader.ReadInt32(); int num = reader.ReadInt32(); Tags = new string[num]; for (int i = 0; i < num; i++) { Tags[i] = reader.ReadString(); } int num2 = reader.ReadInt32(); Badges = new int[num2]; for (int j = 0; j < num2; j++) { Badges[j] = reader.ReadInt32(); } } public static string HashPassword(string password, string salt) { byte[] bytes = Encoding.UTF8.GetBytes(salt); byte[] bytes2 = Encoding.UTF8.GetBytes(password); using HMACSHA256 hMACSHA = new HMACSHA256(bytes); return Convert.ToBase64String(hMACSHA.ComputeHash(bytes2)); } } public struct Bitfield { private bool[] _values; public bool this[Enum key] { get { return GetValue(key); } set { SetValue(key, value); } } public Bitfield(Enum size) { _values = Array.Empty(); _values = new bool[Convert.ToInt32(size)]; } public Bitfield(int size) { _values = Array.Empty(); _values = new bool[size]; } public static Bitfield ReadByte(BinaryReader reader) { byte b = reader.ReadByte(); int num = 8; Bitfield result = new Bitfield(num); for (int i = 0; i < num; i++) { byte b2 = (byte)(1 << i); result._values[i] = (b & b2) != 0; } return result; } public static Bitfield ReadShort(BinaryReader reader) { short num = reader.ReadInt16(); int num2 = 16; Bitfield result = new Bitfield(num2); for (int i = 0; i < num2; i++) { short num3 = (short)(1 << i); result._values[i] = (num & num3) != 0; } return result; } public static Bitfield ReadInteger(BinaryReader reader) { int num = reader.ReadInt32(); int num2 = 32; Bitfield result = new Bitfield(num2); for (int i = 0; i < num2; i++) { int num3 = 1 << i; result._values[i] = (num & num3) != 0; } return result; } public void WriteByte(BinaryWriter writer) { byte b = 0; for (int i = 0; i < _values.Length; i++) { if (_values[i]) { b |= (byte)(1 << i); } } writer.Write(b); } public void WriteShort(BinaryWriter writer) { short num = 0; for (int i = 0; i < _values.Length; i++) { if (_values[i]) { num |= (short)(1 << i); } } writer.Write(num); } public void WriteInteger(BinaryWriter writer) { int num = 0; for (int i = 0; i < _values.Length; i++) { if (_values[i]) { num |= 1 << i; } } writer.Write(num); } public bool GetValue(Enum index) { return _values[Convert.ToInt32(index)]; } public void SetValue(Enum index, bool value) { _values[Convert.ToInt32(index)] = value; } } public enum CharacterNames { Vinyl, Frank, Coil, Red, Tryce, Bel, Rave, DotExeMember, Solace, DjCyber, EclipseMember, DevilTheoryMember, FauxWithBoostPack, FleshPrince, Irene, Felix, OldHeadMember, Base, Jet, Mesh, FuturismMember, Rise, Shine, FauxWithoutBoostPack, DotExeBoss, FelixWithCyberHead } public enum ChatMessageTypes { Chat, PlayerJoinedOrLeft, System, PlayerAFK, ClearChat } public static class CommandUtility { public static string[] ParseArgs(string command, int argNumber) { string text = command.Split(new char[1] { ' ' })[0]; string text2 = command.Substring(text.Length).Trim(); string[] array = new string[argNumber]; for (int i = 0; i < argNumber; i++) { array[i] = ""; } bool flag = false; bool flag2 = false; int num = 0; string text3 = ""; for (int j = 0; j < text2.Length; j++) { char c = text2[j]; if (flag2) { text3 += c; flag2 = false; continue; } switch (c) { case ' ': if (num == argNumber - 1) { text3 += c; } else if (!flag) { if (!string.IsNullOrWhiteSpace(text3)) { array[num] = text3.Trim(); text3 = ""; num++; } } else { text3 += c; } break; case '"': if (flag) { if (!string.IsNullOrWhiteSpace(text3)) { array[num] = text3; text3 = ""; num++; flag = false; } } else { flag = true; } break; case '\\': flag2 = true; break; default: text3 += c; break; } } if (!string.IsNullOrWhiteSpace(text3) && num < argNumber) { array[num] = text3.Trim(); } return array; } } public static class Compression { private static MD5 Hasher = MD5.Create(); public static int HashString(string s) { return BitConverter.ToInt32(Hasher.ComputeHash(Encoding.UTF8.GetBytes(s)), 0); } public static sbyte CompressToByte(float value, float maxValue) { return CompressNormal(value / maxValue); } public static float DecompressFromByte(sbyte compressedValue, float maxValue) { return DecompressNormal(compressedValue) * maxValue; } public static sbyte CompressNormal(float normalValue) { return (sbyte)(normalValue * 127f); } public static float DecompressNormal(sbyte compressedValue) { return (float)compressedValue / 127f; } public static void WriteCompressedQuaternion(Quaternion quat, BinaryWriter writer) { writer.Write(CompressNormal(quat.X)); writer.Write(CompressNormal(quat.Y)); writer.Write(CompressNormal(quat.Z)); writer.Write(CompressNormal(quat.W)); } public static Quaternion ReadCompressedQuaternion(BinaryReader reader) { float x = DecompressNormal(reader.ReadSByte()); float y = DecompressNormal(reader.ReadSByte()); float z = DecompressNormal(reader.ReadSByte()); float w = DecompressNormal(reader.ReadSByte()); return new Quaternion(x, y, z, w); } public static void WriteCompressedVector3Normal(Vector3 vec, BinaryWriter writer) { writer.Write(CompressNormal(vec.X)); writer.Write(CompressNormal(vec.Y)); writer.Write(CompressNormal(vec.Z)); } public static Vector3 ReadCompressedVector3Normal(BinaryReader reader) { float x = DecompressNormal(reader.ReadSByte()); float y = DecompressNormal(reader.ReadSByte()); float z = DecompressNormal(reader.ReadSByte()); return new Vector3(x, y, z); } } public static class Constants { public const uint ProtocolVersion = 24u; public const float DefaultNetworkingTickRate = 1f / 32f; public const float ScoreBattleDuration = 180f; public const int MaxPayloadSize = 10000; public const char CommandChar = '/'; public const int MaxMessageLength = 256; public const int MaxNameLength = 64; public const int MaxCrewNameLength = 32; public const string PropHuntLockedTag = "phlocked"; } public enum GamemodeIDs { ScoreBattle, GraffitiRace, TeamGraffitiRace, ProSkaterScoreBattle, TeamScoreBattle, TeamProSkaterScoreBattle, PropHunt } public enum GenericEvents { Spray, Teleport, GraffitiGameOver, Death, Land } public static class ListExtensions { private static Random rng = new Random(); public static void Shuffle(this IList list) { int num = list.Count; while (num > 1) { num--; int index = rng.Next(num + 1); T value = list[index]; list[index] = list[num]; list[num] = value; } } } public class LobbyPlayer { public uint LobbyId; public ushort Id; public float Score; public bool Ready; public byte Team; public int Wins; public LobbyPlayer() { } public LobbyPlayer(uint lobbyId, ushort playerId, byte team) { LobbyId = lobbyId; Id = playerId; Team = team; } public void Write(BinaryWriter writer) { writer.Write(Id); writer.Write(Score); writer.Write(Ready); writer.Write(Team); writer.Write(Wins); } public void Read(BinaryReader reader) { Id = reader.ReadUInt16(); Score = reader.ReadSingle(); Ready = reader.ReadBoolean(); Team = reader.ReadByte(); Wins = reader.ReadInt32(); } } public class LobbyState { private enum BooleanMask { InGame, AllowTeamSwitching, Challenge, MAX } public bool InGame; public bool AllowTeamSwitching = true; public bool Challenge; public GamemodeIDs Gamemode; public byte[] GamemodeSettings = Array.Empty(); public int Stage; public uint Id; public ushort HostId; public Dictionary Players = new Dictionary(); public Dictionary InvitedPlayers = new Dictionary(); public LobbyState() { } public LobbyState(int stage, uint id, ushort hostId) { Stage = stage; Id = id; HostId = hostId; } public float GetScoreForTeam(byte team) { float num = 0f; foreach (KeyValuePair player in Players) { if (player.Value.Team == team) { num += player.Value.Score; } } return num; } public void Read(BinaryReader reader) { Bitfield bitfield = Bitfield.ReadByte(reader); InGame = bitfield[BooleanMask.InGame]; AllowTeamSwitching = bitfield[BooleanMask.AllowTeamSwitching]; Challenge = bitfield[BooleanMask.Challenge]; Gamemode = (GamemodeIDs)reader.ReadInt32(); int count = reader.ReadInt32(); GamemodeSettings = reader.ReadBytes(count); Stage = reader.ReadInt32(); Id = reader.ReadUInt32(); HostId = reader.ReadUInt16(); Players.Clear(); int num = reader.ReadInt32(); for (int i = 0; i < num; i++) { LobbyPlayer lobbyPlayer = new LobbyPlayer(); lobbyPlayer.Read(reader); lobbyPlayer.LobbyId = Id; Players[lobbyPlayer.Id] = lobbyPlayer; } InvitedPlayers.Clear(); int num2 = reader.ReadInt32(); for (int j = 0; j < num2; j++) { DateTime value = DateTime.FromBinary(reader.ReadInt64()); ushort key = reader.ReadUInt16(); InvitedPlayers[key] = value; } } public void Write(BinaryWriter writer) { Bitfield bitfield = new Bitfield(BooleanMask.MAX); bitfield[BooleanMask.InGame] = InGame; bitfield[BooleanMask.AllowTeamSwitching] = AllowTeamSwitching; bitfield[BooleanMask.Challenge] = Challenge; bitfield.WriteByte(writer); writer.Write((int)Gamemode); writer.Write(GamemodeSettings.Length); writer.Write(GamemodeSettings); writer.Write(Stage); writer.Write(Id); writer.Write(HostId); writer.Write(Players.Count); foreach (KeyValuePair player in Players) { player.Value.Write(writer); } writer.Write(InvitedPlayers.Count); foreach (KeyValuePair invitedPlayer in InvitedPlayers) { writer.Write(invitedPlayer.Value.ToBinary()); writer.Write(invitedPlayer.Key); } } } public class MPStage { public string DisplayName; public int Id; public MPStage(string displayName, int id) { DisplayName = displayName; Id = id; } } public enum PlayerStates : byte { Normal, Graffiti, Toilet, Dead } public static class ReflectionUtility { public static Type GetTypeByName(string name) { foreach (Assembly item in AppDomain.CurrentDomain.GetAssemblies().Reverse()) { Type type = item.GetType(name); if (type != null) { return type; } } return null; } } public class ServerState { public HashSet Tags = new HashSet(); public void Read(BinaryReader reader) { int num = reader.ReadInt32(); for (int i = 0; i < num; i++) { Tags.Add(reader.ReadString()); } } public void Write(BinaryWriter writer) { writer.Write(Tags.Count); foreach (string tag in Tags) { writer.Write(tag); } } } public static class SpecialPlayerUtils { public const string SpecialPlayerName = "Freesoul Elite"; public const string SpecialPlayerCrewName = "Freesoul"; public const SpecialSkins SpecialPlayerSkin = SpecialSkins.SpecialPlayer; public const string SpecialPlayerTag = "elite"; public const string SpecialPlayerUnlockName = "Goonie"; public const string SpecialPlayerUnlockID = "goonieskateboard"; public const string RegularPlayerUnlockNotification = "You've unlocked the Goonie skateboard skin for beating a player who unlocked it!"; public const string SpecialPlayerUnlockNotification = "You've unlocked the Goonie skateboard skin for beating a Freesoul Elite!"; public const string SpecialPlayerNag = "Beat a Freesoul Elite in any gamemode to unlock a skateboard skin."; public const string SpecialPlayerJoinMessage = "A {0} has entered the stage!"; public const string SpecialPlayerLeaveMessage = "A {0} has left!"; public const string SpecialPlayerInviteMessage = "A {0} is challenging you to a {1}."; } public enum SpecialSkins { None = -1, FemaleCop, MaleCop, SpecialPlayer, SeanKingston, Forklift, Jill, Steve, RedMinecraft, Minecraft, LowTierGod } public static class TMPFilter { public class Criteria { public enum Kinds { Whitelist, Blacklist } public Kinds ListKind; public string[] List; public Criteria(string[] list, Kinds listKind) { List = list; ListKind = listKind; } internal bool CheckTag(string tag) { if (List.Contains(tag.ToLowerInvariant())) { return ListKind == Kinds.Whitelist; } return ListKind == Kinds.Blacklist; } } public static string[] EnclosingTags = new string[30] { "align", "allcaps", "b", "color", "cspace", "font", "font-weight", "gradient", "i", "indent", "line-height", "link", "lowercase", "margin", "mark", "mspace", "nobr", "noparse", "pos", "rotate", "s", "size", "smallcaps", "style", "sub", "sup", "u", "uppercase", "voffset", "width" }; public static bool IsValidChatMessage(string message) { message = Sanitize(message); message = RemoveAllTags(message); if (string.IsNullOrWhiteSpace(message)) { return false; } return true; } public static string RemoveAllTags(string text) { text = new Regex("<[^>]*>").Replace(text, string.Empty); return text; } public static string EscapeAllTags(string text) { return FilterTags(text, new Criteria(Array.Empty(), Criteria.Kinds.Whitelist)); } public static string FilterTags(string text, Criteria criteria) { bool flag = false; int num = 0; string text2 = ""; StringBuilder stringBuilder = new StringBuilder(text); int num2 = 0; for (int i = 0; i < text.Length; i++) { char c = text[i]; if (!flag) { if (c == '<') { flag = true; text2 = ""; num = i; } continue; } switch (c) { case '<': flag = true; text2 = ""; num = i; break; case '>': flag = false; if (text2[0] == '/') { text2 = text2.Substring(1); } if (text2[0] == '#') { text2 = "color"; } text2 = text2.ToLowerInvariant(); if (text2.Contains("=")) { text2 = text2.Split(new char[1] { '=' })[0]; } if (!criteria.CheckTag(text2)) { stringBuilder.Insert(num + 1 + num2, "\u200b"); num2++; } break; default: text2 += c; break; } } return stringBuilder.ToString(); } public static string Sanitize(string text) { text = text.Replace("\n", ""); text = text.Replace("\t", ""); text = text.Replace("\r", ""); return text; } public static string CloseAllTags(string text) { bool flag = false; string text2 = ""; List list = new List(); string text3 = text; for (int i = 0; i < text3.Length; i++) { char c = text3[i]; if (!flag) { if (c == '<') { flag = true; text2 = ""; } continue; } switch (c) { case '<': flag = true; text2 = ""; break; case '>': flag = false; if (text2[0] == '/') { if (list.Count > 0) { text2 = text2.Substring(1); if (text2 == list[0]) { list.RemoveAt(0); } } break; } if (text2[0] == '#') { text2 = "color"; } text2 = text2.ToLowerInvariant(); if (text2.Contains("=")) { text2 = text2.Split(new char[1] { '=' })[0]; } if (EnclosingTags.Contains(text2)) { list.Insert(0, text2); } break; default: text2 += c; break; } } string text4 = ""; foreach (string item in list) { text4 = text4 + ""; } text += text4; return text; } } public class UIDProvider { private uint _currentUID = 1u; private HashSet _usedUIDs = new HashSet(); public uint RequestUID() { while (_usedUIDs.Contains(_currentUID)) { if (_currentUID < uint.MaxValue) { _currentUID++; } else { _currentUID = 1u; } } _usedUIDs.Add(_currentUID); return _currentUID++; } public void FreeUID(uint uid) { _usedUIDs.Remove(uid); } } public enum UserKinds { Player, Mod, Admin } } namespace BombRushMP.Common.Packets { public class ClientAuth : Packet { public string AuthKey = ""; public bool Invisible; public ClientState State; public string HWID = ""; public string GUID = ""; public override Packets PacketId => Packets.ClientAuth; public ClientAuth() { } public ClientAuth(string authKey, ClientState state, string hWID, string gUID) { AuthKey = authKey; State = state; HWID = hWID; GUID = gUID; } public override void Read(BinaryReader reader) { if (reader.ReadUInt32() != 24) { throw new IncompatibleProtocolException(); } AuthKey = reader.ReadString(); Invisible = reader.ReadBoolean(); HWID = reader.ReadString(); GUID = reader.ReadString(); State = new ClientState(); State.Read(reader); } public override void Write(BinaryWriter writer) { writer.Write(24u); writer.Write(AuthKey); writer.Write(Invisible); writer.Write(HWID); writer.Write(GUID); State.Write(writer); } } public class ClientChat : Packet { public string Message = ""; public override Packets PacketId => Packets.ClientChat; public ClientChat() { } public ClientChat(string message) { Message = message; } public override void Read(BinaryReader reader) { Message = reader.ReadString(); } public override void Write(BinaryWriter writer) { writer.Write(Message); } } public class ClientComboOver : Packet { public float Score; public override Packets PacketId => Packets.ClientComboOver; public ClientComboOver() { } public ClientComboOver(float score) { Score = score; } public override void Read(BinaryReader reader) { Score = reader.ReadSingle(); } public override void Write(BinaryWriter writer) { writer.Write(Score); } } public class ClientCustomPacket : Packet { public enum SendTargets { Broadcast, Lobby, Players } public IMessage.SendModes SendMode = IMessage.SendModes.ReliableUnordered; public SendTargets TargetMode; public ushort Sender; public ushort[] Targets = new ushort[0]; public byte[] Data = new byte[0]; public int CustomPacketId; public override Packets PacketId => Packets.ClientCustomPacket; public override void Read(BinaryReader reader) { CustomPacketId = reader.ReadInt32(); Sender = reader.ReadUInt16(); int num = reader.ReadInt32(); Targets = new ushort[num]; for (int i = 0; i < num; i++) { Targets[i] = reader.ReadUInt16(); } SendMode = (IMessage.SendModes)reader.ReadInt32(); TargetMode = (SendTargets)reader.ReadInt32(); int count = reader.ReadInt32(); Data = reader.ReadBytes(count); } public override void Write(BinaryWriter writer) { writer.Write(CustomPacketId); writer.Write(Sender); writer.Write(Targets.Length); ushort[] targets = Targets; foreach (ushort value in targets) { writer.Write(value); } writer.Write((int)SendMode); writer.Write((int)TargetMode); writer.Write(Data.Length); writer.Write(Data); } } public class ClientGamemodeCountdown : Packet { public ushort CountdownSeconds = 3; public override Packets PacketId => Packets.ClientGamemodeCountdown; public ClientGamemodeCountdown() { } public ClientGamemodeCountdown(ushort seconds) { CountdownSeconds = seconds; } public override void Read(BinaryReader reader) { CountdownSeconds = reader.ReadUInt16(); } public override void Write(BinaryWriter writer) { writer.Write(CountdownSeconds); } } public class ClientGamemodeScore : Packet { public float Score; public override Packets PacketId => Packets.ClientGameModeScore; public ClientGamemodeScore() { } public ClientGamemodeScore(float score) { Score = score; } public override void Read(BinaryReader reader) { Score = reader.ReadSingle(); } public override void Write(BinaryWriter writer) { writer.Write(Score); } } public class ClientGraffitiRaceGSpots : Packet { public const int MaxGraffitiSpotsPerPacket = 10; public List GraffitiSpots = new List(); public bool FinalPacket = true; public override Packets PacketId => Packets.ClientGraffitiRaceGSpots; public ClientGraffitiRaceGSpots() { } public ClientGraffitiRaceGSpots(List graffitiSpots, bool final) { GraffitiSpots = graffitiSpots; FinalPacket = final; } public override void Read(BinaryReader reader) { FinalPacket = reader.ReadBoolean(); ushort num = reader.ReadUInt16(); for (int i = 0; i < num; i++) { int item = reader.ReadInt32(); GraffitiSpots.Add(item); } } public override void Write(BinaryWriter writer) { writer.Write(FinalPacket); writer.Write((short)GraffitiSpots.Count); foreach (int graffitiSpot in GraffitiSpots) { writer.Write(graffitiSpot); } } } public class ClientGraffitiRaceStart : Packet { public Vector3 SpawnPosition = Vector3.Zero; public Quaternion SpawnRotation = Quaternion.Identity; public override Packets PacketId => Packets.ClientGraffitiRaceStart; public ClientGraffitiRaceStart(Vector3 position, Quaternion rotation) { SpawnPosition = position; SpawnRotation = rotation; } public ClientGraffitiRaceStart() { } public override void Read(BinaryReader reader) { float x = reader.ReadSingle(); float y = reader.ReadSingle(); float z = reader.ReadSingle(); SpawnPosition = new Vector3(x, y, z); SpawnRotation = Quaternion.Normalize(Compression.ReadCompressedQuaternion(reader)); } public override void Write(BinaryWriter writer) { writer.Write(SpawnPosition.X); writer.Write(SpawnPosition.Y); writer.Write(SpawnPosition.Z); Compression.WriteCompressedQuaternion(SpawnRotation, writer); } } public class ClientHitByPlayer : PlayerPacket { public ushort Attacker; public override Packets PacketId => Packets.ClientHitByPlayer; public ClientHitByPlayer() { } public ClientHitByPlayer(ushort attacker) { Attacker = attacker; } public override void Write(BinaryWriter writer) { writer.Write(Attacker); } public override void Read(BinaryReader reader) { Attacker = reader.ReadUInt16(); } } public class ClientLobbyCreate : Packet { public GamemodeIDs GamemodeID; public byte[] Settings; public override Packets PacketId => Packets.ClientLobbyCreate; public ClientLobbyCreate() { } public ClientLobbyCreate(GamemodeIDs gamemode, byte[] settings) { GamemodeID = gamemode; Settings = settings; } public override void Write(BinaryWriter writer) { writer.Write((int)GamemodeID); writer.Write(Settings.Length); writer.Write(Settings); } public override void Read(BinaryReader reader) { GamemodeID = (GamemodeIDs)reader.ReadInt32(); int count = reader.ReadInt32(); Settings = reader.ReadBytes(count); } } public class ClientLobbyDeclineAllInvites : Packet { public override Packets PacketId => Packets.ClientLobbyDeclineAllInvites; } public class ClientLobbyDeclineInvite : Packet { public uint LobbyId; public override Packets PacketId => Packets.ClientLobbyDeclineInvite; public ClientLobbyDeclineInvite() { } public ClientLobbyDeclineInvite(uint lobbyId) { LobbyId = lobbyId; } public override void Write(BinaryWriter writer) { writer.Write(LobbyId); } public override void Read(BinaryReader reader) { LobbyId = reader.ReadUInt32(); } } public class ClientLobbyEnd : Packet { public override Packets PacketId => Packets.ClientLobbyEnd; } public class ClientLobbyInvite : Packet { public ushort InviteeId; public override Packets PacketId => Packets.ClientLobbyInvite; public ClientLobbyInvite() { } public ClientLobbyInvite(ushort inviteeId) { InviteeId = inviteeId; } public override void Write(BinaryWriter writer) { writer.Write(InviteeId); } public override void Read(BinaryReader reader) { InviteeId = reader.ReadUInt16(); } } public class ClientLobbyJoin : Packet { public uint LobbyId; public override Packets PacketId => Packets.ClientLobbyJoin; public ClientLobbyJoin() { } public ClientLobbyJoin(uint lobbyId) { LobbyId = lobbyId; } public override void Read(BinaryReader reader) { LobbyId = reader.ReadUInt32(); } public override void Write(BinaryWriter writer) { writer.Write(LobbyId); } } public class ClientLobbyKick : Packet { public ushort PlayerId; public override Packets PacketId => Packets.ClientLobbyKick; public ClientLobbyKick() { } public ClientLobbyKick(ushort playerId) { PlayerId = playerId; } public override void Write(BinaryWriter writer) { writer.Write(PlayerId); } public override void Read(BinaryReader reader) { PlayerId = reader.ReadUInt16(); } } public class ClientLobbyLeave : Packet { public override Packets PacketId => Packets.ClientLobbyLeave; } public class ClientLobbyResetWins : Packet { public override Packets PacketId => Packets.ClientLobbyResetWins; } public class ClientLobbySetAllowTeamSwitching : Packet { public bool Set = true; public override Packets PacketId => Packets.ClientLobbySetAllowTeamSwitching; public ClientLobbySetAllowTeamSwitching() { } public ClientLobbySetAllowTeamSwitching(bool set) { Set = set; } public override void Read(BinaryReader reader) { Set = reader.ReadBoolean(); } public override void Write(BinaryWriter writer) { writer.Write(Set); } } public class ClientLobbySetChallenge : Packet { public bool Set = true; public override Packets PacketId => Packets.ClientLobbySetChallenge; public ClientLobbySetChallenge() { } public ClientLobbySetChallenge(bool set) { Set = set; } public override void Read(BinaryReader reader) { Set = reader.ReadBoolean(); } public override void Write(BinaryWriter writer) { writer.Write(Set); } } public class ClientLobbySetGamemode : Packet { public GamemodeIDs Gamemode; public byte[] GamemodeSettings = Array.Empty(); public override Packets PacketId => Packets.ClientLobbySetGamemode; public ClientLobbySetGamemode() { } public ClientLobbySetGamemode(GamemodeIDs gamemode, byte[] gamemodeSettings) { Gamemode = gamemode; GamemodeSettings = gamemodeSettings; } public override void Read(BinaryReader reader) { Gamemode = (GamemodeIDs)reader.ReadInt32(); int count = reader.ReadInt32(); GamemodeSettings = reader.ReadBytes(count); } public override void Write(BinaryWriter writer) { writer.Write((int)Gamemode); writer.Write(GamemodeSettings.Length); writer.Write(GamemodeSettings); } } public class ClientLobbySetPlayerTeam : Packet { public ushort PlayerId; public byte TeamId; public override Packets PacketId => Packets.ClientLobbySetPlayerTeam; public ClientLobbySetPlayerTeam() { } public ClientLobbySetPlayerTeam(ushort playerId, byte teamId) { PlayerId = playerId; TeamId = teamId; } public override void Write(BinaryWriter writer) { writer.Write(PlayerId); writer.Write(TeamId); } public override void Read(BinaryReader reader) { PlayerId = reader.ReadUInt16(); TeamId = reader.ReadByte(); } } public class ClientLobbySetReady : Packet { public bool Ready; public override Packets PacketId => Packets.ClientLobbySetReady; public ClientLobbySetReady() { } public ClientLobbySetReady(bool ready) { Ready = ready; } public override void Write(BinaryWriter writer) { writer.Write(Ready); } public override void Read(BinaryReader reader) { Ready = reader.ReadBoolean(); } } public class ClientLobbyStart : Packet { public override Packets PacketId => Packets.ClientLobbyStart; } public class ClientPropHuntDeath : Packet { public override Packets PacketId => Packets.ClientPropHuntDeath; } public class ClientPropHuntSettings : Packet { public float SetupLength; public float MatchLength; public float PingInterval; public int StageHash; public bool PropsBecomeHuntersOnDeath; public bool HuntersRespawnOnDeath; public float RespawnTime; public override Packets PacketId => Packets.ClientPropHuntSettings; public ClientPropHuntSettings() { } public ClientPropHuntSettings(float setupLength, float matchLength, float pingInterval, int stageHash, bool propsBecomeHuntersOnDeath, bool huntersRespawnOnDeath, float respawnTime) { SetupLength = setupLength; MatchLength = matchLength; PingInterval = pingInterval; StageHash = stageHash; PropsBecomeHuntersOnDeath = propsBecomeHuntersOnDeath; HuntersRespawnOnDeath = huntersRespawnOnDeath; RespawnTime = respawnTime; } public override void Write(BinaryWriter writer) { writer.Write(SetupLength); writer.Write(MatchLength); writer.Write(PingInterval); writer.Write(StageHash); writer.Write(PropsBecomeHuntersOnDeath); writer.Write(HuntersRespawnOnDeath); writer.Write(RespawnTime); } public override void Read(BinaryReader reader) { SetupLength = reader.ReadSingle(); MatchLength = reader.ReadSingle(); PingInterval = reader.ReadSingle(); StageHash = reader.ReadInt32(); PropsBecomeHuntersOnDeath = reader.ReadBoolean(); HuntersRespawnOnDeath = reader.ReadBoolean(); RespawnTime = reader.ReadSingle(); } } public class ClientPropHuntShoot : Packet { public ushort Attacker; public ushort Target; public override Packets PacketId => Packets.ClientPropHuntShoot; public ClientPropHuntShoot() { } public ClientPropHuntShoot(ushort target) { Target = target; } public override void Read(BinaryReader reader) { Attacker = reader.ReadUInt16(); Target = reader.ReadUInt16(); } public override void Write(BinaryWriter writer) { writer.Write(Attacker); writer.Write(Target); } } public class ClientPropHuntStageHash : Packet { public int StageHash; public override Packets PacketId => Packets.ClientPropHuntStageHash; public ClientPropHuntStageHash() { } public ClientPropHuntStageHash(int stageHash) { StageHash = stageHash; } public override void Write(BinaryWriter writer) { writer.Write(StageHash); } public override void Read(BinaryReader reader) { StageHash = reader.ReadInt32(); } } public class ClientScoreBattleLength : Packet { public byte Minutes = 3; public override Packets PacketId => Packets.ClientScoreBattleLength; public ClientScoreBattleLength(byte minutes) { Minutes = minutes; } public ClientScoreBattleLength() { } public override void Write(BinaryWriter writer) { writer.Write(Minutes); } public override void Read(BinaryReader reader) { Minutes = reader.ReadByte(); } } public class ClientSetTeam : Packet { public byte Team; public override Packets PacketId => Packets.ClientSetTeam; public ClientSetTeam() { } public ClientSetTeam(byte team) { Team = team; } public override void Read(BinaryReader reader) { Team = reader.ReadByte(); } public override void Write(BinaryWriter writer) { writer.Write(Team); } } public class ClientState : Packet { public Guid CrewBoomCharacter = Guid.Empty; public sbyte Character; public sbyte FallbackCharacter; public byte FallbackOutfit; public byte Outfit; public SpecialSkins SpecialSkin = SpecialSkins.None; public int SpecialSkinVariant = -1; public string Name = "Player"; public string CrewName = ""; public int Stage; public bool HasSpecialUnlock; public bool AllowTeleports = true; public bool ShowBadges = true; public AuthUser User = new AuthUser(); public override Packets PacketId => Packets.ClientState; public override void Read(BinaryReader reader) { if (Guid.TryParse(reader.ReadString(), out var result)) { CrewBoomCharacter = result; } Character = reader.ReadSByte(); FallbackCharacter = reader.ReadSByte(); FallbackOutfit = reader.ReadByte(); Outfit = reader.ReadByte(); Stage = reader.ReadInt32(); Name = reader.ReadString(); CrewName = reader.ReadString(); SpecialSkin = (SpecialSkins)reader.ReadInt32(); SpecialSkinVariant = reader.ReadInt32(); HasSpecialUnlock = reader.ReadBoolean(); AllowTeleports = reader.ReadBoolean(); ShowBadges = reader.ReadBoolean(); new AuthUser(); User.Read(reader); } public override void Write(BinaryWriter writer) { writer.Write(CrewBoomCharacter.ToString()); writer.Write(Character); writer.Write(FallbackCharacter); writer.Write(FallbackOutfit); writer.Write(Outfit); writer.Write(Stage); writer.Write(Name); writer.Write(CrewName); writer.Write((int)SpecialSkin); writer.Write(SpecialSkinVariant); writer.Write(HasSpecialUnlock); writer.Write(AllowTeleports); writer.Write(ShowBadges); User.Write(writer); } } public class IncompatibleProtocolException : Exception { } public class ClientTeamGraffRaceScore : Packet { public int TagHash; public override Packets PacketId => Packets.ClientTeamGraffRaceScore; public ClientTeamGraffRaceScore() { } public ClientTeamGraffRaceScore(int tagHash) { TagHash = tagHash; } public override void Write(BinaryWriter writer) { writer.Write(TagHash); } public override void Read(BinaryReader reader) { TagHash = reader.ReadInt32(); } } public class ClientVisualState : Packet { private enum BooleanMask { MoveStyleEquipped, SprayCanHeld, PhoneHeld, AFK, Hitbox, HitboxLeftLeg, HitboxRightLeg, HitboxUpperBody, HitboxAerial, HitboxRadial, HitboxSpray, BoostpackTrail, Chibi, BoEAnimation, Disguised, Ignore, MAX } private const float PhoneDirectionMaxValue = 2f; public Vector3 Position = Vector3.Zero; public Vector3 VisualPosition = Vector3.Zero; public Vector3 Velocity = Vector3.Zero; public Quaternion Rotation = Quaternion.Identity; public Quaternion VisualRotation = Quaternion.Identity; public bool MoveStyleEquipped; public int MoveStyle; public float GrindDirection; public bool SprayCanHeld; public bool PhoneHeld; public float PhoneDirectionX; public float PhoneDirectionY; public float TurnDirection1; public float TurnDirection2; public float TurnDirection3; public float TurnDirectionSkateboard; public PlayerStates State; public byte DustEmissionRate; public byte BoostpackEffectMode; public byte FrictionEffectMode; public int CurrentAnimation; public float CurrentAnimationTime; public bool AFK; public byte MoveStyleSkin; public int MPMoveStyleSkin = -1; public bool Hitbox; public bool HitboxLeftLeg; public bool HitboxRightLeg; public bool HitboxUpperBody; public bool HitboxAerial; public bool HitboxRadial; public bool HitboxSpray; public bool BoostpackTrail; public bool Chibi; public bool BoEAnimation; public bool Disguised; public int DisguiseId; public bool Ignore; public Vector3 DisguiseScale = Vector3.One; public override Packets PacketId => Packets.ClientVisualState; public override void Write(BinaryWriter writer) { writer.Write((byte)State); writer.Write(Position.X); writer.Write(Position.Y); writer.Write(Position.Z); writer.Write(VisualPosition.X); writer.Write(VisualPosition.Y); writer.Write(VisualPosition.Z); Compression.WriteCompressedQuaternion(Rotation, writer); Compression.WriteCompressedQuaternion(VisualRotation, writer); writer.Write(Velocity.X); writer.Write(Velocity.Y); writer.Write(Velocity.Z); Bitfield bitfield = new Bitfield(BooleanMask.MAX); bitfield[BooleanMask.MoveStyleEquipped] = MoveStyleEquipped; bitfield[BooleanMask.SprayCanHeld] = SprayCanHeld; bitfield[BooleanMask.PhoneHeld] = PhoneHeld; bitfield[BooleanMask.AFK] = AFK; bitfield[BooleanMask.Hitbox] = Hitbox; bitfield[BooleanMask.HitboxLeftLeg] = HitboxLeftLeg; bitfield[BooleanMask.HitboxRightLeg] = HitboxRightLeg; bitfield[BooleanMask.HitboxUpperBody] = HitboxUpperBody; bitfield[BooleanMask.HitboxAerial] = HitboxAerial; bitfield[BooleanMask.HitboxRadial] = HitboxRadial; bitfield[BooleanMask.HitboxSpray] = HitboxSpray; bitfield[BooleanMask.BoostpackTrail] = BoostpackTrail; bitfield[BooleanMask.Chibi] = Chibi; bitfield[BooleanMask.BoEAnimation] = BoEAnimation; bitfield[BooleanMask.Disguised] = Disguised; bitfield[BooleanMask.Ignore] = Ignore; bitfield.WriteShort(writer); writer.Write(MoveStyle); writer.Write(Compression.CompressToByte(PhoneDirectionX, 2f)); writer.Write(Compression.CompressToByte(PhoneDirectionY, 2f)); writer.Write(Compression.CompressNormal(TurnDirection1)); writer.Write(Compression.CompressNormal(TurnDirection2)); writer.Write(Compression.CompressNormal(TurnDirection3)); writer.Write(Compression.CompressNormal(TurnDirectionSkateboard)); writer.Write(Compression.CompressNormal(GrindDirection)); writer.Write(DustEmissionRate); writer.Write(BoostpackEffectMode); writer.Write(FrictionEffectMode); writer.Write(CurrentAnimation); writer.Write(CurrentAnimationTime); writer.Write(MoveStyleSkin); writer.Write(MPMoveStyleSkin); writer.Write(DisguiseId); writer.Write(DisguiseScale.X); writer.Write(DisguiseScale.Y); writer.Write(DisguiseScale.Z); } public override void Read(BinaryReader reader) { State = (PlayerStates)reader.ReadByte(); float x = reader.ReadSingle(); float y = reader.ReadSingle(); float z = reader.ReadSingle(); float x2 = reader.ReadSingle(); float y2 = reader.ReadSingle(); float z2 = reader.ReadSingle(); Rotation = Quaternion.Normalize(Compression.ReadCompressedQuaternion(reader)); VisualRotation = Quaternion.Normalize(Compression.ReadCompressedQuaternion(reader)); float x3 = reader.ReadSingle(); float y3 = reader.ReadSingle(); float z3 = reader.ReadSingle(); Bitfield bitfield = Bitfield.ReadShort(reader); MoveStyleEquipped = bitfield[BooleanMask.MoveStyleEquipped]; SprayCanHeld = bitfield[BooleanMask.SprayCanHeld]; PhoneHeld = bitfield[BooleanMask.PhoneHeld]; AFK = bitfield[BooleanMask.AFK]; bool hitbox2 = (bitfield[BooleanMask.Hitbox] = Hitbox); Hitbox = hitbox2; HitboxLeftLeg = bitfield[BooleanMask.HitboxLeftLeg]; HitboxRightLeg = bitfield[BooleanMask.HitboxRightLeg]; HitboxUpperBody = bitfield[BooleanMask.HitboxUpperBody]; HitboxAerial = bitfield[BooleanMask.HitboxAerial]; HitboxRadial = bitfield[BooleanMask.HitboxRadial]; HitboxSpray = bitfield[BooleanMask.HitboxSpray]; BoostpackTrail = bitfield[BooleanMask.BoostpackTrail]; Chibi = bitfield[BooleanMask.Chibi]; BoEAnimation = bitfield[BooleanMask.BoEAnimation]; Disguised = bitfield[BooleanMask.Disguised]; Ignore = bitfield[BooleanMask.Ignore]; MoveStyle = reader.ReadInt32(); PhoneDirectionX = Compression.DecompressFromByte(reader.ReadSByte(), 2f); PhoneDirectionY = Compression.DecompressFromByte(reader.ReadSByte(), 2f); TurnDirection1 = Compression.DecompressNormal(reader.ReadSByte()); TurnDirection2 = Compression.DecompressNormal(reader.ReadSByte()); TurnDirection3 = Compression.DecompressNormal(reader.ReadSByte()); TurnDirectionSkateboard = Compression.DecompressNormal(reader.ReadSByte()); GrindDirection = Compression.DecompressNormal(reader.ReadSByte()); Position = new Vector3(x, y, z); VisualPosition = new Vector3(x2, y2, z2); Velocity = new Vector3(x3, y3, z3); DustEmissionRate = reader.ReadByte(); BoostpackEffectMode = reader.ReadByte(); FrictionEffectMode = reader.ReadByte(); CurrentAnimation = reader.ReadInt32(); CurrentAnimationTime = reader.ReadSingle(); MoveStyleSkin = reader.ReadByte(); MPMoveStyleSkin = reader.ReadInt32(); DisguiseId = reader.ReadInt32(); float x4 = reader.ReadSingle(); float y4 = reader.ReadSingle(); float z4 = reader.ReadSingle(); DisguiseScale = new Vector3(x4, y4, z4); } } public abstract class Packet { public abstract Packets PacketId { get; } public virtual void Read(BinaryReader reader) { } public virtual void Write(BinaryWriter writer) { } } public static class PacketFactory { private static Dictionary _packetTypeById = new Dictionary(); private static INetworkingInterface NetworkingInterface => NetworkingEnvironment.NetworkingInterface; public static void Initialize() { Type[] types = Assembly.GetExecutingAssembly().GetTypes(); foreach (Type type in types) { if (typeof(Packet).IsAssignableFrom(type) && !type.IsAbstract) { Packet packet = Activator.CreateInstance(type) as Packet; _packetTypeById[packet.PacketId] = type; } } } public static IMessage MessageFromPacket(Packet packet, IMessage.SendModes sendMode, NetChannels channel) { IMessage message = NetworkingInterface.CreateMessage(sendMode, channel, packet.PacketId); using MemoryStream memoryStream = new MemoryStream(); using BinaryWriter writer = new BinaryWriter(memoryStream); packet.Write(writer); message.Add(memoryStream.ToArray()); return message; } public static Packet PacketFromMessage(Packets packetId, IMessage message) { using MemoryStream input = new MemoryStream(message.GetBytes()); using BinaryReader reader = new BinaryReader(input); Packet packet = null; if (_packetTypeById.TryGetValue(packetId, out var value)) { packet = Activator.CreateInstance(value) as Packet; } packet?.Read(reader); return packet; } } public enum Packets : ushort { ClientState, ServerConnectionResponse, ServerClientStates, ClientVisualState, ServerClientVisualStates, PlayerAnimation, PlayerVoice, PlayerGenericEvent, PlayerGraffitiSlash, PlayerGraffitiFinisher, ClientLobbyCreate, ClientLobbyJoin, ClientLobbyLeave, ServerLobbies, ServerLobbyCreateResponse, ServerLobbyDeleted, ClientLobbyStart, ServerLobbyStart, ServerLobbyEnd, ServerGamemodeBegin, ClientGameModeScore, ClientLobbyEnd, ClientGraffitiRaceGSpots, ClientLobbySetGamemode, ServerPlayerCount, ClientLobbySetReady, ClientLobbyInvite, ServerLobbyInvite, ClientLobbyDeclineInvite, ClientLobbyDeclineAllInvites, ClientLobbyKick, ClientChat, ServerChat, ClientComboOver, ClientAuth, ServerBanList, ClientGraffitiRaceStart, ClientGamemodeCountdown, ClientScoreBattleLength, ClientHitByPlayer, ServerSetChibi, ClientSetTeam, ClientTeamGraffRaceScore, ServerTeamGraffRaceScore, ClientLobbySetAllowTeamSwitching, ClientLobbySetPlayerTeam, ClientLobbySetChallenge, ServerLobbySoftUpdate, ServerClientDisconnected, ServerSetSpecialSkin, ServerServerStateUpdate, ServerTeleportPlayer, ServerDamage, ServerSetProp, ClientPropHuntSettings, ServerPropHuntBegin, ClientPropHuntStageHash, ServerPropHuntSpawn, ServerPropHuntPing, ClientPropHuntDeath, ClientPropHuntShoot, ServerPropHuntRespawn, ServerChallenge, ClientLobbyResetWins, ClientCustomPacket } public class PlayerAnimation : PlayerPacket { private enum BooleanMask { ForceOverwrite, Instant, BoE, MAX } public static IMessage.SendModes ClientSendMode = IMessage.SendModes.ReliableUnordered; public static IMessage.SendModes ServerSendMode = IMessage.SendModes.Unreliable; public int NewAnim; public bool ForceOverwrite; public bool Instant; public bool BoE; public float AtTime; public override Packets PacketId => Packets.PlayerAnimation; public PlayerAnimation() { } public PlayerAnimation(int newAnim, bool forceOverwrite = false, bool instant = false, float atTime = -1f) { NewAnim = newAnim; ForceOverwrite = forceOverwrite; Instant = instant; AtTime = atTime; } public override void Write(BinaryWriter writer) { base.Write(writer); writer.Write(ClientId); writer.Write(NewAnim); Bitfield bitfield = new Bitfield(BooleanMask.MAX); bitfield[BooleanMask.Instant] = Instant; bitfield[BooleanMask.ForceOverwrite] = ForceOverwrite; bitfield[BooleanMask.BoE] = BoE; bitfield.WriteByte(writer); writer.Write(Compression.CompressNormal(AtTime)); } public override void Read(BinaryReader reader) { base.Read(reader); ClientId = reader.ReadUInt16(); NewAnim = reader.ReadInt32(); Bitfield bitfield = Bitfield.ReadByte(reader); Instant = bitfield[BooleanMask.Instant]; ForceOverwrite = bitfield[BooleanMask.ForceOverwrite]; BoE = bitfield[BooleanMask.BoE]; AtTime = Compression.DecompressNormal(reader.ReadSByte()); } } public class PlayerGenericEvent : PlayerPacket { public GenericEvents Event; public override Packets PacketId => Packets.PlayerGenericEvent; public PlayerGenericEvent() { } public PlayerGenericEvent(GenericEvents ev) { Event = ev; } public override void Read(BinaryReader reader) { base.Read(reader); Event = (GenericEvents)reader.ReadInt32(); } public override void Write(BinaryWriter writer) { base.Write(writer); writer.Write((int)Event); } } public class PlayerGraffitiFinisher : PlayerPacket { public byte GraffitiSize; public override Packets PacketId => Packets.PlayerGraffitiFinisher; public PlayerGraffitiFinisher() { } public PlayerGraffitiFinisher(byte graffitiSize) { GraffitiSize = graffitiSize; } public override void Read(BinaryReader reader) { base.Read(reader); GraffitiSize = reader.ReadByte(); } public override void Write(BinaryWriter writer) { base.Write(writer); writer.Write(GraffitiSize); } } public class PlayerGraffitiSlash : PlayerPacket { public Vector3 Direction = Vector3.Zero; public override Packets PacketId => Packets.PlayerGraffitiSlash; public PlayerGraffitiSlash() { } public PlayerGraffitiSlash(Vector3 direction) { Direction = direction; } public override void Read(BinaryReader reader) { base.Read(reader); Direction = Compression.ReadCompressedVector3Normal(reader); } public override void Write(BinaryWriter writer) { base.Write(writer); Compression.WriteCompressedVector3Normal(Direction, writer); } } public abstract class PlayerPacket : Packet { public ushort ClientId; public override void Read(BinaryReader reader) { ClientId = reader.ReadUInt16(); } public override void Write(BinaryWriter writer) { writer.Write(ClientId); } } public class PlayerVoice : PlayerPacket { public int AudioClipId; public int VoicePriority; public override Packets PacketId => Packets.PlayerVoice; public override void Read(BinaryReader reader) { base.Read(reader); AudioClipId = reader.ReadInt32(); VoicePriority = reader.ReadInt32(); } public override void Write(BinaryWriter writer) { base.Write(writer); writer.Write(AudioClipId); writer.Write(VoicePriority); } } public class ServerBanList : Packet { public string JsonData = ""; public override Packets PacketId => Packets.ServerBanList; public ServerBanList() { } public ServerBanList(string banList) { JsonData = banList; } public override void Read(BinaryReader reader) { JsonData = reader.ReadString(); } public override void Write(BinaryWriter writer) { writer.Write(JsonData); } } public class ServerChallenge : Packet { public string Challenge = ""; public override Packets PacketId => Packets.ServerChallenge; public ServerChallenge() { } public ServerChallenge(string challenge) { Challenge = challenge; } public override void Read(BinaryReader reader) { Challenge = reader.ReadString(); } public override void Write(BinaryWriter writer) { writer.Write(Challenge); } } public class ServerChat : Packet { public string Author = ""; public string Message = ""; public int[] Badges = Array.Empty(); public ChatMessageTypes MessageType; public override Packets PacketId => Packets.ServerChat; public ServerChat() { } public ServerChat(ChatMessageTypes messageType) { MessageType = messageType; } public ServerChat(string author, string message, int[] badges = null, ChatMessageTypes messageType = ChatMessageTypes.Chat) { Author = author; Message = message; MessageType = messageType; Badges = badges; if (Badges == null) { Badges = Array.Empty(); } } public ServerChat(string message, ChatMessageTypes messageType = ChatMessageTypes.System) { Message = message; MessageType = messageType; } public override void Read(BinaryReader reader) { Author = reader.ReadString(); Message = reader.ReadString(); MessageType = (ChatMessageTypes)reader.ReadInt32(); int num = reader.ReadInt32(); Badges = new int[num]; for (int i = 0; i < num; i++) { Badges[i] = reader.ReadInt32(); } } public override void Write(BinaryWriter writer) { writer.Write(Author); writer.Write(Message); writer.Write((int)MessageType); writer.Write(Badges.Length); int[] badges = Badges; foreach (int value in badges) { writer.Write(value); } } } public class ServerClientDisconnected : Packet { public ushort ClientId; public override Packets PacketId => Packets.ServerClientDisconnected; public ServerClientDisconnected(ushort clientId) { ClientId = clientId; } public ServerClientDisconnected() { } public override void Write(BinaryWriter writer) { writer.Write(ClientId); } public override void Read(BinaryReader reader) { ClientId = reader.ReadUInt16(); } } public class ServerClientStates : Packet { public Dictionary ClientStates = new Dictionary(); public bool Full; public override Packets PacketId => Packets.ServerClientStates; public override void Read(BinaryReader reader) { Full = reader.ReadBoolean(); int num = reader.ReadInt32(); for (int i = 0; i < num; i++) { ushort key = reader.ReadUInt16(); ClientState clientState = new ClientState(); clientState.Read(reader); ClientStates[key] = clientState; } } public override void Write(BinaryWriter writer) { writer.Write(Full); writer.Write(ClientStates.Count); foreach (KeyValuePair clientState in ClientStates) { writer.Write(clientState.Key); clientState.Value.Write(writer); } } } public class ServerClientVisualStates : Packet { public Dictionary ClientVisualStates = new Dictionary(); public override Packets PacketId => Packets.ServerClientVisualStates; public override void Read(BinaryReader reader) { int num = reader.ReadInt32(); for (int i = 0; i < num; i++) { ushort key = reader.ReadUInt16(); ClientVisualState clientVisualState = new ClientVisualState(); clientVisualState.Read(reader); ClientVisualStates[key] = clientVisualState; } } public override void Write(BinaryWriter writer) { writer.Write(ClientVisualStates.Count); foreach (KeyValuePair clientVisualState in ClientVisualStates) { writer.Write(clientVisualState.Key); clientVisualState.Value.Write(writer); } } } public class ServerConnectionResponse : Packet { public ushort LocalClientId; public float TickRate = 1f / 32f; public IMessage.SendModes ClientAnimationSendMode = IMessage.SendModes.ReliableUnordered; public AuthUser User; public ServerState ServerState; public string MOTD = ""; public bool AlwaysShowMOTD; public override Packets PacketId => Packets.ServerConnectionResponse; public override void Read(BinaryReader reader) { LocalClientId = reader.ReadUInt16(); TickRate = reader.ReadSingle(); ClientAnimationSendMode = (IMessage.SendModes)reader.ReadByte(); User = new AuthUser(); User.Read(reader); ServerState = new ServerState(); ServerState.Read(reader); MOTD = reader.ReadString(); AlwaysShowMOTD = reader.ReadBoolean(); } public override void Write(BinaryWriter writer) { writer.Write(LocalClientId); writer.Write(TickRate); writer.Write((byte)ClientAnimationSendMode); User.Write(writer); ServerState.Write(writer); writer.Write(MOTD); writer.Write(AlwaysShowMOTD); } } public class ServerDamage : Packet { public int Damage; public override Packets PacketId => Packets.ServerDamage; public ServerDamage() { } public ServerDamage(int dmg) { Damage = dmg; } public override void Write(BinaryWriter writer) { writer.Write(Damage); } public override void Read(BinaryReader reader) { Damage = reader.ReadInt32(); } } public class ServerGamemodeBegin : Packet { public DateTime StartTime = DateTime.UtcNow; public override Packets PacketId => Packets.ServerGamemodeBegin; public ServerGamemodeBegin() { } public ServerGamemodeBegin(DateTime startTime) { StartTime = startTime; } public override void Read(BinaryReader reader) { StartTime = DateTime.FromBinary(reader.ReadInt64()); } public override void Write(BinaryWriter writer) { writer.Write(StartTime.ToBinary()); } } public class ServerLobbies : Packet { public List Lobbies = new List(); public override Packets PacketId => Packets.ServerLobbies; public ServerLobbies() { } public ServerLobbies(List lobbies) { Lobbies = lobbies; } public override void Read(BinaryReader reader) { int num = reader.ReadInt32(); for (int i = 0; i < num; i++) { LobbyState lobbyState = new LobbyState(); lobbyState.Read(reader); Lobbies.Add(lobbyState); } } public override void Write(BinaryWriter writer) { writer.Write(Lobbies.Count); foreach (LobbyState lobby in Lobbies) { lobby.Write(writer); } } } public class ServerLobbyCreateResponse : Packet { public override Packets PacketId => Packets.ServerLobbyCreateResponse; } public class ServerLobbyDeleted : Packet { public uint LobbyUID; public override Packets PacketId => Packets.ServerLobbyDeleted; public ServerLobbyDeleted() { } public ServerLobbyDeleted(uint lobbyUid) { LobbyUID = lobbyUid; } public override void Read(BinaryReader reader) { LobbyUID = reader.ReadUInt32(); } public override void Write(BinaryWriter writer) { writer.Write(LobbyUID); } } public class ServerLobbyEnd : Packet { public bool Cancelled; public override Packets PacketId => Packets.ServerLobbyEnd; public ServerLobbyEnd() { } public ServerLobbyEnd(bool cancelled) { Cancelled = cancelled; } public override void Read(BinaryReader reader) { Cancelled = reader.ReadBoolean(); } public override void Write(BinaryWriter writer) { writer.Write(Cancelled); } } public class ServerLobbyInvite : Packet { public ushort InviteeId; public ushort InviterId; public uint LobbyId; public override Packets PacketId => Packets.ServerLobbyInvite; public ServerLobbyInvite() { } public ServerLobbyInvite(ushort inviteeId, ushort inviterId, uint lobbyId) { InviteeId = inviteeId; InviterId = inviterId; LobbyId = lobbyId; } public override void Write(BinaryWriter writer) { writer.Write(InviteeId); writer.Write(InviterId); writer.Write(LobbyId); } public override void Read(BinaryReader reader) { InviteeId = reader.ReadUInt16(); InviterId = reader.ReadUInt16(); LobbyId = reader.ReadUInt32(); } } public class ServerLobbySoftUpdate : Packet { public uint LobbyId; public ushort PlayerId; public float Score; public override Packets PacketId => Packets.ServerLobbySoftUpdate; public ServerLobbySoftUpdate() { } public ServerLobbySoftUpdate(uint lobbyId, ushort playerId, float score) { LobbyId = lobbyId; PlayerId = playerId; Score = score; } public override void Write(BinaryWriter writer) { writer.Write(LobbyId); writer.Write(PlayerId); writer.Write(Score); } public override void Read(BinaryReader reader) { LobbyId = reader.ReadUInt32(); PlayerId = reader.ReadUInt16(); Score = reader.ReadSingle(); } } public class ServerLobbyStart : Packet { public override Packets PacketId => Packets.ServerLobbyStart; } public class ServerPlayerCount : Packet { public Dictionary PlayerCountByStage = new Dictionary(); public override Packets PacketId => Packets.ServerPlayerCount; public ServerPlayerCount() { } public ServerPlayerCount(Dictionary playerCountByStage) { PlayerCountByStage = playerCountByStage; } public override void Read(BinaryReader reader) { int num = reader.ReadInt32(); for (int i = 0; i < num; i++) { int key = reader.ReadInt32(); int value = reader.ReadInt32(); PlayerCountByStage[key] = value; } } public override void Write(BinaryWriter writer) { writer.Write(PlayerCountByStage.Count); foreach (KeyValuePair item in PlayerCountByStage) { writer.Write(item.Key); writer.Write(item.Value); } } } public class ServerPropHuntBegin : Packet { public override Packets PacketId => Packets.ServerPropHuntBegin; } public class ServerPropHuntPing : Packet { public override Packets PacketId => Packets.ServerPropHuntPing; } public class ServerPropHuntRespawn : Packet { public override Packets PacketId => Packets.ServerPropHuntRespawn; } public class ServerPropHuntSpawn : Packet { public Vector3 Position; public Quaternion Rotation; public override Packets PacketId => Packets.ServerPropHuntSpawn; public ServerPropHuntSpawn() { } public ServerPropHuntSpawn(Vector3 pos, Quaternion rot) { Position = pos; Rotation = rot; } public override void Write(BinaryWriter writer) { writer.Write(Position.X); writer.Write(Position.Y); writer.Write(Position.Z); writer.Write(Rotation.X); writer.Write(Rotation.Y); writer.Write(Rotation.Z); writer.Write(Rotation.W); } public override void Read(BinaryReader reader) { float x = reader.ReadSingle(); float y = reader.ReadSingle(); float z = reader.ReadSingle(); float x2 = reader.ReadSingle(); float y2 = reader.ReadSingle(); float z2 = reader.ReadSingle(); float w = reader.ReadSingle(); Position = new Vector3(x, y, z); Rotation = new Quaternion(x2, y2, z2, w); } } internal class ServerPropHuntStageHashRequest { } public class ServerServerStateUpdate : Packet { public ServerState State; public override Packets PacketId => Packets.ServerServerStateUpdate; public ServerServerStateUpdate(ServerState state) { State = state; } public ServerServerStateUpdate() { } public override void Read(BinaryReader reader) { State = new ServerState(); State.Read(reader); } public override void Write(BinaryWriter writer) { State.Write(writer); } } public class ServerSetChibi : Packet { public bool Set; public override Packets PacketId => Packets.ServerSetChibi; public ServerSetChibi(bool set) { Set = set; } public ServerSetChibi() { } public override void Write(BinaryWriter writer) { writer.Write(Set); } public override void Read(BinaryReader reader) { Set = reader.ReadBoolean(); } } public class ServerSetProp : Packet { public bool Disguised; public int PropId; public override Packets PacketId => Packets.ServerSetProp; public ServerSetProp() { } public ServerSetProp(bool disguised, int propId) { Disguised = disguised; PropId = propId; } public override void Read(BinaryReader reader) { Disguised = reader.ReadBoolean(); PropId = reader.ReadInt32(); } public override void Write(BinaryWriter writer) { writer.Write(Disguised); writer.Write(PropId); } } public class ServerSetSpecialSkin : Packet { public SpecialSkins SpecialSkin = SpecialSkins.None; public override Packets PacketId => Packets.ServerSetSpecialSkin; public ServerSetSpecialSkin(SpecialSkins specialSkin) { SpecialSkin = specialSkin; } public ServerSetSpecialSkin() { } public override void Write(BinaryWriter writer) { writer.Write((int)SpecialSkin); } public override void Read(BinaryReader reader) { SpecialSkin = (SpecialSkins)reader.ReadInt32(); } } public class ServerTeamGraffRaceScore : Packet { public int TagHash; public ushort PlayerId; public override Packets PacketId => Packets.ServerTeamGraffRaceScore; public ServerTeamGraffRaceScore() { } public ServerTeamGraffRaceScore(ushort playerId, int tagHash) { PlayerId = playerId; TagHash = tagHash; } public override void Read(BinaryReader reader) { PlayerId = reader.ReadUInt16(); TagHash = reader.ReadInt32(); } public override void Write(BinaryWriter writer) { writer.Write(PlayerId); writer.Write(TagHash); } } public class ServerTeleportPlayer : Packet { public Vector3 Position; public Quaternion Rotation; public override Packets PacketId => Packets.ServerTeleportPlayer; public ServerTeleportPlayer() { } public ServerTeleportPlayer(Vector3 position, Quaternion rotation) { Position = position; Rotation = rotation; } public override void Write(BinaryWriter writer) { writer.Write(Position.X); writer.Write(Position.Y); writer.Write(Position.Z); Compression.WriteCompressedQuaternion(Rotation, writer); } public override void Read(BinaryReader reader) { float x = reader.ReadSingle(); float y = reader.ReadSingle(); float z = reader.ReadSingle(); Position = new Vector3(x, y, z); Rotation = Compression.ReadCompressedQuaternion(reader); } } } namespace BombRushMP.Common.Networking { public class ConnectionFailedEventArgs { public readonly string Reason; public ConnectionFailedEventArgs(string reason) { Reason = reason; } } public class DisconnectedEventArgs { public readonly string Reason; public DisconnectedEventArgs(string reason) { Reason = reason; } } public interface IMessage { public enum SendModes { Unreliable, Reliable, ReliableUnordered } byte[] GetBytes(); IMessage Add(byte[] data); } public interface INetClient { bool IsConnected { get; } EventHandler Connected { get; set; } EventHandler MessageReceived { get; set; } EventHandler Disconnected { get; set; } EventHandler ConnectionFailed { get; set; } bool Connect(string address, int port); void Disconnect(); void Update(); void Send(IMessage message); } public interface INetConnection { bool CanQualityDisconnect { get; set; } ushort Id { get; } string Address { get; } void Send(IMessage message); } public interface INetServer { EventHandler MessageReceived { get; set; } EventHandler ClientDisconnected { get; set; } EventHandler ClientConnected { get; set; } int TimeoutTime { set; } void Start(ushort port, ushort maxPlayers); void DisconnectClient(ushort id); void DisconnectClient(INetConnection client); void Update(); void Stop(); } public interface INetworkingInterface { int MaxPayloadSize { get; set; } INetClient CreateClient(); INetServer CreateServer(); IMessage CreateMessage(IMessage.SendModes sendMode, NetChannels channel, Enum packetId); } public class MessageReceivedEventArgs { public readonly ushort MessageId; public readonly IMessage Message; public readonly INetConnection FromConnection; public MessageReceivedEventArgs(ushort messageId, IMessage message, INetConnection fromConnection) { MessageId = messageId; Message = message; FromConnection = fromConnection; } } public enum NetChannels : byte { Default, Gamemodes, ClientAndLobbyUpdates, VisualUpdates, Chat, Animation, Custom, MAX } public static class NetworkingEnvironment { public static INetworkingInterface NetworkingInterface; public static bool UseNativeSocketsIfAvailable = true; public static Action LogEventHandler; public static void Log(string message) { LogEventHandler?.Invoke(message); } } public class ServerConnectedEventArgs { public readonly INetConnection Client; public ServerConnectedEventArgs(INetConnection client) { Client = client; } } public class ServerDisconnectedEventArgs { public readonly INetConnection Client; public readonly string Reason; public ServerDisconnectedEventArgs(INetConnection client, string reason) { Client = client; Reason = reason; } } }