Decompiled source of Fairer Fire Exits v80 v1.2.2

OreoM.FairerFireExits.dll

Decompiled 3 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using DunGen;
using DunGen.Graph;
using FairerFireExits.Networking;
using HarmonyLib;
using LethalConfig;
using LethalConfig.ConfigItems;
using Microsoft.CodeAnalysis;
using OreoM.FairerFireExits.NetcodePatcher;
using Unity.Netcode;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("OreoM.FairerFireExits")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.2.0.0")]
[assembly: AssemblyInformationalVersion("1.2.0+7486ca21a11b9c310c8c11a6b190def0c9a2c0d2")]
[assembly: AssemblyProduct("FairerFireExits")]
[assembly: AssemblyTitle("OreoM.FairerFireExits")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
[module: NetcodePatchedAssembly]
internal class <Module>
{
	static <Module>()
	{
		NetworkVariableSerializationTypes.InitializeSerializer_UnmanagedByMemcpy<bool>();
		NetworkVariableSerializationTypes.InitializeEqualityChecker_UnmanagedIEquatable<bool>();
	}
}
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FairerFireExits
{
	[BepInPlugin("OreoM.FairerFireExits", "FairerFireExits", "1.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class FairerFireExits : BaseUnityPlugin
	{
		public const string LethalConfigGUID = "ainavt.lc.lethalconfig";

		public static FairerFireExits Instance { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		internal static FairerFireExitsConfig FireConfig { get; set; }

		internal static Harmony? Harmony { get; set; }

		private void Awake()
		{
			Logger = ((BaseUnityPlugin)this).Logger;
			Instance = this;
			Patch();
			NetcodePatch();
			Logger.LogInfo((object)"OreoM.FairerFireExits v1.2.0 has loaded!");
		}

		private static void NetcodePatch()
		{
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			Type[] array = types;
			foreach (Type type in array)
			{
				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);
					}
				}
			}
		}

		internal static void Patch()
		{
			//IL_000d: 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_0018: Expected O, but got Unknown
			if (Harmony == null)
			{
				Harmony = new Harmony("OreoM.FairerFireExits");
			}
			Logger.LogDebug((object)"Patching...");
			Harmony.PatchAll();
			Logger.LogDebug((object)"Finished patching!");
		}

		internal static void Unpatch()
		{
			Logger.LogDebug((object)"Unpatching...");
			Harmony? harmony = Harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			Logger.LogDebug((object)"Finished unpatching!");
		}
	}
	public class FairerFireExitsConfig
	{
		internal Dictionary<DungeonFlow, ConfigEntry<bool>> ApplyFireExitChangePerInterior;

		private bool? lethalConfigLoaded;

		public FairerFireExitsConfig(ConfigFile cfg, DungeonFlow[] AllInteriors)
		{
			if (!lethalConfigLoaded.HasValue)
			{
				lethalConfigLoaded = Chainloader.PluginInfos.ContainsKey("ainavt.lc.lethalconfig");
			}
			ApplyFireExitChangePerInterior = new Dictionary<DungeonFlow, ConfigEntry<bool>>();
			cfg.SaveOnConfigSet = false;
			foreach (DungeonFlow val in AllInteriors)
			{
				ConfigEntry<bool> val2 = cfg.Bind<bool>("General", Regex.Replace(((Object)val).name, "Flow$", "", RegexOptions.None), true, "Apply Fairer Fire Exits patch to this interior");
				if (ApplyFireExitChangePerInterior.TryGetValue(val, out ConfigEntry<bool> _))
				{
					FairerFireExits.Logger.LogError((object)(((Object)val).name + " has duplicate entries, this shouldn't happen... skipping this entry"));
					continue;
				}
				if (lethalConfigLoaded.Value)
				{
					AddLethalConfigItem(val2);
				}
				ApplyFireExitChangePerInterior[val] = val2;
			}
			ClearOrphanedEntries(cfg);
			cfg.Save();
			cfg.SaveOnConfigSet = true;
			if (lethalConfigLoaded.Value)
			{
				ConfigLethalConfigModEntry();
			}
		}

		private void ClearOrphanedEntries(ConfigFile cfg)
		{
			PropertyInfo propertyInfo = AccessTools.Property(typeof(ConfigFile), "OrphanedEntries");
			Dictionary<ConfigDefinition, string> dictionary = (Dictionary<ConfigDefinition, string>)propertyInfo.GetValue(cfg);
			dictionary.Clear();
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		private void AddLethalConfigItem(ConfigEntry<bool> entry)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Expected O, but got Unknown
			BoolCheckBoxConfigItem val = new BoolCheckBoxConfigItem(entry, false);
			LethalConfigManager.AddConfigItem((BaseConfigItem)(object)val);
		}

		[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
		private void ConfigLethalConfigModEntry()
		{
			LethalConfigManager.SetModDescription("Choose what modded interiors are affected by this mod!");
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "OreoM.FairerFireExits";

		public const string PLUGIN_NAME = "FairerFireExits";

		public const string PLUGIN_VERSION = "1.2.0";
	}
}
namespace FairerFireExits.Patches
{
	[HarmonyPatch(typeof(DungeonGenerator))]
	internal class DungeonGeneratorPatches
	{
		[HarmonyPatch("Generate")]
		[HarmonyPrefix]
		private static void PreGenerate(DungeonGenerator __instance)
		{
			if (((NetworkBehaviour)FFENetworkManager.Instance).IsServer || ((NetworkBehaviour)FFENetworkManager.Instance).IsHost)
			{
				if (FairerFireExits.FireConfig.ApplyFireExitChangePerInterior.TryGetValue(__instance.DungeonFlow, out ConfigEntry<bool> value) && !value.Value)
				{
					FairerFireExits.Logger.LogInfo((object)("Found current DungeonFlow (" + ((Object)__instance.DungeonFlow).name + ") config but patch is set to false"));
					FFENetworkManager.Instance.shouldUseFireExitPatch.Value = false;
				}
				else
				{
					FFENetworkManager.Instance.shouldUseFireExitPatch.Value = true;
				}
			}
		}

		[HarmonyPatch(typeof(DungeonGenerator), "ProcessGlobalProps")]
		[HarmonyPrefix]
		private static void PreProcessGlobalProps(DungeonGenerator __instance)
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			if (!FFENetworkManager.Instance.shouldUseFireExitPatch.Value)
			{
				return;
			}
			foreach (Tile allTile in __instance.CurrentDungeon.AllTiles)
			{
				GlobalProp[] componentsInChildren = ((Component)allTile).GetComponentsInChildren<GlobalProp>();
				GlobalProp[] array = componentsInChildren;
				foreach (GlobalProp val in array)
				{
					if (val.PropGroupID == 1231)
					{
						val.DepthWeightScale = new AnimationCurve(DungeonGeneratorHelper.fireExitKeyframes);
					}
				}
				SpawnSyncedObject componentInChildren = ((Component)allTile).GetComponentInChildren<SpawnSyncedObject>();
				if (!((Object)(object)componentInChildren == (Object)null) && ((Object)componentInChildren.spawnPrefab).name == "EntranceTeleportA")
				{
					DungeonGeneratorHelper.mainDoorDepth = allTile.Placement.NormalizedPathDepth;
					FairerFireExits.Logger.LogInfo((object)$"Found Main exit at {DungeonGeneratorHelper.mainDoorDepth} of the main path");
				}
			}
		}

		[HarmonyPatch(typeof(DungeonGenerator), "ProcessGlobalProps")]
		[HarmonyTranspiler]
		private static IEnumerable<CodeInstruction> TranspileProcessGlobalProps(IEnumerable<CodeInstruction> codes)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Expected O, but got Unknown
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Expected O, but got Unknown
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Expected O, but got Unknown
			CodeMatcher val = new CodeMatcher(codes, (ILGenerator)null);
			val.MatchForward(true, (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.PropertyGetter(typeof(TilePlacementData), "NormalizedDepth"), (string)null)
			});
			if (val.IsInvalid)
			{
				FairerFireExits.Logger.LogError((object)"Could not the ending pattern. Aborting TranspileProcessGlobalProps transpiler.");
				return codes;
			}
			int pos = val.Pos;
			val.MatchBack(false, (CodeMatch[])(object)new CodeMatch[1]
			{
				new CodeMatch((OpCode?)OpCodes.Ldloc_3, (object)null, (string)null)
			});
			if (val.IsInvalid)
			{
				FairerFireExits.Logger.LogError((object)"Could not the starting pattern. Aborting TranspileProcessGlobalProps transpiler.");
				return codes;
			}
			val.Advance(1);
			int pos2 = val.Pos;
			val.RemoveInstructionsInRange(pos2, pos);
			val.InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[3]
			{
				new CodeInstruction(OpCodes.Ldloc_S, (object)6),
				new CodeInstruction(OpCodes.Ldarg_0, (object)null),
				new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(DungeonGeneratorHelper), "GetNormalizedPathDepthForFireExit", (Type[])null, (Type[])null))
			});
			return val.InstructionEnumeration();
		}
	}
	internal static class DungeonGeneratorHelper
	{
		public const int fireExitGroupID = 1231;

		public static float mainDoorDepth = 0f;

		public static readonly Keyframe[] fireExitKeyframes = (Keyframe[])(object)new Keyframe[5]
		{
			new Keyframe(0f, 0f, 0f, 0f),
			new Keyframe(0.2f, 0f, 7.952512E-06f, 0.04168295f),
			new Keyframe(0.5f, 0.3f, 7.952512E-06f, 0.04168295f),
			new Keyframe(0.8f, 1f, 0.02613646f, 0.02613646f),
			new Keyframe(1f, 1f, 0.02613646f, 0.02613646f)
		};

		public static float GetAdjustedDistanceFromMain(float NormalizedPathDepth)
		{
			mainDoorDepth = 0f;
			float num = Mathf.Max(mainDoorDepth, 1f - mainDoorDepth);
			return Mathf.Abs(NormalizedPathDepth - mainDoorDepth) / num;
		}

		public static float GetNormalizedPathDepthForFireExit(Tile currTile, GlobalProp currProp, DungeonGenerator instance)
		{
			if (!FFENetworkManager.Instance.shouldUseFireExitPatch.Value)
			{
				return currTile.Placement.NormalizedDepth;
			}
			return (currProp.PropGroupID == 1231) ? GetAdjustedDistanceFromMain(currTile.Placement.NormalizedPathDepth) : currTile.Placement.NormalizedDepth;
		}
	}
	[HarmonyPatch(typeof(GameNetworkManager))]
	internal class GameNetworkManagerPatches
	{
		[HarmonyPatch(typeof(GameNetworkManager), "Start")]
		[HarmonyPostfix]
		private static void PostStart(GameNetworkManager __instance)
		{
			FFENetworkManager.CreateAndRegisterPrefab();
			DungeonFlow[] allInteriors = Resources.FindObjectsOfTypeAll<DungeonFlow>();
			FairerFireExits.FireConfig = new FairerFireExitsConfig(((BaseUnityPlugin)FairerFireExits.Instance).Config, allInteriors);
		}

		[HarmonyPatch("Disconnect")]
		[HarmonyPrefix]
		private static void PreDisconnect(GameNetworkManager __instance)
		{
			FFENetworkManager.DespawnNetworkHandler();
		}
	}
	[HarmonyPatch(typeof(StartOfRound))]
	internal class StartOfRoundPatches
	{
		[HarmonyPatch(typeof(StartOfRound), "Awake")]
		[HarmonyPrefix]
		private static void PreAwake(StartOfRound __instance)
		{
			FFENetworkManager.SpawnNetworkHandler();
		}
	}
}
namespace FairerFireExits.Networking
{
	internal class FFENetworkManager : NetworkBehaviour
	{
		private static GameObject prefab;

