Decompiled source of BiomeLock v1.2.1

plugins/BiomeLock.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using JetBrains.Annotations;
using LocalizationManager;
using Microsoft.CodeAnalysis;
using ServerSync;
using TMPro;
using UnityEngine;
using UnityEngine.PostProcessing;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Core.ObjectPool;
using YamlDotNet.Core.Tokens;
using YamlDotNet.Helpers;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.BufferedDeserialization;
using YamlDotNet.Serialization.BufferedDeserialization.TypeDiscriminators;
using YamlDotNet.Serialization.Callbacks;
using YamlDotNet.Serialization.Converters;
using YamlDotNet.Serialization.EventEmitters;
using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.NodeDeserializers;
using YamlDotNet.Serialization.NodeTypeResolvers;
using YamlDotNet.Serialization.ObjectFactories;
using YamlDotNet.Serialization.ObjectGraphTraversalStrategies;
using YamlDotNet.Serialization.ObjectGraphVisitors;
using YamlDotNet.Serialization.Schemas;
using YamlDotNet.Serialization.TypeInspectors;
using YamlDotNet.Serialization.TypeResolvers;
using YamlDotNet.Serialization.Utilities;
using YamlDotNet.Serialization.ValueDeserializers;

[assembly: Guid("E74EB49A-461D-48EA-85BC-F462D60C98C4")]
[assembly: ComVisible(false)]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyProduct("BiomeLock")]
[assembly: AssemblyCompany("Radamanto")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyTitle("BiomeLock")]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyFileVersion("1.2.1")]
[assembly: AssemblyConfiguration("")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.1.0")]
[module: UnverifiableCode]
[module: <9cdc4a4c-fda5-4912-8859-9fa5d3036d01>RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[<232928c7-3891-4d21-8865-cef381af162d>Embedded]
	internal sealed class <232928c7-3891-4d21-8865-cef381af162d>EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[<232928c7-3891-4d21-8865-cef381af162d>Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class <dbedd104-49d4-45b5-9930-e5d6d508bb9a>NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public <dbedd104-49d4-45b5-9930-e5d6d508bb9a>NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public <dbedd104-49d4-45b5-9930-e5d6d508bb9a>NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[<232928c7-3891-4d21-8865-cef381af162d>Embedded]
	[CompilerGenerated]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class <5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public <5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	[<232928c7-3891-4d21-8865-cef381af162d>Embedded]
	internal sealed class <9cdc4a4c-fda5-4912-8859-9fa5d3036d01>RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public <9cdc4a4c-fda5-4912-8859-9fa5d3036d01>RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace BiomeLock
{
	[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
	[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
	public static class BiomeLockAPI
	{
		public static readonly string PrivatePrefix = "bl_";

		public static bool IsReady => BiomeLockKeys.IsInMainScene();

		[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(new byte[] { 2, 1 })]
		[method: <dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(new byte[] { 2, 1 })]
		[field: <dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(new byte[] { 2, 1 })]
		public static event Action<string> OnPrivateKeyAdded;

		[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(new byte[] { 2, 1 })]
		[method: <dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(new byte[] { 2, 1 })]
		[field: <dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(new byte[] { 2, 1 })]
		public static event Action<string> OnPrivateKeyRemoved;

		[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)]
		[method: <5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(2)]
		[field: <dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)]
		public static event Action OnPrivateKeysReset;

		[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)]
		[method: <5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(2)]
		[field: <dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)]
		public static event Action OnPrivateKeysLoaded;

		public static bool HasPrivateKey(string globalOrPrivateKey)
		{
			return globalOrPrivateKey != null && BiomeLockKeys.HasLocalPrivateKey(globalOrPrivateKey);
		}

		public static bool HasProgressionKey(string globalOrPrivateKey)
		{
			return globalOrPrivateKey != null && BiomeLockKeys.HasProgressionKey(globalOrPrivateKey);
		}

		public static IReadOnlyList<string> GetPrivateKeys()
		{
			if (!IsReady)
			{
				return Array.Empty<string>();
			}
			return BiomeLockPrivateKeys.PrivateKeys.OrderBy<string, string>([<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)] (string k) => k, StringComparer.Ordinal).ToList();
		}

		public static bool IsBiomeLocked(Biome biome)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return IsReady && BiomeLock_SE.NeedsRestriction(biome);
		}

		public static bool IsRestricted()
		{
			return IsReady && BiomeLock_SE.HasBiomeLockSE(Player.m_localPlayer);
		}

		public static string ToPrivateKey(string globalOrPrivateKey)
		{
			return BiomeLockKeys.ToPrivateKey(globalOrPrivateKey);
		}

		public static string ToGlobalKey(string globalOrPrivateKey)
		{
			return BiomeLockKeys.ToGlobalKey(globalOrPrivateKey);
		}

		public static void AddRestrictionBypass(Func<Vector3, bool> bypass)
		{
			BiomeLock_SE.AddBypass(bypass);
		}

		public static void RemoveRestrictionBypass(Func<Vector3, bool> bypass)
		{
			BiomeLock_SE.RemoveBypass(bypass);
		}

		internal static void RaisePrivateKeyAdded(string privateKey)
		{
			Raise(BiomeLockAPI.OnPrivateKeyAdded, privateKey);
		}

		internal static void RaisePrivateKeyRemoved(string privateKey)
		{
			Raise(BiomeLockAPI.OnPrivateKeyRemoved, privateKey);
		}

		internal static void RaisePrivateKeysReset()
		{
			Raise(BiomeLockAPI.OnPrivateKeysReset);
		}

		internal static void RaisePrivateKeysLoaded()
		{
			Raise(BiomeLockAPI.OnPrivateKeysLoaded);
		}

		private static void Raise([<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(new byte[] { 2, 1 })] Action<string> handler, string privateKey)
		{
			if (handler == null)
			{
				return;
			}
			privateKey = BiomeLockKeys.ToPrivateKey(privateKey);
			if (privateKey.Length == 0)
			{
				return;
			}
			Delegate[] invocationList = handler.GetInvocationList();
			foreach (Delegate obj in invocationList)
			{
				try
				{
					((Action<string>)obj)(privateKey);
				}
				catch (Exception ex)
				{
					BiomeLockPlugin.Log.LogError((object)("[BiomeLockAPI] " + ex));
				}
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(2)]
		private static void Raise(Action handler)
		{
			if (handler == null)
			{
				return;
			}
			Delegate[] invocationList = handler.GetInvocationList();
			foreach (Delegate obj in invocationList)
			{
				try
				{
					((Action)obj)();
				}
				catch (Exception ex)
				{
					BiomeLockPlugin.Log.LogError((object)("[BiomeLockAPI] " + ex));
				}
			}
		}
	}
	[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
	[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
	internal static class AssetLoader
	{
		private const string ResourceName = "BiomeLock.assets.rd_biome";

		private static bool _loadAttempted;

		[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)]
		private static AssetBundle _bundle;

		[return: <dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)]
		internal static Sprite GetSprite(string name)
		{
			return Load<Sprite>(name);
		}

		[return: <dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)]
		internal static GameObject GetPrefab(string name)
		{
			return Load<GameObject>(name);
		}

		[return: <dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)]
		private static T Load<[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)] T>(string name) where T : Object
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				return default(T);
			}
			AssetBundle bundle = GetBundle();
			return ((Object)(object)bundle != (Object)null) ? bundle.LoadAsset<T>(name) : default(T);
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(2)]
		private static AssetBundle GetBundle()
		{
			if ((Object)(object)_bundle != (Object)null || _loadAttempted)
			{
				return _bundle;
			}
			_loadAttempted = true;
			try
			{
				using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("BiomeLock.assets.rd_biome");
				if (stream == null)
				{
					BiomeLockPlugin.Log.LogError((object)"[AssetLoader] Embedded resource not found: BiomeLock.assets.rd_biome");
					return null;
				}
				using MemoryStream memoryStream = new MemoryStream();
				stream.CopyTo(memoryStream);
				_bundle = AssetBundle.LoadFromMemory(memoryStream.ToArray());
			}
			catch (Exception ex)
			{
				BiomeLockPlugin.Log.LogError((object)("[AssetLoader] " + ex));
				_bundle = null;
			}
			return _bundle;
		}
	}
	[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
	[BepInPlugin("radamanto.BiomeLock", "BiomeLock", "1.2.1")]
	[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
	public class BiomeLockPlugin : BaseUnityPlugin
	{
		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		private sealed class ConfigurationManagerAttributes
		{
			public bool? Browsable = false;
		}

		internal const string ModGUID = "radamanto.BiomeLock";

		internal const string ModName = "BiomeLock";

		internal const string ModVersion = "1.2.1";

		internal static ManualLogSource Log;

		private Harmony _harmony = null;

		internal static ConfigEntry<bool> CE_SE_AdminBypass;

		internal static ConfigEntry<string> CE_SE_BlockedBiomes;

		internal static ConfigEntry<bool> CE_SE_Block_DungeonTeleport;

		internal static ConfigEntry<bool> CE_SE_Block_MapExplore;

		internal static ConfigEntry<bool> CE_SE_Block_AutoPickup;

		internal static ConfigEntry<bool> CE_SE_Block_Pickup;

		internal static ConfigEntry<bool> CE_SE_Block_ItemDropInteract;

		internal static ConfigEntry<bool> CE_SE_Block_PickableInteract;

		internal static ConfigEntry<bool> CE_SE_Block_AttackBlock;

		internal static ConfigEntry<bool> CE_SE_Block_Hammer;

		internal static ConfigEntry<bool> CE_SE_Block_TerrainHoe;

		internal static ConfigEntry<bool> CE_SE_Block_GenericInteract;

		internal static ConfigEntry<bool> CE_SE_Block_DoorInteract;

		internal static ConfigEntry<bool> CE_SE_Block_ContainerInteract;

		internal static ConfigEntry<bool> CE_SE_Broadcast_Enabled;

		internal static ConfigEntry<float> CE_SE_Broadcast_Interval;

		internal static ConfigEntry<bool> CE_SE_AttackBlock_BlacklistEnabled;

		internal static ConfigEntry<string> CE_SE_AttackBlock_BlacklistPrefabs;

		internal static ConfigEntry<bool> CE_GuardianPower_Enabled;

		internal static ConfigEntry<bool> CE_BossPrevKey_Enabled;

		internal static ConfigEntry<bool> CE_BossDay_Enabled;

		internal static ConfigEntry<int> CE_BossDay_Eikthyr;

		internal static ConfigEntry<int> CE_BossDay_Elder;

		internal static ConfigEntry<int> CE_BossDay_Bonemass;

		internal static ConfigEntry<int> CE_BossDay_Moder;

		internal static ConfigEntry<int> CE_BossDay_Yagluth;

		internal static ConfigEntry<int> CE_BossDay_Queen;

		internal static ConfigEntry<int> CE_BossDay_Fader;

		internal static ConfigEntry<int> CE_BossDay_Kall;

		internal static ConfigEntry<bool> CE_SE_Block_SpawnBlock;

		internal static ConfigEntry<bool> CE_SE_Block_MapPins;

		internal static ConfigEntry<bool> CE_GlobalKeys_PrivateKeys;

		internal static ConfigEntry<bool> CE_SE_Block_TraderInteract;

		internal static ConfigEntry<bool> CE_SE_Block_HildirMapTable;

		internal static ConfigEntry<bool> CE_SkillCap_Enabled;

		internal static ConfigEntry<int> CE_SkillCap_Eikthyr;

		internal static ConfigEntry<int> CE_SkillCap_Elder;

		internal static ConfigEntry<int> CE_SkillCap_Bonemass;

		internal static ConfigEntry<int> CE_SkillCap_Moder;

		internal static ConfigEntry<int> CE_SkillCap_Yagluth;

		internal static ConfigEntry<int> CE_SkillCap_Queen;

		internal static ConfigEntry<int> CE_SkillCap_Fader;

		internal static ConfigEntry<int> CE_SkillCap_Kall;

		internal static ConfigEntry<bool> CE_SE_RestrictedMist;

		internal static ConfigEntry<bool> CE_SE_RestrictedMistSfx;

		internal static ConfigEntry<bool> CE_SE_HealthDrain;

		internal static ConfigEntry<float> CE_SE_HealthDrainPerSecond;

		internal static ConfigEntry<float> CE_SE_HealthDrainMinHealth;

		private const float ConfigReloadQuietSeconds = 0.75f;

		[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)]
		internal static ConfigSync ConfigSync;

		[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)]
		private static ConfigEntry<bool> _serverConfigLocked;

		[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)]
		private FileSystemWatcher _configWatcher;

		private DateTime _lastCfgWriteUtc = DateTime.MinValue;

		private DateTime _ignoreEventsUntilUtc = DateTime.MinValue;

		private bool _reloadScheduled;

		internal static ConfigEntry<bool> CE_BossCooldown_Enabled;

		internal static ConfigEntry<int> CE_BossCooldown_Eikthyr;

		internal static ConfigEntry<int> CE_BossCooldown_Elder;

		internal static ConfigEntry<int> CE_BossCooldown_Bonemass;

		internal static ConfigEntry<int> CE_BossCooldown_Moder;

		internal static ConfigEntry<int> CE_BossCooldown_Yagluth;

		internal static ConfigEntry<int> CE_BossCooldown_Queen;

		internal static ConfigEntry<int> CE_BossCooldown_Fader;

		internal static ConfigEntry<int> CE_BossCooldown_Kall;

		private void Awake()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Localizer.Load();
			bool syncReady = BeginConfigSetup();
			SetupBinds();
			EndConfigSetup(syncReady);
			_harmony = new Harmony("radamanto.BiomeLock");
			_harmony.PatchAll();
		}

		private void OnDestroy()
		{
			BiomeLockBossCooldown.ClearPending();
			BiomeLock_SE.RestoreRestrictedMistSky();
			BiomeLock_SE.RestoreRestrictedYggdrasilFog();
			DisposeConfigWatcher();
		}

		public static bool IsLocalPlayerAdmin()
		{
			return ConfigSync != null && ConfigSync.IsAdmin;
		}

		internal static bool AdminBypassActive()
		{
			return CE_SE_AdminBypass.Value && IsLocalPlayerAdmin();
		}

		private void SetupBinds()
		{
			CE_SE_AdminBypass = Cfg("01 - General", "AdminBypass", defaultValue: true, "If true, administrators bypass restrictions.");
			CE_GlobalKeys_PrivateKeys = Cfg("01 - General", "PrivateKeys", defaultValue: true, "If true, redirects content unlocks based on Global Keys to per-player Private Keys.");
			CE_SE_BlockedBiomes = Cfg("02 - BiomeLock", "02.1 - BlockedBiomes", "BlackForest,Swamp,Mountain,Plains,Mistlands,AshLands,DeepNorth", "The biomes listed here will be blocked for players who have not defeated the previous biome’s boss.\nAllowed values: BlackForest, Swamp, Mountain, Plains, Mistlands, AshLands, DeepNorth, Ocean");
			CE_SE_Block_TraderInteract = Cfg("03 - Traders", "03.01 - TraderInteract", defaultValue: true, "If true, blocks interaction with the traders Haldor and the Bog Witch.");
			CE_SE_Block_HildirMapTable = Cfg("03 - Traders", "03.02 - HildirMapTable", defaultValue: true, "If true, blocks interaction on Hildir's map table.");
			CE_SE_Block_DungeonTeleport = Cfg("04 - SE Blocks", "04.01 - Dungeon", defaultValue: true, "If true, blocks dungeon teleport entrances/exits.");
			CE_SE_Block_MapExplore = Cfg("04 - SE Blocks", "04.02 - MapExplore", defaultValue: true, "If true, blocks map exploration.");
			CE_SE_Block_AutoPickup = Cfg("04 - SE Blocks", "04.03 - AutoPickup", defaultValue: true, "If true, blocks automatic pickup.");
			CE_SE_Block_Pickup = Cfg("04 - SE Blocks", "04.04 - Pickup", defaultValue: true, "If true, blocks manual pickup.");
			CE_SE_Block_GenericInteract = Cfg("04 - SE Blocks", "04.05 - Interact", defaultValue: true, "If true, blocks generic world interactions.");
			CE_SE_Block_DoorInteract = Cfg("04 - SE Blocks", "04.06 - DoorInteract", defaultValue: true, "If true, blocks door interactions.");
			CE_SE_Block_ItemDropInteract = Cfg("04 - SE Blocks", "04.07 - ItemDropInteract", defaultValue: true, "If true, blocks item drop interactions.");
			CE_SE_Block_PickableInteract = Cfg("04 - SE Blocks", "04.08 - PickableInteract", defaultValue: true, "If true, blocks pickable interactions.");
			CE_SE_Block_ContainerInteract = Cfg("04 - SE Blocks", "04.09 - ContainerInteract", defaultValue: true, "If true, blocks container interactions.");
			CE_SE_Block_Hammer = Cfg("04 - SE Blocks", "04.10 - Hammer", defaultValue: true, "If true, blocks hammer actions.");
			CE_SE_Block_TerrainHoe = Cfg("04 - SE Blocks", "04.11 - Hoe/Cultivator", defaultValue: true, "If true, blocks terrain modification by hoe/cultivator.");
			CE_SE_Block_MapPins = Cfg("04 - SE Blocks", "04.12 - MapPins", defaultValue: true, "If true, blocks placing pins on the map.");
			CE_SE_Block_SpawnBlock = Cfg("04 - SE Blocks", "04.13 - MobSpawn", defaultValue: true, "If true, blocks mob spawning.");
			CE_SE_Block_AttackBlock = Cfg("04 - SE Blocks", "04.14 - AttackBlock", defaultValue: true, "If true, blocks attacks with weapons, tools, bows, and shields. If BlacklistEnabled is true, only the prefabs listed in BlacklistPrefabs are blocked.");
			CE_SE_AttackBlock_BlacklistEnabled = Cfg("04 - SE Blocks", "04.14.1 - BlacklistEnabled", defaultValue: false, "If true, attacks are blocked only when using the prefabs listed in BlacklistPrefabs. If false, all attacks are blocked.");
			CE_SE_AttackBlock_BlacklistPrefabs = Cfg("04 - SE Blocks", "04.14.2 - BlacklistPrefabs", "", "Comma-separated prefab names whose attacks are blocked when BlacklistEnabled is true.");
			CE_SE_RestrictedMist = Cfg("04 - SE Blocks", "04.15 - RestrictedMist", defaultValue: true, "If true, enables the local fog effect.");
			CE_SE_RestrictedMistSfx = Cfg("04 - SE Blocks", "04.16 - RestrictedMistSound", defaultValue: true, "If true, enables the local fog ambience sound.");
			CE_SE_HealthDrain = Cfg("04 - SE Blocks", "04.17 - HealthDrain", defaultValue: true, "If true, drains player health.");
			CE_SE_HealthDrainPerSecond = Cfg("04 - SE Blocks", "04.17.1 - HealthDrainPerSecond", 2f, "Health drained per second.");
			CE_SE_HealthDrainMinHealth = Cfg("04 - SE Blocks", "04.17.2 - HealthDrainMinHealth", 1f, "Minimum health left after health drain. Use 0 to allow death.");
			CE_SE_Broadcast_Enabled = Cfg("05 - SE Broadcast", "05.01 - Enable", defaultValue: true, "Displays messages in the center of the screen while the SE_BiomeLock is active.");
			CE_SE_Broadcast_Interval = Cfg("05 - SE Broadcast", "05.02 - IntervalSeconds", 8f, "Interval (in seconds) between BiomeLock broadcast messages.");
			CE_GuardianPower_Enabled = Cfg("06 - Guardian Power", "06.01 - Enable", defaultValue: true, "If true, blocks claiming guardian powers at the altar until the player has the required private key.");
			CE_BossPrevKey_Enabled = Cfg("07 - Boss Summon Key", "07.01 - Enable", defaultValue: true, "If true, blocks boss altar interaction until the player has defeated the previous boss.");
			CE_BossDay_Enabled = Cfg("08 - Boss Summon Day", "08.01 - Enable", defaultValue: true, "If true, blocks boss altar interaction until the configured day.");
			CE_BossDay_Eikthyr = Cfg("08 - Boss Summon Day", "08.02 - Eikthyr", 100, "Minimum day required to summon Eikthyr. (0 = disabled)");
			CE_BossDay_Elder = Cfg("08 - Boss Summon Day", "08.03 - Elder", 200, "Minimum day required to summon Elder. (0 = disabled)");
			CE_BossDay_Bonemass = Cfg("08 - Boss Summon Day", "08.04 - Bonemass", 300, "Minimum day required to summon Bonemass. (0 = disabled)");
			CE_BossDay_Moder = Cfg("08 - Boss Summon Day", "08.05 - Moder", 400, "Minimum day required to summon Moder. (0 = disabled)");
			CE_BossDay_Yagluth = Cfg("08 - Boss Summon Day", "08.06 - Yagluth", 500, "Minimum day required to summon Yagluth. (0 = disabled)");
			CE_BossDay_Queen = Cfg("08 - Boss Summon Day", "08.07 - Queen", 600, "Minimum day required to summon The Queen. (0 = disabled)");
			CE_BossDay_Fader = Cfg("08 - Boss Summon Day", "08.08 - Fader", 700, "Minimum day required to summon Fader. (0 = disabled)");
			CE_BossDay_Kall = Cfg("08 - Boss Summon Day", "08.09 - Kall", 800, "Minimum day required to summon Kall Fimbulbringer. (0 = disabled)");
			CE_SkillCap_Enabled = Cfg("09 - Skill Cap", "09.01 - Enable", defaultValue: true, "If true, caps skill (all skills) levels by boss private keys.");
			CE_SkillCap_Eikthyr = Cfg("09 - Skill Cap", "09.02 - Eikthyr", 0, "Maximum skill level (all skills) allowed while the player does NOT have Eikthyr private key. (0 = disabled)");
			CE_SkillCap_Elder = Cfg("09 - Skill Cap", "09.03 - Elder", 0, "Maximum skill level (all skills) allowed while the player does NOT have Elder private key. (0 = disabled)");
			CE_SkillCap_Bonemass = Cfg("09 - Skill Cap", "09.04 - Bonemass", 0, "Maximum skill level (all skills) allowed while the player does NOT have Bonemass private key. (0 = disabled)");
			CE_SkillCap_Moder = Cfg("09 - Skill Cap", "09.05 - Moder", 0, "Maximum skill level (all skills) allowed while the player does NOT have Moder private key. (0 = disabled)");
			CE_SkillCap_Yagluth = Cfg("09 - Skill Cap", "09.06 - Yagluth", 0, "Maximum skill level (all skills) allowed while the player does NOT have Yagluth private key. (0 = disabled)");
			CE_SkillCap_Queen = Cfg("09 - Skill Cap", "09.07 - Queen", 0, "Maximum skill level (all skills) allowed while the player does NOT have The Queen private key. (0 = disabled)");
			CE_SkillCap_Fader = Cfg("09 - Skill Cap", "09.08 - Fader", 0, "Maximum skill level (all skills) allowed while the player does NOT have Fader private key. Example: (0 = disabled)");
			CE_SkillCap_Kall = Cfg("09 - Skill Cap", "09.09 - Kall", 0, "Maximum skill level (all skills) allowed while the player does NOT have Kall Fimbulbringer final defeat private key. (0 = disabled)");
			SetupBossCooldownBinds();
		}

		private bool BeginConfigSetup()
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Expected O, but got Unknown
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			try
			{
				ConfigSync = new ConfigSync(((BaseUnityPlugin)this).Info.Metadata.GUID)
				{
					DisplayName = ((BaseUnityPlugin)this).Info.Metadata.Name,
					CurrentVersion = ((BaseUnityPlugin)this).Info.Metadata.Version.ToString(),
					MinimumRequiredVersion = ((BaseUnityPlugin)this).Info.Metadata.Version.ToString(),
					ModRequired = true
				};
				_serverConfigLocked = ((BaseUnityPlugin)this).Config.Bind<bool>("01 - General", "LockConfiguration", true, new ConfigDescription("If true, the server locks synchronized configs.", (AcceptableValueBase)null, new object[1]
				{
					new ConfigurationManagerAttributes
					{
						Browsable = false
					}
				}));
				ConfigSync.AddLockingConfigEntry<bool>(_serverConfigLocked);
				return true;
			}
			catch (Exception ex)
			{
				Log.LogError((object)("[ConfigSync] " + ex));
				return false;
			}
		}

		private void EndConfigSetup(bool syncReady)
		{
			if (syncReady)
			{
				((BaseUnityPlugin)this).Config.Save();
			}
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = true;
			if (syncReady)
			{
				SetupConfigWatcher();
			}
		}

		protected ConfigEntry<T> Cfg<[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)] T>(string section, string key, T defaultValue, string description, bool synced = true)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			ConfigDescription val = new ConfigDescription(description + (synced ? " [Synced with Server]" : " [Not Synced with Server]"), (AcceptableValueBase)null, Array.Empty<object>());
			ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(section, key, defaultValue, val);
			SyncedConfigEntry<T> syncedConfigEntry = ConfigSync?.AddConfigEntry<T>(val2);
			if (syncedConfigEntry != null)
			{
				syncedConfigEntry.SynchronizedConfig = synced;
			}
			return val2;
		}

		private void SetupConfigWatcher()
		{
			DisposeConfigWatcher();
			try
			{
				_configWatcher = new FileSystemWatcher(Paths.ConfigPath, Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath))
				{
					IncludeSubdirectories = false,
					NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime),
					SynchronizingObject = ThreadingHelper.SynchronizingObject
				};
				_configWatcher.Changed += OnConfigFileChanged;
				_configWatcher.Created += OnConfigFileChanged;
				_configWatcher.Renamed += OnConfigFileChanged;
				_configWatcher.EnableRaisingEvents = true;
			}
			catch (Exception ex)
			{
				Log.LogError((object)("[ConfigWatcher] " + ex));
				_configWatcher = null;
			}
		}

		private void DisposeConfigWatcher()
		{
			if (_configWatcher != null)
			{
				_configWatcher.EnableRaisingEvents = false;
				_configWatcher.Dispose();
				_configWatcher = null;
			}
			_reloadScheduled = false;
		}

		private void OnConfigFileChanged(object sender, FileSystemEventArgs e)
		{
			if (!(DateTime.UtcNow < _ignoreEventsUntilUtc))
			{
				_lastCfgWriteUtc = DateTime.UtcNow;
				if (!_reloadScheduled)
				{
					_reloadScheduled = true;
					((MonoBehaviour)this).StartCoroutine(ReloadConfigAfterQuietPeriod());
				}
			}
		}

		private IEnumerator ReloadConfigAfterQuietPeriod()
		{
			while ((DateTime.UtcNow - _lastCfgWriteUtc).TotalSeconds < 0.75)
			{
				yield return null;
			}
			_reloadScheduled = false;
			FileSystemWatcher watcher = _configWatcher;
			if (watcher == null || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
			{
				yield break;
			}
			watcher.EnableRaisingEvents = false;
			try
			{
				((BaseUnityPlugin)this).Config.Reload();
				_ignoreEventsUntilUtc = DateTime.UtcNow.AddSeconds(1.0);
			}
			catch (Exception ex)
			{
				Log.LogError((object)("[ConfigReload] " + ex));
			}
			finally
			{
				if (_configWatcher == watcher)
				{
					watcher.EnableRaisingEvents = true;
				}
			}
		}

		private void SetupBossCooldownBinds()
		{
			CE_BossCooldown_Enabled = Cfg("10 - Boss Summon Cooldown", "10.01 - Enable", defaultValue: false, "If true, enables individual boss summon cooldowns. Existing day/key restrictions and AdminBypass still apply.");
			CE_BossCooldown_Eikthyr = Cfg("10 - Boss Summon Cooldown", "10.02 - Eikthyr", 1, "Full in-game days between this boss's confirmed summons by the same player in the same world. (0 = disabled)");
			CE_BossCooldown_Elder = Cfg("10 - Boss Summon Cooldown", "10.03 - Elder", 1, "Full in-game days between this boss's confirmed summons by the same player in the same world. (0 = disabled)");
			CE_BossCooldown_Bonemass = Cfg("10 - Boss Summon Cooldown", "10.04 - Bonemass", 1, "Full in-game days between this boss's confirmed summons by the same player in the same world. (0 = disabled)");
			CE_BossCooldown_Moder = Cfg("10 - Boss Summon Cooldown", "10.05 - Moder", 1, "Full in-game days between this boss's confirmed summons by the same player in the same world. (0 = disabled)");
			CE_BossCooldown_Yagluth = Cfg("10 - Boss Summon Cooldown", "10.06 - Yagluth", 1, "Full in-game days between this boss's confirmed summons by the same player in the same world. (0 = disabled)");
			CE_BossCooldown_Queen = Cfg("10 - Boss Summon Cooldown", "10.07 - Queen", 1, "Full in-game days between this boss's confirmed summons by the same player in the same world. (0 = disabled)");
			CE_BossCooldown_Fader = Cfg("10 - Boss Summon Cooldown", "10.08 - Fader", 1, "Full in-game days between this boss's confirmed summons by the same player in the same world. (0 = disabled)");
			CE_BossCooldown_Kall = Cfg("10 - Boss Summon Cooldown", "10.09 - Kall", 1, "Full in-game days between this boss's confirmed summons by the same player in the same world. (0 = disabled)");
		}
	}
	internal static class BiomeLock_GuardianPowerKey
	{
		[HarmonyPatch(typeof(ItemStand), "Interact")]
		private static class Patch_ItemStand_Interact
		{
			[HarmonyPriority(100)]
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(ItemStand __instance, Humanoid user, bool hold, bool alt, ref bool __result)
			{
				if ((Object)(object)user != (Object)(object)Player.m_localPlayer)
				{
					return true;
				}
				if (!ShouldBlock(__instance))
				{
					return true;
				}
				if (!IsPowerActivationInteract(__instance, hold, alt))
				{
					return true;
				}
				BiomeLock_SE.ShowMessage(Player.m_localPlayer, "$biomelock_guardian_power_locked");
				__result = false;
				return false;
			}
		}

		[HarmonyPatch(typeof(ItemStand), "DelayedPowerActivation")]
		private static class Patch_ItemStand_DelayedPowerActivation
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			[HarmonyPriority(100)]
			private static bool Prefix(ItemStand __instance)
			{
				if (!ShouldBlock(__instance))
				{
					return true;
				}
				BiomeLock_SE.ShowMessage(Player.m_localPlayer, "$biomelock_guardian_power_locked");
				return false;
			}
		}

		[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(1)]
		private const string BlockedToken = "$biomelock_guardian_power_locked";

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
		internal static bool ShouldBlock(ItemStand stand)
		{
			if (!BiomeLockPlugin.CE_GuardianPower_Enabled.Value)
			{
				return false;
			}
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return false;
			}
			if ((Object)(object)stand == (Object)null || (Object)(object)stand.m_guardianPower == (Object)null)
			{
				return false;
			}
			if (BiomeLockPlugin.AdminBypassActive())
			{
				return false;
			}
			BossInfo bossInfo = BiomeLockBosses.FromGuardianPower(stand.m_guardianPower);
			return bossInfo != null && BiomeLockKeys.MissingProgressionKey(bossInfo.SkillCapKey);
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
		private static bool IsPowerActivationInteract(ItemStand stand, bool hold, bool alt)
		{
			if (hold || !stand.HaveAttachment())
			{
				return false;
			}
			return !alt || !Object.op_Implicit((Object)(object)stand.m_visualItemDrop) || stand.m_orientationSettings.Count <= 1;
		}
	}
	[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
	[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
	internal sealed class BossInfo
	{
		internal readonly string Prefab;

		internal readonly string SkillCapKey;

		internal readonly string PreviousKey;

		internal readonly string GuardianPower;

		private readonly Func<ConfigEntry<int>> _summonDay;

		private readonly Func<ConfigEntry<int>> _skillCap;

		private readonly Func<ConfigEntry<int>> _cooldownDays;

		internal int SummonDay => _summonDay().Value;

		internal int SkillCap => _skillCap().Value;

		internal int CooldownDays => _cooldownDays().Value;

		internal BossInfo(string prefab, string skillCapKey, string previousKey, string guardianPower, Func<ConfigEntry<int>> summonDay, Func<ConfigEntry<int>> skillCap, Func<ConfigEntry<int>> cooldownDays)
		{
			Prefab = prefab;
			SkillCapKey = skillCapKey;
			PreviousKey = previousKey;
			GuardianPower = guardianPower;
			_summonDay = summonDay;
			_skillCap = skillCap;
			_cooldownDays = cooldownDays;
		}
	}
	[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
	[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
	internal static class BiomeLockBosses
	{
		internal static readonly BossInfo[] All = new BossInfo[8]
		{
			new BossInfo("Eikthyr", "defeated_eikthyr", "", "GP_Eikthyr", () => BiomeLockPlugin.CE_BossDay_Eikthyr, () => BiomeLockPlugin.CE_SkillCap_Eikthyr, () => BiomeLockPlugin.CE_BossCooldown_Eikthyr),
			new BossInfo("gd_king", "defeated_gdking", "defeated_eikthyr", "GP_TheElder", () => BiomeLockPlugin.CE_BossDay_Elder, () => BiomeLockPlugin.CE_SkillCap_Elder, () => BiomeLockPlugin.CE_BossCooldown_Elder),
			new BossInfo("Bonemass", "defeated_bonemass", "defeated_gdking", "GP_Bonemass", () => BiomeLockPlugin.CE_BossDay_Bonemass, () => BiomeLockPlugin.CE_SkillCap_Bonemass, () => BiomeLockPlugin.CE_BossCooldown_Bonemass),
			new BossInfo("Dragon", "defeated_dragon", "defeated_bonemass", "GP_Moder", () => BiomeLockPlugin.CE_BossDay_Moder, () => BiomeLockPlugin.CE_SkillCap_Moder, () => BiomeLockPlugin.CE_BossCooldown_Moder),
			new BossInfo("GoblinKing", "defeated_goblinking", "defeated_dragon", "GP_Yagluth", () => BiomeLockPlugin.CE_BossDay_Yagluth, () => BiomeLockPlugin.CE_SkillCap_Yagluth, () => BiomeLockPlugin.CE_BossCooldown_Yagluth),
			new BossInfo("SeekerQueen", "defeated_queen", "defeated_goblinking", "GP_Queen", () => BiomeLockPlugin.CE_BossDay_Queen, () => BiomeLockPlugin.CE_SkillCap_Queen, () => BiomeLockPlugin.CE_BossCooldown_Queen),
			new BossInfo("Fader", "defeated_fader", "defeated_queen", "GP_Ashlands|GP_Fader", () => BiomeLockPlugin.CE_BossDay_Fader, () => BiomeLockPlugin.CE_SkillCap_Fader, () => BiomeLockPlugin.CE_BossCooldown_Fader),
			new BossInfo("FrozenKing", "defeated_frozenking_p3", "defeated_fader", "GP_DeepNorth", () => BiomeLockPlugin.CE_BossDay_Kall, () => BiomeLockPlugin.CE_SkillCap_Kall, () => BiomeLockPlugin.CE_BossCooldown_Kall)
		};

		private static readonly char[] AliasSeparator = new char[1] { '|' };

		private static readonly Dictionary<string, BossInfo> ByPrefab = BuildIndex((BossInfo b) => b.Prefab);

		private static readonly Dictionary<string, BossInfo> ByGuardianPower = BuildIndex((BossInfo b) => b.GuardianPower);

		private static Dictionary<string, BossInfo> BuildIndex(Func<BossInfo, string> key)
		{
			Dictionary<string, BossInfo> dictionary = new Dictionary<string, BossInfo>(StringComparer.OrdinalIgnoreCase);
			BossInfo[] all = All;
			foreach (BossInfo bossInfo in all)
			{
				string[] array = key(bossInfo).Split(AliasSeparator, StringSplitOptions.RemoveEmptyEntries);
				foreach (string key2 in array)
				{
					dictionary[key2] = bossInfo;
				}
			}
			return dictionary;
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(2)]
		private static BossInfo Find([<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(1)] Dictionary<string, BossInfo> index, string name)
		{
			if (name == null)
			{
				return null;
			}
			string text = Utils.GetPrefabName(name).Trim();
			if (text.Length == 0)
			{
				return null;
			}
			index.TryGetValue(text, out var value);
			return value;
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(2)]
		internal static BossInfo FromPrefab(GameObject prefab)
		{
			return ((Object)(object)prefab == (Object)null) ? null : Find(ByPrefab, ((Object)prefab).name);
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(2)]
		internal static BossInfo FromGuardianPower(StatusEffect guardianPower)
		{
			return ((Object)(object)guardianPower == (Object)null) ? null : Find(ByGuardianPower, ((Object)guardianPower).name);
		}
	}
	internal static class BiomeLock_SkillCapBoss
	{
		internal static int GetEffectiveSkillCap()
		{
			int num = 0;
			BossInfo[] all = BiomeLockBosses.All;
			foreach (BossInfo bossInfo in all)
			{
				int skillCap = bossInfo.SkillCap;
				if (skillCap > 0 && (num <= 0 || skillCap < num) && BiomeLockKeys.MissingProgressionKey(bossInfo.SkillCapKey))
				{
					num = ((num <= 0) ? skillCap : Mathf.Min(num, skillCap));
				}
			}
			return num;
		}
	}
	[HarmonyPatch(typeof(Skills), "RaiseSkill")]
	internal static class BiomeLock_SkillCapBoss_RaiseSkill_Patch
	{
		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
		private static void Prefix(Skills __instance, SkillType skillType, ref float factor)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Invalid comparison between Unknown and I4
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if (!BiomeLockPlugin.CE_SkillCap_Enabled.Value || (int)skillType == 0 || (int)skillType == 999 || factor <= 0f)
			{
				return;
			}
			int effectiveSkillCap = BiomeLock_SkillCapBoss.GetEffectiveSkillCap();
			if (effectiveSkillCap > 0)
			{
				Skill skill = __instance.GetSkill(skillType);
				if (skill != null && skill.m_level >= (float)effectiveSkillCap)
				{
					factor = 0f;
				}
			}
		}
	}
	[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
	[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
	internal static class BiomeLock_BossSummon
	{
		[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
		[HarmonyPatch(typeof(OfferingBowl), "InitiateSpawnBoss")]
		private static class Patch_OfferingBowl_InitiateSpawnBoss
		{
			[HarmonyPriority(200)]
			private static bool Prefix(OfferingBowl __instance, out bool __state)
			{
				__state = false;
				BossInfo restrictedBoss = GetRestrictedBoss(__instance);
				if (restrictedBoss == null)
				{
					return true;
				}
				Player localPlayer = Player.m_localPlayer;
				if (ShouldBlockByDay(restrictedBoss, out var requiredDay, out var currentDay))
				{
					((Character)localPlayer).Message((MessageType)2, BiomeLock_SE.ColorBlocked(string.Format(Localization.instance.Localize("$biomelock_boss_day_locked"), requiredDay, currentDay)), 0, (Sprite)null, false);
					return false;
				}
				if (ShouldBlockByPreviousKey(restrictedBoss))
				{
					BiomeLock_SE.ShowMessage(localPlayer, "$biomelock_boss_prev_key_locked");
					return false;
				}
				return BiomeLockBossCooldown.TryBegin(__instance, restrictedBoss, localPlayer, out __state);
			}

			private static void Postfix(OfferingBowl __instance, bool __state, bool __runOriginal)
			{
				if (__state && !__runOriginal)
				{
					BiomeLockBossCooldown.Cancel(__instance);
				}
			}

			private static void Finalizer(OfferingBowl __instance, bool __state, [<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)] Exception __exception)
			{
				if (__state && __exception != null)
				{
					BiomeLockBossCooldown.Cancel(__instance);
				}
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(OfferingBowl), "RPC_BossSpawnInitiated")]
		private static class Patch_OfferingBowl_BossSpawnInitiated
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static void Postfix(OfferingBowl __instance)
			{
				BiomeLockBossCooldown.Confirm(__instance);
			}
		}

		private const string DayLockedToken = "$biomelock_boss_day_locked";

		private const string PreviousKeyLockedToken = "$biomelock_boss_prev_key_locked";

		[return: <dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)]
		private static BossInfo GetRestrictedBoss(OfferingBowl bowl)
		{
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return null;
			}
			if (BiomeLockPlugin.AdminBypassActive())
			{
				return null;
			}
			if ((Object)(object)bowl == (Object)null)
			{
				return null;
			}
			return BiomeLockBosses.FromPrefab(bowl.m_bossPrefab);
		}

		internal static bool ShouldBlockByDay(BossInfo boss, out int requiredDay, out int currentDay)
		{
			requiredDay = 0;
			currentDay = 0;
			if (!BiomeLockPlugin.CE_BossDay_Enabled.Value)
			{
				return false;
			}
			requiredDay = boss.SummonDay;
			if (requiredDay <= 0)
			{
				return false;
			}
			currentDay = (((Object)(object)EnvMan.instance != (Object)null) ? EnvMan.instance.GetDay() : 0);
			return currentDay < requiredDay;
		}

		internal static bool ShouldBlockByPreviousKey(BossInfo boss)
		{
			if (!BiomeLockPlugin.CE_BossPrevKey_Enabled.Value)
			{
				return false;
			}
			if (boss.PreviousKey.Length == 0)
			{
				return false;
			}
			return BiomeLockKeys.MissingProgressionKey(boss.PreviousKey);
		}
	}
	[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
	[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
	internal static class BiomeLockBossCooldown
	{
		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		private sealed class PendingSummon
		{
			[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(1)]
			internal OfferingBowl Bowl = null;

			internal float Expires;
		}

		private const string SavePrefix = "BL_BossSummon_";

		private const float RequestTimeoutSeconds = 10f;

		private static readonly Dictionary<string, PendingSummon> Pending = new Dictionary<string, PendingSummon>();

		[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)]
		private static Player _player;

		private static long _world;

		private static bool TryGetClock(Player player, out double now, out double dayLength)
		{
			now = (dayLength = 0.0);
			if ((Object)(object)player != (Object)(object)Player.m_localPlayer || (Object)(object)ZNet.instance == (Object)null || ZNet.World == null || (Object)(object)EnvMan.instance == (Object)null)
			{
				return false;
			}
			long uid = ZNet.World.m_uid;
			if ((Object)(object)_player != (Object)(object)player || _world != uid)
			{
				ClearPending();
				_player = player;
				_world = uid;
			}
			now = ZNet.instance.GetTimeSeconds();
			dayLength = EnvMan.instance.m_dayLengthSec;
			return IsValidTime(now) && dayLength > 0.0;
		}

		private static bool IsValidTime(double time)
		{
			return time >= 0.0 && !double.IsNaN(time) && !double.IsInfinity(time);
		}

		private static string FormatRemaining(double days)
		{
			int num = Math.Max(1, (int)Math.Ceiling(days * 1440.0));
			int num2 = num / 1440;
			int num3 = num % 1440 / 60;
			int num4 = num % 60;
			if (num2 > 0)
			{
				return (num3 > 0) ? (num2 + "d " + num3 + "h") : (num2 + "d");
			}
			return (num3 <= 0) ? (num4 + "min") : ((num4 > 0) ? (num3 + "h " + num4 + "min") : (num3 + "h"));
		}

		private static string SaveKey(BossInfo boss)
		{
			return "BL_BossSummon_" + _world.ToString(CultureInfo.InvariantCulture) + "_" + boss.Prefab;
		}

		internal static bool TryBegin(OfferingBowl bowl, BossInfo boss, Player player, out bool reserved)
		{
			reserved = false;
			if (!BiomeLockPlugin.CE_BossCooldown_Enabled.Value || boss.CooldownDays <= 0 || !TryGetClock(player, out var now, out var dayLength))
			{
				return true;
			}
			string key = SaveKey(boss);
			if (player.m_customData != null && player.m_customData.TryGetValue(key, out var value) && double.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result) && IsValidTime(result))
			{
				double num = Math.Min((result + (double)boss.CooldownDays * dayLength - now) / dayLength, boss.CooldownDays);
				if (num > 0.0)
				{
					string text = string.Format(Localization.instance.Localize("$biomelock_boss_cooldown_locked"), FormatRemaining(num));
					((Character)player).Message((MessageType)2, BiomeLock_SE.ColorBlocked(text), 0, (Sprite)null, false);
					return false;
				}
			}
			if (Pending.TryGetValue(key, out var value2) && value2.Expires > Time.realtimeSinceStartup)
			{
				BiomeLock_SE.ShowMessage(player, "$biomelock_boss_summon_pending");
				return false;
			}
			Pending[key] = new PendingSummon
			{
				Bowl = bowl,
				Expires = Time.realtimeSinceStartup + 10f
			};
			reserved = true;
			return true;
		}

		internal static void Confirm(OfferingBowl bowl)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)bowl.m_interactUser != (Object)(object)localPlayer)
			{
				return;
			}
			BossInfo bossInfo = BiomeLockBosses.FromPrefab(bowl.m_bossPrefab);
			if (bossInfo == null || !TryGetClock(localPlayer, out var now, out var _))
			{
				return;
			}
			string key = SaveKey(bossInfo);
			if (!Pending.TryGetValue(key, out var value) || (Object)(object)value.Bowl != (Object)(object)bowl)
			{
				return;
			}
			Pending.Remove(key);
			if (BiomeLockPlugin.CE_BossCooldown_Enabled.Value && bossInfo.CooldownDays > 0 && !BiomeLockPlugin.AdminBypassActive())
			{
				Player val = localPlayer;
				if (val.m_customData == null)
				{
					val.m_customData = new Dictionary<string, string>();
				}
				localPlayer.m_customData[key] = now.ToString("R", CultureInfo.InvariantCulture);
			}
		}

		internal static void Cancel(OfferingBowl bowl)
		{
			BossInfo bossInfo = BiomeLockBosses.FromPrefab(bowl.m_bossPrefab);
			if (bossInfo != null)
			{
				string key = SaveKey(bossInfo);
				if (Pending.TryGetValue(key, out var value) && (Object)(object)value.Bowl == (Object)(object)bowl)
				{
					Pending.Remove(key);
				}
			}
		}

		internal static void ClearPending()
		{
			Pending.Clear();
			_player = null;
			_world = 0L;
		}
	}
	[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
	[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
	internal static class BiomeLockCommands
	{
		[HarmonyPatch(typeof(Terminal), "InitTerminal")]
		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		private static class Terminal_InitTerminal_RegisterCommands
		{
			private static void Postfix()
			{
				Register();
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
			public static ConsoleEvent <0>__ListKeys;

			[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
			public static ConsoleOptionsFetcher <1>__PlayerNames;

			[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
			public static ConsoleEvent <2>__AddKey;

			[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
			public static ConsoleEvent <3>__RemoveKey;

			[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
			public static ConsoleEvent <4>__ResetKeys;
		}

		private static void Register()
		{
			//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_0026: Expected O, but got Unknown
			//IL_004a: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Expected O, but got Unknown
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Expected O, but got Unknown
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: 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_00e5: Expected O, but got Unknown
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Expected O, but got Unknown
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Expected O, but got Unknown
			object obj = <>O.<0>__ListKeys;
			if (obj == null)
			{
				ConsoleEvent val = ListKeys;
				<>O.<0>__ListKeys = val;
				obj = (object)val;
			}
			object obj2 = <>O.<1>__PlayerNames;
			if (obj2 == null)
			{
				ConsoleOptionsFetcher val2 = PlayerNames;
				<>O.<1>__PlayerNames = val2;
				obj2 = (object)val2;
			}
			new ConsoleCommand("bl_listkeys", "[player] - BiomeLock: lists the private keys of a player (admin).", (ConsoleEvent)obj, false, true, false, false, false, false, (ConsoleOptionsFetcher)obj2, false, false, false);
			object obj3 = <>O.<2>__AddKey;
			if (obj3 == null)
			{
				ConsoleEvent val3 = AddKey;
				<>O.<2>__AddKey = val3;
				obj3 = (object)val3;
			}
			object obj4 = <>O.<1>__PlayerNames;
			if (obj4 == null)
			{
				ConsoleOptionsFetcher val4 = PlayerNames;
				<>O.<1>__PlayerNames = val4;
				obj4 = (object)val4;
			}
			new ConsoleCommand("bl_addkey", "<player> <key> - BiomeLock: grants a private key to a player (admin).", (ConsoleEvent)obj3, false, true, false, false, false, false, (ConsoleOptionsFetcher)obj4, false, false, false);
			object obj5 = <>O.<3>__RemoveKey;
			if (obj5 == null)
			{
				ConsoleEvent val5 = RemoveKey;
				<>O.<3>__RemoveKey = val5;
				obj5 = (object)val5;
			}
			object obj6 = <>O.<1>__PlayerNames;
			if (obj6 == null)
			{
				ConsoleOptionsFetcher val6 = PlayerNames;
				<>O.<1>__PlayerNames = val6;
				obj6 = (object)val6;
			}
			new ConsoleCommand("bl_removekey", "<player> <key> - BiomeLock: removes a private key from a player (admin).", (ConsoleEvent)obj5, false, true, false, false, false, false, (ConsoleOptionsFetcher)obj6, false, false, false);
			object obj7 = <>O.<4>__ResetKeys;
			if (obj7 == null)
			{
				ConsoleEvent val7 = ResetKeys;
				<>O.<4>__ResetKeys = val7;
				obj7 = (object)val7;
			}
			object obj8 = <>O.<1>__PlayerNames;
			if (obj8 == null)
			{
				ConsoleOptionsFetcher val8 = PlayerNames;
				<>O.<1>__PlayerNames = val8;
				obj8 = (object)val8;
			}
			new ConsoleCommand("bl_resetkeys", "<player> - BiomeLock: removes all private keys from a player (admin).", (ConsoleEvent)obj7, false, true, false, false, false, false, (ConsoleOptionsFetcher)obj8, false, false, false);
		}

		private static List<string> PlayerNames()
		{
			//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_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return list;
			}
			foreach (PlayerInfo player in ZNet.instance.GetPlayerList())
			{
				if (!string.IsNullOrEmpty(player.m_name))
				{
					list.Add(player.m_name);
				}
			}
			return list;
		}

		private static void ListKeys(ConsoleEventArgs args)
		{
			if (CanRun(args))
			{
				long uid = 0L;
				string text = JoinArgs(args, 1, args.Length);
				if (text.Length <= 0 || TryResolvePlayer(args, text, out uid))
				{
					ZRoutedRpc.instance.InvokeRoutedRPC("BL_ServerListKeys", new object[1] { uid });
				}
			}
		}

		private static void AddKey(ConsoleEventArgs args)
		{
			if (TryParsePlayerAndKey(args, "bl_addkey <player> <key>", out var playerName, out var uid, out var privateKey))
			{
				if (uid == ZNet.GetUID())
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(uid, "BL_SetPrivateKey", new object[1] { privateKey });
				}
				else
				{
					ZRoutedRpc.instance.InvokeRoutedRPC("BL_ServerSetPrivateKey", new object[2] { privateKey, uid });
				}
				args.Context.AddString("[BL] Added " + privateKey + " to " + playerName + ".");
			}
		}

		private static void RemoveKey(ConsoleEventArgs args)
		{
			if (TryParsePlayerAndKey(args, "bl_removekey <player> <key>", out var playerName, out var uid, out var privateKey))
			{
				if (uid == ZNet.GetUID())
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(uid, "BL_RemovePrivateKey", new object[1] { privateKey });
				}
				else
				{
					ZRoutedRpc.instance.InvokeRoutedRPC("BL_ServerRemovePrivateKey", new object[2] { privateKey, uid });
				}
				args.Context.AddString("[BL] Removed " + privateKey + " from " + playerName + ".");
			}
		}

		private static void ResetKeys(ConsoleEventArgs args)
		{
			if (!CanRun(args))
			{
				return;
			}
			string text = JoinArgs(args, 1, args.Length);
			long uid;
			if (text.Length == 0)
			{
				args.Context.AddString("[BL] Usage: bl_resetkeys <player>");
			}
			else if (TryResolvePlayer(args, text, out uid))
			{
				if (uid == ZNet.GetUID())
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(uid, "BL_ResetPrivateKeys", Array.Empty<object>());
				}
				else
				{
					ZRoutedRpc.instance.InvokeRoutedRPC("BL_ServerResetPrivateKeys", new object[1] { uid });
				}
				args.Context.AddString("[BL] Reset all private keys of " + text + ".");
			}
		}

		private static bool CanRun(ConsoleEventArgs args)
		{
			if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null || !BiomeLockKeys.IsInMainScene())
			{
				args.Context.AddString("[BL] Only available in game.");
				return false;
			}
			if (!BiomeLockPlugin.IsLocalPlayerAdmin())
			{
				args.Context.AddString("[BL] Admin only.");
				return false;
			}
			return true;
		}

		private static bool TryParsePlayerAndKey(ConsoleEventArgs args, string usage, out string playerName, out long uid, out string privateKey)
		{
			playerName = string.Empty;
			uid = 0L;
			privateKey = string.Empty;
			if (!CanRun(args))
			{
				return false;
			}
			if (args.Length < 3)
			{
				args.Context.AddString("[BL] Usage: " + usage);
				return false;
			}
			privateKey = BiomeLockKeys.ToPrivateKey(args[args.Length - 1]);
			if (privateKey.Length == 0)
			{
				args.Context.AddString("[BL] Invalid key.");
				return false;
			}
			playerName = JoinArgs(args, 1, args.Length - 1);
			return TryResolvePlayer(args, playerName, out uid);
		}

		private static bool TryResolvePlayer(ConsoleEventArgs args, string playerName, out long uid)
		{
			if (BiomeLockPrivateKeys.TryResolveUidByPlayerName(playerName, out uid))
			{
				return true;
			}
			args.Context.AddString("[BL] Player not found: " + playerName);
			return false;
		}

		private static string JoinArgs(ConsoleEventArgs args, int start, int end)
		{
			if (start >= end)
			{
				return string.Empty;
			}
			return string.Join(" ", args.Args, start, end - start).Trim();
		}
	}
	[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
	[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
	internal static class BiomeLockKeys
	{
		internal const string PrivatePrefix = "bl_";

		internal static readonly HashSet<string> TrackedGlobalKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
		{
			"defeated_eikthyr", "defeated_gdking", "defeated_bonemass", "defeated_dragon", "defeated_goblinking", "defeated_queen", "defeated_fader", "defeated_frozenking", "defeated_frozenking_p3", "defeated_writhan",
			"defeated_hive", "defeated_serpent", "killedtroll", "killed_surtling", "killed_frysling", "killedbat", "hildir1", "hildir2", "hildir3"
		};

		private static readonly Dictionary<string, string> PrivateKeyCache = new Dictionary<string, string>(StringComparer.Ordinal);

		internal static bool IsInMainScene()
		{
			return (Object)(object)ZNetScene.instance != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null;
		}

		internal static string NormalizeKey([<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)] string key)
		{
			return (key ?? string.Empty).Trim().ToLowerInvariant();
		}

		internal static string ToGlobalKey(string globalOrPrivateKey)
		{
			string text = NormalizeKey(globalOrPrivateKey);
			return text.StartsWith("bl_", StringComparison.Ordinal) ? text.Substring("bl_".Length) : text;
		}

		internal static string ToPrivateKey(string globalOrPrivateKey)
		{
			string text = NormalizeKey(globalOrPrivateKey);
			if (text.Length == 0)
			{
				return string.Empty;
			}
			return text.StartsWith("bl_", StringComparison.Ordinal) ? text : ("bl_" + text);
		}

		internal static string ToPrivateKeyCached(string globalOrPrivateKey)
		{
			if (!PrivateKeyCache.TryGetValue(globalOrPrivateKey, out var value))
			{
				value = ToPrivateKey(globalOrPrivateKey);
				PrivateKeyCache[globalOrPrivateKey] = value;
			}
			return value;
		}

		internal static bool IsTrackedGlobalKey(string globalOrPrivateKey)
		{
			return TrackedGlobalKeys.Contains(ToGlobalKey(globalOrPrivateKey));
		}

		internal static bool HasLocalPrivateKey(string globalOrPrivateKey)
		{
			if (!IsInMainScene())
			{
				return false;
			}
			string text = ToPrivateKeyCached(globalOrPrivateKey);
			return text.Length > 0 && BiomeLockPrivateKeys.PrivateKeys.Contains(text);
		}

		internal static bool HasProgressionKey(string globalOrPrivateKey)
		{
			if (BiomeLockPlugin.CE_GlobalKeys_PrivateKeys.Value)
			{
				return HasLocalPrivateKey(globalOrPrivateKey);
			}
			return HasVanillaGlobalKey(globalOrPrivateKey);
		}

		internal static bool MissingProgressionKey(string globalOrPrivateKey)
		{
			return !HasProgressionKey(globalOrPrivateKey);
		}

		private static bool HasVanillaGlobalKey(string globalOrPrivateKey)
		{
			if ((Object)(object)ZoneSystem.instance == (Object)null)
			{
				return false;
			}
			string text = ToGlobalKey(globalOrPrivateKey);
			string text2 = default(string);
			return text.Length > 0 && ZoneSystem.instance.GetGlobalKey(text, ref text2);
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	internal static class BiomeLock_ZoneSystem_GetGlobalKey_RedirectPrivateKeys
	{
		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
		private static bool Prefix(string name, ref string value, ref bool __result)
		{
			if (string.IsNullOrWhiteSpace(name))
			{
				return true;
			}
			if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsDedicated())
			{
				return true;
			}
			if (!BiomeLockPlugin.CE_GlobalKeys_PrivateKeys.Value)
			{
				return true;
			}
			if (!BiomeLockKeys.TrackedGlobalKeys.Contains(name))
			{
				return true;
			}
			if (BiomeLockPlugin.AdminBypassActive())
			{
				return true;
			}
			__result = BiomeLockKeys.HasLocalPrivateKey(name);
			value = string.Empty;
			return false;
		}
	}
	[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
	[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
	internal static class BiomeLockPrivateKeys
	{
		internal const string PlayerSaveKey = "BL_PrivateKeys";

		internal const string RPC_SetPrivateKey = "BL_SetPrivateKey";

		internal const string RPC_RemovePrivateKey = "BL_RemovePrivateKey";

		internal const string RPC_ResetPrivateKeys = "BL_ResetPrivateKeys";

		internal const string RPC_ClientListKeysBegin = "BL_ClientListKeysBegin";

		internal const string RPC_ClientListKeysLine = "BL_ClientListKeysLine";

		internal const string RPC_ServerListKeys = "BL_ServerListKeys";

		internal const string RPC_ServerSetPrivateKeys = "BL_ServerSetPrivateKeys";

		internal const string RPC_ServerSetPrivateKey = "BL_ServerSetPrivateKey";

		internal const string RPC_ServerRemovePrivateKey = "BL_ServerRemovePrivateKey";

		internal const string RPC_ServerResetPrivateKeys = "BL_ServerResetPrivateKeys";

		internal const float ShareRadiusMeters = 120f;

		internal static readonly HashSet<string> PrivateKeys = new HashSet<string>(StringComparer.Ordinal);

		internal static readonly Dictionary<long, HashSet<string>> ServerPrivateKeysByUid = new Dictionary<long, HashSet<string>>();

		private static readonly List<Player> NearbyPlayers = new List<Player>();

		[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)]
		private static ZRoutedRpc _playerRpcOwner;

		[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)]
		private static ZRoutedRpc _serverRpcOwner;

		internal static void EnsurePlayerRpcRegistered()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null && instance != _playerRpcOwner)
			{
				_playerRpcOwner = instance;
				instance.Register<string>("BL_SetPrivateKey", (Action<long, string>)RPC_BL_SetPrivateKey);
				instance.Register<string>("BL_RemovePrivateKey", (Action<long, string>)RPC_BL_RemovePrivateKey);
				instance.Register("BL_ResetPrivateKeys", (Action<long>)RPC_BL_ResetPrivateKeys);
				instance.Register<long, int>("BL_ClientListKeysBegin", (Action<long, long, int>)RPC_BL_ClientListKeysBegin);
				instance.Register<long, string>("BL_ClientListKeysLine", (Action<long, long, string>)RPC_BL_ClientListKeysLine);
			}
		}

		internal static void EnsureServerRpcRegistered()
		{
			ZRoutedRpc instance = ZRoutedRpc.instance;
			if (instance != null && instance != _serverRpcOwner && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
			{
				_serverRpcOwner = instance;
				instance.Register<long>("BL_ServerListKeys", (Action<long, long>)RPC_BL_ServerListKeys);
				instance.Register<string, long>("BL_ServerSetPrivateKeys", (Action<long, string, long>)RPC_BL_ServerSetPrivateKeys);
				instance.Register<string, long>("BL_ServerSetPrivateKey", (Action<long, string, long>)RPC_BL_ServerSetPrivateKey);
				instance.Register<string, long>("BL_ServerRemovePrivateKey", (Action<long, string, long>)RPC_BL_ServerRemovePrivateKey);
				instance.Register<long>("BL_ServerResetPrivateKeys", (Action<long, long>)RPC_BL_ServerResetPrivateKeys);
			}
		}

		private static void SendToServer(string rpcName, string payload)
		{
			if (ZRoutedRpc.instance != null && !((Object)(object)ZNet.instance == (Object)null))
			{
				ZRoutedRpc.instance.InvokeRoutedRPC(rpcName, new object[2]
				{
					payload,
					ZNet.GetUID()
				});
			}
		}

		private static bool IsFromServer(long sender)
		{
			return ZRoutedRpc.instance != null && sender == ZRoutedRpc.instance.GetServerPeerID();
		}

		private static bool IsFromServerOrSelf(long sender)
		{
			return ZRoutedRpc.instance != null && (sender == ZRoutedRpc.instance.GetServerPeerID() || sender == ZRoutedRpc.instance.m_id);
		}

		private static void RPC_BL_SetPrivateKey(long sender, string privateKey)
		{
			try
			{
				if (BiomeLockKeys.IsInMainScene())
				{
					privateKey = BiomeLockKeys.NormalizeKey(privateKey);
					if (privateKey.Length != 0 && PrivateKeys.Add(privateKey))
					{
						SaveKeysToPlayer(Player.m_localPlayer);
						BiomeLockAPI.RaisePrivateKeyAdded(privateKey);
						SendToServer("BL_ServerSetPrivateKey", privateKey);
						BiomeLock_KeyRefresh.NotifyKeysChanged();
					}
				}
			}
			catch (Exception ex)
			{
				BiomeLockPlugin.Log.LogError((object)("[RPC_BL_SetPrivateKey] " + ex));
			}
		}

		private static void RPC_BL_RemovePrivateKey(long sender, string privateKey)
		{
			try
			{
				if (BiomeLockKeys.IsInMainScene() && IsFromServerOrSelf(sender))
				{
					privateKey = BiomeLockKeys.NormalizeKey(privateKey);
					if (privateKey.Length != 0 && PrivateKeys.Remove(privateKey))
					{
						SaveKeysToPlayer(Player.m_localPlayer);
						BiomeLockAPI.RaisePrivateKeyRemoved(privateKey);
						SendToServer("BL_ServerRemovePrivateKey", privateKey);
						BiomeLock_KeyRefresh.NotifyKeysChanged();
					}
				}
			}
			catch (Exception ex)
			{
				BiomeLockPlugin.Log.LogError((object)("[RPC_BL_RemovePrivateKey] " + ex));
			}
		}

		private static void RPC_BL_ResetPrivateKeys(long sender)
		{
			try
			{
				if (BiomeLockKeys.IsInMainScene() && IsFromServerOrSelf(sender))
				{
					PrivateKeys.Clear();
					SaveKeysToPlayer(Player.m_localPlayer);
					BiomeLockAPI.RaisePrivateKeysReset();
					SendToServer("BL_ServerSetPrivateKeys", string.Empty);
					BiomeLock_KeyRefresh.NotifyKeysChanged();
				}
			}
			catch (Exception ex)
			{
				BiomeLockPlugin.Log.LogError((object)("[RPC_BL_ResetPrivateKeys] " + ex));
			}
		}

		private static void RPC_BL_ClientListKeysBegin(long sender, long targetUid, int count)
		{
			if (BiomeLockKeys.IsInMainScene() && IsFromServer(sender))
			{
				ClientConsoleAdd($"[BL] TotalKeys: {count}");
			}
		}

		private static void RPC_BL_ClientListKeysLine(long sender, long targetUid, string key)
		{
			if (BiomeLockKeys.IsInMainScene() && IsFromServer(sender))
			{
				key = BiomeLockKeys.NormalizeKey(key);
				if (key.Length > 0)
				{
					ClientConsoleAdd(key);
				}
			}
		}

		private static void ClientConsoleAdd(string msg)
		{
			if ((Object)(object)Console.instance != (Object)null)
			{
				((Terminal)Console.instance).AddString(msg);
			}
		}

		internal static void ClientDistributeBossPrivateKey(string globalKey)
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!BiomeLockKeys.IsInMainScene() || (Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsDedicated() || ZRoutedRpc.instance == null || !BiomeLockPlugin.CE_GlobalKeys_PrivateKeys.Value || !BiomeLockKeys.IsTrackedGlobalKey(globalKey))
				{
					return;
				}
				string text = BiomeLockKeys.ToPrivateKey(globalKey);
				NearbyPlayers.Clear();
				Player.GetPlayersInRange(((Component)Player.m_localPlayer).transform.position, 120f, NearbyPlayers);
				foreach (Player nearbyPlayer in NearbyPlayers)
				{
					if (!((Object)(object)nearbyPlayer == (Object)null))
					{
						ZDOID zDOID = ((Character)nearbyPlayer).GetZDOID();
						long userID = ((ZDOID)(ref zDOID)).UserID;
						if (userID != 0)
						{
							ZRoutedRpc.instance.InvokeRoutedRPC(userID, "BL_SetPrivateKey", new object[1] { text });
						}
					}
				}
				NearbyPlayers.Clear();
			}
			catch (Exception ex)
			{
				BiomeLockPlugin.Log.LogError((object)("[ClientDistributeBossPrivateKey] " + ex));
			}
		}

		private static void RPC_BL_ServerListKeys(long sender, long targetUid)
		{
			try
			{
				if (!IsSenderAdmin(sender))
				{
					return;
				}
				long num = ((targetUid != 0L) ? targetUid : sender);
				HashSet<string> value;
				List<string> list = (ServerPrivateKeysByUid.TryGetValue(num, out value) ? value.OrderBy<string, string>([<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)] (string s) => s, StringComparer.Ordinal).ToList() : new List<string>());
				ZRoutedRpc.instance.InvokeRoutedRPC(sender, "BL_ClientListKeysBegin", new object[2] { num, list.Count });
				foreach (string item in list)
				{
					ZRoutedRpc.instance.InvokeRoutedRPC(sender, "BL_ClientListKeysLine", new object[2] { num, item });
				}
			}
			catch (Exception ex)
			{
				BiomeLockPlugin.Log.LogError((object)("[RPC_BL_ServerListKeys] " + ex));
			}
		}

		private static bool AllowTrackingOrAdmin(long sender, long uid)
		{
			return uid == sender || IsSenderAdmin(sender);
		}

		private static HashSet<string> GetOrCreateServerSet(long uid)
		{
			if (!ServerPrivateKeysByUid.TryGetValue(uid, out var value))
			{
				value = new HashSet<string>(StringComparer.Ordinal);
				ServerPrivateKeysByUid[uid] = value;
			}
			return value;
		}

		private static bool TryNormalizePrivateKey(ref string privateKey)
		{
			privateKey = BiomeLockKeys.NormalizeKey(privateKey);
			return privateKey.StartsWith("bl_", StringComparison.Ordinal);
		}

		private static void RPC_BL_ServerSetPrivateKeys(long sender, string keysCsv, long targetUid)
		{
			try
			{
				long num = ((targetUid != 0L) ? targetUid : sender);
				if (!AllowTrackingOrAdmin(sender, num))
				{
					return;
				}
				HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
				string[] array = (keysCsv ?? string.Empty).Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				foreach (string text in array)
				{
					string privateKey = text;
					if (TryNormalizePrivateKey(ref privateKey))
					{
						hashSet.Add(privateKey);
					}
				}
				ServerPrivateKeysByUid[num] = hashSet;
			}
			catch (Exception ex)
			{
				BiomeLockPlugin.Log.LogError((object)("[RPC_BL_ServerSetPrivateKeys] " + ex));
			}
		}

		private static void RPC_BL_ServerSetPrivateKey(long sender, string privateKey, long targetUid)
		{
			try
			{
				long num = ((targetUid != 0L) ? targetUid : sender);
				if (AllowTrackingOrAdmin(sender, num) && TryNormalizePrivateKey(ref privateKey))
				{
					GetOrCreateServerSet(num).Add(privateKey);
					if (num != sender)
					{
						ZRoutedRpc.instance.InvokeRoutedRPC(num, "BL_SetPrivateKey", new object[1] { privateKey });
					}
				}
			}
			catch (Exception ex)
			{
				BiomeLockPlugin.Log.LogError((object)("[RPC_BL_ServerSetPrivateKey] " + ex));
			}
		}

		private static void RPC_BL_ServerRemovePrivateKey(long sender, string privateKey, long targetUid)
		{
			try
			{
				long num = ((targetUid != 0L) ? targetUid : sender);
				if (AllowTrackingOrAdmin(sender, num) && TryNormalizePrivateKey(ref privateKey))
				{
					if (ServerPrivateKeysByUid.TryGetValue(num, out var value))
					{
						value.Remove(privateKey);
					}
					if (num != sender)
					{
						ZRoutedRpc.instance.InvokeRoutedRPC(num, "BL_RemovePrivateKey", new object[1] { privateKey });
					}
				}
			}
			catch (Exception ex)
			{
				BiomeLockPlugin.Log.LogError((object)("[RPC_BL_ServerRemovePrivateKey] " + ex));
			}
		}

		private static void RPC_BL_ServerResetPrivateKeys(long sender, long targetUid)
		{
			try
			{
				long num = ((targetUid != 0L) ? targetUid : sender);
				if (AllowTrackingOrAdmin(sender, num))
				{
					ServerPrivateKeysByUid[num] = new HashSet<string>(StringComparer.Ordinal);
					if (num != sender)
					{
						ZRoutedRpc.instance.InvokeRoutedRPC(num, "BL_ResetPrivateKeys", Array.Empty<object>());
					}
				}
			}
			catch (Exception ex)
			{
				BiomeLockPlugin.Log.LogError((object)("[RPC_BL_ServerResetPrivateKeys] " + ex));
			}
		}

		private static bool IsSenderAdmin(long senderUid)
		{
			try
			{
				if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer())
				{
					return false;
				}
				if (ZRoutedRpc.instance != null && senderUid == ZRoutedRpc.instance.m_id)
				{
					return true;
				}
				if (!TryGetPeerByUid(senderUid, out var peer))
				{
					return false;
				}
				string hostName = peer.m_socket.GetHostName();
				return !string.IsNullOrEmpty(hostName) && ZNet.instance.IsAdmin(hostName);
			}
			catch
			{
				return false;
			}
		}

		private static bool TryGetPeerByUid(long uid, out ZNetPeer peer)
		{
			peer = null;
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return false;
			}
			foreach (ZNetPeer peer2 in ZNet.instance.GetPeers())
			{
				if (peer2 != null && peer2.m_uid == uid)
				{
					peer = peer2;
					return true;
				}
			}
			return false;
		}

		internal static bool TryResolveUidByPlayerName(string playerName, out long uid)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			uid = 0L;
			if (string.IsNullOrEmpty(playerName))
			{
				return false;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)null && string.Equals(localPlayer.GetPlayerName(), playerName, StringComparison.OrdinalIgnoreCase))
			{
				uid = ZNet.GetUID();
				return uid != 0;
			}
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return false;
			}
			foreach (PlayerInfo player in ZNet.instance.GetPlayerList())
			{
				if (string.Equals(player.m_name, playerName, StringComparison.OrdinalIgnoreCase))
				{
					ZDOID characterID = player.m_characterID;
					uid = ((ZDOID)(ref characterID)).UserID;
					return uid != 0;
				}
			}
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				if (peer != null && string.Equals(peer.m_playerName, playerName, StringComparison.OrdinalIgnoreCase))
				{
					uid = peer.m_uid;
					return uid != 0;
				}
			}
			return false;
		}

		internal static void LoadKeysFromPlayer(Player p)
		{
			PrivateKeys.Clear();
			if (p.m_customData != null && p.m_customData.TryGetValue("BL_PrivateKeys", out var value) && !string.IsNullOrEmpty(value))
			{
				string[] array = value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				foreach (string key in array)
				{
					string text = BiomeLockKeys.NormalizeKey(key);
					if (text.Length > 0)
					{
						PrivateKeys.Add(text);
					}
				}
			}
			BiomeLock_KeyRefresh.NotifyKeysChanged();
			BiomeLockAPI.RaisePrivateKeysLoaded();
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(2)]
		internal static void SaveKeysToPlayer(Player p)
		{
			if (!((Object)(object)p == (Object)null))
			{
				if (p.m_customData == null)
				{
					p.m_customData = new Dictionary<string, string>();
				}
				p.m_customData["BL_PrivateKeys"] = GetPrivateKeysCsv();
			}
		}

		internal static string GetPrivateKeysCsv()
		{
			return string.Join(",", PrivateKeys.OrderBy<string, string>([<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)] (string s) => s, StringComparer.Ordinal));
		}
	}
	[HarmonyPatch]
	[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
	[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
	internal static class BL_Patches_Player_LoadSaveAndRpc
	{
		[HarmonyPatch(typeof(Player), "EquipInventoryItems")]
		[HarmonyPrefix]
		private static void Player_EquipInventoryItems_Prefix(Player __instance)
		{
			try
			{
				if (BiomeLockKeys.IsInMainScene())
				{
					BiomeLockPrivateKeys.LoadKeysFromPlayer(__instance);
					BiomeLockPrivateKeys.EnsurePlayerRpcRegistered();
					if (ZRoutedRpc.instance != null && (Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsDedicated())
					{
						ZRoutedRpc.instance.InvokeRoutedRPC("BL_ServerSetPrivateKeys", new object[2]
						{
							BiomeLockPrivateKeys.GetPrivateKeysCsv(),
							ZNet.GetUID()
						});
					}
				}
			}
			catch (Exception ex)
			{
				BiomeLockPlugin.Log.LogError((object)("[Player_EquipInventoryItems_Prefix] " + ex));
			}
		}

		[HarmonyPatch(typeof(Player), "Save", new Type[] { typeof(ZPackage) })]
		[HarmonyPrefix]
		private static void Player_Save_Prefix(Player __instance)
		{
			try
			{
				if (!BiomeLockKeys.IsInMainScene())
				{
					BiomeLockPrivateKeys.PrivateKeys.Clear();
				}
				else
				{
					BiomeLockPrivateKeys.SaveKeysToPlayer(__instance);
				}
			}
			catch (Exception ex)
			{
				BiomeLockPlugin.Log.LogError((object)("[Player_Save_Prefix] " + ex));
			}
		}
	}
	[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
	[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
	[HarmonyPatch]
	internal static class BL_Patches_Server_RegisterAndDistribute
	{
		[HarmonyPatch(typeof(ZoneSystem), "Load")]
		[HarmonyPostfix]
		private static void ZoneSystem_Load_Postfix()
		{
			try
			{
				BiomeLockPrivateKeys.EnsureServerRpcRegistered();
			}
			catch (Exception ex)
			{
				BiomeLockPlugin.Log.LogError((object)("[ZoneSystem_Load_Postfix] " + ex));
			}
		}

		[HarmonyPatch(typeof(ZNet), "Disconnect", new Type[] { typeof(ZNetPeer) })]
		[HarmonyPrefix]
		private static void ZNet_Disconnect_Prefix(ZNet __instance, ZNetPeer peer)
		{
			if (!((Object)(object)__instance == (Object)null) && peer != null && __instance.IsServer())
			{
				BiomeLockPrivateKeys.ServerPrivateKeysByUid.Remove(peer.m_uid);
			}
		}

		[HarmonyPatch(typeof(ZoneSystem), "SetGlobalKey", new Type[] { typeof(string) })]
		[HarmonyPostfix]
		private static void ZoneSystem_SetGlobalKey_Postfix(string name)
		{
			string text = BiomeLockKeys.NormalizeKey(name);
			if (text.Length > 0 && BiomeLockKeys.IsTrackedGlobalKey(text))
			{
				BiomeLockPrivateKeys.ClientDistributeBossPrivateKey(text);
			}
		}
	}
	internal static class BiomeLock_KeyRefresh
	{
		private const float RefreshDelay = 0.05f;

		private static bool _pending;

		private static float _nextRunAt;

		internal static void NotifyKeysChanged()
		{
			_pending = true;
			float time = Time.time;
			if (_nextRunAt < time)
			{
				_nextRunAt = time + 0.05f;
			}
		}

		internal static void TryRunPending()
		{
			if (!_pending || Time.time < _nextRunAt)
			{
				return;
			}
			_pending = false;
			if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsDedicated())
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			try
			{
				BiomeLock_SE.ApplyOrRemove(localPlayer);
				localPlayer.UpdateKnownRecipesList();
				localPlayer.UpdateAvailablePiecesList();
				localPlayer.UpdateEvents();
				if ((Object)(object)InventoryGui.instance != (Object)null && InventoryGui.IsVisible())
				{
					InventoryGui.instance.UpdateCraftingPanel(false);
				}
				if ((Object)(object)StoreGui.instance != (Object)null && StoreGui.IsVisible())
				{
					StoreGui.instance.FillList();
				}
			}
			catch (Exception ex)
			{
				BiomeLockPlugin.Log.LogError((object)("[KeyRefresh] " + ex));
			}
		}
	}
	[HarmonyPatch(typeof(Hud), "Update")]
	internal static class BL_Hud_Update_Tick
	{
		private static void Postfix()
		{
			BiomeLock_KeyRefresh.TryRunPending();
			BiomeLock_SE.UpdateBroadcast();
		}
	}
	[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
	[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
	internal static class BiomeLock_SE
	{
		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Player), "UpdateBiome")]
		private static class Player_UpdateBiome_ApplySE
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static void Postfix(Player __instance)
			{
				if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
				{
					float time = Time.time;
					if (!(time < _nextApplyTime))
					{
						_nextApplyTime = time + 0.25f;
						ApplyOrRemove(__instance);
					}
				}
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Humanoid), "StartAttack")]
		private static class Humanoid_StartAttack_Block_All
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Humanoid __instance, ref bool __result)
			{
				Player val = (Player)(object)((__instance is Player) ? __instance : null);
				if (val == null)
				{
					return true;
				}
				if (!ShouldBlockAttack(val, ((Humanoid)val).GetCurrentWeapon()))
				{
					return true;
				}
				ShowThrottledMessage(val, "$biomelock_attack_blocked", ref _nextAttackBlockedMessageTime);
				__result = false;
				return false;
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Humanoid), "IsBlocking")]
		private static class Humanoid_IsBlocking_Block_Parry
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Humanoid __instance, ref bool __result)
			{
				if (!BiomeLockPlugin.CE_SE_Block_AttackBlock.Value)
				{
					return true;
				}
				Player val = (Player)(object)((__instance is Player) ? __instance : null);
				if (val == null || !((Character)val).m_blocking)
				{
					return true;
				}
				if (!ShouldBlockAttack(val, ((Humanoid)val).GetCurrentBlocker()))
				{
					return true;
				}
				__result = false;
				return false;
			}
		}

		[HarmonyPatch(typeof(Attack), "OnAttackTrigger")]
		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		private static class Attack_OnAttackTrigger_Block_All
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Attack __instance)
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null || (Object)(object)__instance.m_character != (Object)(object)localPlayer)
				{
					return true;
				}
				if (!ShouldBlockAttack(localPlayer, ((Humanoid)localPlayer).GetCurrentWeapon()))
				{
					return true;
				}
				ShowThrottledMessage(localPlayer, "$biomelock_attack_blocked", ref _nextAttackBlockedMessageTime);
				return false;
			}
		}

		[HarmonyPatch(typeof(Player), "UpdateAttackBowDraw")]
		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		private static class Player_UpdateAttackBowDraw_Block_Draw
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Player __instance, [<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)] ItemData weapon)
			{
				if (!ShouldBlockAttack(__instance, weapon))
				{
					return true;
				}
				((Humanoid)__instance).m_attackDrawTime = -1f;
				string text = weapon?.m_shared?.m_attack?.m_drawAnimationState;
				if (!string.IsNullOrEmpty(text))
				{
					((Character)__instance).m_zanim.SetBool(text, false);
				}
				return false;
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Player), "UpdatePlacement")]
		private static class Player_UpdatePlacement_Block
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Player __instance)
			{
				return !ShouldBlockBuildTool(__instance);
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Player), "PlacePiece")]
		private static class Player_PlacePiece_Block
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Player __instance)
			{
				return BlockBuildToolWithMessage(__instance);
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Player), "Repair")]
		private static class Player_Repair_Block
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Player __instance)
			{
				return BlockHammerWithMessage(__instance);
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Player), "RemovePiece")]
		private static class Player_RemovePiece_Block
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Player __instance)
			{
				return BlockHammerWithMessage(__instance);
			}
		}

		[HarmonyPatch(typeof(Hud), "TogglePieceSelection")]
		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		private static class Hud_TogglePieceSelection_Block
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Hud __instance)
			{
				if (!ShouldBlockBuildTool(Player.m_localPlayer))
				{
					return true;
				}
				return (Object)(object)__instance != (Object)null && (Object)(object)__instance.m_pieceSelectionWindow != (Object)null && __instance.m_pieceSelectionWindow.activeSelf;
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Teleport), "Interact")]
		private static class Teleport_Interact_BlockDungeon
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Teleport __instance, Humanoid character, bool hold)
			{
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				if (!BiomeLockPlugin.CE_SE_Block_DungeonTeleport.Value || hold)
				{
					return true;
				}
				Player val = (Player)(object)((character is Player) ? character : null);
				if (val == null)
				{
					return true;
				}
				if (!ShouldBlockAtPosition(val, ((Component)__instance).transform.position))
				{
					return true;
				}
				ShowMessage(val, "$biomelock_dungeon_blocked");
				return false;
			}
		}

		[HarmonyPatch(typeof(Player), "UpdateStats", new Type[] { typeof(float) })]
		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		private static class Player_UpdateStats_BiomeLockHealthDrain
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static void Postfix(Player __instance, float dt)
			{
				ApplyHealthDrain(__instance, dt);
			}
		}

		[HarmonyPatch(typeof(Container), "Interact")]
		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		private static class Container_Interact_Block
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Container __instance, Humanoid character, bool hold, ref bool __result)
			{
				//IL_0035: Unknown result type (might be due to invalid IL or missing references)
				if (!BiomeLockPlugin.CE_SE_Block_ContainerInteract.Value || hold)
				{
					return true;
				}
				Player val = (Player)(object)((character is Player) ? character : null);
				if (val == null)
				{
					return true;
				}
				if (!ShouldBlockAtPosition(val, ((Component)__instance).transform.position))
				{
					return true;
				}
				ShowThrottledMessage(val, "$biomelock_interact_blocked", ref _nextContainerInteractBlockedMessageTime);
				__result = false;
				return false;
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Door), "Interact")]
		private static class Door_Interact_Block
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Door __instance, Humanoid character, bool hold, ref bool __result)
			{
				if (!BiomeLockPlugin.CE_SE_Block_DoorInteract.Value || hold)
				{
					return true;
				}
				return !TryBlockDoor(__instance, character, ref __result);
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Door), "UseItem")]
		private static class Door_UseItem_Block
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Door __instance, Humanoid user, ref bool __result)
			{
				if (!BiomeLockPlugin.CE_SE_Block_DoorInteract.Value)
				{
					return true;
				}
				return !TryBlockDoor(__instance, user, ref __result);
			}
		}

		[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(0)]
		[HarmonyPatch]
		private static class Interactable_Interact_Block
		{
			private static readonly Type[] InteractArgs = new Type[3]
			{
				typeof(Humanoid),
				typeof(bool),
				typeof(bool)
			};

			private static bool IsTargetSignature(string first, string second)
			{
				if (first == "user")
				{
					return second == "hold" || second == "repeat";
				}
				if (first == "character")
				{
					return second == "repeat";
				}
				return false;
			}

			private static IEnumerable<MethodBase> TargetMethods()
			{
				Type[] types;
				try
				{
					types = typeof(Interactable).Assembly.GetTypes();
				}
				catch (ReflectionTypeLoadException ex)
				{
					ReflectionTypeLoadException e = ex;
					types = e.Types ?? Array.Empty<Type>();
				}
				HashSet<MethodBase> seen = new HashSet<MethodBase>();
				Type[] array = types;
				foreach (Type t in array)
				{
					if (t == null || t.IsInterface || t.IsAbstract || !typeof(Interactable).IsAssignableFrom(t))
					{
						continue;
					}
					MethodInfo m = t.GetMethod("Interact", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, InteractArgs, null);
					if (m == null || m.GetMethodBody() == null)
					{
						continue;
					}
					ParameterInfo[] ps = m.GetParameters();
					if (IsTargetSignature(ps[0].Name, ps[1].Name))
					{
						MethodBase declared = ((m.DeclaringType == t) ? m : m.DeclaringType.GetMethod("Interact", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, InteractArgs, null));
						if (seen.Add(declared))
						{
							yield return declared;
						}
					}
				}
			}

			private static bool Prefix(object __instance, Humanoid __0, ref bool __result)
			{
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				Player val = (Player)(object)((__0 is Player) ? __0 : null);
				if (val == null)
				{
					return true;
				}
				if (!IsInteractBlockEnabled(__instance))
				{
					return true;
				}
				Component val2 = (Component)((__instance is Component) ? __instance : null);
				if (val2 != null && (Object)(object)val2 != (Object)null)
				{
					if (IsAllowedInteractableGO(val2.gameObject))
					{
						return true;
					}
					if (!ShouldBlockAtPosition(val, val2.transform.position))
					{
						return true;
					}
				}
				else if (!ShouldBlock(val))
				{
					return true;
				}
				ShowThrottledMessage(val, "$biomelock_interact_blocked", ref _nextGenericInteractBlockedMessageTime);
				__result = false;
				return false;
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Minimap), "UpdateExplore")]
		private static class Minimap_UpdateExplore_Block
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Minimap __instance, Player player)
			{
				if (!BiomeLockPlugin.CE_SE_Block_MapExplore.Value)
				{
					return true;
				}
				if ((Object)(object)player == (Object)null || !ShouldBlock(player))
				{
					return true;
				}
				__instance.m_exploreTimer = 0f;
				return false;
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Minimap), "ShowPinNameInput")]
		private static class Minimap_ShowPinNameInput_Block_When_SE_Active
		{
			private static bool Prefix(Vector3 pos)
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				if (!BiomeLockPlugin.CE_SE_Block_MapPins.Value)
				{
					return true;
				}
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null || !ShouldBlockAtPosition(localPlayer, pos))
				{
					return true;
				}
				ShowMessage(localPlayer, "$biomelock_map_pin_blocked");
				return false;
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(EnvMan), "SetEnv")]
		private static class EnvMan_SetEnv_RestrictedMist
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static void Postfix(EnvMan __instance)
			{
				BlendRestrictedMistFog(__instance);
			}
		}

		[HarmonyPatch(typeof(Player), "Update")]
		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		private static class Player_Update_RestrictedMist
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static void Postfix(Player __instance)
			{
				if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
				{
					ApplyRestrictedMist(Time.deltaTime);
				}
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(SpawnSystem), "GetPlayersInZone")]
		private static class SpawnSystem_GetPlayersInZone_FilterRestrictedPlayers
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static void Postfix(List<Player> players)
			{
				if (!BiomeLockPlugin.CE_SE_Block_SpawnBlock.Value || players == null || players.Count == 0)
				{
					return;
				}
				for (int num = players.Count - 1; num >= 0; num--)
				{
					Player val = players[num];
					if ((Object)(object)val != (Object)null && ShouldBlock(val))
					{
						players.RemoveAt(num);
					}
				}
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Player), "IsPlayerInRange", new Type[]
		{
			typeof(Vector3),
			typeof(float)
		})]
		private static class Player_IsPlayerInRange_IgnoreRestrictedPlayers
		{
			private static bool Prefix(Vector3 point, float range, ref bool __result)
			{
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0070: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				if (!BiomeLockPlugin.CE_SE_Block_SpawnBlock.Value)
				{
					return true;
				}
				if (!IsRestrictedLocalPlayer(Player.m_localPlayer))
				{
					return true;
				}
				__result = false;
				foreach (Player allPlayer in Player.GetAllPlayers())
				{
					if ((Object)(object)allPlayer == (Object)null || ShouldBlockAtPosition(allPlayer, point) || !(Vector3.Distance(((Component)allPlayer).transform.position, point) < range))
					{
						continue;
					}
					__result = true;
					break;
				}
				return false;
			}
		}

		[HarmonyPatch(typeof(Player), "IsPlayerInRange", new Type[]
		{
			typeof(Vector3),
			typeof(float),
			typeof(float)
		})]
		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		private static class Player_IsPlayerInRange_Noise_IgnoreRestrictedPlayers
		{
			private static bool Prefix(Vector3 point, float range, float minNoise, ref bool __result)
			{
				//IL_004c: 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_0068: Unknown result type (might be due to invalid IL or missing references)
				if (!BiomeLockPlugin.CE_SE_Block_SpawnBlock.Value || !IsRestrictedLocalPlayer(Player.m_localPlayer))
				{
					return true;
				}
				__result = false;
				foreach (Player allPlayer in Player.GetAllPlayers())
				{
					if (!((Object)(object)allPlayer == (Object)null) && !ShouldBlockAtPosition(allPlayer, point) && !(Vector3.Distance(((Component)allPlayer).transform.position, point) >= range))
					{
						float noiseRange = ((Character)allPlayer).GetNoiseRange();
						if (range <= noiseRange && noiseRange >= minNoise)
						{
							__result = true;
							break;
						}
					}
				}
				return false;
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(EggHatch), "CheckSpawn")]
		private static class EggHatch_CheckSpawn_IgnoreRestrictedPlayers
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(EggHatch __instance)
			{
				//IL_005b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0060: Unknown result type (might be due to invalid IL or missing references)
				//IL_008f: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a7: 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)
				if (!BiomeLockPlugin.CE_SE_Block_SpawnBlock.Value || !IsRestrictedLocalPlayer(Player.m_localPlayer))
				{
					return true;
				}
				if (!__instance.m_nview.IsValid() || !__instance.m_nview.IsOwner())
				{
					return false;
				}
				Vector3 position = ((Component)__instance).transform.position;
				Player val = null;
				float num = __instance.m_triggerDistance;
				foreach (Player allPlayer in Player.GetAllPlayers())
				{
					if (!((Object)(object)allPlayer == (Object)null) && !ShouldBlockAtPosition(allPlayer, position))
					{
						float num2 = Vector3.Distance(((Component)allPlayer).transform.position, position);
						if (num2 < num)
						{
							num = num2;
							val = allPlayer;
						}
					}
				}
				if ((Object)(object)val != (Object)null && !((Character)val).InGhostMode())
				{
					__instance.Hatch();
				}
				return false;
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Player), "AutoPickup")]
		private static class Player_AutoPickup_Block
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Player __instance)
			{
				if (!BiomeLockPlugin.CE_SE_Block_AutoPickup.Value)
				{
					return true;
				}
				return !ShouldBlock(__instance);
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Humanoid), "Pickup")]
		private static class Humanoid_Pickup_Block
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Humanoid __instance)
			{
				if (!BiomeLockPlugin.CE_SE_Block_Pickup.Value)
				{
					return true;
				}
				Player val = (Player)(object)((__instance is Player) ? __instance : null);
				if (val == null || !ShouldBlock(val))
				{
					return true;
				}
				ShowThrottledMessage(val, "$biomelock_pickup_blocked", ref _nextPickupBlockedMessageTime);
				return false;
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		private static class ObjectDB_Awake_RegisterSE
		{
			private static void Postfix()
			{
				EnsureSERegistered();
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Vegvisir), "Interact")]
		private static class Vegvisir_Interact_Block_HildirMapTable
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Vegvisir __instance)
			{
				return !IsBlockedHildirMapTable(__instance);
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Vegvisir), "GetHoverText")]
		private static class Vegvisir_GetHoverText_Block_HildirMapTable
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Vegvisir __instance, ref string __result)
			{
				if (!IsBlockedHildirMapTable(__instance))
				{
					return true;
				}
				__result = string.Empty;
				return false;
			}
		}

		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		[HarmonyPatch(typeof(Vegvisir), "GetHoverName")]
		private static class Vegvisir_GetHoverName_Block_HildirMapTable
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Vegvisir __instance, ref string __result)
			{
				if (!IsBlockedHildirMapTable(__instance))
				{
					return true;
				}
				__result = string.Empty;
				return false;
			}
		}

		[HarmonyPatch(typeof(Trader), "Interact", new Type[]
		{
			typeof(Humanoid),
			typeof(bool),
			typeof(bool)
		})]
		[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(0)]
		private static class Trader_Interact_Block
		{
			[<5a57d5fb-35e9-4f42-9b4f-0b78e262070e>NullableContext(1)]
			private static bool Prefix(Trader __instance, Humanoid character, bool hold)
			{
				if (!BiomeLockPlugin.CE_SE_Block_TraderInteract.Value)
				{
					return true;
				}
				if (hold)
				{
					return true;
				}
				if (BiomeLockPlugin.AdminBypassActive())
				{
					return true;
				}
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer == (Object)null || (Object)(object)character != (Object)(object)localPlayer || (Object)(object)__instance == (Object)null)
				{
					return true;
				}
				if (!TryGetTraderRule(GetTraderPrefabName(__instance), out var requiredKey, out var blockedToken))
				{
					return true;
				}
				if (BiomeLockKeys.HasProgressionKey(requiredKey))
				{
					return true;
				}
				string text = Localization.instance.Localize(blockedToken);
				if (text.IndexOf('$') >= 0)
				{
					text = Localization.instance.Localize(text);
				}
				if ((Object)(object)MessageHud.instance != (Object)null && !string.IsNullOrEmpty(text))
				{
					MessageHud.instance.ShowMessage((MessageType)2, ColorBlocked(text), 0, (Sprite)null, false, true);
				}
				return false;
			}
		}

		private const float ApplyInterval = 0.25f;

		private static readonly char[] BiomeSeparators = new char[6] { ',', ';', ' ', '\t', '\r', '\n' };

		private static Biome _blockedBiomesCache = (Biome)0;

		private static string _blockedBiomesRaw = "";

		private static float _nextApplyTime;

		private const string AttackBlockedToken = "$biomelock_attack_blocked";

		private static float _nextAttackBlockedMessageTime;

		private static readonly HashSet<string> AttackBlacklistPrefabs = new HashSet<string>();

		[<dbedd104-49d4-45b5-9930-e5d6d508bb9a>Nullable(2)]
		private static string _attackBlacklistSource;

		private const float MinBroadcastInterval = 2f;

		private static float _nextBroadcastTime;

		private static readonly string[] BroadcastTokens = new string[5] { "$bl_se_msg_1", "$bl_se_msg_2", "$bl_se_msg_3", "$bl_se_msg_4", "$bl_se_msg_5" };

		private const string HammerBlockedToken = "$biomelock_hammer_blocked";

		private const string TerrainHoeBlockedToken = "$biomelock_terrain_hoe_blocked";

		private static float _nextHammerBlockedMessageTime;

		private const string DungeonBlockedToken = "$biomelock_dungeon_blocked";

		private const float HealthDrainTick = 0.25f;

		private static float _healthDrainTimer;

		private static readonly HashSet<string> AllowedInteractables = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "TombStone", "ShipControlls", "Ladder", "Saddle", "Sadle", "Chair" };

		private const string ContainerInteractBlockedToken = "$biomelock_interact_blocked";

		private static float _nextContainerInteractBlockedMessageTime;

		private const string DoorInteractBlockedToken = "$biomelock_interact_blocked";

		private static float _nextDoorInteractBlockedMessageTime;

		private const string