Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of SSMPEssentials v0.1.2
SSMPEssentials.dll
Decompiled a month agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Timers; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GlobalEnums; using HarmonyLib; using InControl; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using SSMP.Api.Client; using SSMP.Api.Client.Networking; using SSMP.Api.Command; using SSMP.Api.Command.Client; using SSMP.Api.Command.Server; using SSMP.Api.Server; using SSMP.Api.Server.Networking; using SSMP.Game; using SSMP.Game.Settings; using SSMP.Logging; using SSMP.Math; using SSMP.Networking.Packet; using SSMP.Networking.Packet.Data; using SSMPEssentials.Client; using SSMPEssentials.Client.Commands; using SSMPEssentials.Client.Modules; using SSMPEssentials.Client.Packets; using SSMPEssentials.Data; using SSMPEssentials.Server; using SSMPEssentials.Server.Commands; using SSMPEssentials.Server.Modules; using SSMPEssentials.Server.Packets; using SSMPEssentials.Utils; using SSMPEssentials.Utils.Tests; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("SSMPEssentials")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.2.0")] [assembly: AssemblyInformationalVersion("0.1.2+3a63a082276d69e01bd49966d2e99cf58d479675")] [assembly: AssemblyProduct("SSMPEssentials")] [assembly: AssemblyTitle("SSMPEssentials")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/BobbyTheCatfish/SSMP.Utils")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.2.0")] [module: UnverifiableCode] [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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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 BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace SSMPEssentials { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("io.github.bobbythecatfish.ssmp.essentials", "SSMPEssentials", "0.1.2")] public class SSMPEssentialsPlugin : BaseUnityPlugin { private TestManager testManager = new TestManager(); public static readonly List<Action> NextFrames = new List<Action>(); private List<Action> _nextFrames = new List<Action>(); internal static SSMPEssentialsPlugin instance; public const string Id = "io.github.bobbythecatfish.ssmp.essentials"; public static string Name => "SSMPEssentials"; public static string Version => "0.1.2"; private void Awake() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown instance = this; ClientAddon.RegisterAddon((ClientAddon)(object)new SSMPEssentials.Client.Client()); ServerAddon.RegisterAddon((ServerAddon)(object)new SSMPEssentials.Server.Server()); Config.Init(((BaseUnityPlugin)this).Config); ((BaseUnityPlugin)this).Logger.LogInfo((object)("Plugin " + Name + " (io.github.bobbythecatfish.ssmp.essentials) has loaded!")); new Harmony("ssmp.essentials").PatchAll(); HeroController.OnHeroInstanceSet += new HeroSetDelegate(InitializeHCModules); } private void InitializeHCModules(HeroController controller) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown HeroController.OnHeroInstanceSet -= new HeroSetDelegate(InitializeHCModules); Spectate.CreateFreecamUI(); PlayerDeaths.Init(); controller.OnDeath += PlayerDeaths.OnDeath; PlayerHealth.BlueHealthAddListener(); } private void Update() { if (Config.TestsEnabled) { testManager.Update(); } if (_nextFrames.Count > 0) { Action[] array = _nextFrames.ToArray(); _nextFrames.Clear(); Action[] array2 = array; for (int i = 0; i < array2.Length; i++) { array2[i](); } } Inputs.Update(); } private void LateUpdate() { if (NextFrames.Count > 0) { _nextFrames = NextFrames.ToList(); NextFrames.Clear(); } Spectate.Update(); } } } namespace SSMPEssentials.Utils { internal class Common { public static GameObject? HornetObject { get { if (!Object.op_Implicit((Object)(object)HeroController.SilentInstance)) { return null; } return ((Component)HeroController.SilentInstance).gameObject; } } public static string ServerTextColor(string text, Colors color) { return color switch { Colors.White => "&f", Colors.Black => "&1", Colors.Orange => "&6", Colors.Purple => "&5", Colors.Blue => "&b", Colors.Green => "&2", Colors.Red => "&4", Colors.Yellow => "&e", _ => "&f", } + text + "&r"; } public static string LocalTextColor(string text, Colors color) { string text2 = color switch { Colors.White => "#FFFFFF", Colors.Black => "#000000", Colors.Orange => "#FFAA00", Colors.Purple => "#AA00AA", Colors.Blue => "#55FFFF", Colors.Green => "#00AA00", Colors.Red => "#AA0000", Colors.Yellow => "#FFFF55", _ => "#FFFFFF", }; return "<color=" + text2 + ">" + text + "</color>"; } public static string ColoredUsername(IServerPlayer? player, Colors defaultColor = Colors.White) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected I4, but got Unknown if (player == null) { return ServerTextColor("Unknown Player", defaultColor); } string username = player.Username; Team team = player.Team; return (team - 1) switch { 3 => ServerTextColor(username, Colors.Blue), 0 => ServerTextColor(username, Colors.Green), 2 => ServerTextColor(username, Colors.Red), 1 => ServerTextColor(username, Colors.Orange), _ => ServerTextColor(username, defaultColor), }; } public static string ColoredUsername(IClientPlayer? player, Colors defaultColor = Colors.White) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected I4, but got Unknown if (player == null) { return LocalTextColor("Unknown Player", defaultColor); } string username = player.Username; Team team = player.Team; return (team - 1) switch { 3 => LocalTextColor(username, Colors.Blue), 0 => LocalTextColor(username, Colors.Green), 2 => LocalTextColor(username, Colors.Red), 1 => LocalTextColor(username, Colors.Orange), _ => LocalTextColor(username, defaultColor), }; } } public class Packet : IPacketData { public virtual bool IsReliable => true; public virtual bool DropReliableDataIfNewerExists => true; public virtual void WriteData(IPacket packet) { Log.LogInfo("THIS SHOULD NOT RUN"); } public virtual void ReadData(IPacket packet) { Log.LogInfo("THIS SHOULD NOT RUN"); } } internal static class Config { public const uint SSMPApiVersion = 1u; public const string ModName = "SSMP Essentials"; public const string Version = "0.1.2"; private static ConfigEntry<bool>? _testsEnabled; private static ConfigEntry<KeyCode>? _spectateNext; private static ConfigEntry<KeyCode>? _spectatePrevious; private static ConfigEntry<KeyCode>? _exitSpectate; private static ConfigEntry<KeyCode>? _freecamToggle; public static bool TestsEnabled => _testsEnabled?.Value ?? false; public static KeyCode SpectateNext => (KeyCode)(((??)_spectateNext?.Value) ?? 0); public static KeyCode SpectatePrevious => (KeyCode)(((??)_spectatePrevious?.Value) ?? 0); public static KeyCode ExitSpectate => (KeyCode)(((??)_exitSpectate?.Value) ?? 0); public static KeyCode FreecamToggle => (KeyCode)(((??)_freecamToggle?.Value) ?? 0); public static void Init(ConfigFile config) { _spectatePrevious = config.Bind<KeyCode>("Keybinds", "Spectate Previous Player", (KeyCode)50, (ConfigDescription)null); _spectateNext = config.Bind<KeyCode>("Keybinds", "Spectate Next Player", (KeyCode)51, (ConfigDescription)null); _exitSpectate = config.Bind<KeyCode>("Keybinds", "Exit Spectate Mode", (KeyCode)52, (ConfigDescription)null); _freecamToggle = config.Bind<KeyCode>("Keybinds", "Toggle Freecam Mode", (KeyCode)53, (ConfigDescription)null); } } internal enum PacketIDs { Huddle, TeleportRequest, TeleportAccept, Message, PlayerDeath, PlayerHealth, Settings } internal enum Messages { TeleportDenied } internal enum CauseOfDeath { Generic, Player, Enemy, Spikes, Acid, Lava, Pit, Coal, Zap, Explosion, Sink, Steam, Frost } internal enum Colors { Black, White, Blue, Green, Orange, Purple, Red, Yellow } internal static class GameObjectUtils { public static GameObject? FindGameObjectInChildren(this GameObject parent, string path) { string[] array = path.Split('/'); if ((Object)(object)parent == (Object)null) { return null; } for (int i = 0; i < array.Length; i++) { GameObject val = FindGameObjectLayer(array[i], parent); if ((Object)(object)val == (Object)null) { return null; } parent = val; } return parent; } private static GameObject? FindGameObjectLayer(string name, GameObject parent) { int childCount = parent.transform.childCount; for (int i = 0; i < childCount; i++) { Transform child = parent.transform.GetChild(i); if (((Object)child).name == name) { return ((Component)child).gameObject; } } Log.LogWarning(name + " not found"); return null; } } internal static class Inputs { private static float MovementAmount(PlayerAction action, PlayerAction inverseAction) { float num = 0.1f; if (((OneAxisInputControl)action).Value > num) { return ((OneAxisInputControl)action).Value; } if (OneAxisInputControl.op_Implicit((OneAxisInputControl)(object)inverseAction) > num) { return 0f - ((OneAxisInputControl)inverseAction).Value; } return 0f; } private static void FreecamMovement() { float num = 6f; HeroActions inputActions = ManagerSingleton<InputHandler>.Instance.inputActions; if (((OneAxisInputControl)inputActions.Dash).IsPressed) { num = 2f; } Spectate.FreecamMovementVector.x = MovementAmount(inputActions.Right, inputActions.Left) / num; Spectate.FreecamMovementVector.y = MovementAmount(inputActions.Up, inputActions.Down) / num; } public static void Update() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) IClientApi api = SSMPEssentials.Client.Client.api; if (api != null && api.UiManager.ChatBox.IsOpen) { return; } if (Input.GetKeyDown(Config.SpectateNext)) { Spectate.FocusOnPlayer(Spectate.MoveDir.Next); } else if (Input.GetKeyDown(Config.SpectatePrevious)) { Spectate.FocusOnPlayer(Spectate.MoveDir.Prev); } else if (Input.GetKeyDown(Config.ExitSpectate)) { Spectate.ReturnToSelf(); } else if (Input.GetKeyDown(Config.FreecamToggle)) { if (Spectate.freecam) { Spectate.ReturnToSelf(); } else { Spectate.Freecam(); } } if (Spectate.freecam) { FreecamMovement(); } } } internal class FakeLogger : ILogger { public void Debug(string message) { } public void Error(string message) { } public void Info(string message) { } public void Message(string message) { } public void Warn(string message) { } } internal static class Log { private static ILogger logger = (ILogger)(object)new FakeLogger(); public static void SetLogger(ILogger log) { logger = log; } private static bool ShouldLog(LogEventArgs log) { if (log.Source.SourceName == "SSMP" && log.Data is string text && text.StartsWith("[SSMPEssentials")) { return true; } return false; } public static void LogInfo(params object[] data) { foreach (object obj in data) { logger.Info(obj.ToString()); } } public static void LogWarning(params object[] data) { foreach (object obj in data) { logger.Warn(obj.ToString()); } } public static void LogError(params object[] data) { foreach (object obj in data) { logger.Error(obj.ToString()); } } public static void LogFatal(params object[] data) { foreach (object obj in data) { logger.Error(obj.ToString()); } } public static void LogDebug(params object[] data) { foreach (object obj in data) { logger.Debug(obj.ToString()); } } public static void LogMessage(params object[] data) { foreach (object obj in data) { logger.Message(obj.ToString()); } } } internal class NoRepeat<T> : IEnumerable { private List<T> _unused = new List<T>(); private List<T> _used = new List<T>(); private readonly Random random = new Random(); public void Add(T item) { _unused.Add(item); } public IEnumerator GetEnumerator() { return _unused.GetEnumerator(); } public T GetRandom() { if (_used.Count == 0 && _unused.Count <= 1) { if (_unused.Count == 0) { throw new Exception("NoRepeat was empty, could not return a proper value."); } return _unused[0]; } int index = random.Next(_unused.Count); T val = _unused[index]; _unused.RemoveAt(index); if (_unused.Count == 0) { _unused.AddRange(_used); _used = new List<T>(); } _used.Add(val); return val; } } } namespace SSMPEssentials.Utils.Tests { internal class TestManager { private List<BaseTest> tests = new List<BaseTest>(); public TestManager() { tests.Add(new WarpTest()); } public void Update() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) foreach (BaseTest test in tests) { if (Input.GetKeyDown(test.KeyCode)) { test.Execute(); } } } } internal class WarpTest : BaseTest { public override KeyCode KeyCode => (KeyCode)49; public override void Execute() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown SSMPEssentials.Client.PacketReceiver.OnHuddle(new TeleportPacket { Scene = "Bonetown", Position = new Vector2(100f, 15f) }); } } internal abstract class BaseTest { public abstract KeyCode KeyCode { get; } public abstract void Execute(); } } namespace SSMPEssentials.Server { internal static class PacketReceiver { public static void Init() { IServerAddonNetworkReceiver<PacketIDs> networkReceiver = Server.api.NetServer.GetNetworkReceiver<PacketIDs>((ServerAddon)(object)Server.instance, (Func<PacketIDs, IPacketData>)SSMPEssentials.Client.Packets.Packets.Instantiate); networkReceiver.RegisterPacketHandler<TeleportPacket>(PacketIDs.Huddle, (GenericServerPacketHandler<TeleportPacket>)OnHuddle); networkReceiver.RegisterPacketHandler<TeleportRequestPacket>(PacketIDs.TeleportRequest, (GenericServerPacketHandler<TeleportRequestPacket>)OnTeleportRequest); networkReceiver.RegisterPacketHandler<TeleportPacket>(PacketIDs.TeleportAccept, (GenericServerPacketHandler<TeleportPacket>)OnTeleportRequestAccept); networkReceiver.RegisterPacketHandler<MessagePacket>(PacketIDs.Message, (GenericServerPacketHandler<MessagePacket>)OnMessage); networkReceiver.RegisterPacketHandler<DeathPacket>(PacketIDs.PlayerDeath, (GenericServerPacketHandler<DeathPacket>)OnPlayerDeath); networkReceiver.RegisterPacketHandler<HealthPacket>(PacketIDs.PlayerHealth, (GenericServerPacketHandler<HealthPacket>)OnPlayerHealth); } public static void OnHuddle(ushort id, TeleportPacket data) { if (!Server.ServerSettings.HuddleEnabled) { Server.SendMessageToPlayer(id, "Huddles are currently disabled."); return; } IServerPlayer player = Server.GetPlayer(id); if (player == null || !player.IsAuthorized) { Server.SendMessageToPlayer(id, "You need to be authorized to use that command."); return; } if (data.Scene == "") { IServerPlayer player2 = Server.GetPlayer(data.PlayerId); if (player2 == null) { Server.SendMessageToPlayer(id, "I couldn't find that player."); return; } data.Scene = player2.CurrentScene; data.Position = player2.Position ?? Vector2.Zero; } else { data.PlayerId = id; } PacketSender.BroadcastWarp(data.Scene, data.Position, data.PlayerId); } public static void OnTeleportRequest(ushort id, TeleportRequestPacket data) { if (!Server.ServerSettings.TeleportsEnabled) { Server.SendMessageToPlayer(id, "Teleporting is currently disabled."); } else if (Server.GetPlayer(data.PlayerId) == null) { Server.SendMessageToPlayer(id, "I couldn't find that player."); } else { PacketSender.SendTeleportRequest(data.PlayerId, id); } } public static void OnTeleportRequestAccept(ushort id, TeleportPacket data) { if (!Server.ServerSettings.TeleportsEnabled) { Server.SendMessageToPlayer(id, "Teleporting is currently disabled."); } else if (Server.GetPlayer(data.PlayerId) == null) { Server.SendMessageToPlayer(id, "I couldn't find that player."); } else { PacketSender.SendTeleportAccepted(data.PlayerId, id, data.Scene, data.Position); } } public static void OnMessage(ushort id, MessagePacket data) { if (Server.GetPlayer(data.PlayerId) == null) { Server.SendMessageToPlayer(id, "I couldn't find that player."); } else { PacketSender.SendMessage(data.PlayerId, id, data.Message); } } public static void OnPlayerDeath(ushort id, DeathPacket data) { if (!Server.ServerSettings.DeathMessagesEnabled) { return; } IServerPlayer player = Server.GetPlayer(id); if (player != null) { IServerPlayer player2 = Server.GetPlayer(data.KillerID); string text = Common.ColoredUsername(player) + " " + DetermineDeathString(data.Cause, player2); if (data.Cause != CauseOfDeath.Player && data.RanAway) { text = text + " while fighting " + Common.ColoredUsername(player2); } Server.api.ServerManager.BroadcastMessage(text); } } private static string DetermineDeathString(CauseOfDeath cause, IServerPlayer? player) { if (!DeathMessages.Messages.TryGetValue(cause, out NoRepeat<string> value)) { value = DeathMessages.Messages[CauseOfDeath.Generic]; } string text = value.GetRandom(); if (cause == CauseOfDeath.Player) { text = text + " " + Common.ColoredUsername(player); } return text; } private static void OnPlayerHealth(ushort id, HealthPacket data) { Log.LogDebug($"Received health from {id}: {data.Health}"); StoredPlayerData player = PlayerDataTracker.ServerInstance.GetPlayer(id); player.Health = data.Health; PacketSender.BroadcastPlayerHealth(id, player.Health); } } internal static class PacketSender { private static IServerAddonNetworkSender<PacketIDs>? sender; internal static void Init() { sender = Server.api.NetServer.GetNetworkSender<PacketIDs>((ServerAddon)(object)Server.instance); } private static void Broadcast(PacketIDs id, Packet packet, ushort senderId, bool collection = true) { if (sender == null) { Log.LogError("Unable to send packet, packet sender is null."); return; } foreach (IServerPlayer player in Server.api.ServerManager.Players) { if (player.Id != senderId) { if (collection) { sender.SendCollectionData<Packet>(id, packet, player.Id); } else { sender.SendSingleData(id, (IPacketData)(object)packet, player.Id); } } } } internal static void BroadcastWarp(string scene, Vector2 position, ushort destinationPlayerId) { TeleportPacket packet = new TeleportPacket { Scene = scene, Position = position }; Broadcast(PacketIDs.Huddle, packet, destinationPlayerId, collection: false); } internal static void SendTeleportRequest(ushort targetPlayerId, ushort senderId) { TeleportRequestPacket teleportRequestPacket = new TeleportRequestPacket { PlayerId = senderId }; if (sender == null) { Log.LogError("Unable to send packet, packet sender is null."); } else { sender.SendCollectionData<TeleportRequestPacket>(PacketIDs.TeleportRequest, teleportRequestPacket, targetPlayerId); } } internal static void SendTeleportAccepted(ushort playerToTeleportId, ushort destinationPlayerId, string scene, Vector2 position) { TeleportPacket teleportPacket = new TeleportPacket { PlayerId = destinationPlayerId, Position = position, Scene = scene }; if (sender == null) { Log.LogError("Unable to send packet, packet sender is null."); } else { sender.SendSingleData(PacketIDs.TeleportAccept, (IPacketData)(object)teleportPacket, playerToTeleportId); } } internal static void SendMessage(ushort recipientId, ushort senderId, Messages message) { MessagePacket messagePacket = new MessagePacket { Message = message, PlayerId = senderId }; if (sender == null) { Log.LogError("Unable to send packet, packet sender is null."); } else { sender.SendCollectionData<MessagePacket>(PacketIDs.Message, messagePacket, recipientId); } } internal static void BroadcastPlayerHealth(ushort playerId, HealthData health) { PlayerHealthPacket packet = new PlayerHealthPacket { PlayerId = playerId, Health = health }; Broadcast(PacketIDs.PlayerHealth, packet, playerId); } internal static void SendAllPlayerHealth(ushort recipientId) { if (sender == null) { Log.LogError("Unable to send packet, packet sender is null."); return; } foreach (StoredPlayerData allDatum in PlayerDataTracker.ServerInstance.GetAllData()) { PlayerHealthPacket playerHealthPacket = new PlayerHealthPacket { PlayerId = allDatum.Id, Health = allDatum.Health }; sender.SendCollectionData<PlayerHealthPacket>(PacketIDs.PlayerHealth, playerHealthPacket, recipientId); } } internal static void BroadcastSettingsUpdate() { SettingsPacket settingsPacket = new SettingsPacket { ServerSettings = Server.ServerSettings }; if (sender == null) { Log.LogError("Unable to send packet, packet sender is null."); } else { sender.BroadcastSingleData(PacketIDs.Settings, (IPacketData)(object)settingsPacket); } } internal static void SendSettingsUpdate(ushort id) { SettingsPacket settingsPacket = new SettingsPacket { ServerSettings = Server.ServerSettings }; if (sender == null) { Log.LogError("Unable to send packet, packet sender is null."); } else { sender.SendSingleData(PacketIDs.Settings, (IPacketData)(object)settingsPacket, id); } } } internal class Server : ServerAddon { internal static IServerApi api; internal static Server instance; internal static ServerSettings ServerSettings = new ServerSettings(client: false); protected override string Name => "SSMP Essentials"; protected override string Version => "0.1.2"; public override uint ApiVersion => 1u; public override bool NeedsNetwork => true; public override void Initialize(IServerApi serverApi) { instance = this; api = serverApi; Log.SetLogger(((ServerAddon)this).Logger); serverApi.ServerManager.PlayerConnectEvent += SendJoinInfo; ((ICommandManager<IServerCommand>)(object)serverApi.CommandManager).RegisterCommand((IServerCommand)(object)new SettingsCommand()); ServerSettings = SSMPEssentials.Server.Modules.ServerSettings.ReadFromFile(); PacketReceiver.Init(); PacketSender.Init(); Log.LogInfo("SSMP Essentials Server Initialized"); } public static IServerPlayer? GetPlayer(ushort id) { return api.ServerManager.GetPlayer(id); } public static void SendMessageToPlayer(ushort id, string message) { api.ServerManager.SendMessage(id, message); } public static void BroadcastMessage(string message) { api.ServerManager.BroadcastMessage(message); } private static void SendJoinInfo(IServerPlayer player) { PacketSender.SendSettingsUpdate(player.Id); PacketSender.SendAllPlayerHealth(player.Id); } } } namespace SSMPEssentials.Server.Packets { internal class PlayerHealthPacket : HealthPacket { public ushort PlayerId; public override void WriteData(IPacket packet) { base.WriteData(packet); packet.Write(PlayerId); } public override void ReadData(IPacket packet) { base.ReadData(packet); PlayerId = packet.ReadUShort(); } } internal class SettingsPacket : Packet { public ServerSettings ServerSettings; public override void WriteData(IPacket packet) { foreach (PropertyInfo prop in ServerSettings.GetProps()) { if (prop.CanRead) { packet.Write((bool)prop.GetValue(ServerSettings, null)); } } } public override void ReadData(IPacket packet) { ServerSettings = new ServerSettings(client: false); foreach (PropertyInfo prop in ServerSettings.GetProps()) { if (prop.CanWrite) { prop.SetValue(ServerSettings, packet.ReadBool(), null); } } } } public static class Packets { internal class ErrorThrowingPacket : Packet { public ErrorThrowingPacket(PacketIDs id, bool server) { Log.LogError(id.ToString(), server); throw new NotImplementedException(id.ToString()); } } internal static IPacketData Instantiate(PacketIDs packetID) { return (IPacketData)(packetID switch { PacketIDs.Huddle => new TeleportPacket(), PacketIDs.TeleportRequest => new PacketDataCollection<TeleportRequestPacket>(), PacketIDs.TeleportAccept => new TeleportPacket(), PacketIDs.Message => new PacketDataCollection<MessagePacket>(), PacketIDs.PlayerHealth => new PacketDataCollection<PlayerHealthPacket>(), PacketIDs.Settings => new SettingsPacket(), _ => new ErrorThrowingPacket(packetID, server: true), }); } } } namespace SSMPEssentials.Server.Modules { internal class ServerSettings { [CompilerGenerated] private sealed class <GetProps>d__39 : IEnumerable<PropertyInfo>, IEnumerable, IEnumerator<PropertyInfo>, IEnumerator, IDisposable { private int <>1__state; private PropertyInfo <>2__current; private int <>l__initialThreadId; private PropertyInfo[] <>7__wrap1; private int <>7__wrap2; PropertyInfo IEnumerator<PropertyInfo>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <GetProps>d__39(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <>7__wrap1 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: { <>1__state = -1; PropertyInfo[] properties = typeof(ServerSettings).GetProperties(); <>7__wrap1 = properties; <>7__wrap2 = 0; break; } case 1: <>1__state = -1; <>7__wrap2++; break; } if (<>7__wrap2 < <>7__wrap1.Length) { PropertyInfo propertyInfo = <>7__wrap1[<>7__wrap2]; <>2__current = propertyInfo; <>1__state = 1; return true; } <>7__wrap1 = null; return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<PropertyInfo> IEnumerable<PropertyInfo>.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new <GetProps>d__39(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<PropertyInfo>)this).GetEnumerator(); } } [JsonProperty("huddle")] [SettingAlias(new string[] { "huddle" })] public bool HuddleEnabled { get; set; } = true; [JsonProperty("teleport")] [SettingAlias(new string[] { "tp", "teleport" })] public bool TeleportsEnabled { get; set; } = true; [JsonProperty("back")] [SettingAlias(new string[] { "back", "tpback" })] public bool BackEnabled { get; set; } = true; [JsonProperty("teleport_requests")] [SettingAlias(new string[] { "tprequests", "tpa", "tpd", "tpr", "tpreq" })] public bool TeleportsNeedRequests { get; set; } = true; [JsonProperty("death_messages")] [SettingAlias(new string[] { "deathmessages", "death" })] public bool DeathMessagesEnabled { get; set; } = true; [JsonProperty("healthbars")] [SettingAlias(new string[] { "healthbars", "health" })] public bool HealthbarsEnabled { get; set; } = true; [JsonProperty("spectate")] [SettingAlias(new string[] { "spectate" })] public bool SpectateEnabled { get; set; } = true; [JsonProperty("spectate_team")] [SettingAlias(new string[] { "spectateteam" })] public bool SpectateTeamOnly { get; set; } [JsonProperty("freecam")] [SettingAlias(new string[] { "freecam" })] public bool FreecamEnabled { get; set; } = true; private static string Filepath() { return Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "ServerSettings.json"); } public static ServerSettings ReadFromFile() { string text = Filepath(); if (!File.Exists(text)) { Log.LogWarning(text + " doesn't exist"); new ServerSettings(client: false).WriteToFile(); return new ServerSettings(client: false); } try { return JsonConvert.DeserializeObject<ServerSettings>(File.ReadAllText(text)) ?? new ServerSettings(client: false); } catch (Exception arg) { Log.LogError($"Could not load server settings from file:\n{arg}"); return new ServerSettings(client: false); } } public void WriteToFile() { string text = Filepath(); if (!Directory.Exists(Path.GetDirectoryName(text))) { Log.LogWarning(text + " directory doesn't exist"); return; } string text2 = JsonConvert.SerializeObject((object)this, (Formatting)1); if (text2 == null) { return; } try { File.WriteAllText(text, text2); } catch (Exception arg) { Log.LogError($"Could not write server settings to file:\n{arg}"); } } [IteratorStateMachine(typeof(<GetProps>d__39))] public IEnumerable<PropertyInfo> GetProps() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <GetProps>d__39(-2); } public ServerSettings(bool client) { foreach (PropertyInfo prop in GetProps()) { prop.SetValue(this, !client); } } } } namespace SSMPEssentials.Server.Commands { internal class SettingsCommand : IServerCommand, ICommand { private const string SETTING_SUB = "set"; public bool AuthorizedOnly => true; public string Trigger => "/essentials"; public string[] Aliases => new string[3] { "/essential", "/ess", "/e" }; public void Execute(ICommandSender sender, string[] arguments) { string text = "Invalid Syntax. " + Trigger + " set <setting> <true/false>"; if (arguments.Length < 2) { sender.SendMessage(text); return; } IEnumerable<PropertyInfo> props = Server.ServerSettings.GetProps(); List<string> list = new List<string>(); Dictionary<string, PropertyInfo> dictionary = new Dictionary<string, PropertyInfo>(); foreach (PropertyInfo item in props) { SettingAliasAttribute customAttribute = ((MemberInfo)item).GetCustomAttribute<SettingAliasAttribute>(); dictionary.Add(item.Name, item); if (customAttribute == null || customAttribute.Aliases.Length == 0) { list.Add(item.Name); continue; } list.Add(customAttribute.Aliases[0]); string[] aliases = customAttribute.Aliases; foreach (string key in aliases) { dictionary.Add(key, item); } } string text2 = "Valid settings are " + string.Join(", ", list); if (arguments.Length == 2) { sender.SendMessage(text2); return; } string key2 = arguments[2].ToLower().Replace("_", ""); if (!dictionary.TryGetValue(key2, out var value)) { sender.SendMessage(text2); return; } if (arguments.Length == 3) { object value2 = value.GetValue(Server.ServerSettings); sender.SendMessage($"Setting '{value.Name}' currently has value: {value2}"); return; } string text3 = arguments[3].ToLower(); if (text3 != "true" && text3 != "false") { sender.SendMessage(text); return; } bool flag = text3 == "true"; value.SetValue(Server.ServerSettings, flag); Server.BroadcastMessage($"Changed setting '{value.Name}' to: {flag}"); Server.ServerSettings.WriteToFile(); PacketSender.BroadcastSettingsUpdate(); } } } namespace SSMPEssentials.Data { internal static class DeathMessages { public static readonly Dictionary<CauseOfDeath, NoRepeat<string>> Messages = new Dictionary<CauseOfDeath, NoRepeat<string>> { { CauseOfDeath.Generic, new NoRepeat<string> { "died of unnatural causes", "unalived", "was killed", "decided to set up a Cocoon Skip", "took damage equal to or more than their current HP" } }, { CauseOfDeath.Player, new NoRepeat<string> { "lost a duel to", "made masterful use of their vulnerability frames while fighting", "failed to negotiate with", "regrettably ended their encounter with", "fell to one of the classic blunders while fighting" } }, { CauseOfDeath.Enemy, new NoRepeat<string> { "had an intimate encounter with an enemy", "made masterful use of their vulnerability frames", "didn't see the enemy's final form", "mistook an enemy hitbox for a wall", "was squashed by a common bug" } }, { CauseOfDeath.Spikes, new NoRepeat<string> { "got impaled by spikes", "didn't see the sharp things", "fought the spikes and lost", "attempted rudimentary acupuncture", "was pricked to death" } }, { CauseOfDeath.Acid, new NoRepeat<string> { "forgot to equip Isma's Tear before hopping in acid", "mistook sulfuric acid for water", "tried to swim in acid", "got into a fight with a pool of liquid" } }, { CauseOfDeath.Lava, new NoRepeat<string> { "discovered what the sun feels like", "had a charring revelation", "tried to swim in lava", "went up in flames", "discovered the floor was lava" } }, { CauseOfDeath.Pit, new NoRepeat<string> { "fell down a hole", "never hit the bottom", "saw a giant ravine and decided to jump", "hit the ground too hard", "was doomed to fall" } }, { CauseOfDeath.Coal, new NoRepeat<string> { "got hit in the head by a lump of coal", "shouldn't have collected all those hot rocks", "was burned to a crisp by a chunk of rock", "discovered that coals are hot" } }, { CauseOfDeath.Zap, new NoRepeat<string> { "was electrocuted to death", "was utterly shocked", "became one with the Voltvyrm" } }, { CauseOfDeath.Explosion, new NoRepeat<string> { "went Last Judge mode and blew up", "was blown to fluff", "looked back at the explosion", "went out with a bang" } }, { CauseOfDeath.Sink, new NoRepeat<string> { "sunk so low that they couldn't get out", "fell out of the world" } }, { CauseOfDeath.Steam, new NoRepeat<string> { "took a ride in a tea kettle", "fell into a pressure cooker", "got a face full of hot air", "was caught venting", "was blown away by the amount of steam in the organ" } }, { CauseOfDeath.Frost, new NoRepeat<string> { "chilled out a little too hard", "froze up", "froze to death", "forgot to wear a coat", "became an icicle" } } }; } internal class PlayerDataTracker { internal static PlayerDataTracker ClientInstance = new PlayerDataTracker(); internal static PlayerDataTracker ServerInstance = new PlayerDataTracker(); private readonly Dictionary<ushort, StoredPlayerData> data = new Dictionary<ushort, StoredPlayerData>(); public StoredPlayerData GetPlayer(ushort id) { if (data.TryGetValue(id, out StoredPlayerData value)) { return value; } value = new StoredPlayerData(id); data.Add(id, value); return value; } public List<StoredPlayerData> GetAllData() { return data.Values.ToList(); } } internal class StoredPlayerData { public ushort Id; public HealthData Health = new HealthData(); public StoredPlayerData(ushort id) { Id = id; } } public class HealthData { public int Health = 5; public int MaxHealth = 5; public int BlueHealth; public bool LifebloodState; public override string ToString() { return $"{Health}/{MaxHealth} + {BlueHealth} ({LifebloodState})"; } } } namespace SSMPEssentials.Client { internal class Client : ClientAddon { internal static IClientApi api; internal static Client instance; internal static ServerSettings ServerSettings = new ServerSettings(client: true); internal static Action OnServerSettingsUpdate = delegate { }; internal static Action<ServerSettings>? OnSSMPSettingsUpdate; protected override string Name => "SSMP Essentials"; protected override string Version => "0.1.2"; public override uint ApiVersion => 1u; public override bool NeedsNetwork => true; public override void Initialize(IClientApi clientApi) { instance = this; api = clientApi; Log.SetLogger(((ClientAddon)this).Logger); PacketReceiver.Init(); PacketSender.Init(); ((ICommandManager<IClientCommand>)(object)api.CommandManager).RegisterCommand((IClientCommand)(object)new Huddle()); ((ICommandManager<IClientCommand>)(object)api.CommandManager).RegisterCommand((IClientCommand)(object)new TeleportRequest()); ((ICommandManager<IClientCommand>)(object)api.CommandManager).RegisterCommand((IClientCommand)(object)new TeleportAccept()); ((ICommandManager<IClientCommand>)(object)api.CommandManager).RegisterCommand((IClientCommand)(object)new TeleportDeny()); ((ICommandManager<IClientCommand>)(object)api.CommandManager).RegisterCommand((IClientCommand)(object)new TeleportBack()); api.ClientManager.DisconnectEvent += delegate { Spectate.ReturnToSelf(); }; api.ClientManager.PlayerEnterSceneEvent += PlayerHealth.OnPlayerEnter; Spectate.Init(); Log.LogInfo("SSMP Essentials Client Initialized"); } public static void LocalChat(string message) { string message2 = message; SSMPEssentialsPlugin.NextFrames.Add(delegate { api.UiManager.ChatBox.AddMessage(message2); }); } public static IClientPlayer? GetPlayerByName(string username) { string username2 = username; return ((IEnumerable<IClientPlayer>)api.ClientManager.Players).FirstOrDefault((Func<IClientPlayer, bool>)((IClientPlayer p) => p.Username.Equals(username2, StringComparison.CurrentCultureIgnoreCase))); } public static IClientPlayer? GetPlayer(ushort id) { return api.ClientManager.GetPlayer(id); } public static ServerSettings GetClientServerSettings() { IClientManager clientManager = api.ClientManager; ((object)clientManager).GetType(); return Traverse.Create((object)clientManager).Field("_modSettings").Property("ServerSettings", (object[])null) .GetValue<ServerSettings>(); } } internal static class PacketReceiver { public static void Init() { IClientAddonNetworkReceiver<PacketIDs> networkReceiver = Client.api.NetClient.GetNetworkReceiver<PacketIDs>((ClientAddon)(object)Client.instance, (Func<PacketIDs, IPacketData>)SSMPEssentials.Server.Packets.Packets.Instantiate); networkReceiver.RegisterPacketHandler<TeleportPacket>(PacketIDs.Huddle, (GenericClientPacketHandler<TeleportPacket>)OnHuddle); networkReceiver.RegisterPacketHandler<TeleportRequestPacket>(PacketIDs.TeleportRequest, (GenericClientPacketHandler<TeleportRequestPacket>)OnTeleportRequest); networkReceiver.RegisterPacketHandler<TeleportPacket>(PacketIDs.TeleportAccept, (GenericClientPacketHandler<TeleportPacket>)OnTeleportAccepted); networkReceiver.RegisterPacketHandler<MessagePacket>(PacketIDs.Message, (GenericClientPacketHandler<MessagePacket>)OnMessage); networkReceiver.RegisterPacketHandler<PlayerHealthPacket>(PacketIDs.PlayerHealth, (GenericClientPacketHandler<PlayerHealthPacket>)OnHealth); networkReceiver.RegisterPacketHandler<SettingsPacket>(PacketIDs.Settings, (GenericClientPacketHandler<SettingsPacket>)OnSettings); } public static void OnHuddle(TeleportPacket data) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) new Warp(data.Scene, (Vector2)data.Position).WarpToPosition(); } public static void OnTeleportRequest(TeleportRequestPacket data) { IClientPlayer player = Client.GetPlayer(data.PlayerId); if (player == null) { Client.LocalChat("Received teleport request from unknown player. Ignoring."); } else if (!Client.ServerSettings.TeleportsNeedRequests) { PacketSender.SendTeleportAccept(new TeleportRequests.Request(data.PlayerId)); } else { TeleportRequests.AddRequest(player); } } public static void OnTeleportAccepted(TeleportPacket data) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) IClientPlayer player = Client.GetPlayer(data.PlayerId); Client.LocalChat("Teleport request accepted. Teleporting to " + Common.ColoredUsername(player) + " now..."); new Warp(data.Scene, (Vector2)data.Position).WarpToPosition(); } public static void OnMessage(MessagePacket data) { IClientPlayer player = Client.GetPlayer(data.PlayerId); if (data.Message == Messages.TeleportDenied) { string message = Common.ColoredUsername(player) + " denied your teleport request."; Client.LocalChat(message); return; } throw new NotImplementedException(); } public static void OnHealth(PlayerHealthPacket data) { IClientPlayer player = Client.GetPlayer(data.PlayerId); if (player != null) { PlayerHealth.SetPlayerHealth(player, data.Health); } } public static void OnSettings(SettingsPacket data) { Client.ServerSettings = data.ServerSettings; Client.OnServerSettingsUpdate(); } } internal static class PacketSender { private static IClientAddonNetworkSender<PacketIDs>? sender; internal static void Init() { sender = Client.api.NetClient.GetNetworkSender<PacketIDs>((ClientAddon)(object)Client.instance); } private static void SendData(PacketIDs packetId, IPacketData data) { if (Client.api.NetClient.IsConnected && sender != null) { sender.SendSingleData(packetId, data); } } internal static void SendMessage(ushort id, Messages message) { MessagePacket data = new MessagePacket { Message = message, PlayerId = id }; SendData(PacketIDs.Message, (IPacketData)(object)data); } internal static void SendHuddle() { if (Warp.GetHornetScenePosition(out string scene, out Vector2 position)) { Log.LogDebug($"Sending huddle packet for scene {scene} at location {position}"); SendData(PacketIDs.Huddle, (IPacketData)(object)new TeleportPacket { Scene = scene, Position = position }); } } internal static void SendHuddle(ushort id) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Invalid comparison between Unknown and I4 if ((Object)(object)GameManager.SilentInstance == (Object)null || (int)GameManager.SilentInstance.GameState != 4) { Client.LocalChat("Resume the game first!"); return; } Log.LogDebug($"Sending huddle packet for user {id}"); SendData(PacketIDs.Huddle, (IPacketData)(object)new TeleportPacket { Scene = "", Position = Vector2.Zero, PlayerId = id }); } internal static void SendTeleportAccept(TeleportRequests.Request request) { if (Warp.GetHornetScenePosition(out string scene, out Vector2 position)) { request.Responded = true; Log.LogDebug($"Sending teleport accept to {request.PlayerId}"); SendData(PacketIDs.TeleportAccept, (IPacketData)(object)new TeleportPacket { Scene = scene, Position = position, PlayerId = request.PlayerId }); } } internal static void SendTeleportRequest(ushort playerId) { TeleportRequestPacket data = new TeleportRequestPacket { PlayerId = playerId }; SendData(PacketIDs.TeleportRequest, (IPacketData)(object)data); } internal static void SendDeath(CauseOfDeath cause, ushort killerId = 0, bool ranAway = false) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; SceneTeleportMap.GetTeleportMap().TryGetValue(name, out var value); string scene = name; if (value != null) { string str = ((object)(MapZone)(ref value.MapZone)).ToString().Replace('_', ' '); scene = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(str); } DeathPacket data = new DeathPacket { Scene = scene, KillerID = killerId, Cause = cause, RanAway = ranAway }; SendData(PacketIDs.PlayerDeath, (IPacketData)(object)data); } internal static void SendHealth(HealthData healthData) { Log.LogDebug($"Sending health: {healthData}"); HealthPacket data = new HealthPacket { Health = healthData }; SendData(PacketIDs.PlayerHealth, (IPacketData)(object)data); } } } namespace SSMPEssentials.Client.Packets { internal class TeleportPacket : Packet { public ushort PlayerId; public string Scene = ""; public Vector2 Position = Vector2.Zero; public override void WriteData(IPacket packet) { packet.Write(PlayerId); packet.Write(Scene); packet.Write(Position); } public override void ReadData(IPacket packet) { PlayerId = packet.ReadUShort(); Scene = packet.ReadString(); Position = packet.ReadVector2(); } } internal class MessagePacket : IPacketData { public ushort PlayerId; public Messages Message; public bool IsReliable => true; public bool DropReliableDataIfNewerExists => true; public void WriteData(IPacket packet) { packet.Write(PlayerId); packet.Write((ushort)Message); } public void ReadData(IPacket packet) { PlayerId = packet.ReadUShort(); Message = (Messages)packet.ReadUShort(); } } internal class TeleportRequestPacket : IPacketData { public ushort PlayerId; public bool IsReliable => true; public bool DropReliableDataIfNewerExists => true; public void WriteData(IPacket packet) { packet.Write(PlayerId); } public void ReadData(IPacket packet) { PlayerId = packet.ReadUShort(); } } internal class DeathPacket : IPacketData { public ushort KillerID; public CauseOfDeath Cause; public bool RanAway; public string Scene = ""; public bool IsReliable => true; public bool DropReliableDataIfNewerExists => true; public virtual void WriteData(IPacket packet) { packet.Write(KillerID); packet.Write((ushort)Cause); packet.Write(RanAway); packet.Write(Scene); } public virtual void ReadData(IPacket packet) { KillerID = packet.ReadUShort(); Cause = (CauseOfDeath)packet.ReadUShort(); RanAway = packet.ReadBool(); Scene = packet.ReadString(); } } public class HealthPacket : Packet { public HealthData Health = new HealthData(); public override void WriteData(IPacket packet) { packet.Write(Health.Health); packet.Write(Health.MaxHealth); packet.Write(Health.BlueHealth); packet.Write(Health.LifebloodState); } public override void ReadData(IPacket packet) { Health = new HealthData(); Health.Health = packet.ReadInt(); Health.MaxHealth = packet.ReadInt(); Health.BlueHealth = packet.ReadInt(); Health.LifebloodState = packet.ReadBool(); } } public static class Packets { internal static IPacketData Instantiate(PacketIDs packetID) { return (IPacketData)(packetID switch { PacketIDs.Huddle => new TeleportPacket(), PacketIDs.TeleportRequest => new TeleportRequestPacket(), PacketIDs.TeleportAccept => new TeleportPacket(), PacketIDs.Message => new MessagePacket(), PacketIDs.PlayerDeath => new DeathPacket(), PacketIDs.PlayerHealth => new HealthPacket(), _ => new SSMPEssentials.Server.Packets.Packets.ErrorThrowingPacket(packetID, server: false), }); } } } namespace SSMPEssentials.Client.Modules { internal static class PlayerDeaths { public static CauseOfDeath LatestCause = CauseOfDeath.Generic; public static ushort LatestPlayerAttack = 0; public static DateTime LastDamageTime = DateTime.Now; public static DateTime PlayerAttackTime = DateTime.MinValue; public static void Init() { EventRegister val = ((IEnumerable<EventRegister>)((Component)HeroController.instance).gameObject.GetComponents<EventRegister>()).FirstOrDefault((Func<EventRegister, bool>)((EventRegister r) => r.subscribedEvent == "HERO DAMAGED")); if ((Object)(object)val != (Object)null) { ((EventBase)val).ReceivedEvent += LastDitchEffort; } } private static void LastDitchEffort() { if (LastDamageTime.AddSeconds(1.0) < DateTime.Now) { LastDamageTime = DateTime.Now; LatestCause = CauseOfDeath.Generic; } } public static void OnDeath() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (Client.ServerSettings.DeathMessagesEnabled) { bool ranAway = PlayerAttackTime.AddSeconds(15.0) > DateTime.Now; PacketSender.SendDeath(LatestCause, LatestPlayerAttack, ranAway); Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; GameObject hornetObject = Common.HornetObject; if (!((Object)(object)hornetObject == (Object)null)) { LatestCause = CauseOfDeath.Generic; LatestPlayerAttack = 0; TeleportBack.PreviousScene = name; TeleportBack.PreviousLocation = Vector2.op_Implicit(hornetObject.transform.position); } } } public static void DetermineCauseOfDamage(DamageHero damager) { //IL_010e: Unknown result type (might be due to invalid IL or missing references) LastDamageTime = DateTime.Now; if (Object.op_Implicit((Object)(object)((Component)damager).GetComponentInParent<FireballProjectile>())) { LatestCause = CauseOfDeath.Coal; return; } if (((Component)damager).CompareTag("Explosion")) { LatestCause = CauseOfDeath.Explosion; return; } bool flag = false; Transform parent = ((Component)damager).transform; while ((Object)(object)parent != (Object)null && !flag) { if (((Object)parent).name == "Player Prefab") { flag = true; } else { parent = parent.parent; } } Log.LogDebug(flag, ((Object)damager).name); if (flag && Object.op_Implicit((Object)(object)parent)) { LatestCause = CauseOfDeath.Player; IClientPlayer val = ((IEnumerable<IClientPlayer>)Client.api.ClientManager.Players).FirstOrDefault((Func<IClientPlayer, bool>)((IClientPlayer p) => (Object)(object)p.PlayerObject == (Object)(object)((Component)parent).gameObject)); if (val == null) { Log.LogWarning("Attacked by unknown player"); } else { LatestPlayerAttack = (ushort)((val != null) ? val.Id : 0); PlayerAttackTime = DateTime.Now; } } else { LatestCause = DetermineHazardType(damager.hazardType); } } private static CauseOfDeath DetermineHazardType(HazardType hazardType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected I4, but got Unknown return (hazardType - 1) switch { 0 => CauseOfDeath.Enemy, 1 => CauseOfDeath.Spikes, 2 => CauseOfDeath.Acid, 3 => CauseOfDeath.Lava, 4 => CauseOfDeath.Pit, 5 => CauseOfDeath.Coal, 6 => CauseOfDeath.Zap, 7 => CauseOfDeath.Explosion, 8 => CauseOfDeath.Sink, 9 => CauseOfDeath.Steam, 10 => CauseOfDeath.Generic, _ => CauseOfDeath.Generic, }; } } internal static class PlayerHealth { private static GameObject? maskPrefab; public const int MAX_HEALTH = 10; public const int MAX_BLUE_MASKS = 8; public const int MAX_TOTAL_HEALTH = 18; public const int NORMAL_MASK_ID = 9; public const int MISSING_MASK_ID = 0; public const int BLUE_MASK_ID = 50; public const int HIVE_MASK_ID = 194; public static void OnHealthChange() { PlayerData playerData = HeroController.instance.playerData; PacketSender.SendHealth(new HealthData { Health = playerData.health, MaxHealth = playerData.maxHealth, BlueHealth = playerData.healthBlue, LifebloodState = HeroController.instance.IsInLifebloodState }); } public static void BlueHealthAddListener() { string path = "In-game/Anchor TL/Hud Canvas Offset/Hud Canvas/Health"; GameObject val = ((Component)GameCameras.instance.hudCamera).gameObject.FindGameObjectInChildren(path); if ((Object)(object)val != (Object)null) { EventRegister val2 = ((IEnumerable<EventRegister>)val.GetComponents<EventRegister>()).FirstOrDefault((Func<EventRegister, bool>)((EventRegister r) => r.SubscribedEvent == "ADD BLUE HEALTH")); if ((Object)(object)val2 == (Object)null) { Log.LogError("Unable to hook Lifeblood Health Updates"); } else { ((EventBase)val2).ReceivedEvent += OnHealthChange; } } } public static void OnPlayerEnter(IClientPlayer player) { GameObject playerContainer = player.PlayerContainer; if (!((Object)(object)playerContainer == (Object)null)) { FindOrCreateHealthBar(playerContainer, player.Id).Refresh(); } } public static void SetPlayerHealth(IClientPlayer player, HealthData healthData) { int health = Math.Clamp(healthData.Health, 0, 10); int maxHealth = Math.Clamp(healthData.MaxHealth, 0, 10); int blueHealth = Math.Clamp(healthData.BlueHealth, 0, 8); HealthData health2 = PlayerDataTracker.ClientInstance.GetPlayer(player.Id).Health; health2.Health = health; health2.MaxHealth = maxHealth; health2.BlueHealth = blueHealth; health2.LifebloodState = healthData.LifebloodState; GameObject playerContainer = player.PlayerContainer; if (!((Object)(object)playerContainer == (Object)null)) { FindOrCreateHealthBar(playerContainer, player.Id).Refresh(); } } public static HealthDisplay FindOrCreateHealthBar(GameObject playerContainer, ushort id) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) HealthDisplay healthDisplay = playerContainer.GetComponentInChildren<HealthDisplay>(); if ((Object)(object)healthDisplay == (Object)null) { Log.LogDebug("Creating display"); GameObject val = new GameObject("Player Health Display"); Extensions.SetParentReset(val.transform, playerContainer.transform); healthDisplay = val.AddComponent<HealthDisplay>(); } else { Log.LogDebug("Display found"); } healthDisplay.Owner = id; return healthDisplay; } private static GameObject GetMask() { if ((Object)(object)maskPrefab != (Object)null) { return maskPrefab; } string path = "In-game/Anchor TL/Hud Canvas Offset/Hud Canvas/Health/Health 2+/Idle"; GameObject? obj = ((Component)GameCameras.instance.hudCamera).gameObject.FindGameObjectInChildren(path); if ((Object)(object)obj == (Object)null) { throw new Exception("Couldn't find health icon"); } GameObject obj2 = Object.Instantiate<GameObject>(obj); SpriteFlash val = default(SpriteFlash); if (obj2.TryGetComponent<SpriteFlash>(ref val)) { Object.DestroyImmediate((Object)(object)val); } SteelSoulAnimProxy val2 = default(SteelSoulAnimProxy); if (obj2.TryGetComponent<SteelSoulAnimProxy>(ref val2)) { Object.DestroyImmediate((Object)(object)val2); } obj2.layer = 0; obj2.SetActive(false); maskPrefab = obj2; return maskPrefab; } public static void CreateHealthBar(GameObject healthBar) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) healthBar.layer = 5; Vector2 spacing = default(Vector2); ((Vector2)(ref spacing))..ctor(-0.3f, 0.4f); float num = 0.2f; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(0f, 2f); int constraintCount = 6; Vector2 cellSize = default(Vector2); ((Vector2)(ref cellSize))..ctor(1.76f, 1.55f); Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(1.43f, 1.43f); int num2 = 15; int num3 = 9; healthBar.AddComponent<KeepWorldScalePositive>(); healthBar.AddComponent<Canvas>().renderMode = (RenderMode)2; GridLayoutGroup obj = healthBar.AddComponent<GridLayoutGroup>(); ((LayoutGroup)obj).childAlignment = (TextAnchor)7; obj.startCorner = (Corner)0; obj.startAxis = (Axis)0; obj.cellSize = cellSize; obj.spacing = spacing; obj.constraint = (Constraint)1; obj.constraintCount = constraintCount; healthBar.AddComponent<ContentSizeFitter>(); RectTransform component = healthBar.GetComponent<RectTransform>(); component.pivot = new Vector2(0.5f, 0f); component.SetSizeWithCurrentAnchors((Axis)0, (float)num2); component.SetSizeWithCurrentAnchors((Axis)1, (float)num3); Extensions.SetLocalPosition2D((Transform)(object)component, val); Extensions.SetScale2D((Transform)(object)component, new Vector2(num, num)); GameObject mask = GetMask(); tk2dSpriteAnimator val3 = default(tk2dSpriteAnimator); for (int i = 0; i < 18; i++) { GameObject obj2 = Object.Instantiate<GameObject>(mask); Extensions.SetParentReset(obj2.transform, healthBar.transform); Extensions.SetScale2D((Transform)(object)Extensions.AddComponentIfNotPresent<RectTransform>(obj2), val2); if (obj2.TryGetComponent<tk2dSpriteAnimator>(ref val3)) { Object.Destroy((Object)(object)val3); } } } } public class HealthDisplay : MonoBehaviour { public ushort Owner; public HealthData Health = new HealthData(); private void Awake() { Log.LogDebug("Health display awoke"); Extensions.Reset(((Component)this).transform); PlayerHealth.CreateHealthBar(((Component)this).gameObject); Client.OnServerSettingsUpdate = (Action)Delegate.Combine(Client.OnServerSettingsUpdate, new Action(OnSettingsChange)); OnSettingsChange(); } private void OnSettingsChange() { if (Client.ServerSettings.HealthbarsEnabled) { Log.LogDebug("Settings changed, enabling"); ((Component)this).gameObject.SetActive(true); Refresh(); } else { Log.LogDebug("Settings changed, disabling"); ((Component)this).gameObject.SetActive(false); } } public void Refresh() { StoredPlayerData player = PlayerDataTracker.ClientInstance.GetPlayer(Owner); Health = player.Health; int num = Health.MaxHealth + Health.BlueHealth; for (int i = 0; i < 18; i++) { Transform child = ((Component)this).transform.GetChild(i); int num2 = i + 1; if (num2 > num) { ((Component)child).gameObject.SetActive(false); continue; } ((Component)child).gameObject.SetActive(true); tk2dSprite component = ((Component)child).GetComponent<tk2dSprite>(); if (num2 <= Health.Health) { if (Health.LifebloodState) { ((tk2dBaseSprite)component).SetSprite(50); } else { ((tk2dBaseSprite)component).SetSprite(9); } } else if (num2 <= Health.MaxHealth) { ((tk2dBaseSprite)component).SetSprite(0); } else { ((tk2dBaseSprite)component).SetSprite(50); } } ((Component)this).gameObject.SetActive(Client.ServerSettings.HealthbarsEnabled); } } internal static class Spectate { internal enum MoveDir { Prev, Next } [CompilerGenerated] private static class <>O { public static Action<IClientPlayer> <0>__AddPlayer; public static Action<IClientPlayer> <1>__RemovePlayer; public static PausedEvent <2>__OnPauseChange; } private static List<IClientPlayer> InScene = new List<IClientPlayer>(); public static GameObject? FollowedPlayer; private static int FollowedPlayerIndex = -1; public static bool freecam = false; public static Vector2 FreecamMovementVector = Vector2.zero; private static GameObject? arrows; private static GameObject? LeftArrow; private static GameObject? RightArrow; private static GameObject? UpArrow; private static GameObject? DownArrow; private static bool Following => FollowedPlayerIndex != -1; public static void Init() { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown Client.api.ClientManager.PlayerEnterSceneEvent += AddPlayer; Client.api.ClientManager.PlayerLeaveSceneEvent += RemovePlayer; Client.api.ClientManager.PlayerDisconnectEvent += RemovePlayer; SceneManager.activeSceneChanged += delegate { ReturnToSelf(wasSceneChange: true); }; GameManager instance = GameManager.instance; object obj = <>O.<2>__OnPauseChange; if (obj == null) { PausedEvent val = OnPauseChange; <>O.<2>__OnPauseChange = val; obj = (object)val; } instance.GamePausedChange += (PausedEvent)obj; Client.OnServerSettingsUpdate = (Action)Delegate.Combine(Client.OnServerSettingsUpdate, (Action)delegate { if (!Client.ServerSettings.FreecamEnabled && freecam) { ReturnToSelf(); } if (!Client.ServerSettings.SpectateEnabled && Following) { ReturnToSelf(); } InScene = GetPlayersInScene(); }); Client.OnSSMPSettingsUpdate = (Action<ServerSettings>)Delegate.Combine(Client.OnSSMPSettingsUpdate, (Action<ServerSettings>)delegate(ServerSettings s) { InScene = GetPlayersInScene(s); }); } public static void Unload() { Client.api.ClientManager.PlayerEnterSceneEvent -= AddPlayer; Client.api.ClientManager.PlayerLeaveSceneEvent -= RemovePlayer; } public static void FocusOnPlayer(MoveDir dir) { if (InScene.Count == 0) { Client.LocalChat("There isn't anyone to spectate in this room."); return; } if (!Client.ServerSettings.SpectateEnabled) { Client.LocalChat("Spectating is currently disabled."); ReturnToSelf(); return; } int followedPlayerIndex = FollowedPlayerIndex; EndPreviousMode(); ToggleVignette(status: false); FollowedPlayerIndex = followedPlayerIndex; if (dir == MoveDir.Prev) { if (FollowedPlayerIndex <= 0) { FollowedPlayerIndex = InScene.Count - 1; } else { FollowedPlayerIndex--; } } else if (FollowedPlayerIndex == -1 || FollowedPlayerIndex == InScene.Count - 1) { FollowedPlayerIndex = 0; } else { FollowedPlayerIndex++; } FollowedPlayer = InScene[FollowedPlayerIndex].PlayerObject; if (!((Object)(object)FollowedPlayer == (Object)null)) { Transform transform = FollowedPlayer.transform; ImmobilizePlayer(); GameManager.instance.cameraCtrl.camTarget.heroTransform = transform; FixMasks(FollowedPlayer); if ((Object)(object)arrows != (Object)null) { arrows.SetActive(true); } ToggleUpDownArrows(status: false); } } public static void Update() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) CameraController val = (((Object)(object)GameManager.SilentInstance != (Object)null) ? GameManager.SilentInstance.cameraCtrl : null); if (!((Object)(object)val == (Object)null)) { if (freecam) { Vector3 position = ((Component)val.cam).transform.position; Vector2 val2 = FreecamMovementVector + Vector2.op_Implicit(position); SetFreecamBoundsArrows(val2); val.SnapTo(val2.x, val2.y); } else if (Following) { val.camTarget.ExitLockZone(); } } } private static void SetFreecamBoundsArrows(Vector2 position) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) CameraController cameraCtrl = GameManager.instance.cameraCtrl; bool flag = position.x <= 14.8f; bool flag2 = position.x >= cameraCtrl.xLimit - 0.2f; bool flag3 = position.y <= 8.5f; bool flag4 = position.y >= cameraCtrl.yLimit - 0.2f; if ((Object)(object)LeftArrow != (Object)null) { LeftArrow.SetActive(!flag); } if ((Object)(object)RightArrow != (Object)null) { RightArrow.SetActive(!flag2); } if ((Object)(object)DownArrow != (Object)null) { DownArrow.SetActive(!flag3); } if ((Object)(object)UpArrow != (Object)null) { UpArrow.SetActive(!flag4); } } private static void EndPreviousMode() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) FreecamMovementVector = Vector2.zero; freecam = false; FollowedPlayerIndex = -1; FollowedPlayer = null; ToggleUpDownArrows(status: true); ToggleVignette(status: true); GameManager.instance.cameraCtrl.camTarget.heroTransform = HeroController.instance.transform; FixMasks(((Component)HeroController.instance).gameObject); } public static void ReturnToSelf(bool wasSceneChange = false) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) FollowedPlayerIndex = -1; FollowedPlayer = null; FreecamMovementVector = Vector2.zero; freecam = false; ToggleVignette(status: true); if ((Object)(object)HeroController.instance != (Object)null) { RestoreControl(); GameManager.instance.cameraCtrl.camTarget.heroTransform = HeroController.instance.transform; if (!wasSceneChange) { FixMasks(((Component)HeroController.instance).gameObject); } } if ((Object)(object)arrows != (Object)null) { arrows.SetActive(false); } } private static void ToggleVignette(bool status) { GameObject val = (((Object)(object)HeroController.SilentInstance != (Object)null) ? ((Component)HeroController.SilentInstance).gameObject : null); if ((Object)(object)val != (Object)null) { GameObject val2 = val.FindGameObjectInChildren("Vignette"); if ((Object)(object)val2 != (Object)null) { val2.SetActive(status); } } } private static void FixMasks(GameObject playerObject) { Remasker[] array = Resources.FindObjectsOfTypeAll<Remasker>(); Collider2D component = playerObject.GetComponent<Collider2D>(); Remasker[] array2 = array; foreach (Remasker val in array2) { if (!((Object)(object)val == (Object)null)) { Collider2D component2 = ((Component)val).GetComponent<Collider2D>(); if ((Object)(object)component2 != (Object)null && component2.IsTouching(component)) { val.Entered(); } else { val.Exited(false); } } } } public static void Freecam() { if (freecam) { return; } if (!Client.ServerSettings.FreecamEnabled) { Client.LocalChat("Freecam is currently disabled."); ReturnToSelf(); return; } EndPreviousMode(); ToggleVignette(status: false); freecam = true; ImmobilizePlayer(); FixMasks(((Component)HeroController.instance).gameObject); if ((Object)(object)arrows != (Object)null) { arrows.SetActive(true); } ToggleUpDownArrows(status: true); } private static void ImmobilizePlayer() { HeroController.instance.IgnoreInput(); HeroController.instance.ResetMotion(true); } private static void RestoreControl() { HeroController.instance.UnPauseInput(); } public static void CreateFreecamUI() { //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) Transform child = ((Component)GameManager.instance.gameCams.hudCamera).transform.GetChild(0); GameObject obj = Object.Instantiate<GameObject>(((Component)child.GetChild(4).GetChild(2).GetChild(1) .GetChild(0)).gameObject, child); obj.SetActive(false); DownArrow = ((Component)obj.transform.GetChild(0)).gameObject; LeftArrow = ((Component)obj.transform.GetChild(1)).gameObject; RightArrow = ((Component)obj.transform.GetChild(2)).gameObject; UpArrow = ((Component)obj.transform.GetChild(3)).gameObject; DownArrow.transform.localPosition = new Vector3(0f, -7.5f, 45f); LeftArrow.transform.localPosition = new Vector3(-13.5f, 0f, 45f); RightArrow.transform.localPosition = new Vector3(13.5f, 0f, 45f); UpArrow.transform.localPosition = new Vector3(0f, 7.5f, 45f); arrows = obj; } private static void ToggleUpDownArrows(bool status) { if (!((Object)(object)arrows == (Object)null)) { if (Object.op_Implicit((Object)(object)DownArrow)) { DownArrow.SetActive(status); } if (Object.op_Implicit((Object)(object)UpArrow)) { UpArrow.SetActive(status); } } } private static void OnPauseChange(bool isPaused) { if (!isPaused && (freecam || Following)) { ReturnToSelf(); } } private static bool CanSpectatePlayer(IClientPlayer player) { ServerSettings clientServerSettings = Client.GetClientServerSettings(); return CanSpectatePlayer(player, clientServerSettings); } private static bool CanSpectatePlayer(IClientPlayer player, ServerSettings settings) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (!Client.ServerSettings.SpectateTeamOnly) { return true; } if (!settings.TeamsEnabled) { return true; } return player.Team == Client.api.ClientManager.Team; } public static void AddPlayer(IClientPlayer player) { if (CanSpectatePlayer(player) && !InScene.Contains(player)) { InScene.Add(player); } } public static void RemovePlayer(IClientPlayer player) { IClientPlayer player2 = player; int num = InScene.FindIndex((IClientPlayer p) => p.Id == player2.Id); if (num == -1) { return; } InScene.RemoveAt(num); if (Following) { if (InScene.Count == 0) { ReturnToSelf(); } else if (num == InScene.Count - 1) { FocusOnPlayer(MoveDir.Prev); } } } private static List<IClientPlayer> GetPlayersInScene() { return (from p in Client.api.ClientManager.Players.ToList() where p.IsInLocalScene && CanSpectatePlayer(p) select p).ToList(); } private static List<IClientPlayer> GetPlayersInScene(ServerSettings settings) { ServerSettings settings2 = settings; return (from p in Client.api.ClientManager.Players.ToList() where p.IsInLocalScene && CanSpectatePlayer(p, settings2) select p).ToList(); } } internal static class TeleportRequests { internal class Request { private static ushort requestId; public ushort RequestId; public ushort PlayerId; public bool Responded; public Request(ushort id) { PlayerId = id; RequestId = requestId++; } } private static readonly List<Request> requests = new List<Request>(); public static void AddRequest(IClientPlayer player) { IClientPlayer player2 = player; requests.RemoveAll((Request r) => r.PlayerId == player2.Id); Request request = new Request(player2.Id); requests.Add(request); Client.LocalChat(Common.ColoredUsername(player2) + " has requested to teleport to you. Use /tpaccept or /tpdeny within 30 seconds to respond."); Timer timer = new Timer(30000.0); timer.Elapsed += delegate { timer.Stop(); if (requests.Contains(request)) { requests.Remove(request); request.Responded = true; Client.LocalChat("Teleport from " + Common.ColoredUsername(player2) + " expired."); } }; timer.AutoReset = false; timer.Start(); } public static void RespondToRequest(bool accepted, string username = "") { Request request = null; if (username != "") { IClientPlayer player = Client.GetPlayerByName(username); if (player == null) { Client.LocalChat("Player '" + username + "' not found."); return; } request = requests.LastOrDefault((Request r) => r.PlayerId == player.Id); if (request == null) { Client.LocalChat(Common.ColoredUsername(player) + " hasn't sent you a request."); return; } } else { if (requests.Count == 0) { Client.LocalChat("You don't have any pending teleport requests."); return; } request = requests.Last(); requests.RemoveAt(requests.Count - 1); } if (request.Responded) { if (!string.IsNullOrEmpty(username)) { Client.LocalChat("That teleport request expired."); } else { Client.LocalChat("You don't have any active teleport requests."); } return; } request.Responded = true; if (!accepted) { PacketSender.SendMessage(request.PlayerId, Messages.TeleportDenied); Client.LocalChat("Teleport request denied."); } else { Client.LocalChat("Teleport request accepted."); PacketSender.SendTeleportAccept(request); } } } internal class Warp { private static bool teleporting; private string scene; private Vector2 position; public Warp(string scene, Vector2 position) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) this.scene = scene; this.position = position; } private void SetHornetPosition() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) GameManager.instance.OnFinishedEnteringScene -= new EnterSceneEvent(SetHornetPosition); Log.LogDebug("Setting hornet position"); GameObject hornetObject = Common.HornetObject; if ((Object)(object)hornetObject != (Object)null) { Extensions.SetPosition2D(hornetObject.transform, position); } teleporting = false; } public void WarpToPosition() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; GameObject hornetObject = Common.HornetObject; if ((Object)(object)hornetObject == (Object)null || teleporting) { FailedWarp(scene); return; } TeleportBack.PreviousScene = name; TeleportBack.PreviousLocation = Vector2.op_Implicit(hornetObject.transform.position); teleporting = true; if (scene == name) { SetHornetPosition(); } else { WarpToScene(); } } private void WarpToScene() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown SceneTeleportMap.GetTeleportMap().TryGetValue(scene, out var value); if (value == null) { FailedWarp(scene); return; } SceneLoadInfo val = new SceneLoadInfo { SceneName = scene, EntryGateName = value.TransitionGates[0], PreventCameraFadeOut = true, WaitForSceneTransitionCameraFade = false, AlwaysUnloadUnusedAssets = true, IsFirstLevelForPlayer = false }; GameManager.instance.BeginSceneTransition(val); GameManager.instance.OnFinishedEnteringScene += new EnterSceneEvent(SetHornetPosition); } private static void FailedWarp(string scene) { Client.LocalChat("I couldn't warp you. Please join the rest of the server in " + scene + "."); } public static bool GetHornetScenePosition(out string scene, out Vector2 position) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); scene = ((Scene)(ref activeScene)).name; position = Vector2.Zero; if ((Object)(object)GameManager.SilentInstance == (Object)null || (int)GameManager.SilentInstance.GameState != 4) { Client.LocalChat("Resume the game first!"); return false; } if (scene == null) { Client.LocalChat("I couldn't find the current scene!"); Log.LogError("ACTUAL ERROR: Unable to find current scene."); return false; } GameObject hornetObject = Common.HornetObject; if ((Object)(object)hornetObject == (Object)null) { Client.LocalChat("I couldn't find your position. Uh oh!"); Log.LogError("ACTUAL ERROR: Unable to find hornet object"); return false; } position = (Vector2)Vector2.op_Implicit(hornetObject.transform.position); return true; } } } namespace SSMPEssentials.Client.Modules.Patches { [HarmonyPatch] internal class DamageHeroPatch { [HarmonyPrefix] [HarmonyPatch(typeof(DamageHero), "OnAwake")] public static void DamageHeroAwake(DamageHero __instance) { DamageHero __instance2 = __instance; __instance2.HeroDamaged += delegate { PlayerDeaths.DetermineCauseOfDamage(__instance2); Log.LogDebug(PlayerDeaths.LatestCause); }; } [HarmonyPrefix] [HarmonyPatch(typeof(HeroController), "DoSpecialDamage")] public static void DoSpecialDamage(HeroController __instance, bool isFrostDamage) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Invalid comparison between Unknown and I4 if (!__instance.takeNoDamage && (int)CheatManager.Invincibility == 0 && (int)ToolItemManager.ActiveState != 1 && !__instance.cState.transitioning) { PlayerDeaths.LastDamageTime = DateTime.Now; if (isFrostDamage) { Log.LogInfo("Froze"); PlayerDeaths.LatestCause = CauseOfDeath.Frost; } else { Log.LogInfo("Generic Damage Type"); PlayerDeaths.LatestCause = CauseOfDeath.Generic; } } } } [HarmonyPatch] internal class HealthPatch { [HarmonyPostfix] [HarmonyPatch(typeof(PlayerData), "AddHealth")] public static void AddHealth(PlayerData __instance) { PlayerHealth.OnHealthChange(); } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerData), "TakeHealth")] public static void TakeHealth(PlayerData __instance) { PlayerHealth.OnHealthChange(); } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerData), "AddToMaxHealth")] public static void AddToMaxHealth(PlayerData __instance) { PlayerHealth.OnHealthChange(); } [HarmonyPostfix] [HarmonyPatch(typeof(PlayerData), "MaxHealth")] public static void MaxHealth(PlayerData __instance) { PlayerHealth.OnHealthChange(); } [HarmonyPostfix] [HarmonyPatch(typeof(HeroController), "UpdateBlueHealth")] public static void UpdateBlueHealth(PlayerData __instance) { PlayerHealth.OnHealthChange(); } } [HarmonyPatch] internal class MaskerPatch { [HarmonyPatch(typeof(Remasker), "OnTriggerEnter2D")] [HarmonyPrefix] public static bool OnTriggerEnter2D(Remasker __instance, Collider2D collision) { if ((Object)(object)Spectate.FollowedPlayer != (Object)null && (Object)(object)((Component)collision).gameObject == (Object)(object)Spectate.FollowedPlayer) { __instance.Entered(); return false; } return true; } [HarmonyPatch(typeof(Remasker), "OnTriggerExit2D")] [HarmonyPrefix] public static bool OnTriggerExit2D(Remasker __instance, Collider2D collision) { if ((Object)(object)Spectate.FollowedPlayer != (Object)null && (Object)(object)((Component)collision).gameObject == (Object)(object)Spectate.FollowedPlayer) { __instance.Exited(false); return false; } return true; } } [HarmonyPatch] internal class SSMPServerSettingUpdate { [HarmonyTargetMethod] public static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("SSMP.Networking.Packet.Data.ServerSettingsUpdate"); if (type == null) { Log.LogError("Unable to receive SSMP server setting updates (type)"); return null; } MethodInfo methodInfo = AccessTools.Method(type, "ReadData", (Type[])null, (Type[])null); if (methodInfo == null) { Log.LogError("Unable to receive SSMP server setting updates (method)"); return null; } return methodInfo; } [HarmonyPostfix] private static void Postfix(object __instance) { ServerSettings value = Traverse.Create(__instance).Property("ServerSettings", (object[])null).GetValue<ServerSettings>(); Client.OnSSMPSettingsUpdate?.Invoke(value); } } [HarmonyPatch] internal class SSMPTeamUpdate { [HarmonyTargetMethod] public static MethodBase TargetMethod() { Type type = AccessTools.TypeByName("SSMP.Game.Client.ClientPlayerData"); if (type == null) { Log.LogError("Unable to receive SSMP team updates (type)"); return null; } MethodInfo methodInfo = AccessTools.PropertySetter(type, "Team"); if (methodInfo == null) { Log.LogError("Unable to receive SSMP team updates (method)"); return null; } return methodInfo; } [HarmonyPostfix] public static void Postfix(IClientPlayer __instance) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (__instance.IsInLocalScene) { Team team = __instance.Team; if (Client.api.ClientManager.Team == team) { Spectate.AddPlayer(__instance); } else { Spectate.RemovePlayer(__instance); } } } } } namespace SSMPEssentials.Client.Commands { internal class Huddle : IClientCommand, ICommand { public bool AuthorizedOnly => false; public string Trigger => "/huddle"; public string[] Aliases => new string[1] { "/tpall" }; public void Execute(string[] arguments) { List<string> list = arguments.ToList(); list.RemoveAt(0); string text = string.Join(" ", list); if (list.Count <= 0) { PacketSender.SendHuddle(); return; } IClientPlayer playerByName = Client.GetPlayerByName(text); if (playerByName != null) { PacketSender.SendHuddle(playerByName.Id); } else { Client.LocalChat("Player '" + text + "' not found."); } } } internal class TeleportAccept : IClientCommand, ICommand { public string Trigger => "/tpaccept"; public string[] Aliases => new string[1] { "/tpa" }; public void Execute(string[] arguments) { string usernameFromArgs = TeleportRequest.GetUsernameFromArgs(arguments, required: false); TeleportRequests.RespondToRequest(accepted: true, usernameFromArgs); } } internal class TeleportDeny : IClientCommand, ICommand { public string Trigger => "/tpdeny"; public string[] Aliases => new string[1] { "/tpd" }; public void Execute(string[] arguments) { string usernameFromArgs = TeleportRequest.GetUsernameFromArgs(arguments, required: false); TeleportRequests.RespondToRequest(accepted: false, usernameFromArgs); } } internal class TeleportBack : IClientCommand, ICommand { public static string PreviousScene = ""; public static Vector2 PreviousLocation = Vector2.zero; public string Trigger => "/back"; public string[] Aliases => Array.Empty<string>(); public void Execute(string[] arguments) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (!Client.ServerSettings.BackEnabled) { Client.LocalChat("/back is currently disabled."); } else if (PreviousScene == "") { Client.LocalChat("I don't have your previous location."); } else { new Warp(PreviousScene, PreviousLocation).WarpToPosition(); } } } internal class TeleportRequest : IClientCommand, ICommand { public string Trigger => "/tp"; public string[] Aliases => new string[1] { "/teleport" }; public void Execute(string[] arguments) { IClientPlayer userFromArgs = GetUserFromArgs(arguments, required: true); if (userFromArgs != null) { Client.LocalChat("Teleport request sent to " + Common.ColoredUsername(userFromArgs) + "."); PacketSender.SendTeleportRequest(userFromArgs.Id); } } public static string GetUsernameFromArgs(string[] arguments, bool required) { if (arguments.Length < 2) { if (required) { Client.LocalChat("You need to specify a user."); } return ""; } List<string> list = arguments.ToList(); list.RemoveAt(0); string text = string.Join(" ", list); if (string.IsNullOrEmpty(text)) { if (required) { Client.LocalChat("You need to specify a user."); } return ""; } return text; } public static IClientPlayer? GetUserFromArgs(string[] arguments, bool required) { string usernameFromArgs = GetUsernameFromArgs(arguments, required); if (usernameFromArgs == "") { return null; } IClientPlayer playerByName = Client.GetPlayerByName(usernameFromArgs); if (playerByName != null) { return playerByName; } Client.LocalChat("Player '" + usernameFromArgs + "' not found."); return null; } } }