		private const bool default_shouldUseFireExitPatch = true;

		public NetworkVariable<bool> shouldUseFireExitPatch = new NetworkVariable<bool>(true, (NetworkVariableReadPermission)0, (NetworkVariableWritePermission)0);

		public static FFENetworkManager Instance { get; private set; }

		public static void CreateAndRegisterPrefab()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_002a: 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)
			if (!((Object)(object)prefab != (Object)null))
			{
				prefab = new GameObject("OreoM.FairerFireExits Prefab");
				GameObject obj = prefab;
				((Object)obj).hideFlags = (HideFlags)(((Object)obj).hideFlags | 0x3D);
				NetworkObject obj2 = prefab.AddComponent<NetworkObject>();
				FieldInfo field = typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.NonPublic);
				field.SetValue(obj2, GetHash("OreoM.FairerFireExits"));
				prefab.AddComponent<FFENetworkManager>();
				NetworkManager.Singleton.AddNetworkPrefab(prefab);
				FairerFireExits.Logger.LogInfo((object)"Network prefab created and registered");
			}
		}

		private static uint GetHash(string value)
		{
			return value?.Aggregate(17u, (uint current, char c) => (current * 31) ^ c) ?? 0;
		}

		public static void SpawnNetworkHandler()
		{
			if (NetworkManager.Singleton.IsServer || NetworkManager.Singleton.IsHost)
			{
				Object.Instantiate<GameObject>(prefab).GetComponent<NetworkObject>().Spawn(false);
				FairerFireExits.Logger.LogInfo((object)"Network handler spawned");
			}
		}

		public static void DespawnNetworkHandler()
		{
			if ((Object)(object)Instance != (Object)null && ((Component)Instance).gameObject.GetComponent<NetworkObject>().IsSpawned && (NetworkManager.Singleton.IsServer || NetworkManager.Singleton.IsHost))
			{
				((Component)Instance).gameObject.GetComponent<NetworkObject>().Despawn(true);
				FairerFireExits.Logger.LogInfo((object)"Network handler despawned");
			}
		}

		private void Awake()
		{
			Instance = this;
		}

		protected override void __initializeVariables()
		{
			if (shouldUseFireExitPatch == null)
			{
				throw new Exception("FFENetworkManager.shouldUseFireExitPatch cannot be null. All NetworkVariableBase instances must be initialized.");
			}
			((NetworkVariableBase)shouldUseFireExitPatch).Initialize((NetworkBehaviour)(object)this);
			((NetworkBehaviour)this).__nameNetworkVariable((NetworkVariableBase)(object)shouldUseFireExitPatch, "shouldUseFireExitPatch");
			base.NetworkVariableFields.Add((NetworkVariableBase)(object)shouldUseFireExitPatch);
			((NetworkBehaviour)this).__initializeVariables();
		}

		protected internal override string __getTypeName()
		{
			return "FFENetworkManager";
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace OreoM.FairerFireExits.NetcodePatcher
{
	[AttributeUsage(AttributeTargets.Module)]
	internal class NetcodePatchedAssemblyAttribute : Attribute
	{
	}
}