Decompiled source of DawnLibNullDungeonGuard v1.0.0

BepInEx\plugins\DawnLibNullDungeonGuard\DawnLibNullDungeonGuard.dll

Decompiled 16 hours ago
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: AssemblyVersion("0.0.0.0")]
namespace CodexPatches.DawnLibNullDungeonGuard;

[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("codex.dawnlibnulldungeonguard", "DawnLib Null Dungeon Guard", "1.0.0")]
public sealed class Plugin : BaseUnityPlugin
{
	public const string PluginGuid = "codex.dawnlibnulldungeonguard";

	public const string PluginName = "DawnLib Null Dungeon Guard";

	public const string PluginVersion = "1.0.0";

	internal static ManualLogSource Log;

	private void Awake()
	{
		//IL_0010: Unknown result type (might be due to invalid IL or missing references)
		Log = ((BaseUnityPlugin)this).Logger;
		try
		{
			new Harmony("codex.dawnlibnulldungeonguard").PatchAll(typeof(Plugin).Assembly);
			Log.LogInfo((object)"Installed DawnLib null dungeon guard.");
		}
		catch (Exception ex)
		{
			Log.LogError((object)("Failed to install DawnLib null dungeon guard: " + ex));
		}
	}
}
[HarmonyPatch]
internal static class LoadDungeonBundleMoveNextPatch
{
	private static bool generatedOnceAfterNull;

	private static MethodBase TargetMethod()
	{
		Type type = AccessTools.TypeByName("Dawn.DungeonRegistrationHandler+<LoadDungeonBundle>d__11");
		if (!(type == null))
		{
			return AccessTools.Method(type, "MoveNext", (Type[])null, (Type[])null);
		}
		return null;
	}

	private static bool Prefix(object __instance, ref bool __result)
	{
		try
		{
			FieldInfo fieldInfo = AccessTools.Field(__instance.GetType(), "<>1__state");
			if ((fieldInfo == null) ? true : ((byte)(int)fieldInfo.GetValue(__instance) != 0))
			{
				return true;
			}
			object currentDungeonFlow = GetCurrentDungeonFlow();
			if (currentDungeonFlow == null)
			{
				return true;
			}
			object dawnInfo = GetDawnInfo(currentDungeonFlow);
			if (dawnInfo != null)
			{
				return true;
			}
			Plugin.Log.LogWarning((object)("DawnLib returned null DawnDungeonInfo for dungeon flow '" + GetObjectName(currentDungeonFlow) + "'. Letting vanilla/LLL generation continue."));
			GenerateCurrentDungeon();
			generatedOnceAfterNull = true;
			if (fieldInfo != null)
			{
				fieldInfo.SetValue(__instance, -2);
			}
			__result = false;
			return false;
		}
		catch (Exception ex)
		{
			Plugin.Log.LogWarning((object)("Guard prefix failed; allowing DawnLib original coroutine to run. " + ex));
			return true;
		}
	}

	private static Exception Finalizer(Exception __exception, object __instance, ref bool __result)
	{
		if (__exception == null)
		{
			return null;
		}
		if (!(__exception is NullReferenceException))
		{
			return __exception;
		}
		try
		{
			object currentDungeonFlow = GetCurrentDungeonFlow();
			object obj = ((currentDungeonFlow == null) ? null : GetDawnInfo(currentDungeonFlow));
			if (currentDungeonFlow != null && obj == null)
			{
				Plugin.Log.LogWarning((object)("Caught DawnLib null dungeon crash for flow '" + GetObjectName(currentDungeonFlow) + "'. Suppressing and continuing generation."));
				if (!generatedOnceAfterNull)
				{
					GenerateCurrentDungeon();
					generatedOnceAfterNull = true;
				}
				FieldInfo fieldInfo = AccessTools.Field(__instance.GetType(), "<>1__state");
				if (fieldInfo != null)
				{
					fieldInfo.SetValue(__instance, -2);
				}
				__result = false;
				return null;
			}
		}
		catch (Exception ex)
		{
			Plugin.Log.LogError((object)("Guard finalizer failed while handling DawnLib null reference: " + ex));
		}
		return __exception;
	}

	private static object GetCurrentDungeonFlow()
	{
		object staticProperty = GetStaticProperty("RoundManager", "Instance");
		object field = GetField(staticProperty, "dungeonGenerator");
		object field2 = GetField(field, "Generator");
		return GetField(field2, "DungeonFlow");
	}

	private static object GetDawnInfo(object dungeonFlow)
	{
		Type type = AccessTools.TypeByName("Dawn.DungeonFlowExtensions");
		MethodInfo methodInfo = AccessTools.Method(type, "GetDawnInfo", (Type[])null, (Type[])null);
		if (!(methodInfo == null))
		{
			return methodInfo.Invoke(null, new object[1] { dungeonFlow });
		}
		return null;
	}

	private static void GenerateCurrentDungeon()
	{
		object staticProperty = GetStaticProperty("RoundManager", "Instance");
		object field = GetField(staticProperty, "dungeonGenerator");
		MethodInfo methodInfo = ((field == null) ? null : AccessTools.Method(field.GetType(), "Generate", (Type[])null, (Type[])null));
		if (methodInfo == null)
		{
			Plugin.Log.LogWarning((object)"Could not find RuntimeDungeon.Generate(); generation was not resumed.");
		}
		else
		{
			methodInfo.Invoke(field, null);
		}
	}

	private static object GetStaticProperty(string typeName, string propertyName)
	{
		Type type = AccessTools.TypeByName(typeName);
		PropertyInfo propertyInfo = AccessTools.Property(type, propertyName);
		if (!(propertyInfo == null))
		{
			return propertyInfo.GetValue(null, null);
		}
		return null;
	}

	private static object GetField(object instance, string fieldName)
	{
		if (instance == null)
		{
			return null;
		}
		FieldInfo fieldInfo = AccessTools.Field(instance.GetType(), fieldName);
		if (!(fieldInfo == null))
		{
			return fieldInfo.GetValue(instance);
		}
		return null;
	}

	private static string GetObjectName(object obj)
	{
		if (obj == null)
		{
			return "<null>";
		}
		PropertyInfo propertyInfo = AccessTools.Property(obj.GetType(), "name");
		object obj2 = ((propertyInfo == null) ? null : propertyInfo.GetValue(obj, null));
		if (obj2 != null)
		{
			return obj2.ToString();
		}
		return obj.ToString();
	}
}