Decompiled source of AuroraProjectButter v1.3.0

plugins/AuroraProjectButter.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
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("AuroraProjectButter")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.3.0.0")]
[assembly: AssemblyInformationalVersion("1.3.0")]
[assembly: AssemblyProduct("AuroraProjectButter")]
[assembly: AssemblyTitle("AuroraProjectButter")]
[assembly: AssemblyVersion("1.3.0.0")]
namespace AuroraProjectButter;

[BepInPlugin("freyja.AuroraProjectButter", "AuroraProjectButter", "1.3.0")]
public class ButterPlugin : BaseUnityPlugin
{
	internal struct DeferredDungeon
	{
		public DungeonGenerator Generator;

		public Vector3 Position;
	}

	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static ConsoleEvent <>9__27_0;

		public static Func<MethodInfo, bool> <>9__31_0;

		public static Func<MethodInfo, bool> <>9__31_1;

		public static Func<MethodInfo, bool> <>9__31_2;

		public static Func<MethodInfo, bool> <>9__31_3;

		public static Func<MethodInfo, bool> <>9__32_0;

		public static Func<ParameterInfo, string> <>9__32_1;

		public static Predicate<DeferredDungeon> <>9__37_0;

		internal void <Awake>b__27_0(ConsoleEventArgs args)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			DungeonCleanup();
			Player localPlayer = Player.m_localPlayer;
			float num = ((localPlayer != null) ? ((Component)localPlayer).transform.position.y : float.NaN);
			bool flag = IsPlayerTeleporting();
			bool flag2 = IsInGracePeriod();
			args.Context.AddString("[AuroraProjectButter v1.3.0]");
			args.Context.AddString($"  Dungeon Deferral: {TotalDeferred} deferred, {TotalAllowed} allowed, {Deferred.Count} queued");
			args.Context.AddString($"  Sky Filter: {SkyObjectsBlocked} blocked, {SkyObjectsAllowed} allowed");
			args.Context.AddString($"  Player Y: {num:F1}  Teleporting: {flag}  Grace: {flag2}");
			args.Context.AddString($"  World radius: {WorldRadius.Value}");
		}

		internal bool <ApplyDungeonPatches>b__31_0(MethodInfo m)
		{
			return m.Name == "Generate" && !m.IsAbstract;
		}

		internal bool <ApplyDungeonPatches>b__31_1(MethodInfo mi)
		{
			return mi.Name == "Interact";
		}

		internal bool <ApplyDungeonPatches>b__31_2(MethodInfo mi)
		{
			return mi.Name == "HaveTarget";
		}

		internal bool <ApplyDungeonPatches>b__31_3(MethodInfo mi)
		{
			return mi.Name == "OnSpawned";
		}

		internal bool <ApplySkyFilterPatches>b__32_0(MethodInfo m)
		{
			return m.Name == "CreateObject" && !m.IsAbstract;
		}

		internal string <ApplySkyFilterPatches>b__32_1(ParameterInfo p)
		{
			return p.ParameterType.Name;
		}

		internal bool <DungeonCleanup>b__37_0(DeferredDungeon d)
		{
			return (Object)(object)d.Generator == (Object)null;
		}
	}

	public const string PluginGUID = "freyja.AuroraProjectButter";

	public const string PluginName = "AuroraProjectButter";

	public const string PluginVersion = "1.3.0";

	internal static ButterPlugin Instance;

	internal static ManualLogSource Logger;

	private Harmony _harmony;

	internal static readonly List<DeferredDungeon> Deferred = new List<DeferredDungeon>();

	internal static bool IsForceLoading;

	internal static bool IsTeleporting;

	internal static float PlayerSpawnTime = -1f;

	internal static float TeleportEndTime = -1f;

	internal static MethodInfo DG_AwakeMethod;

	internal static int TotalDeferred;

	internal static int TotalAllowed;

	internal static int SkyObjectsBlocked;

	internal static int SkyObjectsAllowed;

	public static ConfigEntry<bool> ModEnabled;

	public static ConfigEntry<bool> VerboseLogging;

	public static ConfigEntry<float> SearchRadius;

	public static ConfigEntry<float> TeleportDelay;

	public static ConfigEntry<bool> ShowLoadingMsg;

	public static ConfigEntry<float> SpawnGracePeriod;

	public static ConfigEntry<bool> SkyFilterEnabled;

	public static ConfigEntry<float> SkyThreshold;

	public static ConfigEntry<float> TeleportGracePeriod;

	public static ConfigEntry<float> WorldRadius;

	private void Awake()
	{
		//IL_0170: Unknown result type (might be due to invalid IL or missing references)
		//IL_017a: Expected O, but got Unknown
		//IL_01da: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d1: Expected O, but got Unknown
		Instance = this;
		Logger = ((BaseUnityPlugin)this).Logger;
		ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Master toggle.");
		VerboseLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "VerboseLogging", false, "Extra logging.");
		SearchRadius = ((BaseUnityPlugin)this).Config.Bind<float>("DungeonDeferral", "SearchRadius", 300f, "Max distance from entrance to find deferred dungeon.");
		TeleportDelay = ((BaseUnityPlugin)this).Config.Bind<float>("DungeonDeferral", "TeleportDelay", 2.5f, "Seconds to wait after loading dungeon before teleport.");
		ShowLoadingMsg = ((BaseUnityPlugin)this).Config.Bind<bool>("DungeonDeferral", "ShowLoadingMessage", true, "Show 'Loading dungeon...' message.");
		SpawnGracePeriod = ((BaseUnityPlugin)this).Config.Bind<float>("DungeonDeferral", "SpawnGracePeriod", 2f, "Seconds after login to allow all loading.");
		SkyFilterEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("SkyFilter", "Enabled", true, "Skip creating GameObjects for dungeon interior objects while on surface.");
		SkyThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("SkyFilter", "SkyThresholdY", 1000f, "Objects above this Y are considered dungeon interiors.");
		TeleportGracePeriod = ((BaseUnityPlugin)this).Config.Bind<float>("SkyFilter", "TeleportGracePeriod", 5f, "Seconds after ANY teleport where sky filter is disabled. Prevents loading screen freeze.");
		WorldRadius = ((BaseUnityPlugin)this).Config.Bind<float>("SkyFilter", "WorldRadius", 15000f, "Objects beyond this X/Z distance from world center are never filtered. Set higher than your world radius to protect custom sky zones. Default 15000 covers most Expand World Size configs.");
		_harmony = new Harmony("freyja.AuroraProjectButter");
		Logger.LogInfo((object)"── Dungeon Deferral patches ──");
		ApplyDungeonPatches();
		Logger.LogInfo((object)"── Sky Object Filter patches ──");
		ApplySkyFilterPatches();
		object obj = <>c.<>9__27_0;
		if (obj == null)
		{
			ConsoleEvent val = delegate(ConsoleEventArgs args)
			{
				//IL_001c: Unknown result type (might be due to invalid IL or missing references)
				DungeonCleanup();
				Player localPlayer = Player.m_localPlayer;
				float num = ((localPlayer != null) ? ((Component)localPlayer).transform.position.y : float.NaN);
				bool flag = IsPlayerTeleporting();
				bool flag2 = IsInGracePeriod();
				args.Context.AddString("[AuroraProjectButter v1.3.0]");
				args.Context.AddString($"  Dungeon Deferral: {TotalDeferred} deferred, {TotalAllowed} allowed, {Deferred.Count} queued");
				args.Context.AddString($"  Sky Filter: {SkyObjectsBlocked} blocked, {SkyObjectsAllowed} allowed");
				args.Context.AddString($"  Player Y: {num:F1}  Teleporting: {flag}  Grace: {flag2}");
				args.Context.AddString($"  World radius: {WorldRadius.Value}");
			};
			<>c.<>9__27_0 = val;
			obj = (object)val;
		}
		new ConsoleCommand("butter_status", "Show AuroraProjectButter stats", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		Logger.LogInfo((object)"=== AuroraProjectButter v1.3.0 loaded ===");
		Logger.LogInfo((object)"  Dungeon Deferral: ON");
		Logger.LogInfo((object)string.Format("  Sky Filter: {0} (Y > {1}, grace {2}s, radius {3})", SkyFilterEnabled.Value ? "ON" : "OFF", SkyThreshold.Value, TeleportGracePeriod.Value, WorldRadius.Value));
	}

	private void OnDestroy()
	{
		Harmony harmony = _harmony;
		if (harmony != null)
		{
			harmony.UnpatchSelf();
		}
	}

	internal static bool IsPlayerTeleporting()
	{
		if (IsTeleporting)
		{
			return true;
		}
		if (IsForceLoading)
		{
			return true;
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return false;
		}
		try
		{
			FieldInfo field = typeof(Player).GetField("m_teleporting", BindingFlags.Instance | BindingFlags.NonPublic);
			if (field != null)
			{
				return (bool)field.GetValue(localPlayer);
			}
		}
		catch
		{
		}
		return false;
	}

	internal static bool IsInGracePeriod()
	{
		float time = Time.time;
		if (PlayerSpawnTime > 0f && time - PlayerSpawnTime < SpawnGracePeriod.Value)
		{
			return true;
		}
		if (TeleportEndTime > 0f && time - TeleportEndTime < TeleportGracePeriod.Value)
		{
			return true;
		}
		return false;
	}

	private void ApplyDungeonPatches()
	{
		//IL_004f: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Expected O, but got Unknown
		//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f0: Expected O, but got Unknown
		//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01ae: Expected O, but got Unknown
		//IL_0273: Unknown result type (might be due to invalid IL or missing references)
		//IL_0281: Expected O, but got Unknown
		//IL_0314: Unknown result type (might be due to invalid IL or missing references)
		//IL_0321: Expected O, but got Unknown
		//IL_03b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c6: Expected O, but got Unknown
		try
		{
			DG_AwakeMethod = typeof(DungeonGenerator).GetMethod("Awake", BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			if (DG_AwakeMethod != null)
			{
				_harmony.Patch((MethodBase)DG_AwakeMethod, new HarmonyMethod(typeof(DungeonPatches), "Awake_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Logger.LogInfo((object)"  OK: DungeonGenerator.Awake()");
			}
			else
			{
				Logger.LogError((object)"  FAIL: DungeonGenerator.Awake()");
			}
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"  DG.Awake: {arg}");
		}
		try
		{
			MethodInfo method = typeof(DungeonGenerator).GetMethod("LoadRoomPrefabsAsync", BindingFlags.Instance | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
			if (method != null)
			{
				_harmony.Patch((MethodBase)method, new HarmonyMethod(typeof(DungeonPatches), "LoadAsync_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Logger.LogInfo((object)"  OK: LoadRoomPrefabsAsync() (fallback)");
			}
		}
		catch (Exception ex)
		{
			Logger.LogWarning((object)("  LoadAsync: " + ex.Message));
		}
		try
		{
			List<MethodInfo> list = (from m in typeof(DungeonGenerator).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where m.Name == "Generate" && !m.IsAbstract
				select m).ToList();
			MethodInfo method2 = typeof(DungeonPatches).GetMethod("Generate_Prefix", BindingFlags.Static | BindingFlags.Public);
			int num = 0;
			foreach (MethodInfo item in list)
			{
				try
				{
					_harmony.Patch((MethodBase)item, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					num++;
				}
				catch
				{
				}
			}
			Logger.LogInfo((object)$"  OK: {num} Generate overload(s)");
		}
		catch (Exception arg2)
		{
			Logger.LogError((object)$"  Generate: {arg2}");
		}
		try
		{
			MethodInfo methodInfo = typeof(Teleport).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo mi) => mi.Name == "Interact");
			if (methodInfo != null)
			{
				_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(DungeonPatches), "Teleport_Interact_Prefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Logger.LogInfo((object)"  OK: Teleport.Interact");
			}
		}
		catch (Exception arg3)
		{
			Logger.LogError((object)$"  Teleport.Interact: {arg3}");
		}
		try
		{
			MethodInfo methodInfo2 = typeof(Teleport).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo mi) => mi.Name == "HaveTarget");
			if (methodInfo2 != null)
			{
				_harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(DungeonPatches), "HaveTarget_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Logger.LogInfo((object)"  OK: Teleport.HaveTarget");
			}
		}
		catch (Exception ex2)
		{
			Logger.LogWarning((object)("  HaveTarget: " + ex2.Message));
		}
		try
		{
			MethodInfo methodInfo3 = typeof(Player).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo mi) => mi.Name == "OnSpawned");
			if (methodInfo3 != null)
			{
				_harmony.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(DungeonPatches), "Player_OnSpawned_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Logger.LogInfo((object)"  OK: Player.OnSpawned");
			}
		}
		catch (Exception ex3)
		{
			Logger.LogWarning((object)("  Player.OnSpawned: " + ex3.Message));
		}
	}

	private void ApplySkyFilterPatches()
	{
		//IL_018b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0199: Expected O, but got Unknown
		//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Expected O, but got Unknown
		if (!SkyFilterEnabled.Value)
		{
			Logger.LogInfo((object)"  Sky Filter DISABLED in config.");
			return;
		}
		try
		{
			List<MethodInfo> list = (from m in typeof(ZNetScene).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
				where m.Name == "CreateObject" && !m.IsAbstract
				select m).ToList();
			MethodInfo method = typeof(SkyFilterPatches).GetMethod("CreateObject_Prefix", BindingFlags.Static | BindingFlags.Public);
			int num = 0;
			foreach (MethodInfo item in list)
			{
				ParameterInfo[] parameters = item.GetParameters();
				if (parameters.Length >= 1 && parameters[0].ParameterType == typeof(ZDO))
				{
					_harmony.Patch((MethodBase)item, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					string text = string.Join(", ", parameters.Select((ParameterInfo p) => p.ParameterType.Name));
					Logger.LogInfo((object)("  OK: ZNetScene.CreateObject(" + text + ")"));
					num++;
				}
			}
			if (num == 0)
			{
				Logger.LogWarning((object)"  No ZDO-parameter CreateObject found. Trying all overloads...");
				foreach (MethodInfo item2 in list)
				{
					try
					{
						_harmony.Patch((MethodBase)item2, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						num++;
					}
					catch
					{
					}
				}
			}
			if (num == 0)
			{
				Logger.LogError((object)"  FAIL: Could not patch any ZNetScene.CreateObject!");
			}
		}
		catch (Exception arg)
		{
			Logger.LogError((object)$"  ZNetScene.CreateObject: {arg}");
		}
	}

	internal static bool ShouldDefer(string caller, Vector3 genPos)
	{
		//IL_0084: 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)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_0056: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
		//IL_0178: Unknown result type (might be due to invalid IL or missing references)
		//IL_017e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0104: Unknown result type (might be due to invalid IL or missing references)
		//IL_014c: Unknown result type (might be due to invalid IL or missing references)
		if (!ModEnabled.Value)
		{
			return false;
		}
		if (IsForceLoading)
		{
			return false;
		}
		if ((Object)(object)Player.m_localPlayer == (Object)null)
		{
			if (VerboseLogging.Value)
			{
				Logger.LogInfo((object)$"[ALLOW:no-player] {caller} at {genPos:F0}");
			}
			TotalAllowed++;
			return false;
		}
		Vector3 position = ((Component)Player.m_localPlayer).transform.position;
		if (IsInGracePeriod())
		{
			if (VerboseLogging.Value)
			{
				Logger.LogInfo((object)$"[ALLOW:grace] {caller} at {genPos:F0}");
			}
			TotalAllowed++;
			return false;
		}
		if (position.y > 1000f)
		{
			if (VerboseLogging.Value)
			{
				Logger.LogInfo((object)$"[ALLOW:in-dungeon] {caller} at {genPos:F0}");
			}
			TotalAllowed++;
			return false;
		}
		if (IsPlayerTeleporting())
		{
			if (VerboseLogging.Value)
			{
				Logger.LogInfo((object)$"[ALLOW:teleporting] {caller} at {genPos:F0}");
			}
			TotalAllowed++;
			return false;
		}
		Logger.LogInfo((object)$"[DEFER] {caller} at {genPos:F0}, player Y={position.y:F0}");
		TotalDeferred++;
		return true;
	}

	internal static void DeferDungeon(DungeonGenerator gen)
	{
		//IL_0019: Unknown result type (might be due to invalid IL or missing references)
		//IL_001e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0057: 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)
		Vector3 position = ((Component)gen).transform.position;
		if (!Deferred.Any((DeferredDungeon d) => (Object)(object)d.Generator == (Object)(object)gen))
		{
			Deferred.Add(new DeferredDungeon
			{
				Generator = gen,
				Position = position
			});
		}
	}

	internal static DeferredDungeon? FindNearest(Vector3 origin, float maxDist)
	{
		//IL_002d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0037: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		DungeonCleanup();
		DeferredDungeon? result = null;
		float num = float.MaxValue;
		foreach (DeferredDungeon item in Deferred)
		{
			float num2 = item.Position.x - origin.x;
			float num3 = item.Position.z - origin.z;
			float num4 = Mathf.Sqrt(num2 * num2 + num3 * num3);
			if (num4 < maxDist && num4 < num)
			{
				num = num4;
				result = item;
			}
		}
		return result;
	}

	internal static void RemoveDeferred(DungeonGenerator gen)
	{
		Deferred.RemoveAll((DeferredDungeon d) => (Object)(object)d.Generator == (Object)(object)gen || (Object)(object)d.Generator == (Object)null);
	}

	internal static void DungeonCleanup()
	{
		Deferred.RemoveAll((DeferredDungeon d) => (Object)(object)d.Generator == (Object)null);
	}

	internal static void ForceLoadDungeon(DungeonGenerator gen)
	{
		//IL_003a: Unknown result type (might be due to invalid IL or missing references)
		if (DG_AwakeMethod == null)
		{
			Logger.LogError((object)"[REPLAY] No Awake method!");
			return;
		}
		IsForceLoading = true;
		try
		{
			Logger.LogInfo((object)$"[REPLAY] Awake() at {((Component)gen).transform.position:F0}");
			DG_AwakeMethod.Invoke(gen, null);
		}
		finally
		{
			IsForceLoading = false;
		}
	}

	internal static Coroutine RunCoroutine(IEnumerator routine)
	{
		ButterPlugin instance = Instance;
		return (instance != null) ? ((MonoBehaviour)instance).StartCoroutine(routine) : null;
	}
}
internal static class SkyFilterPatches
{
	public static bool CreateObject_Prefix(ZDO __0)
	{
		//IL_0088: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: Unknown result type (might be due to invalid IL or missing references)
		//IL_008e: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0137: Unknown result type (might be due to invalid IL or missing references)
		if (!ButterPlugin.SkyFilterEnabled.Value)
		{
			return true;
		}
		if (__0 == null)
		{
			return true;
		}
		if ((Object)(object)Player.m_localPlayer == (Object)null)
		{
			return true;
		}
		if (ButterPlugin.IsPlayerTeleporting())
		{
			ButterPlugin.SkyObjectsAllowed++;
			return true;
		}
		if (ButterPlugin.IsInGracePeriod())
		{
			ButterPlugin.SkyObjectsAllowed++;
			return true;
		}
		Vector3 position = __0.GetPosition();
		float y = position.y;
		if (y <= ButterPlugin.SkyThreshold.Value)
		{
			return true;
		}
		float num = Mathf.Sqrt(position.x * position.x + position.z * position.z);
		if (num > ButterPlugin.WorldRadius.Value)
		{
			ButterPlugin.SkyObjectsAllowed++;
			if (ButterPlugin.VerboseLogging.Value)
			{
				ButterPlugin.Logger.LogInfo((object)$"[SkyFilter:ALLOW] Outside world radius: Y={y:F0} dist={num:F0}");
			}
			return true;
		}
		float y2 = ((Component)Player.m_localPlayer).transform.position.y;
		if (y2 > ButterPlugin.SkyThreshold.Value)
		{
			ButterPlugin.SkyObjectsAllowed++;
			return true;
		}
		ButterPlugin.SkyObjectsBlocked++;
		if (ButterPlugin.VerboseLogging.Value && ButterPlugin.SkyObjectsBlocked % 100 == 1)
		{
			ButterPlugin.Logger.LogInfo((object)$"[SkyFilter:BLOCK] #{ButterPlugin.SkyObjectsBlocked} Y={y:F0} dist={num:F0}");
		}
		return false;
	}
}
internal static class DungeonPatches
{
	[CompilerGenerated]
	private sealed class <LoadAndTeleport>d__5 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public Teleport teleport;

		public ButterPlugin.DeferredDungeon deferred;

		public Humanoid character;

		private Exception <ex>5__1;

		private Exception <ex>5__2;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <LoadAndTeleport>d__5(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<ex>5__1 = null;
			<ex>5__2 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				if (ButterPlugin.ShowLoadingMsg.Value)
				{
					Player localPlayer = Player.m_localPlayer;
					if (localPlayer != null)
					{
						((Character)localPlayer).Message((MessageType)2, "Loading dungeon...", 0, (Sprite)null);
					}
				}
				ButterPlugin.TeleportEndTime = Time.time;
				<>2__current = null;
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				if ((Object)(object)deferred.Generator != (Object)null)
				{
					try
					{
						ButterPlugin.ForceLoadDungeon(deferred.Generator);
					}
					catch (Exception ex)
					{
						<ex>5__1 = ex;
						ButterPlugin.Logger.LogError((object)$"[OnDemand] Failed: {<ex>5__1}");
					}
					ButterPlugin.RemoveDeferred(deferred.Generator);
				}
				<>2__current = (object)new WaitForSeconds(ButterPlugin.TeleportDelay.Value);
				<>1__state = 2;
				return true;
			case 2:
				<>1__state = -1;
				ButterPlugin.TeleportEndTime = Time.time;
				if ((Object)(object)teleport != (Object)null && (Object)(object)character != (Object)null)
				{
					ButterPlugin.IsTeleporting = true;
					try
					{
						teleport.Interact(character, false, false);
					}
					catch (Exception ex)
					{
						<ex>5__2 = ex;
						ButterPlugin.Logger.LogError((object)$"[OnDemand] Teleport: {<ex>5__2}");
					}
					finally
					{
						ButterPlugin.IsTeleporting = false;
					}
				}
				return false;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	public static void Player_OnSpawned_Postfix(Player __instance)
	{
		//IL_0035: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)__instance == (Object)(object)Player.m_localPlayer)
		{
			ButterPlugin.PlayerSpawnTime = Time.time;
			ButterPlugin.TeleportEndTime = Time.time;
			ButterPlugin.Logger.LogInfo((object)$"[Spawn] Player at {((Component)__instance).transform.position:F0}");
		}
	}

	public static bool Awake_Prefix(DungeonGenerator __instance)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		if (ButterPlugin.ShouldDefer("Awake", ((Component)__instance).transform.position))
		{
			ButterPlugin.DeferDungeon(__instance);
			return false;
		}
		return true;
	}

	public static bool LoadAsync_Prefix(DungeonGenerator __instance)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		if (ButterPlugin.ShouldDefer("LoadAsync", ((Component)__instance).transform.position))
		{
			ButterPlugin.DeferDungeon(__instance);
			return false;
		}
		return true;
	}

	public static bool Generate_Prefix(DungeonGenerator __instance)
	{
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		if (ButterPlugin.ShouldDefer("Generate", ((Component)__instance).transform.position))
		{
			ButterPlugin.DeferDungeon(__instance);
			return false;
		}
		return true;
	}

	public static bool Teleport_Interact_Prefix(Teleport __instance, Humanoid character, bool hold, bool alt)
	{
		//IL_0059: Unknown result type (might be due to invalid IL or missing references)
		//IL_0085: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
		if (!ButterPlugin.ModEnabled.Value)
		{
			return true;
		}
		if (ButterPlugin.IsTeleporting)
		{
			return true;
		}
		if ((Object)(object)character != (Object)(object)Player.m_localPlayer)
		{
			return true;
		}
		if (hold)
		{
			return true;
		}
		if (((Component)Player.m_localPlayer).transform.position.y > 1000f)
		{
			ButterPlugin.TeleportEndTime = Time.time;
			return true;
		}
		ButterPlugin.DeferredDungeon? deferredDungeon = ButterPlugin.FindNearest(((Component)__instance).transform.position, ButterPlugin.SearchRadius.Value);
		if (!deferredDungeon.HasValue)
		{
			ButterPlugin.TeleportEndTime = Time.time;
			return true;
		}
		ButterPlugin.Logger.LogInfo((object)$"[OnDemand] Entrance → loading dungeon at {deferredDungeon.Value.Position:F0}");
		ButterPlugin.RunCoroutine(LoadAndTeleport(__instance, deferredDungeon.Value, character));
		return false;
	}

	[IteratorStateMachine(typeof(<LoadAndTeleport>d__5))]
	private static IEnumerator LoadAndTeleport(Teleport teleport, ButterPlugin.DeferredDungeon deferred, Humanoid character)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <LoadAndTeleport>d__5(0)
		{
			teleport = teleport,
			deferred = deferred,
			character = character
		};
	}

	public static void HaveTarget_Postfix(Teleport __instance, ref bool __result)
	{
		//IL_002b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: Unknown result type (might be due to invalid IL or missing references)
		if (ButterPlugin.ModEnabled.Value && (!((Object)(object)Player.m_localPlayer != (Object)null) || !(((Component)Player.m_localPlayer).transform.position.y > 1000f)) && !__result && ButterPlugin.FindNearest(((Component)__instance).transform.position, ButterPlugin.SearchRadius.Value).HasValue)
		{
			__result = true;
		}
	}
}