Decompiled source of MoreDungeonResets v1.0.0

MoreDungeonResets.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
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(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("MoreDungeonResets")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("Valheim mod to automatically and safely reset dungeons on a schedule.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+b5c927effd9df04016f44334c844368a17f792f0")]
[assembly: AssemblyProduct("MoreDungeonResets")]
[assembly: AssemblyTitle("MoreDungeonResets")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 MoreDungeonResets
{
	[HarmonyPatch(typeof(Terminal), "Awake")]
	public static class AdminCommands
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static ConsoleEvent <>9__1_0;

			internal void <Postfix>b__1_0(ConsoleEventArgs args)
			{
				//IL_0088: 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_00a9: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
				//IL_00df: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
				if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer())
				{
					args.Context.AddString("You must be an admin/server host to run this command.");
					return;
				}
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null)
				{
					args.Context.AddString("You must be spawned in the world to use this command.");
					return;
				}
				DungeonGenerator val = null;
				float num = 50f;
				DungeonGenerator[] array = Object.FindObjectsOfType<DungeonGenerator>();
				Vector3 val3 = default(Vector3);
				foreach (DungeonGenerator val2 in array)
				{
					float num2 = Vector3.Distance(((Component)localPlayer).transform.position, ((Component)val2).transform.position);
					((Vector3)(ref val3))..ctor(((Component)val2).transform.position.x, ((Component)localPlayer).transform.position.y, ((Component)val2).transform.position.z);
					float num3 = Vector3.Distance(((Component)localPlayer).transform.position, val3);
					float num4 = Mathf.Min(num2, num3);
					if (num4 < num)
					{
						num = num4;
						val = val2;
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					string text = ((Object)val).name.Replace("(Clone)", "").Trim();
					args.Context.AddString("[MoreDungeonResets] Forcing manual reset of " + text + "...");
					Plugin.Log.LogInfo((object)("Admin manually triggered reset for " + text + "."));
					DungeonResetter.ResetDungeonSafe(val);
					args.Context.AddString("[MoreDungeonResets] Reset complete!");
				}
				else
				{
					args.Context.AddString("No dungeon found within 50 meters.");
				}
			}
		}

		private static bool _initialized;

		private static void Postfix()
		{
			//IL_0045: 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_003b: Expected O, but got Unknown
			if (_initialized)
			{
				return;
			}
			_initialized = true;
			object obj = <>c.<>9__1_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					//IL_0088: 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_00a9: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
					//IL_00df: Unknown result type (might be due to invalid IL or missing references)
					//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
					if (!Object.op_Implicit((Object)(object)ZNet.instance) || !ZNet.instance.IsServer())
					{
						args.Context.AddString("You must be an admin/server host to run this command.");
					}
					else
					{
						Player localPlayer = Player.m_localPlayer;
						if ((Object)(object)localPlayer == (Object)null)
						{
							args.Context.AddString("You must be spawned in the world to use this command.");
						}
						else
						{
							DungeonGenerator val2 = null;
							float num = 50f;
							DungeonGenerator[] array = Object.FindObjectsOfType<DungeonGenerator>();
							Vector3 val4 = default(Vector3);
							foreach (DungeonGenerator val3 in array)
							{
								float num2 = Vector3.Distance(((Component)localPlayer).transform.position, ((Component)val3).transform.position);
								((Vector3)(ref val4))..ctor(((Component)val3).transform.position.x, ((Component)localPlayer).transform.position.y, ((Component)val3).transform.position.z);
								float num3 = Vector3.Distance(((Component)localPlayer).transform.position, val4);
								float num4 = Mathf.Min(num2, num3);
								if (num4 < num)
								{
									num = num4;
									val2 = val3;
								}
							}
							if ((Object)(object)val2 != (Object)null)
							{
								string text = ((Object)val2).name.Replace("(Clone)", "").Trim();
								args.Context.AddString("[MoreDungeonResets] Forcing manual reset of " + text + "...");
								Plugin.Log.LogInfo((object)("Admin manually triggered reset for " + text + "."));
								DungeonResetter.ResetDungeonSafe(val2);
								args.Context.AddString("[MoreDungeonResets] Reset complete!");
							}
							else
							{
								args.Context.AddString("No dungeon found within 50 meters.");
							}
						}
					}
				};
				<>c.<>9__1_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("mdr_reset", "Forces a reset of the closest dungeon within 50 meters.", (ConsoleEvent)obj, true, false, true, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}
	}
	public class DungeonResetter
	{
		[HarmonyPatch(typeof(ZNetScene), "Awake")]
		public static class ZNetScene_Awake_Patch
		{
			private static void Postfix(ZNetScene __instance)
			{
				if ((Object)(object)__instance == (Object)null || __instance.m_prefabs == null)
				{
					return;
				}
				foreach (GameObject prefab in __instance.m_prefabs)
				{
					if ((Object)(object)prefab.GetComponent<DungeonGenerator>() != (Object)null)
					{
						string text = ((Object)prefab).name.Replace("(Clone)", "").Trim();
						if (!Plugin.DungeonToggles.ContainsKey(text))
						{
							Plugin.RegisterDungeon(text, text);
						}
					}
				}
			}
		}

		[HarmonyPatch(typeof(EnvMan), "OnMorning")]
		public static class EnvMan_OnMorning_Patch
		{
			private static void Postfix()
			{
				if (Plugin.EnableAutoReset.Value)
				{
					DungeonGenerator[] array = Object.FindObjectsOfType<DungeonGenerator>();
					foreach (DungeonGenerator dg in array)
					{
						EvaluateDungeon(dg);
					}
				}
			}
		}

		[HarmonyPatch(typeof(DungeonGenerator), "Awake")]
		public static class DungeonGenerator_Awake_Patch
		{
			private static void Postfix(DungeonGenerator __instance)
			{
				if (Plugin.EnableAutoReset.Value)
				{
					EvaluateDungeon(__instance);
				}
			}
		}

		public static void EvaluateDungeon(DungeonGenerator dg)
		{
			ZNetView component = ((Component)dg).GetComponent<ZNetView>();
			if ((Object)(object)component == (Object)null || !component.IsValid() || !component.IsOwner())
			{
				return;
			}
			string text = ((Object)dg).name.Replace("(Clone)", "").Trim();
			if (Plugin.DungeonToggles.TryGetValue(text, out var value) && !value.Value)
			{
				return;
			}
			int day = EnvMan.instance.GetDay(ZNet.instance.GetTimeSeconds());
			int num = component.GetZDO().GetInt("MDR_LastResetDay", day);
			if (component.GetZDO().GetInt("MDR_LastResetDay", -1) == -1)
			{
				component.GetZDO().Set("MDR_LastResetDay", day);
			}
			else
			{
				if (day - num < Plugin.ResetIntervalDays.Value)
				{
					return;
				}
				if (IsPlayerInside(dg))
				{
					if (Plugin.EnableDebugLogging.Value)
					{
						Plugin.Log.LogInfo((object)("[MoreDungeonResets] Player inside " + text + ". Skipping reset."));
					}
					return;
				}
				if (Plugin.EnableDebugLogging.Value)
				{
					Plugin.Log.LogInfo((object)("[MoreDungeonResets] Wiping and Regenerating " + text + "..."));
				}
				component.GetZDO().Set("MDR_LastResetDay", day);
				ResetDungeonSafe(dg);
			}
		}

		public static bool IsPlayerInside(DungeonGenerator dg)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			List<Player> list = new List<Player>();
			Player.GetPlayersInRange(((Component)dg).transform.position, Mathf.Max(new float[3]
			{
				dg.m_zoneSize.x,
				dg.m_zoneSize.y,
				dg.m_zoneSize.z
			}) + 15f, list);
			return list.Count > 0;
		}

		public static void ResetDungeonSafe(DungeonGenerator dg)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: 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_0064: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			if (((Component)dg).transform.position.y < 1000f)
			{
				Plugin.Log.LogWarning((object)$"[MoreDungeonResets] SAFETY ABORT: Dungeon {((Object)dg).name} is too low (Y: {((Component)dg).transform.position.y}). Skipping to protect world data.");
				return;
			}
			Vector3 position = ((Component)dg).transform.position;
			Bounds val = default(Bounds);
			((Bounds)(ref val))..ctor(position, dg.m_zoneSize);
			List<ZDO> list = new List<ZDO>();
			if (ZDOMan.instance != null)
			{
				Dictionary<ZDOID, ZDO> dictionary = AccessTools.FieldRefAccess<ZDOMan, Dictionary<ZDOID, ZDO>>("m_objectsByID").Invoke(ZDOMan.instance);
				if (dictionary != null)
				{
					foreach (KeyValuePair<ZDOID, ZDO> item in dictionary)
					{
						ZDO value = item.Value;
						if (((Bounds)(ref val)).Contains(value.GetPosition()))
						{
							GameObject prefab = ZNetScene.instance.GetPrefab(value.GetPrefab());
							if (!((Object)(object)prefab != (Object)null) || (!((Object)(object)prefab.GetComponent<Player>() != (Object)null) && !((Object)(object)prefab.GetComponent<DungeonGenerator>() != (Object)null) && !((Object)(object)prefab.GetComponent<LocationProxy>() != (Object)null)))
							{
								list.Add(value);
							}
						}
					}
				}
			}
			foreach (ZDO item2 in list)
			{
				ZDOMan.instance.DestroyZDO(item2);
			}
			if (Plugin.EnableDebugLogging.Value)
			{
				Plugin.Log.LogInfo((object)$"[MoreDungeonResets] Wiped {list.Count} objects from interior. Regenerating...");
			}
			dg.Generate((SpawnMode)0);
			string text = ((Object)dg).name.Replace("(Clone)", "").Trim();
			if (text == "DG_DvergrBoss" || text == "Mistlands_DvergrBossEntrance1")
			{
				ApplyQueenFix(dg);
			}
		}

		private static void ApplyQueenFix(DungeonGenerator dg)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: 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_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			if (Plugin.EnableDebugLogging.Value)
			{
				Plugin.Log.LogInfo((object)"[MoreDungeonResets] Applying special Queen Fix logic...");
			}
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(((Component)dg).transform.position.x, ((Component)dg).transform.position.z);
			int stableHashCode = StringExtensionMethods.GetStableHashCode("dvergr_boss_door");
			int stableHashCode2 = StringExtensionMethods.GetStableHashCode("Spawner_SeekerQueen");
			bool flag = false;
			Bounds val2 = default(Bounds);
			((Bounds)(ref val2))..ctor(((Component)dg).transform.position, dg.m_zoneSize);
			if (ZDOMan.instance != null)
			{
				Dictionary<ZDOID, ZDO> dictionary = AccessTools.FieldRefAccess<ZDOMan, Dictionary<ZDOID, ZDO>>("m_objectsByID").Invoke(ZDOMan.instance);
				if (dictionary != null)
				{
					Vector2 val3 = default(Vector2);
					foreach (KeyValuePair<ZDOID, ZDO> item in dictionary)
					{
						ZDO value = item.Value;
						if (value.GetPrefab() == StringExtensionMethods.GetStableHashCode("dungeon_queen_door") || value.GetPrefab() == StringExtensionMethods.GetStableHashCode("piece_queendoor") || value.GetPrefab() == StringExtensionMethods.GetStableHashCode("dvergr_boss_door"))
						{
							((Vector2)(ref val3))..ctor(value.GetPosition().x, value.GetPosition().z);
							if (Vector2.Distance(val, val3) < 150f)
							{
								value.Set("state", 0);
								if (Plugin.EnableDebugLogging.Value)
								{
									Plugin.Log.LogInfo((object)"[MoreDungeonResets] Queen Sealbreaker door has been successfully resealed!");
								}
							}
						}
						if (value.GetPrefab() == stableHashCode2 && ((Bounds)(ref val2)).Contains(value.GetPosition()))
						{
							flag = true;
							value.Set("alive_time", 0L);
						}
					}
				}
			}
			if (!flag)
			{
				Plugin.Log.LogWarning((object)"[MoreDungeonResets] Queen spawner was missing after regen! Injecting a new one manually.");
				Vector3 val4 = ((Component)dg).transform.position + new Vector3(0f, 5f, 0f);
				GameObject prefab = ZNetScene.instance.GetPrefab("Spawner_SeekerQueen");
				if ((Object)(object)prefab != (Object)null)
				{
					Object.Instantiate<GameObject>(prefab, val4, Quaternion.identity);
				}
			}
		}
	}
	[BepInPlugin("com.loathe.MoreDungeonResets", "More Dungeon Resets", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGUID = "com.loathe.MoreDungeonResets";

		public const string PluginName = "More Dungeon Resets";

		public const string PluginVersion = "1.0.0";

		private readonly Harmony _harmony = new Harmony("com.loathe.MoreDungeonResets");

		public static Plugin Instance;

		public static ManualLogSource Log;

		public static ConfigEntry<bool> EnableAutoReset;

		public static ConfigEntry<int> ResetIntervalDays;

		public static ConfigEntry<bool> EnableDebugLogging;

		public static Dictionary<string, ConfigEntry<bool>> DungeonToggles = new Dictionary<string, ConfigEntry<bool>>();

		private void Awake()
		{
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			EnableAutoReset = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Global", "Enable Auto Reset", true, "Enable the automatic lazy-resetting of dungeons.");
			ResetIntervalDays = ((BaseUnityPlugin)this).Config.Bind<int>("1 - Global", "Reset Interval (Days)", 30, "How many in-game days must pass before a dungeon is eligible to be reset again.");
			EnableDebugLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - Global", "Enable Debug Logging", true, "Prints detailed logs to the console about ZDO deletions and reset math.");
			RegisterDungeon("Crypt", "Sunken Crypts", "2 - Dungeons", defaultValue: true, "Enable resetting of Swamp Sunken Crypts.");
			RegisterDungeon("TrollCave", "Troll Caves", "2 - Dungeons", defaultValue: true, "Enable resetting of Black Forest Troll Caves.");
			RegisterDungeon("TrollCave02", "Troll Caves 02", "2 - Dungeons", defaultValue: true, "Enable resetting of Black Forest Troll Caves variant.");
			RegisterDungeon("BurialChamber", "Burial Chambers", "2 - Dungeons", defaultValue: true, "Enable resetting of Black Forest Burial Chambers.");
			RegisterDungeon("MountainCave", "Frost Caves", "2 - Dungeons", defaultValue: true, "Enable resetting of Mountain Frost Caves.");
			RegisterDungeon("Mistlands_DvergrTownEntrance", "Infested Mines", "2 - Dungeons", defaultValue: true, "Enable resetting of Mistlands Infested Mines.");
			RegisterDungeon("Mistlands_DvergrBossEntrance1", "Queen Citadel", "2 - Dungeons", defaultValue: true, "Enable resetting of the Queen's Infested Citadel (Includes the custom door/spawner fix).");
			RegisterDungeon("Hildir_cave", "Smouldering Tombs", "3 - Hildir", defaultValue: true, "Enable resetting of Hildir's Smouldering Tombs.");
			RegisterDungeon("Hildir_crypt", "Howling Caverns", "3 - Hildir", defaultValue: true, "Enable resetting of Hildir's Howling Caverns.");
			RegisterDungeon("Hildir_camp", "Sealed Tower", "3 - Hildir", defaultValue: false, "Enable resetting of Hildir's Sealed Tower (Note: This is mostly an exterior structure).");
			_harmony.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin com.loathe.MoreDungeonResets is loaded!");
		}

		public static void RegisterDungeon(string prefabName, string displayName, string category = "4 - Modded Dungeons", bool defaultValue = true, string description = "")
		{
			string text = prefabName.Replace("(Clone)", "").Trim();
			if (!DungeonToggles.ContainsKey(text))
			{
				if (string.IsNullOrEmpty(description))
				{
					description = "Enable resetting of " + displayName + " (" + text + ")";
				}
				ConfigEntry<bool> value = ((BaseUnityPlugin)Instance).Config.Bind<bool>(category, "Reset " + displayName, defaultValue, description);
				DungeonToggles[text] = value;
				Log.LogInfo((object)("Registered config for dungeon: " + text + " as '" + displayName + "'"));
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "MoreDungeonResets";

		public const string PLUGIN_NAME = "MoreDungeonResets";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}