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 FacilityMeltdownCustom v1.0.0
FacilityMeltdown.dll
Decompiled 9 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Biodiversity.Util.Assetloading; using FacilityMeltdown.API; using FacilityMeltdown.Behaviours; using FacilityMeltdown.Config; using FacilityMeltdown.Lang; using FacilityMeltdown.MeltdownSequence.Behaviours; using FacilityMeltdown.Patches; using FacilityMeltdown.Util; using FacilityMeltdown.Util.Attributes; using FacilityMeltdown.Util.Config; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; using UnityEngine.Events; using UnityEngine.Rendering.HighDefinition; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("ClientNetworkTransform")] [assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")] [assembly: IgnoresAccessChecksTo("DissonanceVoip")] [assembly: IgnoresAccessChecksTo("EasyTextEffects")] [assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")] [assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")] [assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")] [assembly: IgnoresAccessChecksTo("Unity.Burst")] [assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")] [assembly: IgnoresAccessChecksTo("Unity.Collections")] [assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")] [assembly: IgnoresAccessChecksTo("Unity.Jobs")] [assembly: IgnoresAccessChecksTo("Unity.Mathematics")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")] [assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Relay")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("Unity.Timeline")] [assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("FacilityMeltdown")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("FacilityMeltdown")] [assembly: AssemblyTitle("FacilityMeltdown")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace Biodiversity.Util.Assetloading { [AttributeUsage(AttributeTargets.Property)] internal class LoadFromBundleAttribute : Attribute { public string BundleFile { get; private set; } public LoadFromBundleAttribute(string bundleFile) { BundleFile = bundleFile; base..ctor(); } } } namespace FacilityMeltdown { [BepInPlugin("me.loaforc.facilitymeltdown", "FacilityMeltdownFork", "1.0.0")] public class MeltdownPlugin : BaseUnityPlugin { internal const string modGUID = "me.loaforc.facilitymeltdown"; internal const string modName = "FacilityMeltdownFork"; internal const string modVersion = "1.0.0"; internal static MeltdownPlugin instance; internal static ManualLogSource logger; internal static Harmony harmony = new Harmony("me.loaforc.facilitymeltdown"); internal static MeltdownAssets assets { get; private set; } public static bool loadedFully { get; private set; } internal static MeltdownConfig config { get; set; } internal static MeltdownClientConfig clientConfig { get; private set; } private void Awake() { if (!((Object)(object)instance == (Object)null)) { return; } instance = this; logger = Logger.CreateLogSource("me.loaforc.facilitymeltdown"); if (RunLoadStep("Assets.Init", "Getting assets", delegate { assets = new MeltdownAssets(); }) && RunLoadStep("LangParser.Init", "Getting possible languages", LangParser.Init) && RunLoadStep("new MeltdownConfig()", "Setting up config", delegate { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown config = new MeltdownConfig(((BaseUnityPlugin)this).Config); clientConfig = new MeltdownClientConfig(new ConfigFile(Utility.CombinePaths(new string[2] { Paths.ConfigPath, "me.loaforc.facilitymeltdown.Client.cfg" }), false, MetadataHelper.GetMetadata((object)this))); logger.LogDebug((object)$"Test Config Value: {config.ApparatusValue}"); ((BaseUnityPlugin)this).Config.ClearOrphans(); clientConfig.configFile.ClearOrphans(); }) && RunLoadStep("LangParser.SetLanguage", "Setting language", delegate { LangParser.SetLanguage(clientConfig.Language); }) && RunLoadStep("RegisterPatches", "Integrating into LethalCompany", RegisterPatches) && RunLoadStep("RegisterNetworking", "Making sure everything is networked", RegisterNetworking)) { if (!RunLoadStep("CompatibleDependency.Init", "Checking for any soft dependencies", delegate { CompatibleDependencyAttribute.Init((BaseUnityPlugin)(object)this); })) { logger.LogWarning((object)"Doing something with soft dependencies broke, meltdown itself should be fine."); } loadedFully = true; logger.LogInfo((object)"FacilityMeltdownFork:1.0.0 by loaforc has loaded (modified by baer1)! have fun :}"); logger.LogInfo((object)" .-_; ;_-. "); logger.LogInfo((object)" / / \\ \\ "); logger.LogInfo((object)" | | | | "); logger.LogInfo((object)" \\ \\.---./ / "); logger.LogInfo((object)" .-\\\"\"~ .---. ~\"\"-."); logger.LogInfo((object)" ,`.-~// .'`---`'. \\\\~-.`,"); logger.LogInfo((object)" ' ` | | \\(_)/ | | `' "); logger.LogInfo((object)" , \\ \\ | | / / , "); logger.LogInfo((object)" ;`'.,_\\ `-'-' /_,.'`; "); logger.LogInfo((object)" '-._ _.-'^'-._ _.-' "); } } private bool RunLoadStep(string stepName, string descrption, Action callback) { try { callback(); } catch (Exception ex) { logger.LogError((object)("`" + stepName + "` caused an exception to be thrown, meltdown may or may not work, look for more errors.")); logger.LogError((object)ex); return false; } logger.LogInfo((object)(stepName.PadRight(25) + " == " + descrption)); return true; } private void RegisterNetworking() { Type[] array = new Type[1] { typeof(MeltdownHandler) }; foreach (Type type in array) { try { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.NonPublic); MethodInfo[] array2 = methods; foreach (MethodInfo methodInfo in array2) { object[] customAttributes = methodInfo.GetCustomAttributes(typeof(RuntimeInitializeOnLoadMethodAttribute), inherit: false); if (customAttributes.Length != 0) { methodInfo.Invoke(null, null); } } } catch (Exception) { logger.LogWarning((object)"supressed an error from netcode patcher, probably fine but should still log that something happened."); } } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] private void RegisterPatches() { foreach (Type item in from t in Assembly.GetExecutingAssembly().GetLoadableTypes() where t.IsClass && t.Namespace == "FacilityMeltdown.Patches" select t) { logger.LogDebug((object)("Registering Patch handler: " + item.Name)); harmony.PatchAll(item); } } } internal static class ExtensionMethods { private static Random rng = new Random(); public static void Shuffle<T>(this IList<T> list) { int num = list.Count; while (num > 1) { num--; int index = rng.Next(num + 1); T value = list[index]; list[index] = list[num]; list[num] = value; } } public static float Remap(this float value, float from1, float to1, float from2, float to2) { return (value - from1) / (to1 - from1) * (to2 - from2) + from2; } public static List<PlayerControllerB> GetConnectedPlayers(this StartOfRound startOfRound) { return startOfRound.allPlayerScripts.Where((PlayerControllerB player) => player.isPlayerControlled).ToList(); } public static void SpawnEnemy(this EnemyVent vent, SpawnableEnemyWithRarity enemy) { //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) //IL_0013: 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_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) Vector3 position = vent.floorNode.position; float y = vent.floorNode.eulerAngles.y; GameObject val = Object.Instantiate<GameObject>(enemy.enemyType.enemyPrefab, position, Quaternion.Euler(new Vector3(0f, y, 0f))); EnemyAI component = val.GetComponent<EnemyAI>(); ((NetworkBehaviour)component).NetworkObject.Spawn(true); RoundManager.Instance.SpawnedEnemies.Add(component); vent.OpenVentClientRpc(); vent.occupied = false; } internal static string Translate(this string text) { return LangParser.GetTranslation(text); } internal static void ClearOrphans(this ConfigFile config) { PropertyInfo property = ((object)config).GetType().GetProperty("OrphanedEntries", BindingFlags.Instance | BindingFlags.NonPublic); Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)property.GetValue(config, null); dictionary.Clear(); config.Save(); } internal static IEnumerable<Type> GetLoadableTypes(this Assembly assembly) { if (assembly == null) { throw new ArgumentNullException("assembly"); } try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { return ex.Types.Where((Type t) => t != null); } } internal static (int hours, int minutes) GetCurrentTime(this TimeOfDay timeOfDay) { int num = Mathf.FloorToInt(timeOfDay.normalizedTimeOfDay * 60f * (float)timeOfDay.numberOfHours + 360f); int item = Mathf.FloorToInt((float)(num / 60)); return (item, num % 60); } } internal class MeltdownAssets : AssetBundleLoader<MeltdownAssets> { [LoadFromBundle("meltdownmusic.mp3")] public AudioClip defaultMusic { get; private set; } [LoadFromBundle("shockwave.mp3")] public AudioClip shockwave { get; private set; } [LoadFromBundle("FacilityExplosion.prefab")] public GameObject facilityExplosionPrefab { get; private set; } [LoadFromBundle("MeltdownHandler.prefab")] public GameObject meltdownHandlerPrefab { get; private set; } [LoadFromBundle("Shockwave.prefab")] public GameObject shockwavePrefab { get; private set; } [LoadFromBundle("HealthKeyword.asset")] public TerminalKeyword healthKeyword { get; private set; } [LoadFromBundle("ReactorKeyword.asset")] public TerminalKeyword reactorKeyword { get; private set; } [LoadFromBundle("ReactorHealthReport.asset")] public TerminalNode reactorHealthNode { get; private set; } public GameObject[] facilityEffects { get; private set; } public AudioClip[] warnings { get; private set; } public MeltdownAssets() : base("facilitymeltdown") { } protected override void FinishLoadingAssets(AssetBundle bundle) { warnings = (AudioClip[])(object)new AudioClip[4] { LoadAsset<AudioClip>(bundle, "warning1.mp3"), LoadAsset<AudioClip>(bundle, "warning2.mp3"), LoadAsset<AudioClip>(bundle, "warning3.mp3"), LoadAsset<AudioClip>(bundle, "warning4.mp3") }; facilityEffects = (GameObject[])(object)new GameObject[2] { LoadAsset<GameObject>(bundle, "Dust.prefab"), LoadAsset<GameObject>(bundle, "Waterstream.prefab") }; TerminalPatch.terminalKeywordsToRegister.Add(healthKeyword); TerminalPatch.terminalKeywordsToRegister.Add(reactorKeyword); TerminalPatch.terminalNodesToRegister.Add(reactorHealthNode); } } } namespace FacilityMeltdown.Util { internal abstract class AssetBundleLoader<T> where T : AssetBundleLoader<T> { public AssetBundleLoader(string filePath) { AssetBundle val = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), filePath)); MeltdownPlugin.logger.LogDebug((object)("[Assets] AssetBundle `" + filePath + "` contains these objects: \n" + string.Join("\n", val.GetAllAssetNames()))); Type typeFromHandle = typeof(T); PropertyInfo[] properties = typeFromHandle.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { LoadFromBundleAttribute loadFromBundleAttribute = (LoadFromBundleAttribute)propertyInfo.GetCustomAttribute(typeof(LoadFromBundleAttribute)); if (loadFromBundleAttribute != null) { MeltdownPlugin.logger.LogDebug((object)("[Assets] Got LoadFromBundle attribute on `" + propertyInfo.Name + "`. Loading asset: `" + loadFromBundleAttribute.BundleFile + "` into the [roperty.")); propertyInfo.SetValue(this, LoadAsset<Object>(val, loadFromBundleAttribute.BundleFile.ToLower(CultureInfo.GetCultureInfo("en-GB")))); } } GameObject[] array = val.LoadAllAssets<GameObject>(); foreach (GameObject val2 in array) { if (!((Object)(object)val2.GetComponent<NetworkObject>() == (Object)null) && !GameNetworkManagerPatch.networkPrefabsToRegister.Contains(val2)) { GameNetworkManagerPatch.networkPrefabsToRegister.Add(val2); } } FinishLoadingAssets(val); } protected virtual void FinishLoadingAssets(AssetBundle bundle) { } protected AssetType LoadAsset<AssetType>(AssetBundle bundle, string path) where AssetType : Object { AssetType val = bundle.LoadAsset<AssetType>(path); if ((Object)(object)val == (Object)null) { throw new ArgumentException(path + " is not valid in the assetbundle!"); } return val; } } } namespace FacilityMeltdown.Util.Config { [AttributeUsage(AttributeTargets.Property)] internal class ConfigDescAttribute : Attribute { public string Description { get; private set; } public ConfigDescAttribute(string desc) { Description = desc; base..ctor(); } } [AttributeUsage(AttributeTargets.Property)] internal class ConfigGroupAttribute : Attribute { public string Group { get; private set; } public ConfigGroupAttribute(string Group) { this.Group = Group; base..ctor(); } } [AttributeUsage(AttributeTargets.Property)] internal class ConfigIgnoreAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property)] internal class ConfigRangeAttribute : Attribute { internal float Min { get; private set; } internal float Max { get; private set; } internal ConfigRangeAttribute(float min, float max) { Min = min; Max = max; } } [Serializable] internal abstract class LoafConfig<T> where T : LoafConfig<T> { internal List<(PropertyInfo, object)> configEntries = new List<(PropertyInfo, object)>(); internal ConfigFile configFile { get; private set; } public LoafConfig(ConfigFile configFile) { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Expected O, but got Unknown //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Expected O, but got Unknown //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Expected O, but got Unknown if (configFile == null) { return; } this.configFile = configFile; string header = "Misc"; Type typeFromHandle = typeof(T); PropertyInfo[] properties = typeFromHandle.GetProperties(); foreach (PropertyInfo propertyInfo in properties) { if (propertyInfo.GetCustomAttribute(typeof(ConfigIgnoreAttribute)) == null) { ConfigGroupAttribute configGroupAttribute = (ConfigGroupAttribute)propertyInfo.GetCustomAttribute(typeof(ConfigGroupAttribute)); if (configGroupAttribute != null) { header = configGroupAttribute.Group.Replace(" ", ""); } string text = "no description here :pensive:"; ConfigDescAttribute configDescAttribute = (ConfigDescAttribute)propertyInfo.GetCustomAttribute(typeof(ConfigDescAttribute)); if (configDescAttribute != null) { text = configDescAttribute.Description; } ConfigDescription val = new ConfigDescription(text, (AcceptableValueBase)null, Array.Empty<object>()); ConfigRangeAttribute configRangeAttribute = (ConfigRangeAttribute)propertyInfo.GetCustomAttribute(typeof(ConfigRangeAttribute)); val = ((configRangeAttribute == null) ? new ConfigDescription(text, (AcceptableValueBase)null, Array.Empty<object>()) : ((!(propertyInfo.PropertyType == typeof(int))) ? new ConfigDescription(text, (AcceptableValueBase)(object)new AcceptableValueRange<float>(configRangeAttribute.Min, configRangeAttribute.Max), Array.Empty<object>()) : new ConfigDescription(text, (AcceptableValueBase)(object)new AcceptableValueRange<int>((int)configRangeAttribute.Min, (int)configRangeAttribute.Max), Array.Empty<object>()))); if (propertyInfo.PropertyType == typeof(float)) { BindProperty<float>(propertyInfo, header, val); } if (propertyInfo.PropertyType == typeof(int)) { BindProperty<int>(propertyInfo, header, val); } if (propertyInfo.PropertyType == typeof(string)) { BindProperty<string>(propertyInfo, header, val); } if (propertyInfo.PropertyType == typeof(bool)) { BindProperty<bool>(propertyInfo, header, val); } } } } protected void BindProperty<V>(PropertyInfo property, string header, ConfigDescription description) { ConfigEntry<V> val = configFile.Bind<V>(header, property.Name, (V)property.GetValue(this), description); configEntries.Add((property, val)); property.SetValue(this, val.Value); } } internal abstract class LoafSyncedConfig<T> : LoafConfig<T> where T : LoafSyncedConfig<T> { internal static T Default { get; private set; } internal LoafSyncedConfig(ConfigFile file) : base(file) { if (Default == null) { Default = (T)this; } } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property)] internal class RequiresRestartAttribute : Attribute { public bool RequiresRestart { get; private set; } public RequiresRestartAttribute(bool requiresRestart = true) { RequiresRestart = requiresRestart; base..ctor(); } } } namespace FacilityMeltdown.Util.Attributes { internal class CompatibleDependencyAttribute : BepInDependency { public Type Handler; public CompatibleDependencyAttribute(string guid, Type handlerType) : base(guid, (DependencyFlags)2) { Handler = handlerType; } public static void Init(BaseUnityPlugin source) { IEnumerable<CompatibleDependencyAttribute> customAttributes = ((MemberInfo)((object)source).GetType()).GetCustomAttributes<CompatibleDependencyAttribute>(); foreach (CompatibleDependencyAttribute item in customAttributes) { if (Chainloader.PluginInfos.ContainsKey(((BepInDependency)item).DependencyGUID)) { item.Handler.GetMethod("Initialize", BindingFlags.Static | BindingFlags.NonPublic)?.Invoke(null, null); item.Handler = null; } } } } } namespace FacilityMeltdown.Patches { [HarmonyPatch(typeof(LungProp))] internal static class ApparaticePatch { [HarmonyPrefix] [HarmonyPatch("EquipItem")] internal static void LungProp_EquipItem(LungProp __instance, ref bool ___isLungDocked) { if (!((NetworkBehaviour)__instance).IsHost || !___isLungDocked || MeltdownAPI.MeltdownStarted) { return; } try { if (MeltdownPlugin.config.OverrideApparatusValue) { ((GrabbableObject)__instance).scrapValue = MeltdownPlugin.config.ApparatusValue; } GameObject val = Object.Instantiate<GameObject>(MeltdownPlugin.assets.meltdownHandlerPrefab); val.GetComponent<NetworkObject>().Spawn(false); } catch (Exception ex) { MeltdownPlugin.logger.LogError((object)ex); } } [HarmonyPrefix] [HarmonyPatch("Start")] internal static void LungProp_Start(LungProp __instance) { MeltdownMoonMapper.EnsureMeltdownMoonMapper(); MeltdownInteriorMapper.EnsureMeltdownInteriorMapper(); try { if (MeltdownPlugin.config.OverrideApparatusValue) { ((GrabbableObject)__instance).scrapValue = MeltdownPlugin.config.ApparatusValue; } MeltdownPlugin.logger.LogDebug((object)((GrabbableObject)__instance).scrapValue); } catch (Exception ex) { MeltdownPlugin.logger.LogError((object)ex); } } } [HarmonyPatch(typeof(EntranceTeleport))] internal static class EntranceTeleportPatch { [HarmonyPrefix] [HarmonyPatch("FindExitPoint")] private static bool EntranceTeleport_FindEntrancePoint(ref bool __result) { return (Object)(object)MeltdownHandler.Instance == (Object)null || !MeltdownHandler.Instance.HasExplosionOccured() || (__result = false); } } [HarmonyPatch(typeof(GameNetworkManager))] internal class GameNetworkManagerPatch { internal static List<GameObject> networkPrefabsToRegister = new List<GameObject>(); [HarmonyPatch("Start")] [HarmonyPrefix] private static void GameNetworkManager_Start() { foreach (GameObject item in networkPrefabsToRegister) { NetworkManager.Singleton.AddNetworkPrefab(item); MeltdownPlugin.logger.LogDebug((object)("Registered " + ((Object)item).name + " as a network prefab.")); } MeltdownPlugin.logger.LogInfo((object)$"Succesfully registered {networkPrefabsToRegister.Count} network prefabs."); } [HarmonyPostfix] [HarmonyPatch("StartDisconnect")] public static void GameNetworkManager_StartDisconnect() { MeltdownPlugin.config = LoafSyncedConfig<MeltdownConfig>.Default; } } [HarmonyPatch(typeof(PlayerControllerB))] internal static class PlayerControllerPatch { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnRequestSync; public static HandleNamedMessageDelegate <1>__OnReceiveSync; } private const string MESSAGE_REQUEST = "meltdown_OnRequestConfigSync"; private const string MESSAGE_RECIEVE = "meltdown_OnRecieveConfigSync"; private const int IntSize = 4; [HarmonyPostfix] [HarmonyPatch("ConnectClientToPlayerObject")] private static void SyncConfig() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown if (NetworkManager.Singleton.IsHost) { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<0>__OnRequestSync; if (obj == null) { HandleNamedMessageDelegate val = OnRequestSync; <>O.<0>__OnRequestSync = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("meltdown_OnRequestConfigSync", (HandleNamedMessageDelegate)obj); return; } CustomMessagingManager customMessagingManager2 = NetworkManager.Singleton.CustomMessagingManager; object obj2 = <>O.<1>__OnReceiveSync; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnReceiveSync; <>O.<1>__OnReceiveSync = val2; obj2 = (object)val2; } customMessagingManager2.RegisterNamedMessageHandler("meltdown_OnRecieveConfigSync", (HandleNamedMessageDelegate)obj2); RequestSync(); } public static void RequestSync() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) if (NetworkManager.Singleton.IsHost) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1); try { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("meltdown_OnRequestConfigSync", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } public static void OnRequestSync(ulong clientId, FastBufferReader _) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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) if (!NetworkManager.Singleton.IsHost) { return; } MeltdownPlugin.logger.LogInfo((object)$"Config sync request received from client: {clientId}"); byte[] bytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject((object)MeltdownPlugin.config)); int num = bytes.Length; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(num + 4, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe<int>(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteBytesSafe(bytes, -1, 0); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("meltdown_OnRecieveConfigSync", clientId, val, (NetworkDelivery)3); } catch (Exception arg) { MeltdownPlugin.logger.LogInfo((object)$"Error occurred syncing config with client: {clientId}\n{arg}"); } finally { ((IDisposable)(FastBufferWriter)(ref val)).Dispose(); } } private static void OnReceiveSync(ulong _, FastBufferReader reader) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown if (!((FastBufferReader)(ref reader)).TryBeginRead(4)) { MeltdownPlugin.logger.LogError((object)"Config sync error: Could not begin reading buffer."); return; } int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe<int>(ref num, default(ForPrimitives)); if (!((FastBufferReader)(ref reader)).TryBeginRead(num)) { MeltdownPlugin.logger.LogError((object)"Config sync error: Host could not sync."); return; } byte[] bytes = new byte[num]; ((FastBufferReader)(ref reader)).ReadBytesSafe(ref bytes, num, 0); MeltdownPlugin.logger.LogDebug((object)Encoding.UTF8.GetString(bytes)); MeltdownPlugin.config = JsonConvert.DeserializeObject<MeltdownConfig>(Encoding.UTF8.GetString(bytes), new JsonSerializerSettings { ContractResolver = (IContractResolver)(object)new IncludePrivateSetterContractResolver() }); MeltdownPlugin.logger.LogDebug((object)"Deserialized values are: "); PropertyInfo[] properties = MeltdownPlugin.config.GetType().GetProperties(); foreach (PropertyInfo propertyInfo in properties) { MeltdownPlugin.logger.LogDebug((object)$"{propertyInfo.Name} => {propertyInfo.GetValue(MeltdownPlugin.config)}"); } MeltdownPlugin.logger.LogInfo((object)"Successfully synced config with host."); } } internal class IncludePrivateSetterContractResolver : DefaultContractResolver { protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) JsonProperty val = ((DefaultContractResolver)this).CreateProperty(member, memberSerialization); if (!val.Writable && member is PropertyInfo propertyInfo) { val.Writable = propertyInfo.GetSetMethod(nonPublic: true) != null; } return val; } } [HarmonyPatch(typeof(StartOfRound))] internal static class StartOfRoundPatches { [HarmonyPrefix] [HarmonyPatch("EndOfGame")] internal static void StartOfRound_EndOfGame() { MeltdownHandler instance = MeltdownHandler.Instance; Object.Destroy((Object)(object)((instance != null) ? ((Component)instance).gameObject : null)); MeltdownMoonMapper instance2 = MeltdownMoonMapper.Instance; Object.Destroy((Object)(object)((instance2 != null) ? ((Component)instance2).gameObject : null)); MeltdownInteriorMapper instance3 = MeltdownInteriorMapper.Instance; Object.Destroy((Object)(object)((instance3 != null) ? ((Component)instance3).gameObject : null)); } } [HarmonyPatch(typeof(Terminal))] internal class TerminalPatch { internal class ReactorHealthReport { public float reactorInstability; public float timeRemaining; public float generatedAt = Time.time; public string GetFlavourText() { if (timeRemaining / (float)MeltdownPlugin.config.MeltdownTime > 0.75f) { return "reactorscan.result.flavour.start"; } if (timeRemaining / (float)MeltdownPlugin.config.MeltdownTime > 0.5f) { return "reactorscan.result.flavour.low"; } if (timeRemaining / (float)MeltdownPlugin.config.MeltdownTime > 0.33f) { return "reactorscan.result.flavour.medium"; } if (timeRemaining / (float)MeltdownPlugin.config.MeltdownTime > 0.15f) { return "reactorscan.result.flavour.high"; } return ""; } public string GetTeminalOutput() { string text = "reactorscan.result.unstable".Translate(); text = SubstituteVariables(text); return text + "\n\n" + SubstituteVariables(GetFlavourText().Translate()) + "\n\n"; } } internal static float lastHealthCheck; internal static ReactorHealthReport lastReport; internal static List<TerminalKeyword> terminalKeywordsToRegister = new List<TerminalKeyword>(); internal static List<TerminalNode> terminalNodesToRegister = new List<TerminalNode>(); internal static string SubstituteVariables(string text) { StringBuilder stringBuilder = new StringBuilder(text); stringBuilder.Replace("<cooldown>", MeltdownPlugin.config.ShipScanCooldown.ToString()); stringBuilder.Replace("<instability>", lastReport.reactorInstability.ToString()); stringBuilder.Replace("<time_left>", lastReport.timeRemaining.ToString()); return stringBuilder.ToString(); } internal static string GetTextForNode() { if (Object.op_Implicit((Object)(object)MeltdownHandler.Instance)) { string text = "reactorscan.error.overheat"; if (ReactorHealthCheckReady()) { lastHealthCheck = Time.time; lastReport = GetNewReactorHealthReport(); text = "reactorscan.success"; } return SubstituteVariables(text.Translate()) + lastReport.GetTeminalOutput(); } return "reactorscan.result.stable".Translate(); } internal static bool ReactorHealthCheckReady() { return Time.time >= lastHealthCheck + MeltdownPlugin.config.ShipScanCooldown; } internal static ReactorHealthReport GetNewReactorHealthReport() { float num = ((float)MeltdownPlugin.config.MeltdownTime - MeltdownHandler.Instance.meltdownTimer) / (float)MeltdownPlugin.config.MeltdownTime * 100f; num = Mathf.Round(num / MeltdownPlugin.config.ShipScanAccuracy) * MeltdownPlugin.config.ShipScanAccuracy; float timeRemaining = (1f - num / 100f) * (float)MeltdownPlugin.config.MeltdownTime; return new ReactorHealthReport { reactorInstability = num, timeRemaining = timeRemaining }; } [HarmonyPostfix] [HarmonyPatch("Awake")] internal static void RegisterNodes(Terminal __instance) { __instance.terminalNodes.allKeywords = CollectionExtensions.AddRangeToArray<TerminalKeyword>(__instance.terminalNodes.allKeywords, terminalKeywordsToRegister.ToArray()); __instance.terminalNodes.terminalNodes.AddRange(terminalNodesToRegister); } [HarmonyPostfix] [HarmonyPatch("TextPostProcess")] internal static void ProcessReactorText(TerminalNode node, ref string __result) { if ((Object)(object)node == (Object)(object)MeltdownPlugin.assets.reactorHealthNode) { __result = "\n\n\n" + GetTextForNode(); } } [HarmonyPostfix] [HarmonyPatch(typeof(StormyWeather), "GetMetalObjectsAfterDelay")] internal static void CancelCoroutine(StormyWeather __instance, ref IEnumerator __result) { ((MonoBehaviour)__instance).StopCoroutine(__result); } } } namespace FacilityMeltdown.MeltdownSequence { public static class MeltdownEffects { private static readonly int On = Animator.StringToHash("on"); public static List<(Light light, Color originalColour)> SetupEmergencyLights() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) foreach (Light allPoweredLight in RoundManager.Instance.allPoweredLights) { allPoweredLight.color = MeltdownInteriorMapper.Instance.outsideEmergencyLightColour; } List<(Light, Color)> list = new List<(Light, Color)>(); list.AddRange(MeltdownMoonMapper.Instance.outsideEmergencyLights.Select((Light light) => (light, light.color))); return list; } public static IEnumerator RepeatUntilEndOfMeltdown(Func<IEnumerator> enumerator) { yield return (object)new WaitForSeconds(Random.Range(0f, 1f)); while (true) { MeltdownPlugin.logger.LogDebug((object)"looping effect"); yield return enumerator(); } } public static IEnumerator WithDelay(IEnumerator enumerator, float delay) { yield return (object)new WaitForSeconds(delay); yield return enumerator; } public static IEnumerator WithDelay(Action callback, float delay) { yield return (object)new WaitForSeconds(delay); callback(); } public static IEnumerator WithRandomDelay(Func<IEnumerator> enumerator, float min, float max) { yield return WithDelay(enumerator(), Random.Range(min, max)); } public static IEnumerator WithRandomDelay(Action callback, float min, float max) { yield return WithDelay(callback, Random.Range(min, max)); } public static IEnumerator AtProgress(IEnumerator enumerator, float progress) { while (MeltdownAPI.MeltdownStarted && MeltdownHandler.Instance.Progress > progress) { yield return null; } yield return enumerator; } public static IEnumerator AtProgress(Action callback, float progress) { while (MeltdownAPI.MeltdownStarted && MeltdownHandler.Instance.Progress > progress) { yield return null; } callback(); } public static IEnumerator EmergencyLights(float onTime, float offTime, List<(Light light, Color originalColour)> originalLightColours) { MeltdownPlugin.logger.LogDebug((object)"Switching lights ON"); foreach (Animator animator2 in RoundManager.Instance.allPoweredLightsAnimators) { animator2.SetBool(On, true); } foreach (Light light2 in MeltdownMoonMapper.Instance.outsideEmergencyLights) { light2.color = MeltdownMoonMapper.Instance.outsideEmergencyLightColour; } yield return (object)new WaitForSeconds(onTime); MeltdownPlugin.logger.LogDebug((object)"Switching lights OFF"); foreach (Animator animator in RoundManager.Instance.allPoweredLightsAnimators) { animator.SetBool(On, false); } foreach (var (light, originalColour) in originalLightColours) { light.color = originalColour; } yield return (object)new WaitForSeconds(offTime); } public static void InsideParticleEffects() { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0089: Unknown result type (might be due to invalid IL or missing references) if (MeltdownPlugin.clientConfig.ScreenShake) { RaycastHit val2 = default(RaycastHit); for (int i = 0; i < Random.Range(5, 15); i++) { Vector3 val = GetRandomPositionInsideFacility() + Vector3.up; if (Physics.Raycast(new Ray(val, Vector3.up), ref val2, 20f, 256)) { GameObject val3 = MeltdownPlugin.assets.facilityEffects[Random.Range(0, MeltdownPlugin.assets.facilityEffects.Length)]; Object.Instantiate<GameObject>(val3, ((Component)MeltdownHandler.Instance).transform, true); val3.transform.position = ((RaycastHit)(ref val2)).point; } } } if (GameNetworkManager.Instance.localPlayerController.isInsideFactory) { Object.Instantiate<GameObject>(StartOfRound.Instance.explosionPrefab, GetRandomPositionNearPlayer(), Quaternion.Euler(-90f, 0f, 0f), RoundManager.Instance.mapPropsContainer.transform); } if (MeltdownPlugin.clientConfig.ScreenShake) { HUDManager.Instance.ShakeCamera((ScreenShakeType)((MeltdownHandler.Instance.Progress > 0.5f) ? 1 : 3)); } } public static IEnumerator WarningAnnouncer(AudioSource source) { source.volume = (float)MeltdownPlugin.clientConfig.MusicVolume / 100f + 0.2f; AudioClip sound = MeltdownPlugin.assets.warnings[Random.Range(0, MeltdownPlugin.assets.warnings.Length)]; source.clip = sound; source.Play(); yield return (object)new WaitForSeconds(source.clip.length); } private static Vector3 PlacePositionInsideFacility(Vector3 position, float radius = 10f) { //IL_0005: 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_000f: 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) return RoundManager.Instance.GetRandomNavMeshPositionInRadius(position, radius, default(NavMeshHit)); } private static Vector3 GetRandomPositionNearPlayer(float radius = 15f) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: 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) //IL_001f: 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) return PlacePositionInsideFacility(((Component)GameNetworkManager.Instance.localPlayerController).transform.position + Random.insideUnitSphere * radius); } private static Vector3 GetRandomPositionInsideFacility() { //IL_0022: 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) return PlacePositionInsideFacility(RoundManager.Instance.insideAINodes[Random.Range(0, RoundManager.Instance.insideAINodes.Length)].transform.position); } } } namespace FacilityMeltdown.MeltdownSequence.Behaviours { internal class FacilityExplosionHandler : MonoBehaviour { private PlayerControllerB player; private float size; private float time; private LocalVolumetricFog internalFog; private void Awake() { player = GameNetworkManager.Instance.localPlayerController; internalFog = ((Component)this).GetComponent<LocalVolumetricFog>(); if ((Object)(object)internalFog == (Object)null) { MeltdownPlugin.logger.LogError((object)"Failed to get volumetric fog!"); } if (MeltdownPlugin.clientConfig.ScreenShake) { HUDManager.Instance.ShakeCamera((ScreenShakeType)0); HUDManager.Instance.ShakeCamera((ScreenShakeType)1); HUDManager.Instance.ShakeCamera((ScreenShakeType)2); HUDManager.Instance.ShakeCamera((ScreenShakeType)3); } if (!player.isPlayerDead && player.isInsideFactory) { if (player.isInElevator) { MeltdownPlugin.logger.LogWarning((object)"Player is inside ship and facility at the same time!! Did you teleport out? Aborting kill"); } else { KillPlayer(); } } } private void Update() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) time += Time.deltaTime * 10f; size = TimeToSize(time); ((Component)this).transform.localScale = Vector3.one * size; if ((Object)(object)internalFog != (Object)null) { internalFog.parameters.size = Vector3.one * size * 1.25f; } if (!ShouldIgnorePlayer() && PlayerIsInsideFireball()) { player.KillPlayer(Vector3.zero, false, (CauseOfDeath)3, 0, default(Vector3)); } } private void KillPlayer() { //IL_0006: 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_0016: Unknown result type (might be due to invalid IL or missing references) player.KillPlayer(Vector3.zero, false, (CauseOfDeath)3, 0, default(Vector3)); } private bool PlayerIsInsideFireball() { //IL_0006: 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) return Vector3.Distance(((Component)this).transform.position, ((Component)player).transform.position) < size; } private bool ShouldIgnorePlayer() { return player.isPlayerDead || (player.isInElevator && StartOfRound.Instance.shipIsLeaving); } private float TimeToSize(float t) { return Mathf.Log(t) + 3f + 2f * t; } } public class MeltdownHandler : NetworkBehaviour { [CompilerGenerated] private static class <>O { public static Action <0>__InsideParticleEffects; public static RpcReceiveHandler <1>____rpc_handler_StartMeltdownClientRpc; } private static readonly int PullLever = Animator.StringToHash("pullLever"); internal float meltdownTimer; private bool meltdownStarted; private GameObject explosion; private GameObject shockwave; [SerializeField] private AudioSource meltdownMusic; [SerializeField] private AudioSource warningSource; private const uint START_MELTDOWN_CLIENT_RPC_ID = 1765422140u; public float TimeLeftUntilMeltdown => meltdownTimer; public float Progress => 1f - TimeLeftUntilMeltdown / (float)MeltdownPlugin.config.MeltdownTime; private static PlayerControllerB Player => GameNetworkManager.Instance.localPlayerController; internal static MeltdownHandler Instance { get; private set; } private Vector3 effectOrigin => MeltdownMoonMapper.Instance.EffectOrigin; [ClientRpc] private void StartMeltdownClientRpc() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 //IL_02f3: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: 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_0073: Invalid comparison between Unknown and I4 //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) NetworkManager networkManager = ((NetworkBehaviour)this).NetworkManager; if (networkManager == null || !networkManager.IsListening) { return; } if ((int)base.__rpc_exec_stage != 1 && (networkManager.IsServer || networkManager.IsHost)) { ClientRpcParams val = default(ClientRpcParams); FastBufferWriter val2 = ((NetworkBehaviour)this).__beginSendClientRpc(1765422140u, val, (RpcDelivery)0); ((NetworkBehaviour)this).__endSendClientRpc(ref val2, 1765422140u, val, (RpcDelivery)0); } if ((int)base.__rpc_exec_stage != 1 || (!networkManager.IsClient && !networkManager.IsHost)) { return; } base.__rpc_exec_stage = (__RpcExecStage)0; if ((Object)(object)Instance != (Object)null) { return; } Instance = this; Stopwatch stopwatch = new Stopwatch(); MeltdownPlugin.logger.LogInfo((object)"Beginning Meltdown Sequence! I'd run if I were you!"); stopwatch.Start(); MeltdownMoonMapper.EnsureMeltdownMoonMapper(); MeltdownInteriorMapper.EnsureMeltdownInteriorMapper(); if ((Object)(object)MeltdownInteriorMapper.Instance == (Object)null) { MeltdownPlugin.logger.LogError((object)"WHAT. Just ensured that the interior mapper exists and it doesnt?!?"); } if ((Object)(object)MeltdownMoonMapper.Instance == (Object)null) { MeltdownPlugin.logger.LogError((object)"WHAT. Just ensured that the moon mapper exists and it doesnt?!?"); } stopwatch.Stop(); MeltdownPlugin.logger.LogDebug((object)$"Ensuring data objects exist: {stopwatch.ElapsedMilliseconds}ms"); meltdownTimer = MeltdownPlugin.config.MeltdownTime; stopwatch.Restart(); stopwatch.Stop(); MeltdownPlugin.logger.LogDebug((object)$"Creating audio: {stopwatch.ElapsedMilliseconds}ms"); stopwatch.Restart(); ((MonoBehaviour)this).StartCoroutine(MeltdownEffects.WithDelay(delegate { HUDManager.Instance.ReadDialogue(GetDialogue("meltdown.dialogue.start")); }, 5f)); ((MonoBehaviour)this).StartCoroutine(MeltdownEffects.WithDelay(MeltdownEffects.RepeatUntilEndOfMeltdown(() => MeltdownEffects.WithRandomDelay(() => MeltdownEffects.WarningAnnouncer(warningSource), 10f, 15f)), 10f)); ((MonoBehaviour)this).StartCoroutine(MeltdownEffects.RepeatUntilEndOfMeltdown(() => MeltdownEffects.WithRandomDelay((Action)MeltdownEffects.InsideParticleEffects, 10f, 15f))); if (MeltdownPlugin.config.EmergencyLights) { try { List<(Light, Color)> originalLightColours = MeltdownEffects.SetupEmergencyLights(); ((MonoBehaviour)this).StartCoroutine(MeltdownEffects.RepeatUntilEndOfMeltdown(() => MeltdownEffects.EmergencyLights(2f, 5f, originalLightColours))); } catch (Exception arg) { MeltdownPlugin.logger.LogError((object)$"Failed to set the emergency light colour: {arg}"); } } ((MonoBehaviour)this).StartCoroutine(MeltdownEffects.RepeatUntilEndOfMeltdown(() => MeltdownEffects.WithRandomDelay(delegate { //IL_003e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)shockwave != (Object)null) { Object.Destroy((Object)(object)shockwave); } shockwave = Object.Instantiate<GameObject>(MeltdownPlugin.assets.shockwavePrefab); shockwave.transform.position = effectOrigin; }, 25f, 35f))); ((MonoBehaviour)this).StartCoroutine(MeltdownEffects.AtProgress((Action)HUDManager.Instance.RadiationWarningHUD, 0.5f)); stopwatch.Stop(); MeltdownPlugin.logger.LogDebug((object)$"Starting effects: {stopwatch.ElapsedMilliseconds}ms"); if (((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsServer) { SpawnEnemies(); } stopwatch.Restart(); if (effectOrigin == Vector3.zero) { MeltdownPlugin.logger.LogError((object)"Effect Origin is Vector3.Zero! We couldn't find the effect origin"); HUDManager.Instance.DisplayGlobalNotification("Failed to find effect origin... Things will look broken."); } if (MeltdownPlugin.clientConfig.ScreenShake) { HUDManager.Instance.ShakeCamera((ScreenShakeType)3); HUDManager.Instance.ShakeCamera((ScreenShakeType)2); } stopwatch.Stop(); MeltdownPlugin.logger.LogDebug((object)$"Getting effect origin: {stopwatch.ElapsedMilliseconds}ms"); stopwatch.Restart(); MeltdownAPI.OnMeltdownStart(); stopwatch.Stop(); MeltdownPlugin.logger.LogDebug((object)$"MeltdownAPI.OnMeltdownStart(): {stopwatch.ElapsedMilliseconds}ms"); meltdownStarted = true; } private void SpawnEnemies() { Stopwatch stopwatch = Stopwatch.StartNew(); List<string> disallowed = MeltdownPlugin.config.GetDisallowedEnemies(); List<SpawnableEnemyWithRarity> list = RoundManager.Instance.currentLevel.Enemies.Where((SpawnableEnemyWithRarity enemy) => !EnemyCannotBeSpawned(enemy.enemyType) && !disallowed.Contains(enemy.enemyType.enemyName)).ToList(); stopwatch.Stop(); MeltdownPlugin.logger.LogDebug((object)$"Filtering enemies: {stopwatch.ElapsedMilliseconds}ms"); stopwatch.Restart(); List<EnemyVent> list2 = RoundManager.Instance.allEnemyVents.Where((EnemyVent vent) => !vent.occupied).ToList(); stopwatch.Stop(); MeltdownPlugin.logger.LogDebug((object)$"Filtering vents: {stopwatch.ElapsedMilliseconds}ms"); stopwatch.Restart(); for (int i = 0; i < Mathf.Min(MeltdownPlugin.config.MonsterSpawnAmount, list2.Count); i++) { EnemyVent val = list2[Random.Range(0, list2.Count)]; list2.Remove(val); SpawnableEnemyWithRarity val2 = list[Random.Range(0, list2.Count)]; RoundManager instance = RoundManager.Instance; instance.currentEnemyPower += val2.enemyType.PowerLevel; MeltdownPlugin.logger.LogInfo((object)("Spawning a " + val2.enemyType.enemyName + " during the meltdown sequence")); val.SpawnEnemy(val2); } stopwatch.Stop(); MeltdownPlugin.logger.LogDebug((object)$"Spawning enemies: {stopwatch.ElapsedMilliseconds}ms"); } public override void OnNetworkSpawn() { if (MeltdownPlugin.loadedFully && ((NetworkBehaviour)this).IsHost) { StartMeltdownClientRpc(); } } internal bool EnemyCannotBeSpawned(EnemyType type) { return type.spawningDisabled || type.numberSpawned >= type.MaxCount; } internal static DialogueSegment[] GetDialogue(string translation) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown JArray translationSet = LangParser.GetTranslationSet(translation); DialogueSegment[] array = (DialogueSegment[])(object)new DialogueSegment[((JContainer)translationSet).Count]; for (int i = 0; i < ((JContainer)translationSet).Count; i++) { array[i] = new DialogueSegment { bodyText = ((string)translationSet[i])?.Replace("<meltdown_time>", Math.Round((float)MeltdownPlugin.config.MeltdownTime / 60f).ToString()), speakerText = "meltdown.dialogue.speaker".Translate() }; } return array; } private void OnDisable() { if (!((Object)(object)Instance != (Object)(object)this)) { MeltdownPlugin.logger.LogInfo((object)"Cleaning up MeltdownHandler."); Instance = null; if ((Object)(object)explosion != (Object)null) { Object.Destroy((Object)(object)explosion); } if ((Object)(object)shockwave != (Object)null) { Object.Destroy((Object)(object)shockwave); } if (!meltdownStarted) { MeltdownPlugin.logger.LogError((object)"MeltdownHandler was disabled without starting a meltdown, a client most likely failed the MeltdownReadyCheck. If you are going to report this make sure to provide ALL client logs."); } } } private void Update() { //IL_0116: Unknown result type (might be due to invalid IL or missing references) if (!meltdownStarted || HasExplosionOccured()) { return; } StartOfRound instance = StartOfRound.Instance; meltdownMusic.volume = (float)MeltdownPlugin.clientConfig.MusicVolume / 100f; if (!Player.isInsideFactory && !MeltdownPlugin.clientConfig.MusicPlaysOutside) { meltdownMusic.volume = 0f; } meltdownTimer -= Time.deltaTime; if (meltdownTimer <= 3f && !instance.shipIsLeaving) { ((MonoBehaviour)this).StartCoroutine(ShipTakeOff()); } if (meltdownTimer <= 0f) { meltdownMusic.Stop(); GameObject val = MeltdownMoonMapper.Instance.explosionPrefab; if ((Object)(object)val == (Object)null) { val = MeltdownPlugin.assets.facilityExplosionPrefab; } explosion = Object.Instantiate<GameObject>(val); explosion.transform.position = effectOrigin; FacilityExplosionHandler facilityExplosionHandler = default(FacilityExplosionHandler); if (!explosion.TryGetComponent<FacilityExplosionHandler>(ref facilityExplosionHandler)) { explosion.AddComponent<FacilityExplosionHandler>(); } } } private IEnumerator ShipTakeOff() { StartOfRound shipManager = StartOfRound.Instance; shipManager.shipLeftAutomatically = true; shipManager.shipIsLeaving = true; HUDManager.Instance.ReadDialogue(GetDialogue("meltdown.dialogue.shiptakeoff")); yield return (object)new WaitForSeconds(3f); yield return (object)new WaitForSeconds(3f); ((Behaviour)HUDManager.Instance.shipLeavingEarlyIcon).enabled = false; StartMatchLever startMatchLever = Object.FindObjectOfType<StartMatchLever>(); startMatchLever.triggerScript.animationString = "SA_PushLeverBack"; startMatchLever.leverHasBeenPulled = false; startMatchLever.triggerScript.interactable = false; startMatchLever.leverAnimatorObject.SetBool(PullLever, false); shipManager.ShipLeave(); yield return (object)new WaitForSeconds(1.5f); shipManager.SetSpectateCameraToGameOverMode(true, (PlayerControllerB)null); if (GameNetworkManager.Instance.localPlayerController.isPlayerDead) { GameNetworkManager.Instance.localPlayerController.SetSpectatedPlayerEffects(true); } } public bool HasExplosionOccured() { return (Object)(object)explosion != (Object)null; } private static void __rpc_handler_StartMeltdownClientRpc(NetworkBehaviour target, FastBufferReader reader, __RpcParams rpcParams) { //IL_0025: 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) NetworkManager networkManager = target.NetworkManager; if (!((Object)(object)networkManager == (Object)null) && networkManager.IsListening) { target.__rpc_exec_stage = (__RpcExecStage)1; ((MeltdownHandler)(object)target).StartMeltdownClientRpc(); target.__rpc_exec_stage = (__RpcExecStage)0; } } public override void __initializeRpcs() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown object obj = <>O.<1>____rpc_handler_StartMeltdownClientRpc; if (obj == null) { RpcReceiveHandler val = __rpc_handler_StartMeltdownClientRpc; <>O.<1>____rpc_handler_StartMeltdownClientRpc = val; obj = (object)val; } ((NetworkBehaviour)this).__registerRpc(1765422140u, (RpcReceiveHandler)obj, "StartMeltdownClientRpc"); ((NetworkBehaviour)this).__initializeRpcs(); } public override string __getTypeName() { return "MeltdownHandler"; } } public class Shockwave : MonoBehaviour { private bool localPlayerCameraShake; private float size; private AudioSource sound; private Renderer renderer; private void Awake() { sound = ((Component)this).gameObject.AddComponent<AudioSource>(); sound.clip = MeltdownPlugin.assets.shockwave; sound.spatialBlend = 0f; sound.loop = false; renderer = ((Component)this).GetComponent<Renderer>(); } private void Update() { //IL_002a: 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) PlayerControllerB localPlayerController = GameNetworkManager.Instance.localPlayerController; size += Time.deltaTime * 50f; ((Component)this).transform.localScale = Vector3.one * size; if (localPlayerController.isInsideFactory) { renderer.enabled = false; return; } renderer.enabled = true; if (PlayerIsInsideShockwave() && !localPlayerCameraShake && MeltdownPlugin.clientConfig.ScreenShake) { ScreenShake(); localPlayerCameraShake = true; sound.Play(); } } private void ScreenShake() { HUDManager.Instance.ShakeCamera((ScreenShakeType)1); } internal bool PlayerIsInsideShockwave() { //IL_0006: 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) return Vector3.Distance(((Component)this).transform.position, ((Component)GameNetworkManager.Instance.localPlayerController).transform.position) <= size; } } } namespace FacilityMeltdown.Lang { internal static class LangParser { internal static Dictionary<string, string> languages { get; private set; } internal static Dictionary<string, object> loadedLanguage { get; private set; } internal static Dictionary<string, object> defaultLanguage { get; private set; } internal static void Init() { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("FacilityMeltdown.Lang.defs.json"); using StreamReader streamReader = new StreamReader(stream); string text = streamReader.ReadToEnd(); languages = JsonConvert.DeserializeObject<Dictionary<string, string>>(text); } internal static Dictionary<string, object> LoadLanguage(string id) { using Stream stream = File.Open(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "lang", id + ".json"), FileMode.Open); using StreamReader streamReader = new StreamReader(stream); string text = streamReader.ReadToEnd(); return JsonConvert.DeserializeObject<Dictionary<string, object>>(text); } internal static void SetLanguage(string id) { MeltdownPlugin.logger.LogInfo((object)("Loading language: " + languages[id] + " (" + id + ")")); loadedLanguage = LoadLanguage(id); MeltdownPlugin.logger.LogInfo((object)("Loaded " + languages[id])); } internal static string GetTranslation(string translation) { if (loadedLanguage.TryGetValue(translation, out var value)) { return (string)value; } if (defaultLanguage.TryGetValue(translation, out value)) { MeltdownPlugin.logger.LogError((object)("Falling back to english. for translation: " + translation)); return (string)value; } if (translation == "lang.missing") { MeltdownPlugin.logger.LogError((object)"LANG.MISSING IS MISSING!!!!! THIS IS BAD!! VERY BAD!!"); return "lang.missing; <translation_id>"; } return GetTranslation("lang.missing").Replace("<translation_id>", translation); } internal static JArray GetTranslationSet(string translation) { //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_0085: Expected O, but got Unknown if (loadedLanguage.TryGetValue(translation, out var value)) { MeltdownPlugin.logger.LogInfo((object)value.GetType()); return (JArray)((value is JArray) ? value : null); } if (defaultLanguage.TryGetValue(translation, out value)) { MeltdownPlugin.logger.LogError((object)("Falling back to english. for translation (dialogue): " + translation)); return (JArray)((value is JArray) ? value : null); } JArray val = new JArray(); val.Add(JToken.op_Implicit(GetTranslation("lang.missing").Replace("<translation_id>", translation))); return val; } } } namespace FacilityMeltdown.Config { [RequiresRestart(false)] internal class MeltdownClientConfig : LoafConfig<MeltdownClientConfig> { [ConfigGroup("Audio")] [ConfigDesc("What volume the music plays at. Also controls the volume of the random voicelines that play")] [ConfigRange(0f, 100f)] public int MusicVolume { get; private set; } = 100; [ConfigDesc("Does the music play outside the facility?")] public bool MusicPlaysOutside { get; private set; } = true; [ConfigGroup("Visuals")] [ConfigDesc("Whether or not to shake the screen during the meltdown sequence. Doesn't control other places of screen shake in the game.")] public bool ScreenShake { get; private set; } = true; [ConfigDesc("Should meltdown sequence contain particle effects? Doesn't include particle effects on the fireball.")] public bool ParticleEffects { get; private set; } = true; [ConfigIgnore] [RequiresRestart(true)] public string Language { get; private set; } = "en"; internal MeltdownClientConfig(ConfigFile file) : base(file) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown BindProperty<string>(typeof(MeltdownClientConfig).GetProperty("Language"), "Language", new ConfigDescription("What language should FacilityMeltdown use? NOTE: This only affects facility meltdown and won't change the rest of the games langauge\nSome Languages may also need FontPatcher(https://thunderstore.io/c/lethal-company/p/LeKAKiD/FontPatcher/)\nLanguages Available: " + string.Join(", ", LangParser.languages.Keys), (AcceptableValueBase)null, Array.Empty<object>())); } } internal class MeltdownConfig : LoafSyncedConfig<MeltdownConfig> { [ConfigGroup("GameBalance")] [ConfigDesc("Whether or not FacilityMeltdown should override appartus value. Only disable for compatibility reasons.")] public bool OverrideApparatusValue { get; private set; } = true; [ConfigDesc("When overriding the apparatus value what should it's base value be?")] [ConfigRange(80f, 500f)] public int ApparatusValue { get; private set; } = 240; [ConfigDesc("How many monsters should spawn during the meltdown sequence? Set to 0 to disable.")] [ConfigRange(0f, 10f)] public int MonsterSpawnAmount { get; private set; } = 5; [ConfigDesc("Should the lights turn on periodically? Disabling this option makes them permanently off. (Matches Vanilla Behaviour)")] public bool EmergencyLights { get; private set; } = true; [ConfigDesc("What enemies to exclude from spawning in the meltdown sequence. Comma seperated list. Supports modded entities.")] public string DisallowedEnemies { get; private set; } = "Centipede,Hoarding bug"; [ConfigDesc("How long until the ship's scanner can scan the reactor. (Doesn't affect the vanilla `scan` command)")] [ConfigRange(0f, 20f)] public float ShipScanCooldown { get; private set; } = 15f; [ConfigDesc("How accurate is the ship's scanner when scanning the reactor. Higher values mean it is more uncertain, and lower values is more accurate. (Doesn't affect the vanilla `scan` command)")] [ConfigRange(0f, 100f)] public float ShipScanAccuracy { get; private set; } = 15f; [ConfigGroup("Integrations")] [ConfigDesc("Should the apparatus value be multiplied by the current weather. Requires WeatherRegistry to work.")] public bool WeatherRegistryIntegration { get; private set; } = true; [ConfigGroup("UNSUPPORTED")] [ConfigDesc("ABSOLUETLY NOT SUPPORTED OR RECOMMENDED! Change the length of the meltdown sequence. If this breaks I am not fixing it, you have been warned.")] [ConfigRange(60f, 300f)] public int MeltdownTime { get; private set; } = 120; public MeltdownConfig(ConfigFile file) : base(file) { } public List<string> GetDisallowedEnemies() { return DisallowedEnemies.Split(',').ToList(); } } } namespace FacilityMeltdown.Behaviours { public class MeltdownEvents : MonoBehaviour { [Serializable] public class Marker { internal bool Triggered; [field: SerializeField] public float Progress { get; private set; } = 0.5f; [field: SerializeField] public UnityEvent OnMarker { get; private set; } } [SerializeField] private UnityEvent OnMeltdownStart; [SerializeField] private List<Marker> markers = new List<Marker>(); private void OnEnable() { MeltdownAPI.OnMeltdownStart = (Action)Delegate.Combine(MeltdownAPI.OnMeltdownStart, new Action(OnMeltdownStart.Invoke)); } private void OnDisable() { MeltdownAPI.OnMeltdownStart = (Action)Delegate.Remove(MeltdownAPI.OnMeltdownStart, new Action(OnMeltdownStart.Invoke)); } private void Update() { if (!MeltdownAPI.MeltdownStarted) { return; } foreach (Marker marker in markers) { if (!marker.Triggered && !(marker.Progress > MeltdownHandler.Instance.Progress)) { marker.OnMarker.Invoke(); marker.Triggered = true; } } } } public class MeltdownInteriorMapper : MonoBehaviour { public static MeltdownInteriorMapper Instance { get; private set; } [Tooltip("Colour to flash lights with, should probably just leave this at red. Only applies to inside lights.")] [field: SerializeField] public Color outsideEmergencyLightColour { get; private set; } = Color.red; private void Awake() { Instance = this; } private void OnDisable() { if ((Object)(object)Instance != (Object)null) { Instance = null; } } internal static void EnsureMeltdownInteriorMapper() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Instance != (Object)null) && !((Object)(object)Object.FindObjectOfType<MeltdownInteriorMapper>() != (Object)null)) { MeltdownPlugin.logger.LogInfo((object)"Creating InteriorMapper!"); Instance = new GameObject("DefaultMeltdownInteriorMappings").AddComponent<MeltdownInteriorMapper>(); } } } public class MeltdownMoonMapper : MonoBehaviour { [SerializeField] [Tooltip("Lights to flash red during the meltdown sequence. Doesn't include inside lights.")] public List<Light> outsideEmergencyLights = new List<Light>(); public static MeltdownMoonMapper Instance { get; private set; } [Tooltip("Colour to flash lights with, should probably just leave this at red. Only applies to outside lights.")] [field: SerializeField] public Color outsideEmergencyLightColour { get; private set; } = Color.red; [field: SerializeField] public GameObject shockwavePrefab { get; private set; } [field: SerializeField] public GameObject explosionPrefab { get; private set; } [field: SerializeField] public Vector3 EffectOrigin { get; private set; } private void Awake() { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) Instance = this; if (EffectOrigin == Vector3.zero) { EffectOrigin = RoundManager.FindMainEntrancePosition(false, true); } } private void OnDisable() { if ((Object)(object)Instance != (Object)null) { Instance = null; } } internal static void EnsureMeltdownMoonMapper() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Instance != (Object)null) && !((Object)(object)Object.FindObjectOfType<MeltdownMoonMapper>() != (Object)null)) { MeltdownPlugin.logger.LogInfo((object)"Creating MoonMapper!"); Instance = new GameObject("DefaultMeltdownMappings").AddComponent<MeltdownMoonMapper>(); Instance.outsideEmergencyLights = (from light in GameObject.Find("Environment").GetComponentsInChildren<Light>() where CheckParentForDisallowed(((Component)light).transform) select light).ToList(); } } private static bool CheckParentForDisallowed(Transform child) { bool flag; switch (((Object)((Component)child).gameObject).name) { case "Sun": case "ItemShipAnimContainer": case "MapPropsContainer": flag = true; break; default: flag = false; break; } return !flag && ((Object)(object)child.parent == (Object)null || CheckParentForDisallowed(child.parent)); } } } namespace FacilityMeltdown.API { public static class MeltdownAPI { internal static Action OnMeltdownStart = delegate { }; public static bool MeltdownStarted => (Object)(object)MeltdownHandler.Instance != (Object)null; public static void StartMeltdown(string modGUID) { if (!MeltdownStarted) { MeltdownPlugin.logger.LogInfo((object)("A mod (" + modGUID + ") has begun a meltdown!")); if (!((NetworkBehaviour)GameNetworkManager.Instance.localPlayerController).IsHost) { MeltdownPlugin.logger.LogWarning((object)"Local Player isn't host! Aborting!!"); return; } GameObject val = Object.Instantiate<GameObject>(MeltdownPlugin.assets.meltdownHandlerPrefab); val.GetComponent<NetworkObject>().Spawn(false); } } public static void RegisterMeltdownListener(Action callback) { OnMeltdownStart = (Action)Delegate.Combine(OnMeltdownStart, callback); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }