using 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;
}
}
}