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 Prop Hunt v1.0.3
PropHuntMod.dll
Decompiled 2 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.CodeDom.Compiler; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using System.Timers; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using GlobalEnums; using HarmonyLib; using HutongGames.PlayMaker; using HutongGames.PlayMaker.Actions; using InControl; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using NoRepeat; using PropHuntMod.Commands; using PropHuntMod.Networking.Client; using PropHuntMod.Networking.Server; using PropHuntMod.Patches; using PropHuntMod.Players; using PropHuntMod.Props; using PropHuntMod.Utils; 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.Settings; using SSMP.Logging; using SSMP.Math; using SSMP.Networking.Packet; using SSMP.Networking.Packet.Data; using TeamCherry.Localization; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("PropHuntMod")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("PropHuntMod")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("ea9e15ba-4504-4c36-baa6-8f85bee1da18")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.0.0")] 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; } } } namespace NoRepeat { public class NoRepeat<T> { private readonly Random random = new Random(); public List<T> used { get; private set; } public List<T> inputValues { get; private set; } public NoRepeat(List<T> values) { inputValues = values; used = new List<T>(); } public T GetRandom() { if (used.Count == 0 && inputValues.Count <= 1) { if (inputValues.Count == 0) { return default(T); } return inputValues[0]; } int index = random.Next(inputValues.Count); T val = inputValues[index]; inputValues.RemoveAt(index); if (inputValues.Count == 0) { inputValues.AddRange(used); used = new List<T>(); Log.LogDebug("Resetting NoRepeat"); } used.Add(val); return val; } public T GetSpecific(Func<T, bool> func) { T val = inputValues.FirstOrDefault(func); if (val != null) { return val; } return used.FirstOrDefault(func); } } } namespace PropHuntMod { [BepInPlugin("com.bobbythecatfish.prophunt", "Prop Hunt", "1.0.3")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInProcess("Hollow Knight Silksong.exe")] public class PropHuntMod : BaseUnityPlugin { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static HeroSetDelegate <>9__10_0; internal void <Awake>b__10_0(HeroController heroController) { AttackCooldownPatches.ModifySprintFSM(); } } internal static PropHuntMod Instance; internal SelfHornetManager hornet = new SelfHornetManager(); internal SelfCoverManager cover = new SelfCoverManager(); private static PropMovementControls movement; internal static Dictionary<ushort, PlayerManager> playerManager = new Dictionary<ushort, PlayerManager>(); internal static IClientApi client; internal static bool modEnabled = false; internal static bool showHitboxes = false; internal static List<Action> nextFrameActions = new List<Action>(); private static List<Action> _nextFrames = new List<Action>(); private void Awake() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown Instance = this; Config.LoadConfig(((BaseUnityPlugin)this).Config); ClientAddon.RegisterAddon((ClientAddon)(object)new Client()); ServerAddon.RegisterAddon((ServerAddon)(object)new Server()); object obj = <>c.<>9__10_0; if (obj == null) { HeroSetDelegate val = delegate { AttackCooldownPatches.ModifySprintFSM(); }; <>c.<>9__10_0 = val; obj = (object)val; } HeroController.OnHeroInstanceSet += (HeroSetDelegate)obj; } public static void Initialize(IClientApi clientApi) { Log.LogInfo("Prop Hunt mod Loaded."); client = clientApi; Harmony.CreateAndPatchAll(typeof(PropHuntMod), "prophunt"); Harmony.CreateAndPatchAll(typeof(NoDamage), "prophunt"); Harmony.CreateAndPatchAll(typeof(BaseCoverManager), "prophunt"); Harmony.CreateAndPatchAll(typeof(AttackCooldownPatches), "prophunt"); Harmony.CreateAndPatchAll(typeof(ScenePatches), "prophunt"); modEnabled = true; movement = new PropMovementControls(); } public static void Unload() { Harmony.UnpatchID("prophunt"); modEnabled = false; } private bool IsInputDisabled() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Invalid comparison between Unknown and I4 HeroController instance = HeroController.instance; if (instance != null && instance.IsInputBlocked() && PropMovementControls.MovementState == MovementState.Normal) { return true; } GameManager silentInstance = GameManager.SilentInstance; if (silentInstance != null && (int)silentInstance.GameState == 1) { return true; } GameObject currentSelectedGameObject = EventSystem.current.currentSelectedGameObject; if ((Object)(object)currentSelectedGameObject != (Object)null) { InputField component = currentSelectedGameObject.GetComponent<InputField>(); if (component != null && ((Component)component).gameObject.activeInHierarchy) { return true; } } return false; } private void Update() { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) if (!modEnabled) { return; } if (_nextFrames.Count > 0) { foreach (Action nextFrame in _nextFrames) { nextFrame(); } _nextFrames.Clear(); } if ((Object)(object)hornet.hornet != (Object)null) { hornet.EnsureHornetHidden(); } if ((Object)(object)hornet.hornet == (Object)null) { return; } movement?.Update(); if (!IsInputDisabled()) { if (Input.GetKeyDown(Config.HideHornetKey)) { hornet.ToggleHornet(); } if (Input.GetKeyDown(Config.SwapPropKey)) { cover.EnableRandomProp(); } if (Input.GetKeyDown(Config.ResetKey)) { cover.DisableProp(hornet); } } } private void LateUpdate() { if (nextFrameActions.Count > 0) { _nextFrames = nextFrameActions.ToList(); nextFrameActions.Clear(); } } } } namespace PropHuntMod.Networking.Server { internal class Server : ServerAddon { public static Server instance; public static GameState GameState = GameState.NotStarted; private static readonly Dictionary<ushort, ServerPlayer> players = new Dictionary<ushort, ServerPlayer>(); internal static IServerApi api = null; protected override string Name => "Prop Hunt"; protected override string Version => "1.0.3"; public override uint ApiVersion => 1u; public override bool NeedsNetwork => true; public SeekerTimer SeekerTimer { get; private set; } public override void Initialize(IServerApi serverApi) { instance = this; api = serverApi; Log.SetLogger(((ServerAddon)this).Logger); Log.LogInfo("Prop Hunt Server Loaded."); Reset(); ServerNetwork.Init(serverApi, (ServerAddon)(object)this); ((ICommandManager<IServerCommand>)(object)serverApi.CommandManager).RegisterCommand((IServerCommand)(object)new ServerCommands()); serverApi.ServerManager.PlayerConnectEvent += delegate(IServerPlayer player) { ServerPlayer player2 = GetPlayer(player.Id); if (GameState == GameState.SeekerWait) { player2.seeker = true; ServerNetwork.SendRoundStart(player.Id, GameState == GameState.Playing); } }; serverApi.ServerManager.PlayerDisconnectEvent += delegate(IServerPlayer player) { players.Remove(player.Id); CheckGameOver(player); }; } public void Reset(bool disconnect = false) { Log.LogInfo("Resetting server"); GameState = GameState.NotStarted; SeekerTimer?.CancelTimer(); SeekerTimer = null; if (disconnect) { foreach (IServerPlayer player in api.ServerManager.Players) { api.ServerManager.DisconnectPlayer(player.Id, (DisconnectReason)0); } } players.Clear(); } internal static ServerPlayer GetPlayer(ushort playerID) { if (!players.TryGetValue(playerID, out var value)) { value = new ServerPlayer(playerID); players.Add(playerID, value); } return value; } public void Announce(string announcement) { Log.LogDebug("Announcement: " + announcement); api.ServerManager.BroadcastMessage(announcement); } public void Message(ushort recipientID, string message) { Log.LogDebug($"Message to {recipientID}: {message}"); api.ServerManager.SendMessage(recipientID, message); } public string DetermineWinner() { string text = null; foreach (ServerPlayer value in players.Values) { if (!string.IsNullOrEmpty(value.propName)) { if (text != null) { return null; } text = value.PlayerAvatar.Username; } } return text; } private void PickSeekers() { int num = Mathf.Clamp(Config.SeekerCount, 1, players.Count - 1); Log.LogDebug($"Choosing {num} seekers"); for (int i = 0; i < num; i++) { List<ServerPlayer> list = players.Values.Where((ServerPlayer p) => !p.seeker).ToList(); if (list.Count == 0) { Log.LogDebug($"Ran out of seekers to choose (Picked {i}/{num})"); break; } ServerPlayer randomElement = Extensions.GetRandomElement<ServerPlayer>(list); randomElement.seeker = true; Log.LogDebug(randomElement.PlayerAvatar.Username + " is a seeker"); } } private void ResetPlayers() { foreach (ServerPlayer value in players.Values) { value.seeker = false; value.hidden = false; value.swapCount = 0; value.ResetProp(); } } public void GameStart() { if (players.Count < 2) { Announce("...Well that's awkward. I can't start a game without two people!"); return; } ResetPlayers(); PickSeekers(); EnsureSettings(); GameState = GameState.SeekerWait; int seekerCountdown = Config.SeekerCountdown; Announce($"The game has begun! Hiders have a {seekerCountdown} second head start. Good luck!"); SeekerTimer = new SeekerTimer(seekerCountdown); ServerNetwork.BroadcastRoundStart(); } public void CheckGameOver(IServerPlayer playerHit, bool canceled = false) { if (GameState != 0 && (players.Values.All((ServerPlayer p) => string.IsNullOrEmpty(p.propName)) || canceled)) { ServerNetwork.BroadcastGameOver(playerHit, canceled); if (canceled) { Announce("The game has been stopped early!"); SeekerTimer?.CancelTimer(); } else { Announce(playerHit.Username + " was the last bug standing! Congrats!"); } GameState = GameState.NotStarted; ResetPlayers(); } } private void EnsureSettings() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown IServerSettings serverSettings = ((ServerAddon)this).ServerApi.ServerManager.ServerSettings; ServerSettings val = new ServerSettings { AllowSkins = serverSettings.AllowSkins, DisplayNames = serverSettings.DisplayNames, OnlyBroadcastMapIconWithCompass = serverSettings.OnlyBroadcastMapIconWithCompass, TeamsEnabled = serverSettings.TeamsEnabled, AlwaysShowMapIcons = false, IsPvpEnabled = false }; ((ServerAddon)this).ServerApi.ServerManager.ApplyServerSettings(val); } } public class SeekerTimer { public int seconds; private Timer timer; private void SetTimer(int seconds) { this.seconds = seconds; timer = new Timer(1000.0); timer.Elapsed += delegate { OnSecond(); }; timer.AutoReset = true; timer.Start(); } private void OnSecond() { seconds--; if (seconds <= 0) { timer.Stop(); timer = null; Server.instance.Announce("[Seekers]: Ready or not, here we come!"); Server.GameState = GameState.Playing; ServerNetwork.BroadcastSeekerStart(); } else if (seconds <= 5) { Server.instance.Announce($"[Seekers]: {seconds}..."); } } public void CancelTimer() { if (timer != null) { timer.Stop(); timer = null; } } public SeekerTimer(int seconds) { SetTimer(seconds); } } internal class ServerPlayer { public ushort id; public bool hidden; public bool seeker; public string propName; public string propPath; public Vector3 propLocation = Consts.DEFAULT_LOCATION; public float propRotation; public float propScale = 1f; public int swapCount; public IServerPlayer PlayerAvatar => Server.api.ServerManager.GetPlayer(id); public ServerPlayer(ushort id) { this.id = id; } public void ResetProp() { propName = ""; propPath = ""; propLocation = Consts.DEFAULT_LOCATION; propRotation = 0f; propScale = 1f; } } internal struct BypassTicket { public int Id; public CorrectiveActions action; public BypassTicket(int Id = -1, CorrectiveActions action = CorrectiveActions.None) { this.Id = Id; this.action = action; } } internal static class ServerNetwork { private static IServerAddonNetworkSender<CustomPackets> sender; private static IServerAddonNetworkReceiver<CustomPackets> receiver; private static readonly Dictionary<ushort, List<BypassTicket>> tickets = new Dictionary<ushort, List<BypassTicket>>(); private static int TicketID = 0; private static BypassTicket GenerateTicket(ushort playerID, CorrectiveActions action) { if (!tickets.ContainsKey(playerID)) { tickets[playerID] = new List<BypassTicket>(); } BypassTicket bypassTicket = default(BypassTicket); bypassTicket.action = action; bypassTicket.Id = TicketID; BypassTicket bypassTicket2 = bypassTicket; tickets[playerID].Add(bypassTicket2); TicketID++; return bypassTicket2; } private static bool IsValidTicket(ushort playerID, int ticketID, params CorrectiveActions[] action) { if (ticketID == -1) { return false; } if (!tickets.ContainsKey(playerID)) { return false; } int num = tickets[playerID].FindIndex((BypassTicket t) => t.Id == ticketID && action.Contains(t.action)); if (num == -1) { return false; } tickets[playerID].RemoveAt(num); return true; } public static void Broadcast(ushort senderID, CustomPackets packetID, Packet data, bool collection) { foreach (IServerPlayer player in Server.api.ServerManager.Players) { if (player.Id != senderID) { if (collection) { sender.SendCollectionData<Packet>(packetID, data, player.Id); } else { sender.SendSingleData(packetID, (IPacketData)(object)data, player.Id); } } } } private static void FailedAction(ushort senderID, ushort affectedID, CustomPackets packetType, CorrectiveActions fix) { int bypassTicketID = -1; if (fix == CorrectiveActions.ToggleHornetFalse || fix == CorrectiveActions.PreviousScene || fix == CorrectiveActions.RestoreLastProp) { bypassTicketID = GenerateTicket(senderID, fix).Id; } sender.SendCollectionData<FailedAction>(CustomPackets.FailedAction, new FailedAction { AffectedID = affectedID, FailedPacket = packetType, FixMethod = fix, BypassTicketID = bypassTicketID }, senderID); } public static void ForwardPropSwap(ushort id, string propName, string propPath) { Log.LogDebug($"Broadcasting prop swap from {id}: {propName}"); Broadcast(id, CustomPackets.PropSwap, new PropSwap { Id = id, propName = propName, propPath = propPath }, collection: true); } public static void BroadcastRoundStart() { Log.LogDebug("Broadcasting round start"); foreach (IServerPlayer player in Server.api.ServerManager.Players) { SendRoundStart(player.Id); } } public static void SendRoundStart(ushort id, bool started = false) { ServerPlayer player = Server.GetPlayer(id); RoundStart roundStart = new RoundStart { IsSeeker = player.seeker, PropSwapLimit = 0, SeekerWaitTime = ((!started) ? Server.instance.SeekerTimer.seconds : 0), SeekerAttackCooldown = Config.AttackCooldown }; sender.SendSingleData(CustomPackets.RoundStart, (IPacketData)(object)roundStart, id); } public static void ForwardPropLocation(ushort id, Vector3 propPosition, float propRotation, float propScale) { Log.LogDebug($"Broadcasting prop location from {id}: {propPosition}, {propRotation}, {propScale}"); BaseCoverManager.ConstrainPropLocation(ref propPosition, ref propRotation, ref propScale); Broadcast(id, CustomPackets.PropLocation, new PropLocation { Id = id, PropPosition = propPosition, PropRotation = propRotation, PropScale = propScale }, collection: true); } public static void ForwardHideStatus(ushort id, bool isHiding) { Log.LogDebug($"Broadcasting hide status from {id}: {isHiding}"); Broadcast(id, CustomPackets.HideStatus, new HideStatus { Id = id, IsHiding = isHiding }, collection: true); } public static void ForwardPropFound(ushort id, ushort propOwnerID) { Log.LogDebug($"Broadcasting prop found from {id}: {propOwnerID}"); foreach (IServerPlayer player in Server.api.ServerManager.Players) { PropFound propFound = new PropFound { IsClientFound = (player.Id == propOwnerID), PropOwnerID = propOwnerID }; sender.SendCollectionData<PropFound>(CustomPackets.PropFound, propFound, player.Id); } } public static void BroadcastGameOver(IServerPlayer winner, bool canceled) { Log.LogDebug("Broadcasting game over"); foreach (IServerPlayer player in Server.api.ServerManager.Players) { GameOver gameOver = new GameOver { IsWinner = (!canceled && ((winner != null) ? new ushort?(winner.Id) : null) == player.Id), WasCanceled = canceled, WinnerUsername = (((winner != null) ? winner.Username : null) ?? "Nobody") }; sender.SendSingleData(CustomPackets.GameOver, (IPacketData)(object)gameOver, player.Id); } } public static void BroadcastSeekerStart() { Log.LogDebug("Broadcasting seeker start"); sender.BroadcastSingleData(CustomPackets.SeekerStart, (IPacketData)(object)new SeekerStart()); } public static void Init(IServerApi serverApi, ServerAddon serverAddon) { sender = serverApi.NetServer.GetNetworkSender<CustomPackets>(serverAddon); receiver = serverApi.NetServer.GetNetworkReceiver<CustomPackets>(serverAddon, (Func<CustomPackets, IPacketData>)global::PropHuntMod.Networking.Client.Packets.Instantiate); receiver.RegisterPacketHandler<global::PropHuntMod.Networking.Client.PropSwap>(CustomPackets.PropSwap, (GenericServerPacketHandler<global::PropHuntMod.Networking.Client.PropSwap>)OnPropSwap); receiver.RegisterPacketHandler<global::PropHuntMod.Networking.Client.PropLocation>(CustomPackets.PropLocation, (GenericServerPacketHandler<global::PropHuntMod.Networking.Client.PropLocation>)OnPropLocation); receiver.RegisterPacketHandler<global::PropHuntMod.Networking.Client.PropFound>(CustomPackets.PropFound, (GenericServerPacketHandler<global::PropHuntMod.Networking.Client.PropFound>)OnPropFound); receiver.RegisterPacketHandler<global::PropHuntMod.Networking.Client.Sync>(CustomPackets.Sync, (GenericServerPacketHandler<global::PropHuntMod.Networking.Client.Sync>)OnSync); if (Config.AllowDebugFeatures) { receiver.RegisterPacketHandler<global::PropHuntMod.Networking.Client.HideStatus>(CustomPackets.HideStatus, (GenericServerPacketHandler<global::PropHuntMod.Networking.Client.HideStatus>)OnHideStatus); } } private static void OnPropSwap(ushort id, global::PropHuntMod.Networking.Client.PropSwap data) { ServerPlayer player = Server.GetPlayer(id); bool flag = string.IsNullOrEmpty(data.propPath); if (player.seeker && Server.GameState != 0 && !flag) { Server.instance.Message(id, "You're a seeker! You can't hide this round."); FailedAction(id, id, CustomPackets.PropSwap, CorrectiveActions.DisableClientProp); return; } bool flag2 = IsValidTicket(id, data.TicketID, CorrectiveActions.RestoreLastProp, CorrectiveActions.PreviousScene); if (flag) { player.propName = ""; player.propPath = ""; } else { player.propName = data.propName; player.propPath = data.propPath; } if (!flag2) { player.swapCount++; } ForwardPropSwap(id, player.propName, player.propPath); } private static void OnPropLocation(ushort id, global::PropHuntMod.Networking.Client.PropLocation data) { ServerPlayer player = Server.GetPlayer(id); if (player.seeker && Server.GameState != 0) { Server.instance.Message(id, "You're a seeker! You can't hide this round."); FailedAction(id, id, CustomPackets.PropSwap, CorrectiveActions.DisableClientProp); return; } player.propLocation = data.PropPosition; player.propRotation = data.PropRotation; player.propScale = data.PropScale; BaseCoverManager.ConstrainPropLocation(ref player.propLocation, ref player.propRotation, ref player.propScale); ForwardPropLocation(id, player.propLocation, player.propRotation, player.propScale); } private static void OnSync(ushort id, global::PropHuntMod.Networking.Client.Sync data) { ServerPlayer player = Server.GetPlayer(id); if (player.seeker) { player.ResetProp(); } else { player.propName = data.PropName ?? ""; player.propPath = data.PropPath ?? ""; player.propLocation = data.PropLocation; player.propRotation = data.PropRotation; player.propScale = data.PropRotation; } BaseCoverManager.ConstrainPropLocation(ref player.propLocation, ref player.propRotation, ref player.propScale); ForwardPropSwap(id, player.propName, player.propPath); ForwardPropLocation(id, player.propLocation, player.propRotation, player.propScale); Server.instance.CheckGameOver(player.PlayerAvatar); } private static void OnHideStatus(ushort id, global::PropHuntMod.Networking.Client.HideStatus data) { ServerPlayer player = Server.GetPlayer(id); if (Server.GameState != 0 && player.seeker && data.IsHiding && !IsValidTicket(id, data.TicketID, CorrectiveActions.ToggleHornetFalse)) { Server.instance.Message(id, "You're a seeker! You can't hide this round."); FailedAction(id, id, CustomPackets.HideStatus, CorrectiveActions.ToggleHornetTrue); } else { player.hidden = data.IsHiding; ForwardHideStatus(id, data.IsHiding); } } private static void OnPropFound(ushort id, global::PropHuntMod.Networking.Client.PropFound data) { ServerPlayer player = Server.GetPlayer(data.PropOwnerID); ServerPlayer player2 = Server.GetPlayer(id); if (Server.GameState == GameState.SeekerWait) { Server.instance.Message(id, "You're still in the waiting period. No seeking yet!"); FailedAction(id, data.PropOwnerID, CustomPackets.PropFound, CorrectiveActions.RestoreTriggerHandler); return; } if (Server.GameState == GameState.Playing) { if (player.seeker) { Server.instance.Message(id, "That player is a seeker!"); FailedAction(id, data.PropOwnerID, CustomPackets.PropFound, CorrectiveActions.DisablePlayerProp); return; } if (!player2.seeker) { Server.instance.Message(id, "You're not a seeker! You can't find people this round."); FailedAction(id, data.PropOwnerID, CustomPackets.PropFound, CorrectiveActions.RestoreTriggerHandler); return; } player.seeker = true; } if (string.IsNullOrEmpty(player.propName)) { Server.instance.Message(id, "That player has already been found. You might be out of sync."); FailedAction(id, data.PropOwnerID, CustomPackets.PropFound, CorrectiveActions.DisablePlayerProp); return; } player.ResetProp(); ForwardPropFound(id, data.PropOwnerID); Server.instance.Announce(player.PlayerAvatar.Username + " was found by " + player2.PlayerAvatar.Username + "!"); if (Server.GameState == GameState.Playing) { Server.instance.CheckGameOver(player.PlayerAvatar); } } } public class PropSwap : global::PropHuntMod.Networking.Client.PropSwap { public override bool DropReliableDataIfNewerExists => false; public ushort Id { get; set; } public override void WriteData(IPacket packet) { packet.Write(Id); base.WriteData(packet); } public override void ReadData(IPacket packet) { Id = packet.ReadUShort(); base.ReadData(packet); } } public class RoundStart : Packet { public bool IsSeeker; public ushort PropSwapLimit; public int SeekerWaitTime; public float SeekerAttackCooldown; public override void WriteData(IPacket packet) { packet.Write(IsSeeker); packet.Write(PropSwapLimit); packet.Write(SeekerWaitTime); packet.Write(SeekerAttackCooldown); } public override void ReadData(IPacket packet) { IsSeeker = packet.ReadBool(); PropSwapLimit = packet.ReadUShort(); SeekerWaitTime = packet.ReadInt(); SeekerAttackCooldown = packet.ReadFloat(); } } public class PropLocation : global::PropHuntMod.Networking.Client.PropLocation { public override bool DropReliableDataIfNewerExists => false; public ushort Id { get; set; } public override void WriteData(IPacket packet) { packet.Write(Id); base.WriteData(packet); } public override void ReadData(IPacket packet) { Id = packet.ReadUShort(); base.ReadData(packet); } } public class HideStatus : global::PropHuntMod.Networking.Client.HideStatus { public override bool DropReliableDataIfNewerExists => false; public ushort Id { get; set; } public override void WriteData(IPacket packet) { packet.Write(Id); base.WriteData(packet); } public override void ReadData(IPacket packet) { Id = packet.ReadUShort(); base.ReadData(packet); } } public class PropFound : global::PropHuntMod.Networking.Client.PropFound { public override bool DropReliableDataIfNewerExists => false; public bool IsClientFound { get; set; } public override void WriteData(IPacket packet) { packet.Write(IsClientFound); base.WriteData(packet); } public override void ReadData(IPacket packet) { IsClientFound = packet.ReadBool(); base.ReadData(packet); } } public class SeekerStart : Packet { } public class GameOver : Packet { public string WinnerUsername { get; set; } public bool IsWinner { get; set; } public bool WasCanceled { get; set; } public override void WriteData(IPacket packet) { packet.Write(WinnerUsername); packet.Write(IsWinner); packet.Write(WasCanceled); } public override void ReadData(IPacket packet) { WinnerUsername = packet.ReadString(); IsWinner = packet.ReadBool(); WasCanceled = packet.ReadBool(); } } public class FailedAction : Packet { public CustomPackets FailedPacket; public CorrectiveActions FixMethod; public ushort AffectedID; public int BypassTicketID; public override void WriteData(IPacket packet) { packet.Write((int)FailedPacket); packet.Write((int)FixMethod); packet.Write(AffectedID); packet.Write(BypassTicketID); } public override void ReadData(IPacket packet) { FailedPacket = (CustomPackets)packet.ReadInt(); FixMethod = (CorrectiveActions)packet.ReadInt(); AffectedID = packet.ReadUShort(); BypassTicketID = packet.ReadUShort(); } } public static class Packets { internal static IPacketData Instantiate(CustomPackets packetID) { return (IPacketData)(packetID switch { CustomPackets.PropSwap => new PacketDataCollection<PropSwap>(), CustomPackets.RoundStart => new RoundStart(), CustomPackets.PropLocation => new PacketDataCollection<PropLocation>(), CustomPackets.HideStatus => new PacketDataCollection<HideStatus>(), CustomPackets.PropFound => new PacketDataCollection<PropFound>(), CustomPackets.GameOver => new GameOver(), CustomPackets.SeekerStart => new SeekerStart(), CustomPackets.FailedAction => new PacketDataCollection<FailedAction>(), _ => throw new NotImplementedException(packetID.ToString()), }); } } } namespace PropHuntMod.Networking.Client { internal enum Teams { Hunter = 4, Seeker = 3 } internal class Client : ClientAddon { public static GameState GameState; public static bool isSeeker; public static ushort propSwaps; public static ushort maxPropSwaps; public static float seekerAttackCooldown; protected override string Name => "Prop Hunt"; protected override string Version => "1.0.3"; public override uint ApiVersion => 1u; public override bool NeedsNetwork => true; public override void Initialize(IClientApi clientApi) { PropHuntMod.Initialize(clientApi); Log.SetLogger(((ClientAddon)this).Logger); Log.LogInfo("Prop Hunt Client Loaded."); ClientNetwork.Init(clientApi, (ClientAddon)(object)this); clientApi.ClientManager.ConnectEvent += delegate { string[] array = new string[5] { "Prop Hunt Commands:", "/ph start: starts a round", "/ph stop: stops a round", "/ph config: configure server settings", "/sync: syncs other player's props" }; for (int i = 0; i < array.Length; i++) { LocalMessage(array[i]); } }; clientApi.ClientManager.DisconnectEvent += delegate { GameState = GameState.NotStarted; isSeeker = false; propSwaps = 0; maxPropSwaps = 0; PropHuntMod.playerManager.Clear(); global::PropHuntMod.Networking.Server.Server.instance.Reset(disconnect: true); }; clientApi.ClientManager.PlayerConnectEvent += delegate(IClientPlayer player) { PlayerManager.GetPlayerManager(player.Id); }; clientApi.ClientManager.PlayerDisconnectEvent += delegate(IClientPlayer player) { PropHuntMod.playerManager.Remove(player.Id); }; clientApi.ClientManager.PlayerEnterSceneEvent += delegate(IClientPlayer player) { PlayerManager playerManager = PlayerManager.GetPlayerManager(player.Id); playerManager.hornetManager.SetHornet(); playerManager.EnsurePropCover(); }; ((ICommandManager<IClientCommand>)(object)clientApi.CommandManager).RegisterCommand((IClientCommand)(object)new ShowHitboxes()); ((ICommandManager<IClientCommand>)(object)clientApi.CommandManager).RegisterCommand((IClientCommand)(object)new global::PropHuntMod.Commands.Sync()); } public static void LocalMessage(string message) { PropHuntMod.client.UiManager.ChatBox.AddMessage(message); } } internal static class ClientErrorCorrection { [CompilerGenerated] private sealed class <PreviousScene>d__2 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public FailedAction data; private int <i>5__2; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PreviousScene>d__2(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <i>5__2 = 0; break; case 1: <>1__state = -1; <i>5__2++; break; } if (<i>5__2 < 5 && string.IsNullOrEmpty(ScenePatches.PreviousScene)) { Log.LogWarning($"Attempt {<i>5__2 + 1} to find previous scene failed"); <>2__current = (object)new WaitForSeconds(1f); <>1__state = 1; return true; } if (string.IsNullOrEmpty(ScenePatches.PreviousScene)) { PropHuntMod.client.ClientManager.Disconnect(); Client.LocalMessage("Fatal Error: Unable to find previous scene."); return false; } SceneLoadInfo val = new SceneLoadInfo { SceneName = ScenePatches.PreviousScene, PreventCameraFadeOut = true, WaitForSceneTransitionCameraFade = false, Visualization = (SceneLoadVisualizations)0, AlwaysUnloadUnusedAssets = true, IsFirstLevelForPlayer = false }; ScenePatches.SceneTransitionTicket = data.BypassTicketID; GameManager.instance.BeginSceneTransition(val); 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(); } } public static void DiagnoseError(FailedAction data) { switch (data.FixMethod) { case CorrectiveActions.DisableClientProp: SelfCoverManager.instance.DisableProp(logOnFail: false, isSceneChange: false, data.BypassTicketID); break; case CorrectiveActions.DisablePlayerProp: DisablePlayerProp(data); break; case CorrectiveActions.PreviousScene: ((MonoBehaviour)PropHuntMod.Instance).StartCoroutine(PreviousScene(data)); break; case CorrectiveActions.ToggleHornetTrue: SelfHornetManager.instance.ToggleHornet(show: true); break; case CorrectiveActions.ToggleHornetFalse: SelfHornetManager.instance.ToggleHornet(show: false, data.BypassTicketID); break; case CorrectiveActions.RestoreLastProp: RestoreLastProp(data); break; case CorrectiveActions.RestoreTriggerHandler: RestoreTriggerHandler(data); break; case CorrectiveActions.BecomeSeeker: BecomeSeeker(); break; default: throw new NotImplementedException(data.FixMethod.ToString()); case CorrectiveActions.None: break; } } private static void DisablePlayerProp(FailedAction data) { PlayerManager.GetPlayerManager(data.AffectedID).SetProp("", ""); } [IteratorStateMachine(typeof(<PreviousScene>d__2))] private static IEnumerator PreviousScene(FailedAction data) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <PreviousScene>d__2(0) { data = data }; } public static void RestoreLastProp(FailedAction data) { SelfCoverManager instance = SelfCoverManager.instance; GameObject obj = PropValidation.FindGameObject(instance.PrevCoverPath); Prop prop = PropValidation.PrepareProp(obj); if ((Object)(object)obj == (Object)null || prop == null) { Log.LogFatal("Couldn't restore previous prop " + instance.PrevCoverPath); } else { SelfCoverManager.instance.EnableProp(prop, data.BypassTicketID); } } private static void RestoreTriggerHandler(FailedAction data) { GameObject cover = PlayerManager.GetPlayerManager(data.AffectedID).coverManager.cover; if ((Object)(object)cover != (Object)null) { if ((Object)(object)cover.GetComponent<TriggerHandler>() == (Object)null) { TriggerHandler triggerHandler = cover.AddComponent<TriggerHandler>(); triggerHandler.isRemote = true; triggerHandler.playerID = data.AffectedID; } else { Log.LogDebug($"Player {data.AffectedID} still had their TriggerHandler. Not restoring."); } } else { Log.LogError($"Player {data.AffectedID}'s prop was already destroyed. Can't restore trigger handler"); } } private static void BecomeSeeker() { Client.isSeeker = true; if (Client.GameState == GameState.SeekerWait) { SelfHornetManager.instance.SetSeekerObscure(enabled: true); } } } internal static class ClientNetwork { private static IClientApi api; private static IClientAddonNetworkSender<CustomPackets> sender; private static IClientAddonNetworkReceiver<CustomPackets> receiver; private static void SendData(CustomPackets packetId, IPacketData data) { if (api.NetClient.IsConnected && sender != null) { sender.SendSingleData(packetId, data); } } private static void SendCollectionData(CustomPackets packetId, Packet data) { if (api.NetClient.IsConnected && sender != null) { sender.SendCollectionData<Packet>(packetId, data); } } public static void SendPropSwap(Prop prop, int ticket = -1) { Log.LogDebug("Sending prop swap: " + prop?.name); SendData(CustomPackets.PropSwap, (IPacketData)(object)new PropSwap { propName = (prop?.name ?? ""), propPath = (prop?.path ?? ""), TicketID = ticket }); } public static void SendPropLocation(Vector3 propPosition, float propRotation, float propScale) { Log.LogDebug($"Sending prop location: {propPosition}, {propRotation}, {propScale}"); SendData(CustomPackets.PropLocation, (IPacketData)(object)new PropLocation { PropPosition = propPosition, PropRotation = propRotation, PropScale = propScale }); } public static void SendHideStatus(bool isHiding, int ticket = -1) { Log.LogDebug($"Sending hide status: {isHiding}"); SendData(CustomPackets.HideStatus, (IPacketData)(object)new HideStatus { IsHiding = isHiding, TicketID = ticket }); } public static void SendPropFound(ushort propOwnerID) { Log.LogDebug($"Sending prop found: {propOwnerID}"); SendCollectionData(CustomPackets.PropFound, new PropFound { PropOwnerID = propOwnerID }); } public static void SendSync(string propName, string propPath, Vector3 propPosition, float propRotation, float propScale) { Log.LogDebug($"Sending sync data: {propName}, {propPosition}, {propRotation}, {propScale}"); SendData(CustomPackets.Sync, (IPacketData)(object)new Sync { PropName = propName, PropPath = propPath, PropLocation = propPosition, PropRotation = propRotation, PropScale = propScale }); } public static void Init(IClientApi clientApi, ClientAddon clientAddon) { api = clientApi; sender = clientApi.NetClient.GetNetworkSender<CustomPackets>(clientAddon); receiver = clientApi.NetClient.GetNetworkReceiver<CustomPackets>(clientAddon, (Func<CustomPackets, IPacketData>)global::PropHuntMod.Networking.Server.Packets.Instantiate); receiver.RegisterPacketHandler<global::PropHuntMod.Networking.Server.PropSwap>(CustomPackets.PropSwap, (GenericClientPacketHandler<global::PropHuntMod.Networking.Server.PropSwap>)OnPropSwap); receiver.RegisterPacketHandler<global::PropHuntMod.Networking.Server.PropLocation>(CustomPackets.PropLocation, (GenericClientPacketHandler<global::PropHuntMod.Networking.Server.PropLocation>)OnPropLocation); receiver.RegisterPacketHandler<global::PropHuntMod.Networking.Server.PropFound>(CustomPackets.PropFound, (GenericClientPacketHandler<global::PropHuntMod.Networking.Server.PropFound>)OnPropFound); receiver.RegisterPacketHandler<RoundStart>(CustomPackets.RoundStart, (GenericClientPacketHandler<RoundStart>)OnRoundStart); receiver.RegisterPacketHandler<GameOver>(CustomPackets.GameOver, (GenericClientPacketHandler<GameOver>)OnGameOver); receiver.RegisterPacketHandler<SeekerStart>(CustomPackets.SeekerStart, (GenericClientPacketHandler<SeekerStart>)OnSeekerStart); receiver.RegisterPacketHandler<FailedAction>(CustomPackets.FailedAction, (GenericClientPacketHandler<FailedAction>)ClientErrorCorrection.DiagnoseError); if (Config.AllowDebugFeatures) { receiver.RegisterPacketHandler<global::PropHuntMod.Networking.Server.HideStatus>(CustomPackets.HideStatus, (GenericClientPacketHandler<global::PropHuntMod.Networking.Server.HideStatus>)OnHideStatus); } } private static void OnPropSwap(global::PropHuntMod.Networking.Server.PropSwap data) { PlayerManager.GetPlayerManager(data.Id).SetProp(data.propName, data.propPath); Log.LogDebug($"{data.Id} prop set to {data.propName}"); } private static void OnRoundStart(RoundStart data) { bool flag = data.SeekerWaitTime == 0; if (flag) { Client.GameState = GameState.Playing; } else { Client.GameState = GameState.SeekerWait; } Client.isSeeker = data.IsSeeker; Client.propSwaps = 0; Client.maxPropSwaps = data.PropSwapLimit; Client.seekerAttackCooldown = data.SeekerAttackCooldown; if (data.IsSeeker) { Client.LocalMessage("You're a seeker!"); SelfCoverManager.instance.DisableProp(logOnFail: false); if (!flag) { SelfHornetManager.instance.SetSeekerObscure(enabled: true); EffectsManager.SetTitle("SEEKER", $"Wait time: {data.SeekerWaitTime} seconds", "YOUR ROLE:", large: true, 10f); } else { EffectsManager.SetTitle("SEEKER", "It's go time!", "YOUR ROLE:", large: true, 10f); } } else { EffectsManager.SetTitle("HIDER", "", "YOUR ROLE:"); SelfCoverManager.instance.EnableRandomProp(); Client.LocalMessage("You're hiding this round!"); } } private static void OnPropLocation(global::PropHuntMod.Networking.Server.PropLocation data) { PlayerManager.GetPlayerManager(data.Id).SetPropLocation(data.PropPosition, data.PropRotation, data.PropScale); Log.LogDebug($"{data.Id} prop moved to {data.PropPosition}, {data.PropRotation}, {data.PropScale}"); } private static void OnHideStatus(global::PropHuntMod.Networking.Server.HideStatus data) { PlayerManager.GetPlayerManager(data.Id).SetHideStatus(data.IsHiding); Log.LogDebug($"{data.Id} hiding status set to {data.IsHiding}"); } private static void OnPropFound(global::PropHuntMod.Networking.Server.PropFound data) { if (data.IsClientFound) { Log.LogDebug("I've been found!"); SelfCoverManager.instance.FindProp(SelfHornetManager.instance); if (Client.GameState == GameState.Playing) { Client.isSeeker = true; } } else { PlayerManager playerManager = PlayerManager.GetPlayerManager(data.PropOwnerID); playerManager.coverManager.FindProp(playerManager.hornetManager); playerManager.SetProp("", ""); Log.LogDebug(playerManager.PlayerAvatar.Username + " has been found"); } EffectsManager.PlayFoundSound(data.IsClientFound); } private static void OnGameOver(GameOver data) { Client.GameState = GameState.NotStarted; Client.isSeeker = false; Client.propSwaps = 0; SelfHornetManager.instance.SetSeekerObscure(enabled: false); SelfCoverManager.instance.DisableProp(); EffectsManager.PlayGameOverSound(!data.WasCanceled && data.IsWinner); string main = (data.WasCanceled ? "Round Canceled" : (data.IsWinner ? "You Won!" : "Round Complete")); string sub = ((data.IsWinner || data.WasCanceled) ? "" : (data.WinnerUsername + " won!")); EffectsManager.SetTitle(main, sub); if (data.IsWinner) { EffectsManager.PlayConfetti(); } GameManager.instance.FreezeMoment((FreezeMomentTypes)10, (Action)null); } private static void OnSeekerStart(SeekerStart data) { Client.GameState = GameState.Playing; if (Client.isSeeker) { SelfHornetManager.instance.SetSeekerObscure(enabled: false); } } } public class Packet : IPacketData { public bool IsReliable => true; public virtual bool DropReliableDataIfNewerExists => true; public virtual void ReadData(IPacket packet) { } public virtual void WriteData(IPacket packet) { } } public class PropSwap : Packet { public string propName = ""; public string propPath = ""; public int TicketID = -1; public override void WriteData(IPacket packet) { packet.Write(propName); packet.Write(propPath); packet.Write(TicketID); } public override void ReadData(IPacket packet) { propName = packet.ReadString(); propPath = packet.ReadString(); TicketID = packet.ReadInt(); } } public class PropLocation : Packet { public Vector3 PropPosition { get; set; } public float PropRotation { get; set; } public float PropScale { get; set; } public override void WriteData(IPacket packet) { packet.Write(PropPosition); packet.Write(PropRotation); packet.Write(PropScale); } public override void ReadData(IPacket packet) { PropPosition = packet.ReadVector3(); PropRotation = packet.ReadFloat(); PropScale = packet.ReadFloat(); } } public class HideStatus : Packet { public int TicketID = -1; public bool IsHiding { get; set; } public override void WriteData(IPacket packet) { packet.Write(IsHiding); packet.Write(TicketID); } public override void ReadData(IPacket packet) { IsHiding = packet.ReadBool(); TicketID = packet.ReadInt(); } } public class PropFound : Packet { public override bool DropReliableDataIfNewerExists => false; public ushort PropOwnerID { get; set; } public override void WriteData(IPacket packet) { packet.Write(PropOwnerID); } public override void ReadData(IPacket packet) { PropOwnerID = packet.ReadUShort(); } } public class Sync : Packet { public string PropName { get; set; } public string PropPath { get; set; } public Vector3 PropLocation { get; set; } public float PropRotation { get; set; } public float PropScale { get; set; } public override void WriteData(IPacket packet) { packet.Write(PropName); packet.Write(PropPath); packet.Write(PropLocation); packet.Write(PropRotation); packet.Write(PropScale); } public override void ReadData(IPacket packet) { PropName = packet.ReadString(); PropPath = packet.ReadString(); PropLocation = packet.ReadVector3(); PropRotation = packet.ReadFloat(); PropScale = packet.ReadFloat(); } } public static class Packets { internal static IPacketData Instantiate(CustomPackets packetID) { return (IPacketData)(packetID switch { CustomPackets.PropSwap => new PropSwap(), CustomPackets.PropLocation => new PropLocation(), CustomPackets.HideStatus => new HideStatus(), CustomPackets.PropFound => new PacketDataCollection<PropFound>(), CustomPackets.Sync => new Sync(), _ => throw new NotImplementedException(packetID.ToString()), }); } } } namespace PropHuntMod.Properties { [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [DebuggerNonUserCode] [CompilerGenerated] internal class Resources { private static ResourceManager resourceMan; private static CultureInfo resourceCulture; [EditorBrowsable(EditorBrowsableState.Advanced)] internal static ResourceManager ResourceManager { get { if (resourceMan == null) { resourceMan = new ResourceManager("PropHuntMod.Properties.Resources", typeof(Resources).Assembly); } return resourceMan; } } [EditorBrowsable(EditorBrowsableState.Advanced)] internal static CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } internal static byte[] bundle => (byte[])ResourceManager.GetObject("bundle", resourceCulture); internal static byte[] icon => (byte[])ResourceManager.GetObject("icon", resourceCulture); internal static byte[] manifest => (byte[])ResourceManager.GetObject("manifest", resourceCulture); internal Resources() { } } } namespace PropHuntMod.Props { internal enum Direction { Left, Right, Up, Down, Front, Back, Reset, RotateLeft, RotateRight, ScaleUp, ScaleDown } internal class SelfCoverManager : BaseCoverManager { public static SelfCoverManager instance; internal bool movedRecently; internal SelfCoverManager() { isRemote = false; instance = this; } public void MoveProp(Direction direction, KeyCode key, ref bool moved, bool onlyOnce = false) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (base.IsHiding && (!onlyOnce || Input.GetKeyDown(key)) && (onlyOnce || Input.GetKey(key))) { moved = true; float distance = ((Input.GetKey((KeyCode)308) || Input.GetKey((KeyCode)307)) ? 0.01f : 0.1f); MoveProp(direction, distance); } } public void MoveProp(Direction direction, float distance = 0.1f) { //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Expected O, but got Unknown if (!base.IsHiding) { Log.LogError("No cover, can't move"); return; } float num = base.Position.X; float num2 = base.Position.Y; float num3 = base.Position.Z; float num4 = base.Rotation; float num5 = base.Scale; SelfHornetManager selfHornetManager = SelfHornetManager.instance; if (selfHornetManager.HornetExists()) { bool flag = Extensions.GetScaleX(selfHornetManager.hornet.transform) < 1f; switch (direction) { case Direction.Left: num = ((!flag) ? (num - distance) : (num + distance)); break; case Direction.Right: num = ((!flag) ? (num + distance) : (num - distance)); break; case Direction.Up: num2 += distance; break; case Direction.Down: num2 -= distance; break; case Direction.Front: num3 -= distance; break; case Direction.Back: num3 += distance; break; case Direction.ScaleUp: num5 *= 1f + distance / 5f; break; case Direction.ScaleDown: num5 /= 1f + distance / 5f; break; case Direction.RotateLeft: num4 = ((!flag) ? (num4 + distance * 10f) : (num4 - distance * 10f)); break; case Direction.RotateRight: num4 = ((!flag) ? (num4 - distance * 10f) : (num4 + distance * 10f)); break; case Direction.Reset: num = Consts.DEFAULT_LOCATION.X; num2 = Consts.DEFAULT_LOCATION.Y; num3 = Consts.DEFAULT_LOCATION.Z; num4 = 0f; num5 = 1f; break; default: Log.LogError($"Invalid movement direction {direction} ({(int)direction})"); return; } Vector3 location = new Vector3(num, num2, num3); SetPropLocation(location, num4, num5); movedRecently = true; } } public void SendPropPosition() { if (movedRecently) { if (!base.IsHiding) { Log.LogError("No cover, can't send prop position"); } else { movedRecently = false; ClientNetwork.SendPropLocation(base.Position, base.Rotation, base.Scale); } } } public void EnableRandomProp() { if (PropValidation.currentSceneObjects == null) { PropValidation.GetAllProps(); } if (!IsSeeker()) { if (Client.maxPropSwaps > 0 && Client.propSwaps >= Client.maxPropSwaps) { Client.LocalMessage($"You've reached the max number of prop swaps (${Client.maxPropSwaps})."); return; } Prop random = PropValidation.currentSceneObjects.GetRandom(); EnableProp(random); Log.LogDebug(random.path); Log.LogDebug(PropValidation.FindGameObject(random.path)); } } public bool EnableProp(Prop prop, int ticket = -1) { if (IsSeeker()) { return false; } Log.LogDebug("Enabling prop"); bool num = base.EnableProp(SelfHornetManager.instance, prop); if (num) { ClientNetwork.SendPropSwap(prop, ticket); Client.propSwaps++; } return num; } public bool DisableProp(bool logOnFail = true, bool isSceneChange = false, int ticket = -1) { bool num = base.DisableProp(SelfHornetManager.instance, logOnFail); if (num && !isSceneChange) { PropMovementControls.Instance.SetMovementState(MovementState.Normal); ClientNetwork.SendPropSwap(null, ticket); PropHuntMod.showHitboxes = false; } return num; } public override void OnHit(TriggerHandler handler) { Log.LogError("UH OH! ON HIT IS SUPPOSED TO BE A REMOTE PLAYER!"); } private bool IsSeeker() { if (Client.isSeeker) { Client.LocalMessage("You're a seeker! You can't enable props right now."); return true; } return false; } public override bool EnableProp(BaseHornetManager hornet, Prop prop) { return EnableProp(prop); } public override bool DisableProp(BaseHornetManager hornet, bool logOnFail = true) { return DisableProp(logOnFail); } } internal class BaseCoverManager { internal GameObject cover; internal string CoverPath; internal string PrevCoverPath; public ushort playerID; internal bool isRemote = true; internal Vector3 Position { get { //IL_001a: 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) GameObject obj = cover; Vector3? val = ((obj != null) ? new Vector3?(obj.transform.localPosition) : null); return (val.HasValue ? ((Vector3)val.GetValueOrDefault()) : null) ?? Consts.DEFAULT_LOCATION; } } internal float Rotation { get { GameObject obj = cover; if (obj == null) { return 0f; } return Extensions.GetLocalRotation2D(obj.transform); } } internal float Scale { get; private set; } = 1f; internal Vector2 OriginalScale { get; private set; } = Vector2.one; public bool IsHiding => (Object)(object)cover != (Object)null; public void SetPropLocation(Vector3 location) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (!IsHiding) { Log.LogError("No cover, can't set prop position"); } else { cover.transform.localPosition = (Vector3)location; } } public void SetPropRotation(float rotation) { if (!IsHiding) { Log.LogError("No cover, can't set prop rotation"); } else { Extensions.SetLocalRotation2D(cover.transform, rotation); } } public void SetPropScale(float scale) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) Scale = scale; if (!IsHiding) { Log.LogError("No cover, can't set prop scale"); } else { Extensions.SetScale2D(cover.transform, OriginalScale * scale); } } public void SetPropLocation(Vector3 location, float rotation, float scale) { if (!IsHiding) { Log.LogError("No cover, can't set any prop location"); return; } ConstrainPropLocation(ref location, ref rotation, ref scale); SetPropLocation(location); SetPropRotation(rotation); SetPropScale(scale); } public static void ConstrainPropLocation(ref Vector3 location, ref float rotation, ref float scale) { location.X = Mathf.Clamp(location.X, -2f, 2f); location.Y = Mathf.Clamp(location.Y, -4f, 4f); location.Z = Mathf.Clamp(location.Z, -8f, 8f); rotation %= 360f; scale = Mathf.Clamp(scale, 0.5f, 2f); } public virtual bool DisableProp(BaseHornetManager manager, bool logOnFail = true) { if (!IsHiding) { if (logOnFail) { Log.LogError("No cover to disable"); } return false; } Log.LogDebug($"Destroying prop {cover}"); Object.Destroy((Object)(object)cover); cover = null; manager.ToggleHornet(show: true); return true; } public void FindProp(BaseHornetManager manager) { if (!IsHiding) { Log.LogError("No cover to disable"); return; } cover.transform.parent = null; manager.ToggleHornet(show: true); GameObject coverCopy = cover.gameObject; cover = null; Object.Destroy((Object)(object)coverCopy.GetComponent<TriggerHandler>()); EffectsManager.SweepGameObject(coverCopy, delegate { Object.Destroy((Object)(object)coverCopy); }); } public virtual bool EnableProp(BaseHornetManager hornet, Prop prop) { //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) if (prop == null) { Client.LocalMessage("There isn't any valid cover here. Try another room."); Log.LogError("No valid cover found"); return false; } if (IsHiding) { Log.LogWarning("Destroying cover..."); PrevCoverPath = CoverPath; Object.Destroy((Object)(object)cover); cover = null; } if (!hornet.HornetExists()) { return false; } try { Log.LogDebug("Creating prop"); if (PrevCoverPath == null) { PrevCoverPath = prop.path; } cover = Object.Instantiate<GameObject>(prop.go, hornet.hornet.transform); ((Object)cover).name = prop.name; CoverPath = prop.path; SpriteRenderer component = cover.GetComponent<SpriteRenderer>(); if ((Object)(object)component != (Object)null) { ((Renderer)component).enabled = true; component.maskInteraction = (SpriteMaskInteraction)0; } OriginalScale = Vector2.op_Implicit(cover.transform.lossyScale); SetPropLocation(Consts.DEFAULT_LOCATION, 0f, 1f); cover.SetActive(true); cover.layer = 20; hornet.ToggleHornet(show: false); TriggerHandler component2 = cover.GetComponent<TriggerHandler>(); component2.playerID = playerID; component2.isRemote = isRemote; } catch (Exception ex) { Log.LogError("Ran into an error instantiating cover."); Log.LogError(ex); } return true; } public virtual void OnHit(TriggerHandler handler) { Log.LogDebug($"Found {playerID}"); Object.Destroy((Object)(object)handler); ClientNetwork.SendPropFound(playerID); } } internal class TriggerHandler : MonoBehaviour { public ushort playerID; public bool isRemote; private void OnTriggerEnter2D(Collider2D other) { if (isRemote && ((Component)other).tag == "Nail Attack" && ((Client.GameState == GameState.Playing) ? Client.isSeeker : (!SelfCoverManager.instance.IsHiding)) && Object.op_Implicit((Object)(object)((Component)other).GetComponentInParent<HeroController>())) { PlayerManager.GetPlayerManager(playerID).coverManager.OnHit(this); } } } internal class PropMovementControls { private static float StickThreshold = 0.02f; private static SpriteRenderer StateIndicator; private static Sprite MoveXY; private static Sprite MoveZ; private static Sprite Rotate; private static Sprite Scale; private bool moved; public static PropMovementControls Instance; internal static MovementState MovementState = MovementState.Normal; private InputBlockingMechanism blocker = new InputBlockingMechanism(); private bool ModeSwitchPressed; public PropMovementControls() { if (Instance == null) { Instance = this; } } private void ChangeModes() { if (!SelfCoverManager.instance.IsHiding) { SetMovementState(MovementState.Normal); } else if (MovementState == MovementState.Normal) { SetMovementState(MovementState.Move2D); } else if (MovementState == MovementState.Move2D) { SetMovementState(MovementState.MoveZ); } else if (MovementState == MovementState.MoveZ) { SetMovementState(MovementState.Scale); } else if (MovementState == MovementState.Scale) { SetMovementState(MovementState.Rotate); } else { SetMovementState(MovementState.Normal); } } private bool ResetPosition() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown(Config.PropPositionReset)) { MoveProp(Direction.Reset); SetMovementState(MovementState.Normal); moved = true; return true; } return false; } private bool CheckStick(OneAxisInputControl input, Direction direction, bool useValue = true) { if (input.IsPressed && input.Value > StickThreshold) { float num = 0.1f; if (useValue) { num = input.Value / 5f; } if (((OneAxisInputControl)ManagerSingleton<InputHandler>.Instance.inputActions.Dash).IsPressed) { num /= 2f; } MoveProp(direction, num); return true; } return false; } private void NonKeypadUpdate(OneAxisInputControl switchModeButton, OneAxisInputControl left, OneAxisInputControl right, OneAxisInputControl up, OneAxisInputControl down, bool useValue) { left.Enabled = true; right.Enabled = true; up.Enabled = true; down.Enabled = true; switchModeButton.Enabled = true; ((OneAxisInputControl)ManagerSingleton<InputHandler>.Instance.inputActions.Dash).Enabled = true; if (switchModeButton.IsPressed && !ModeSwitchPressed) { ChangeModes(); ModeSwitchPressed = true; } else if (!switchModeButton.IsPressed) { ModeSwitchPressed = false; } if (MovementState == MovementState.Move2D) { if (!CheckStick(left, Direction.Left, useValue)) { CheckStick(right, Direction.Right, useValue); } if (!CheckStick(up, Direction.Up, useValue)) { CheckStick(down, Direction.Down, useValue); } } else if (MovementState == MovementState.MoveZ) { if (!CheckStick(left, Direction.Back, useValue)) { CheckStick(right, Direction.Front, useValue); } if (!CheckStick(up, Direction.Back, useValue)) { CheckStick(down, Direction.Front, useValue); } } else if (MovementState == MovementState.Scale) { if (!CheckStick(left, Direction.ScaleUp, useValue)) { CheckStick(right, Direction.ScaleDown, useValue); } if (!CheckStick(up, Direction.ScaleUp, useValue)) { CheckStick(down, Direction.ScaleDown, useValue); } } else if (MovementState == MovementState.Rotate && !CheckStick(left, Direction.RotateLeft, useValue)) { CheckStick(right, Direction.RotateRight, useValue); } } private void ControllerUpdate(bool rightStick = true) { TwoAxisInputControl val = (rightStick ? InputManager.ActiveDevice.RightStick : InputManager.ActiveDevice.LeftStick); if (val != null) { InputControl val2 = (rightStick ? InputManager.ActiveDevice.RightStickButton : InputManager.ActiveDevice.LeftStickButton); if (val2 != null) { NonKeypadUpdate((OneAxisInputControl)(object)val2, val.Left, val.Right, val.Up, val.Down, useValue: true); } } } private void NumpadUpdate() { SelfCoverManager instance = SelfCoverManager.instance; instance.MoveProp(Direction.Left, (KeyCode)260, ref moved); instance.MoveProp(Direction.Right, (KeyCode)262, ref moved); instance.MoveProp(Direction.Up, (KeyCode)264, ref moved); instance.MoveProp(Direction.Down, (KeyCode)258, ref moved); instance.MoveProp(Direction.Front, (KeyCode)263, ref moved); instance.MoveProp(Direction.Back, (KeyCode)265, ref moved); instance.MoveProp(Direction.RotateLeft, (KeyCode)257, ref moved); instance.MoveProp(Direction.RotateRight, (KeyCode)259, ref moved); instance.MoveProp(Direction.ScaleUp, (KeyCode)270, ref moved); instance.MoveProp(Direction.ScaleDown, (KeyCode)269, ref moved); } private void KeyboardUpdate() { HeroActions inputActions = ManagerSingleton<InputHandler>.Instance.inputActions; NonKeypadUpdate((OneAxisInputControl)(object)inputActions.Taunt, (OneAxisInputControl)(object)inputActions.Left, (OneAxisInputControl)(object)inputActions.Right, (OneAxisInputControl)(object)inputActions.Up, (OneAxisInputControl)(object)inputActions.Down, useValue: false); } public void Update() { if (!ResetPosition()) { switch (Config.MovementMethod) { case MovementMethods.ControllerRightStick: ControllerUpdate(); break; case MovementMethods.ControllerLeftStick: ControllerUpdate(rightStick: false); break; case MovementMethods.Numpad: NumpadUpdate(); break; case MovementMethods.KeyboardMovement: KeyboardUpdate(); break; } if (!moved) { SelfCoverManager.instance.SendPropPosition(); } moved = false; } } private void MoveProp(Direction direction, float distance = 0.1f) { moved = true; SelfCoverManager.instance.MoveProp(direction, distance); } public void SetMovementState(MovementState newState) { Log.LogDebug($"Movement State: {MovementState} -> {newState}"); MovementState = newState; switch (newState) { case MovementState.Move2D: HeroController.instance.AddInputBlocker((object)blocker); break; case MovementState.Normal: PropHuntMod.nextFrameActions.Add(delegate { HeroController.instance.RemoveInputBlocker((object)blocker); }); break; } if ((Object)(object)StateIndicator == (Object)null) { CreateMovementIndicator(); } switch (newState) { case MovementState.Normal: StateIndicator.sprite = null; break; case MovementState.Move2D: StateIndicator.sprite = MoveXY; break; case MovementState.MoveZ: StateIndicator.sprite = MoveZ; break; case MovementState.Scale: StateIndicator.sprite = Scale; break; case MovementState.Rotate: StateIndicator.sprite = Rotate; break; } } private void CreateMovementIndicator() { //IL_0105: Unknown result type (might be due to invalid IL or missing references) AssetBundle obj = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "prophunt.bundle")); Sprite[] source = obj.LoadAllAssets<Sprite>(); MoveXY = source.First((Sprite a) => ((Object)a).name == "MoveXY"); MoveZ = source.First((Sprite a) => ((Object)a).name == "MoveZ"); Rotate = source.First((Sprite a) => ((Object)a).name == "Rotate"); Scale = source.First((Sprite a) => ((Object)a).name == "Scale"); obj.Unload(false); Transform val = ((Component)GameCameras.instance.hudCamera).transform.Find("In-game/Anchor TL/Hud Canvas Offset/Hud Canvas"); Transform val2 = val.Find("Delivery Icon/Parent/Delivery Icon Sprite"); Transform obj2 = Object.Instantiate<Transform>(val2, val); ((Component)obj2).transform.position = val2.position; ((Component)obj2).gameObject.SetActive(true); StateIndicator = ((Component)obj2).GetComponent<SpriteRenderer>(); StateIndicator.sprite = null; } } internal class InputBlockingMechanism { } public class Prop { public string name; public string path; public GameObject go; } internal static class PropValidation { private static readonly string[] extraNames = new string[2] { "corpse", "quest_board" }; private static readonly PhysLayers[] invalidLayers = (PhysLayers[])(object)new PhysLayers[2] { (PhysLayers)11, (PhysLayers)17 }; private static GameObject PropParent; private static readonly Type[] allowedTypes = new Type[13] { typeof(Transform), typeof(MeshFilter), typeof(Renderer), typeof(MeshRenderer), typeof(SpriteRenderer), typeof(tk2dSprite), typeof(tk2dSpriteAnimator), typeof(tk2dSpriteAnimation), typeof(tk2dSpriteAnimationClip), typeof(tk2dSpriteAnimationFrame), typeof(tk2dLookAnimNPC), typeof(CurveRotationAnimation), typeof(JitterSelf) }; public static NoRepeat<Prop> currentSceneObjects { get; private set; } private static bool HasScript(GameObject obj) { if (!Object.op_Implicit((Object)(object)obj.GetComponent<Breakable>()) && !Object.op_Implicit((Object)(object)obj.GetComponent<PlayMakerNPC>()) && !Object.op_Implicit((Object)(object)obj.GetComponent<BasicNPC>()) && !Object.op_Implicit((Object)(object)obj.GetComponent<QuestBoardInteractable>())) { return Object.op_Implicit((Object)(object)obj.GetComponent<PushableRubble>()); } return true; } private static void LogSpecificObj(string objectName, string condition) { if (objectName == "Bonechurch_shop") { Log.LogInfo(condition); } } private static bool IsValidProp(string scene, GameObject gameObject) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) if (!gameObject.activeInHierarchy) { LogSpecificObj(((Object)gameObject).name, "inactive"); return false; } if (Regex.IsMatch(((Object)gameObject).name, "^pebble$|^junk_push|^Small_bell_push|^weaver_corpse_shrine|^Weaver Corpse Glow", RegexOptions.IgnoreCase)) { return false; } if (((Object)gameObject).name.Contains("(Clone)")) { LogSpecificObj(((Object)gameObject).name, "clone"); return false; } if (invalidLayers.Contains((PhysLayers)gameObject.layer)) { string name2 = ((Object)gameObject).name; PhysLayers val = (PhysLayers)gameObject.layer; LogSpecificObj(name2, "layer " + ((object)(PhysLayers)(ref val)).ToString()); return false; } SpriteRenderer renderer = gameObject.GetComponent<SpriteRenderer>(); if ((Object)(object)renderer == (Object)null && (Object)(object)gameObject.GetComponent<tk2dSprite>() == (Object)null) { LogSpecificObj(((Object)gameObject).name, "no renderer"); return false; } SpriteRenderer obj = renderer; object obj2; if (obj == null) { obj2 = null; } else { Sprite sprite = obj.sprite; obj2 = ((sprite != null) ? ((Object)sprite).name : null); } if (obj2 != null && ExtraProps.banned.Any((string p) => p == ((Object)renderer.sprite).name)) { LogSpecificObj(((Object)gameObject).name, "black fader"); return false; } SpriteRenderer obj3 = renderer; float num; if (obj3 == null) { num = 1f; } else { Color color = obj3.color; num = ((Color)(ref color)).grayscale; } if (num < 0.75f) { LogSpecificObj(((Object)gameObject).name, "too dark"); return false; } LogSpecificObj(((Object)gameObject).name, "passed negative"); if (HasScript(gameObject)) { return true; } string name = ((Object)gameObject).name.ToLower(); if (extraNames.Any((string n) => name.Contains(n))) { return true; } if (ExtraProps.IsExtraProp(scene, gameObject)) { return true; } return false; } private static bool IsGameObjectDuplicate(SpriteRenderer newObjRenderer, GameObject existingGameObject) { try { SpriteRenderer renderer = GetRenderer(existingGameObject); if ((Object)(object)((renderer != null) ? renderer.sprite : null) == (Object)null || (Object)(object)((newObjRenderer != null) ? newObjRenderer.sprite : null) == (Object)null) { return false; } return ((Object)renderer.sprite).name == ((Object)newObjRenderer.sprite).name; } catch (Exception ex) { Log.LogError(((Object)existingGameObject).name + " failed, no sprite on one of the objects?"); Log.LogError(ex); return true; } } private static SpriteRenderer GetRenderer(GameObject gameObject) { SpriteRenderer val = gameObject.GetComponent<SpriteRenderer>(); if ((Object)(object)((val != null) ? val.sprite : null) == (Object)null) { val = ((IEnumerable<SpriteRenderer>)gameObject.GetComponentsInChildren<SpriteRenderer>()).FirstOrDefault((Func<SpriteRenderer, bool>)((SpriteRenderer s) => (Object)(object)s.sprite != (Object)null)); } return val; } public static void GetAllProps() { //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; Log.LogDebug("Preparing all props for scene " + name); GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>(); List<GameObject> list = new List<GameObject>(); ExtraProps.Init(); GameObject[] array2 = array; foreach (GameObject val in array2) { if (IsValidProp(name, val)) { LogSpecificObj(((Object)val).name, "valid prop"); SpriteRenderer renderer = GetRenderer(val); if ((Object)(object)renderer == (Object)null) { LogSpecificObj(((Object)val).name, "no renderer"); } else if (list.Any((GameObject o) => IsGameObjectDuplicate(renderer, o))) { LogSpecificObj(((Object)val).name, "duplicate object"); } else { list.Add(val); } } } PrepareAllProps(list); AddPropsToOutput(name); } private static void AddPropsToOutput(string scene) { List<Prop> inputValues = currentSceneObjects.inputValues; string value = string.Format("{0},{1},\"{2}\"", scene, inputValues.Count, string.Join("\n", inputValues.Select((Prop x) => x.name))); StreamWriter streamWriter = File.AppendText(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "PropReport.csv")); streamWriter.WriteLine(value); streamWriter.Close(); } private static void RemoveComponents<T>(GameObject gameObject, bool keepOnParent = false) where T : Component { T[] componentsInChildren = gameObject.GetComponentsInChildren<T>(); foreach (T val in componentsInChildren) { if (!keepOnParent || (Object)(object)((Component)val).gameObject != (Object)(object)gameObject.gameObject) { Object.Destroy((Object)(object)val); } } } private static void StripProp(GameObject gameObject) { MonoBehaviour[] componentsInChildren = gameObject.GetComponentsInChildren<MonoBehaviour>(true); foreach (MonoBehaviour val in componentsInChildren) { Type type = ((object)val).GetType(); if (!allowedTypes.Any((Type t) => type == t)) { Object.Destroy((Object)(object)val); } } RemoveComponents<Collider2D>(gameObject, keepOnParent: false); RemoveComponents<Rigidbody2D>(gameObject, keepOnParent: true); Transform[] componentsInChildren2 = gameObject.GetComponentsInChildren<Transform>(); foreach (Transform val2 in componentsInChildren2) { if (!Object.op_Implicit((Object)(object)((Component)val2).GetComponentInChildren<Renderer>()) && !Object.op_Implicit((Object)(object)((Component)val2).GetComponentInChildren<ParticleSystem>())) { Object.Destroy((Object)(object)((Component)val2).gameObject); } } } private static string GeneratePropPath(GameObject prop) { string text = ((Object)prop).name; _ = prop.transform.parent; while ((Object)(object)prop.transform.parent != (Object)null) { prop = ((Component)prop.transform.parent).gameObject; text = ((Object)prop).name + "/" + text; } return text; } public static Prop PrepareProp(GameObject prop, bool assignParent = true) { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prop == (Object)null) { Log.LogError("Unknown prop to prepare"); return null; } GameObject val; try { if (assignParent) { val = Object.Instantiate<GameObject>(prop, PropParent.transform); } else { val = Object.Instantiate<GameObject>(prop); val.SetActive(false); } val.layer = 20; ((Object)val).name = ((Object)prop).name; Breakable component = val.GetComponent<Breakable>(); if ((Object)(object)component != (Object)null && component.IsBroken) { SpriteRenderer component2 = val.GetComponent<SpriteRenderer>(); if ((Object)(object)component2 != (Object)null) { ((Renderer)component2).enabled = true; } } } catch (Exception ex) { Log.LogError("Ran into an error instantiating cover " + ((Object)prop).name + "."); Log.LogError(ex); return null; } StripProp(val); Quaternion rotation = val.transform.rotation; val.transform.rotation = Quaternion.identity; if (!AddPropHitbox(val)) { Log.LogError("Couldn't add hitbox for " + ((Object)prop).name); Object.Destroy((Object)(object)val); return null; } val.transform.rotation = rotation; return new Prop { name = ((Object)val).name, go = val, path = GeneratePropPath(prop) }; } private static bool AddPropHitbox(GameObject prop) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) Renderer[] array = (from r in prop.GetComponentsInChildren<Renderer>(false) where !(r is LineRenderer) && !(r is ParticleSystemRenderer) select r).ToArray(); if (array.Length == 0) { Log.LogError("No renderers found"); return false; } Bounds bounds = array[0].bounds; Renderer[] array2 = array; foreach (Renderer val in array2) { string text = ((Object)val).name.ToLower(); if (!text.StartsWith("haze") && !text.StartsWith("light") && !text.StartsWith("vignette") && !text.EndsWith("fader") && !text.EndsWith("glow") && !text.EndsWith("cutout") && !(text == "lit")) { ((Bounds)(ref bounds)).Encapsulate(val.bounds); } } Vector3 val2 = prop.transform.InverseTransformVector(((Bounds)(ref bounds)).size); BoxCollider2D val3 = prop.AddComponent<BoxCollider2D>(); ((Collider2D)val3).isTrigger = true; ((Collider2D)val3).offset = Vector2.op_Implicit(prop.transform.InverseTransformPoint(((Bounds)(ref bounds)).center)); val3.size = new Vector2(Mathf.Abs(val2.x), Mathf.Abs(val2.y)); if ((val3.size.x > 20f && val3.size.y > 20f) || val3.size.x >= 30f || val3.size.y >= 30f) { Log.LogError($"Prop {((Object)prop).name} was too frickin big (${val3.size})"); return false; } Extensions.AddComponentIfNotPresent<Rigidbody2D>(prop).bodyType = (RigidbodyType2D)1; prop.AddComponent<LineRenderer>(); prop.AddComponent<DebugViewCollider>(); prop.AddComponent<TriggerHandler>(); array2 = array; foreach (Renderer val4 in array2) { if (!((Object)(object)((Component)val4).gameObject == (Object)(object)prop)) { Extensions.AddComponentIfNotPresent<LineRenderer>(((Component)val4).gameObject); ((Component)val4).gameObject.AddComponent<DebugViewBounds>(); } } return true; } private static void PrepareAllProps(List<GameObject> props) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown if ((Object)(object)PropParent != (Object)null) { Object.Destroy((Object)(object)PropParent); } PropParent = new GameObject("PROP PARENT"); PropParent.SetActive(false); if (!SelfHornetManager.instance.HornetExists()) { return; } List<Prop> list = new List<Prop>(); foreach (GameObject prop2 in props) { Prop prop = PrepareProp(prop2); if (prop != null) { list.Add(prop); } } currentSceneObjects = new NoRepeat<Prop>(list); } public static void ResetProps() { Log.LogDebug("Resetting props"); currentSceneObjects = null; } public static GameObject FindGameObject(string path) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) string[] names = path.Split(new char[1] { '/' }); Scene activeScene = SceneManager.GetActiveScene(); GameObject val = ((IEnumerable<GameObject>)((Scene)(ref activeScene)).GetRootGameObjects()).FirstOrDefault((Func<GameObject, bool>)((GameObject go) => ((Object)go).name == names[0])); if ((Object)(object)val == (Object)null) { return null; } for (int i = 1; i < names.Length; i++) { GameObject val2 = FindGameObjectLayer(names[i], val); if ((Object)(object)val2 == (Object)null) { return null; } val = val2; } return val; } 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; } } return null; } } internal class DebugViewCollider : MonoBehaviour { private Color borderColor = Color.white; private readonly float lineWidth = 0.05f; private LineRenderer lineRenderer; private BoxCollider2D collider; private bool Show => PropHuntMod.showHitboxes; private void Awake() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) collider = ((Component)this).GetComponent<BoxCollider2D>(); lineRenderer = ((Component)this).GetComponent<LineRenderer>(); lineRenderer.loop = true; lineRenderer.useWorldSpace = true; lineRenderer.startWidth = lineWidth; lineRenderer.endWidth = lineWidth; ((Renderer)lineRenderer).material = new Material(Shader.Find("Sprites/Default")); lineRenderer.startColor = borderColor; lineRenderer.endColor = borderColor; } private void LateUpdate() { if (Show) { DrawBox(collider); } else { lineRenderer.positionCount = 0; } } private void DrawBox(BoxCollider2D box) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: 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) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_0047: 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_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) Vector2 val = box.size * 0.5f; Vector2 offset = ((Collider2D)box).offset; SetPositions((Vector3[])(object)new Vector3[4] { Vector2.op_Implicit(offset + new Vector2(0f - val.x, 0f - val.y)), Vector2.op_Implicit(offset + new Vector2(val.x, 0f - val.y)), Vector2.op_Implicit(offset + new Vector2(val.x, val.y)), Vector2.op_Implicit(offset + new Vector2(0f - val.x, val.y)) }); } private void SetPositions(Vector3[] localPoints) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) lineRenderer.positionCount = localPoints.Length; for (int i = 0; i < localPoints.Length; i++) { lineRenderer.SetPosition(i, ((Component)this).transform.TransformPoint(localPoints[i])); } } } internal class DebugViewBounds : MonoBehaviour { private LineRenderer lineRenderer; private Renderer[] renderers; private Color borderColor = Color.red; private readonly float lineWidth = 0.05f; private bool Show => PropHuntMod.showHitboxes; private void Awake() { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) lineRenderer = ((Component)this).GetComponent<LineRenderer>(); lineRenderer.loop = true; lineRenderer.useWorldSpace = true; lineRenderer.startWidth = lineWidth; lineRenderer.endWidth = lineWidth; ((Renderer)lineRenderer).material = new Material(Shader.Find("Sprites/Default")); lineRenderer.startColor = borderColor; lineRenderer.endColor = borderColor; renderers = ((Component)this).GetComponents<Renderer>(); } private void LateUpdate() { if (Show) { Renderer[] array = renderers; foreach (Renderer renderer in array) { DrawBox(renderer); } } } private void DrawBox(Renderer renderer) { //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_0009: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_0040: 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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) Bounds localBounds = renderer.localBounds; Vector2 val = Vector2.op_Implicit(Extensions.DivideElements(((Bounds)(ref localBounds)).size, (float?)2.1f, (float?)2.1f, (float?)null)); localBounds = renderer.localBounds; Vector2 val2 = Vector2.op_Implicit(((Bounds)(ref localBounds)).center); SetPositions((Vector3[])(object)new Vector3[4] { Vector2.op_Implicit(val2 + new Vector2(0f - val.x, 0f - val.y)), Vector2.op_Implicit(val2 + new Vector2(val.x, 0f - val.y)), Vector2.op_Implicit(val2 + new Vector2(val.x, val.y)), Vector2.op_Implicit(val2 + new Vector2(0f - val.x, val.y)) }); } private void SetPositions(Vector3[] localPoints) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) lineRenderer.positionCount = localPoints.Length; for (int i = 0; i < localPoints.Length; i++) { lineRenderer.SetPosition(i, ((Component)this).transform.TransformPoint(localPoints[i])); } } } internal static class ExtraProps { private static string[] sceneProps; private static string[] scenePrefixes; private static string scenePrefix; public static string[] global = new string[0]; public static string[] banned = new string[0]; public static void Init() { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) Scene activeScene = SceneManager.GetActiveScene(); string scene = ((Scene)(ref activeScene)).name; if (scenePrefixes != null) { string text = scenePrefixes.FirstOrDefault((string p) => scene.StartsWith(p)); if (string.IsNullOrEmpty(text)) { Log.LogDebug("EPI: Scene not in extra props list"); sceneProps = null; scenePrefix = null; return; } if (text == scenePrefix) { Log.LogDebug("EPI: Scene is same."); return; } } Log.LogDebug("Proceeding with extra prop loading"); Dictionary<string, string[]> dictionary = JsonConvert.DeserializeObject<Dictionary<string, string[]>>(File.ReadAllText(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "ExtraProps.json"))); scenePrefixes = dictionary.Keys.ToArray(); string text2 = dictionary.Keys.FirstOrDefault((string s) => scene.StartsWith(s)); global = dictionary["GLOBAL"]; if (string.IsNullOrEmpty(text2)) { Log.LogError("EPI: key not found"); sceneProps = null; scenePrefix = null; } else { sceneProps = dictionary[text2]; scenePrefix = text2; banned = dictionary["BANNED"]; } } public static bool IsExtraProp(string scene, GameObject gameObject) { //IL_0047: 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) if (string.IsNullOrEmpty(scene)) { return false; } if (sceneProps == null) { return false; } SpriteRenderer renderer = gameObject.GetComponent<SpriteRenderer>(); SpriteRenderer obj = renderer; if ((Object)(object)((obj != null) ? obj.sprite : null) == (Object)null) { return false; } Color color = renderer.color; if (((Color)(ref color)).grayscale < 0.75f) { return false; } bool flag = global.Any((string p) => ((Object)renderer.sprite).name.StartsWith(p)) || sceneProps.Any((string p) => ((Object)renderer.sprite).name.StartsWith(p)); if (flag && banned.Any((string p) => ((Object)renderer.sprite).name == p)) { flag = false; } return flag; } } } namespace PropHuntMod.Players { internal class PlayerManager { public BaseHornetManager hornetManager; public BaseCoverManager coverManager; public string currentCoverObjName = ""; public string currentCoverObjPath = ""; public Vector3 currentCoverObjLocation = Consts.DEFAULT_LOCATION; public float currentCoverObjRotation; public float currentCoverObjScale = 1f; public bool currentHideState; public ushort playerID; public IClientPlayer PlayerAvatar => PropHuntMod.client.ClientManager.GetPlayer(playerID); public PlayerManager(ushort playerID) { hornetManager = new BaseHornetManager(); coverManager = new BaseCoverManager(); this.playerID = playerID; hornetManager.playerID = playerID; coverManager.playerID = playerID; IClientPlayer val = default(IClientPlayer); PropHuntMod.client.ClientManager.TryGetPlayer(playerID, ref val); if (val == null) { Log.LogError($"No remotePlayer for {playerID}. Are they remote?"); } else { PropHuntMod.playerManager.Add(playerID, this); } } public static PlayerManager GetPlayerManager(ushort playerID) { PropHuntMod.playerManager.TryGetValue(playerID, out var value); if (value == null) { return new PlayerManager(playerID); } return value; } public bool IsHostInSameRoom() { //IL_0056: 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) if (PlayerAvatar == null) { return false; } bool isInLocalScene = PlayerAvatar.IsInLocalScene; if (isInLocalScene) { Log.LogDebug($"{playerID} is in the same room"); } else { object[] array = new object[1]; object arg = playerID; Scene activeScene = SceneManager.GetActiveScene(); array[0] = $"{arg} is in another room, you are in {((Scene)(ref activeScene)).name}"; Log.LogDebug(array); } return isInLocalScene; } public void EnsurePropCover() { if (string.IsNullOrEmpty(currentCoverObjName)) { coverManager.DisableProp(hornetManager); hornetManager.ToggleHornet(show: true); } else if (IsHostInSameRoom()) { GameObject val = PropValidation.FindGameObject(currentCoverObjPath); if ((Object)(object)val == (Object)null) { Log.LogError($"Couldn't find prop {currentCoverObjName} for player {playerID}"); return; } Prop prop = PropValidation.PrepareProp(val, assignParent: false); if (prop == null) { Log.LogError($"Couldn't prepare prop for player {playerID}"); } else { coverManager.EnableProp(hornetManager, prop); coverManager.SetPropLocation(currentCoverObjLocation, currentCoverObjRotation, currentCoverObjScale); Object.Destroy((Object)(object)prop.go); } } else { coverManager.DisableProp(hornetManager, logOnFail: false); } } public void SetProp(string name, string path) { if (string.IsNullOrEmpty(name) || string.IsNullOrEmpty(path)) { name = ""; path = ""; } currentCoverObjName = name; currentCoverObjPath = path; ResetCoverPosition(); EnsurePropCover(); } public void SetPropLocation(Vector3 location, float rotation, float scale) { currentCoverObjLocation = location; currentCoverObjRotation = rotation; currentCoverObjScale = scale; if (IsHostInSameRoom()) { coverManager.SetPropLocation(location, rotation, scale); } } public void SetHideStatus(bool hiding) { hornetManager.shouldBeShown = !hiding; if (IsHostInSameRoom()) { hornetManager.ToggleHornet(!hiding); } } public void ResetCoverPosition() { SetPropLocation(Consts.DEFAULT_LOCATION, 0f, 1f); } public static void EnsureAllPropCovers() { Debug.Log((object)$"Ensuring cover for {PropHuntMod.playerManager.Count} players"); foreach (PlayerManager value in PropHuntMod.playerManager.Values) { value.EnsurePropCover(); } } } internal class InputBlocker { } internal class SelfHornetManager : BaseHornetManager { private static InputBlocker blocker = new InputBlocker(); public static SelfHornetManager instance; private SpriteRenderer obscurance; public SelfHornetManager() { isRemote = false; instance = this; } public void ToggleHornet() { if (Config.AllowDebugFeatures || Se