Decompiled source of BiomeLock v1.0.9
plugins/BiomeLock.dll
Decompiled 2 days ago
The result has been truncated due to the large size, download it to view full contents!
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 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: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("BiomeLock")] [assembly: AssemblyDescription("Biome gating via private keys, WAP-like flow")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("BiomeLock")] [assembly: AssemblyCopyright("Copyright © 2025")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("b8f1a3c4-5dcf-4df6-899e-73f354a55c84")] [assembly: AssemblyFileVersion("1.2.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace LocalizationManager { [PublicAPI] public class Localizer { private static readonly Dictionary<string, Dictionary<string, Func<string>>> PlaceholderProcessors; private static readonly Dictionary<string, Dictionary<string, string>> loadedTexts; private static readonly ConditionalWeakTable<Localization, string> localizationLanguage; private static readonly List<WeakReference<Localization>> localizationObjects; private static BaseUnityPlugin? _plugin; private static readonly List<string> fileExtensions; private static BaseUnityPlugin plugin { get { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown if (_plugin == null) { IEnumerable<TypeInfo> source; try { source = Assembly.GetExecutingAssembly().DefinedTypes.ToList(); } catch (ReflectionTypeLoadException ex) { source = from t in ex.Types where t != null select t.GetTypeInfo(); } _plugin = (BaseUnityPlugin)Chainloader.ManagerObject.GetComponent((Type)source.First((TypeInfo t) => t.IsClass && typeof(BaseUnityPlugin).IsAssignableFrom(t))); } return _plugin; } } public static event Action? OnLocalizationComplete; private static void UpdatePlaceholderText(Localization localization, string key) { localizationLanguage.TryGetValue(localization, out var value); string text = loadedTexts[value][key]; if (PlaceholderProcessors.TryGetValue(key, out var value2)) { text = value2.Aggregate(text, (string current, KeyValuePair<string, Func<string>> kv) => current.Replace("{" + kv.Key + "}", kv.Value())); } localization.AddWord(key, text); } public static void AddPlaceholder<T>(string key, string placeholder, ConfigEntry<T> config, Func<T, string>? convertConfigValue = null) where T : notnull { Func<T, string> convertConfigValue2 = convertConfigValue; if (convertConfigValue2 == null) { convertConfigValue2 = (T val) => val.ToString(); } if (!PlaceholderProcessors.ContainsKey(key)) { PlaceholderProcessors[key] = new Dictionary<string, Func<string>>(); } config.SettingChanged += delegate { UpdatePlaceholder(); }; if (loadedTexts.ContainsKey(Localization.instance.GetSelectedLanguage())) { UpdatePlaceholder(); } void UpdatePlaceholder() { PlaceholderProcessors[key][placeholder] = () => convertConfigValue2(config.Value); UpdatePlaceholderText(Localization.instance, key); } } public static void AddText(string key, string text) { List<WeakReference<Localization>> list = new List<WeakReference<Localization>>(); foreach (WeakReference<Localization> localizationObject in localizationObjects) { if (localizationObject.TryGetTarget(out var target)) { Dictionary<string, string> dictionary = loadedTexts[localizationLanguage.GetOrCreateValue(target)]; if (!target.m_translations.ContainsKey(key)) { dictionary[key] = text; target.AddWord(key, text); } } else { list.Add(localizationObject); } } foreach (WeakReference<Localization> item in list) { localizationObjects.Remove(item); } } public static void Load() { _ = plugin; } public static void LoadLocalizationLater(Localization __instance) { LoadLocalization(Localization.instance, __instance.GetSelectedLanguage()); } public static void SafeCallLocalizeComplete() { Localizer.OnLocalizationComplete?.Invoke(); } private static void LoadLocalization(Localization __instance, string language) { if (!localizationLanguage.Remove(__instance)) { localizationObjects.Add(new WeakReference<Localization>(__instance)); } localizationLanguage.Add(__instance, language); Dictionary<string, string> dictionary = new Dictionary<string, string>(); foreach (string item in from f in Directory.GetFiles(Path.GetDirectoryName(Paths.PluginPath), plugin.Info.Metadata.Name + ".*", SearchOption.AllDirectories) where fileExtensions.IndexOf(Path.GetExtension(f)) >= 0 select f) { string[] array = Path.GetFileNameWithoutExtension(item).Split(new char[1] { '.' }); if (array.Length >= 2) { string text = array[1]; if (dictionary.ContainsKey(text)) { Debug.LogWarning((object)("Duplicate key " + text + " found for " + plugin.Info.Metadata.Name + ". The duplicate file found at " + item + " will be skipped.")); } else { dictionary[text] = item; } } } byte[] array2 = LoadTranslationFromAssembly("English"); if (array2 == null) { throw new Exception("Found no English localizations in mod " + plugin.Info.Metadata.Name + ". Expected an embedded resource translations/English.json or translations/English.yml."); } string input = Encoding.UTF8.GetString(array2).TrimStart(new char[1] { '\ufeff' }); Dictionary<string, string> dictionary2 = new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(input); if (dictionary2 == null) { throw new Exception("Localization for mod " + plugin.Info.Metadata.Name + " failed: Localization file was empty."); } string text2 = null; if (language != "English") { if (dictionary.TryGetValue(language, out var value)) { text2 = File.ReadAllText(value); } else { byte[] array3 = LoadTranslationFromAssembly(language); if (array3 != null) { text2 = Encoding.UTF8.GetString(array3); } } } if (text2 == null && dictionary.TryGetValue("English", out var value2)) { text2 = File.ReadAllText(value2); } if (text2 != null) { text2 = text2.TrimStart(new char[1] { '\ufeff' }); foreach (KeyValuePair<string, string> item2 in new DeserializerBuilder().IgnoreFields().Build().Deserialize<Dictionary<string, string>>(text2) ?? new Dictionary<string, string>()) { dictionary2[item2.Key] = item2.Value; } } loadedTexts[language] = dictionary2; foreach (KeyValuePair<string, string> item3 in dictionary2) { UpdatePlaceholderText(__instance, item3.Key); } } static Localizer() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Expected O, but got Unknown //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown PlaceholderProcessors = new Dictionary<string, Dictionary<string, Func<string>>>(); loadedTexts = new Dictionary<string, Dictionary<string, string>>(); localizationLanguage = new ConditionalWeakTable<Localization, string>(); localizationObjects = new List<WeakReference<Localization>>(); fileExtensions = new List<string>(2) { ".json", ".yml" }; Harmony val = new Harmony("org.bepinex.helpers.LocalizationManager"); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(Localization), "SetupLanguage", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalization", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "SetupGui", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "LoadLocalizationLater", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); val.Patch((MethodBase)AccessTools.DeclaredMethod(typeof(FejdStartup), "Start", (Type[])null, (Type[])null), (HarmonyMethod)null, new HarmonyMethod(AccessTools.DeclaredMethod(typeof(Localizer), "SafeCallLocalizeComplete", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } private static byte[]? LoadTranslationFromAssembly(string language) { foreach (string fileExtension in fileExtensions) { byte[] array = ReadEmbeddedFileBytes("translations." + language + fileExtension); if (array != null) { return array; } } return null; } public static byte[]? ReadEmbeddedFileBytes(string resourceFileName, Assembly? containingAssembly = null) { using MemoryStream memoryStream = new MemoryStream(); if ((object)containingAssembly == null) { containingAssembly = Assembly.GetCallingAssembly(); } string text = containingAssembly.GetManifestResourceNames().FirstOrDefault((string str) => str.EndsWith(resourceFileName, StringComparison.Ordinal)); if (text != null) { containingAssembly.GetManifestResourceStream(text)?.CopyTo(memoryStream); } return (memoryStream.Length == 0L) ? null : memoryStream.ToArray(); } } public static class LocalizationManagerVersion { public const string Version = "1.4.1"; } } namespace BiomeLock { public static class BiomeLockAPI { public const string PrivatePrefix = "bl_"; private static bool _resolved; private static Type? _tKeys; private static FieldInfo? _fiPrivateKeys; private static MethodInfo? _miNormalizeKey; private static void ResolveOnce() { if (_resolved) { return; } _resolved = true; _tKeys = Type.GetType("BiomeLock.BiomeLockPrivateKeys, " + typeof(BiomeLockPlugin).Assembly.GetName().Name, throwOnError: false); if (_tKeys == null) { _tKeys = typeof(BiomeLockPlugin).Assembly.GetType("BiomeLock.BiomeLockPrivateKeys", throwOnError: false); } if (!(_tKeys == null)) { _fiPrivateKeys = _tKeys.GetField("PrivateKeys", BindingFlags.Static | BindingFlags.NonPublic); if (_fiPrivateKeys == null) { _fiPrivateKeys = _tKeys.GetField("PrivateKeys", BindingFlags.Static | BindingFlags.Public); } _miNormalizeKey = _tKeys.GetMethod("NormalizeKey", BindingFlags.Static | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null) ?? _tKeys.GetMethod("NormalizeKey", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null); } } private static bool IsAvailable() { try { return (Object)(object)ZNetScene.instance != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null; } catch { return false; } } private static string NormalizeKey(string key) { if (key == null) { return string.Empty; } ResolveOnce(); try { if (_miNormalizeKey != null) { return (string)_miNormalizeKey.Invoke(null, new object[1] { key }); } } catch { } return key.Trim().ToLowerInvariant(); } private static string ToPrivateKey(string globalOrPrivateKey) { string text = NormalizeKey(globalOrPrivateKey); if (text.Length == 0) { return string.Empty; } if (text.StartsWith("bl_", StringComparison.Ordinal)) { return text; } return "bl_" + text; } public static bool HasPrivateKey(string globalOrPrivateKey) { if (!IsAvailable()) { return false; } string text = ToPrivateKey(globalOrPrivateKey); if (text.Length == 0) { return false; } HashSet<string> hashSet = TryGetPrivateKeysRef(); if (hashSet == null) { return false; } lock (hashSet) { return hashSet.Contains(text); } } private static HashSet<string>? TryGetPrivateKeysRef() { ResolveOnce(); if (_fiPrivateKeys == null) { return null; } try { return _fiPrivateKeys.GetValue(null) as HashSet<string>; } catch { return null; } } } internal static class AssetLoader { private static AssetBundle _bundle; private const string ResourceName = "BiomeLock.assets.rd_biome"; internal static void LoadBundle() { if ((Object)(object)_bundle != (Object)null) { return; } try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); using Stream stream = executingAssembly.GetManifestResourceStream("BiomeLock.assets.rd_biome"); if (stream != null) { byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); _bundle = AssetBundle.LoadFromMemory(array); } } catch { } } internal static Sprite GetSprite(string name) { LoadBundle(); if ((Object)(object)_bundle == (Object)null) { return null; } try { return _bundle.LoadAsset<Sprite>(name); } catch { return null; } } } internal static class BiomeLock_SE { [HarmonyPatch(typeof(Vegvisir), "Interact")] private static class Vegvisir_Interact_Block_HildirMapTable { private static bool Prefix(Vegvisir __instance) { try { if (!BiomeLockPlugin.CE_SE_Block_HildirMapTable.Value) { return true; } if ((Object)(object)__instance == (Object)null) { return true; } if (IsHildirMapTable(__instance)) { return false; } return true; } catch { return true; } } } [HarmonyPatch(typeof(Vegvisir), "GetHoverText")] private static class Vegvisir_GetHoverText_Block_HildirMapTable { private static bool Prefix(Vegvisir __instance, ref string __result) { try { if (!BiomeLockPlugin.CE_SE_Block_HildirMapTable.Value) { return true; } if ((Object)(object)__instance == (Object)null) { return true; } if (IsHildirMapTable(__instance)) { __result = string.Empty; return false; } return true; } catch { return true; } } } [HarmonyPatch(typeof(Vegvisir), "GetHoverName")] private static class Vegvisir_GetHoverName_Block_HildirMapTable { private static bool Prefix(Vegvisir __instance, ref string __result) { try { if (!BiomeLockPlugin.CE_SE_Block_HildirMapTable.Value) { return true; } if ((Object)(object)__instance == (Object)null) { return true; } if (IsHildirMapTable(__instance)) { __result = string.Empty; return false; } return true; } catch { return true; } } } [HarmonyPatch(typeof(Humanoid), "StartAttack")] private static class Humanoid_StartAttack_Block_All { private static bool Prefix(Humanoid __instance, ref bool __result) { try { if (!BiomeLockPlugin.CE_SE_Block_AttackBlock.Value) { return true; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if ((Object)(object)val == (Object)null) { return true; } if (!ShouldBlock(val)) { return true; } __result = false; return false; } catch { return true; } } } [HarmonyPatch(typeof(Humanoid), "IsBlocking")] private static class Humanoid_IsBlocking_Block_Parry { private static bool Prefix(Humanoid __instance, ref bool __result) { try { if (!BiomeLockPlugin.CE_SE_Block_AttackBlock.Value) { return true; } Player val = (Player)(object)((__instance is Player) ? __instance : null); if ((Object)(object)val == (Object)null) { return true; } if (!ShouldBlock(val)) { return true; } __result = false; return false; } catch { return true; } } } [HarmonyPatch(typeof(Attack), "OnAttackTrigger")] private static class Attack_OnAttackTrigger_Block_All { private static bool Prefix(Attack __instance) { try { if (!BiomeLockPlugin.CE_SE_Block_AttackBlock.Value) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return true; } if ((Object)(object)__instance.m_character != (Object)(object)localPlayer) { return true; } if (!ShouldBlock(localPlayer)) { return true; } return false; } catch { return true; } } } [HarmonyPatch(typeof(Player), "UpdateAttackBowDraw")] private static class Player_UpdateAttackBowDraw_Block_Draw { private static bool Prefix(Player __instance, ItemData weapon, float dt) { try { if (!BiomeLockPlugin.CE_SE_Block_AttackBlock.Value) { return true; } if ((Object)(object)__instance == (Object)null) { return true; } if (!ShouldBlock(__instance)) { return true; } ((Humanoid)__instance).m_attackDrawTime = -1f; if (weapon != null && weapon.m_shared != null && weapon.m_shared.m_attack != null && !string.IsNullOrEmpty(weapon.m_shared.m_attack.m_drawAnimationState)) { ((Character)__instance).m_zanim.SetBool(weapon.m_shared.m_attack.m_drawAnimationState, false); } return false; } catch { return true; } } } [HarmonyPatch(typeof(Player), "UpdateBiome")] private static class Player_UpdateBiome_ApplySE { private static void Postfix(Player __instance) { try { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { ApplyOrRemove(__instance); } } catch { } } } [HarmonyPatch(typeof(Hud), "Update")] private static class Hud_Update_Broadcast { private static void Postfix(Hud __instance) { if (!BiomeLockPlugin.CE_SE_Broadcast_Enabled.Value) { return; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null || !((Character)localPlayer).GetSEMan().HaveStatusEffect(SE_Hash)) { return; } float time = Time.time; float num = Mathf.Max(2f, BiomeLockPlugin.CE_SE_Broadcast_Interval.Value); if (time < _nextBroadcastTime) { return; } _nextBroadcastTime = time + num; if (BroadcastTokens.Length != 0) { string text = BroadcastTokens[Random.Range(0, BroadcastTokens.Length)]; string text2 = ((Localization.instance != null) ? Localization.instance.Localize(text) : text); MessageHud instance = MessageHud.instance; if (instance != null) { instance.ShowMessage((MessageType)2, text2, 0, (Sprite)null, false); } } } } [HarmonyPatch(typeof(ObjectDB), "Awake")] private static class ObjectDB_Awake_RegisterSE { private static void Postfix() { try { EnsureSERegistered(); } catch { } } } [HarmonyPatch(typeof(Teleport), "Interact")] private static class Teleport_Interact_BlockDungeon { private static bool Prefix(Teleport __instance, Humanoid character, bool hold, bool alt) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) try { if (!BiomeLockPlugin.CE_SE_Block_DungeonTeleport.Value) { return true; } if (hold) { return true; } Player val = (Player)(object)((character is Player) ? character : null); if ((Object)(object)val == (Object)null) { return true; } SEMan sEMan = ((Character)val).GetSEMan(); if (sEMan == null || !sEMan.HaveStatusEffect(SE_HASH)) { return true; } Biome biome = Heightmap.FindBiome(((Component)__instance).transform.position); if (!NeedsRestriction(val, biome)) { return true; } ((Character)val).Message((MessageType)2, "$biomelock_dungeon_blocked", 0, (Sprite)null); return false; } catch { return true; } } } [HarmonyPatch(typeof(Player), "UpdatePlacement")] private static class Player_UpdatePlacement_Block { private static bool Prefix(Player __instance) { if (!BiomeLockPlugin.CE_SE_Block_Hammer.Value) { return true; } return !ShouldBlock(__instance); } } [HarmonyPatch(typeof(Player), "PlacePiece")] private static class Player_PlacePiece_Block { private static bool Prefix(Player __instance) { if (!BiomeLockPlugin.CE_SE_Block_Hammer.Value) { return true; } return !ShouldBlock(__instance); } } [HarmonyPatch(typeof(Player), "Repair")] private static class Player_Repair_Block { private static bool Prefix(Player __instance) { if (!BiomeLockPlugin.CE_SE_Block_Hammer.Value) { return true; } return !ShouldBlock(__instance); } } [HarmonyPatch(typeof(Player), "RemovePiece")] private static class Player_RemovePiece_Block { private static bool Prefix(Player __instance) { if (!BiomeLockPlugin.CE_SE_Block_Hammer.Value) { return true; } return !ShouldBlock(__instance); } } [HarmonyPatch(typeof(Hud), "TogglePieceSelection")] private static class Hud_TogglePieceSelection_Block { private static bool Prefix(Hud __instance) { if (!BiomeLockPlugin.CE_SE_Block_Hammer.Value) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return true; } if (!ShouldBlock(localPlayer)) { return true; } if ((Object)(object)__instance != (Object)null && (Object)(object)__instance.m_pieceSelectionWindow != (Object)null && __instance.m_pieceSelectionWindow.activeSelf) { return true; } return false; } } [HarmonyPatch(typeof(Player), "AutoPickup")] private static class Player_AutoPickup_Block { private static bool Prefix(Player __instance) { if (!BiomeLockPlugin.CE_SE_Block_AutoPickup.Value) { return true; } return !ShouldBlock(__instance); } } [HarmonyPatch(typeof(Humanoid), "Pickup")] private static class Humanoid_Pickup_Block { private static bool Prefix(Humanoid __instance) { if (!BiomeLockPlugin.CE_SE_Block_Pickup.Value) { return true; } Player val = (Player)(object)((__instance is Player) ? __instance : null); return (Object)(object)val == (Object)null || !ShouldBlock(val); } } [HarmonyPatch] private static class Interact_Implementations_Block_UserHoldAlt { [CompilerGenerated] private sealed class <TargetMethods>d__0 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IDisposable, IEnumerator { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; private Assembly <asm>5__1; private Type <interactable>5__2; private Type[] <types>5__3; private ReflectionTypeLoadException <e>5__4; private int <i>5__5; private Type <t>5__6; private MethodInfo <m>5__7; private ParameterInfo[] <ps>5__8; MethodBase IEnumerator<MethodBase>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <TargetMethods>d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <asm>5__1 = null; <interactable>5__2 = null; <types>5__3 = null; <e>5__4 = null; <t>5__6 = null; <m>5__7 = null; <ps>5__8 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; <t>5__6 = null; <m>5__7 = null; <ps>5__8 = null; goto IL_0211; } <>1__state = -1; <asm>5__1 = typeof(Interactable).Assembly; <interactable>5__2 = typeof(Interactable); try { <types>5__3 = <asm>5__1.GetTypes(); } catch (ReflectionTypeLoadException ex) { <e>5__4 = ex; <types>5__3 = <e>5__4.Types ?? Array.Empty<Type>(); } <i>5__5 = 0; goto IL_0223; IL_0223: if (<i>5__5 < <types>5__3.Length) { <t>5__6 = <types>5__3[<i>5__5]; if (!(<t>5__6 == null) && !<t>5__6.IsInterface && !<t>5__6.IsAbstract && <interactable>5__2.IsAssignableFrom(<t>5__6)) { <m>5__7 = <t>5__6.GetMethod("Interact", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[3] { typeof(Humanoid), typeof(bool), typeof(bool) }, null); if (!(<m>5__7 == null) && <m>5__7.GetMethodBody() != null) { <ps>5__8 = <m>5__7.GetParameters(); if (<ps>5__8.Length == 3 && string.Equals(<ps>5__8[0].Name, "user", StringComparison.Ordinal) && string.Equals(<ps>5__8[1].Name, "hold", StringComparison.Ordinal)) { <>2__current = <m>5__7; <>1__state = 1; return true; } } } goto IL_0211; } return false; IL_0211: int num2 = <i>5__5 + 1; <i>5__5 = num2; goto IL_0223; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new <TargetMethods>d__0(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<MethodBase>)this).GetEnumerator(); } } [IteratorStateMachine(typeof(<TargetMethods>d__0))] private static IEnumerable<MethodBase> TargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <TargetMethods>d__0(-2); } private static bool Prefix(object __instance, Humanoid user, bool hold, bool alt, ref bool __result) { try { if (!BiomeLockPlugin.CE_SE_Block_GenericInteract.Value) { return true; } Player val = (Player)(object)((user is Player) ? user : null); if ((Object)(object)val == (Object)null) { return true; } if (!ShouldBlock(val)) { return true; } Component val2 = (Component)((__instance is Component) ? __instance : null); if ((Object)(object)val2 != (Object)null && IsAllowedInteractableGO(val2.gameObject)) { return true; } __result = false; return false; } catch { return true; } } } [HarmonyPatch] private static class Interact_Implementations_Block_CharacterRepeatAlt { [CompilerGenerated] private sealed class <TargetMethods>d__0 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IDisposable, IEnumerator { private int <>1__state; private MethodBase <>2__current; private int <>l__initialThreadId; private Assembly <asm>5__1; private Type <interactable>5__2; private Type[] <types>5__3; private ReflectionTypeLoadException <e>5__4; private int <i>5__5; private Type <t>5__6; private MethodInfo <m>5__7; private ParameterInfo[] <ps>5__8; MethodBase IEnumerator<MethodBase>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <TargetMethods>d__0(int <>1__state) { this.<>1__state = <>1__state; <>l__initialThreadId = Environment.CurrentManagedThreadId; } [DebuggerHidden] void IDisposable.Dispose() { <asm>5__1 = null; <interactable>5__2 = null; <types>5__3 = null; <e>5__4 = null; <t>5__6 = null; <m>5__7 = null; <ps>5__8 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; <t>5__6 = null; <m>5__7 = null; <ps>5__8 = null; goto IL_0211; } <>1__state = -1; <asm>5__1 = typeof(Interactable).Assembly; <interactable>5__2 = typeof(Interactable); try { <types>5__3 = <asm>5__1.GetTypes(); } catch (ReflectionTypeLoadException ex) { <e>5__4 = ex; <types>5__3 = <e>5__4.Types ?? Array.Empty<Type>(); } <i>5__5 = 0; goto IL_0223; IL_0223: if (<i>5__5 < <types>5__3.Length) { <t>5__6 = <types>5__3[<i>5__5]; if (!(<t>5__6 == null) && !<t>5__6.IsInterface && !<t>5__6.IsAbstract && <interactable>5__2.IsAssignableFrom(<t>5__6)) { <m>5__7 = <t>5__6.GetMethod("Interact", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[3] { typeof(Humanoid), typeof(bool), typeof(bool) }, null); if (!(<m>5__7 == null) && <m>5__7.GetMethodBody() != null) { <ps>5__8 = <m>5__7.GetParameters(); if (<ps>5__8.Length == 3 && string.Equals(<ps>5__8[0].Name, "character", StringComparison.Ordinal) && string.Equals(<ps>5__8[1].Name, "repeat", StringComparison.Ordinal)) { <>2__current = <m>5__7; <>1__state = 1; return true; } } } goto IL_0211; } return false; IL_0211: int num2 = <i>5__5 + 1; <i>5__5 = num2; goto IL_0223; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } [DebuggerHidden] IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator() { if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId) { <>1__state = 0; return this; } return new <TargetMethods>d__0(0); } [DebuggerHidden] IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable<MethodBase>)this).GetEnumerator(); } } [IteratorStateMachine(typeof(<TargetMethods>d__0))] private static IEnumerable<MethodBase> TargetMethods() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <TargetMethods>d__0(-2); } private static bool Prefix(object __instance, Humanoid character, bool repeat, bool alt, ref bool __result) { try { if (!BiomeLockPlugin.CE_SE_Block_GenericInteract.Value) { return true; } Player val = (Player)(object)((character is Player) ? character : null); if ((Object)(object)val == (Object)null) { return true; } if (!ShouldBlock(val)) { return true; } Component val2 = (Component)((__instance is Component) ? __instance : null); if ((Object)(object)val2 != (Object)null && IsAllowedInteractableGO(val2.gameObject)) { return true; } __result = false; return false; } catch { return true; } } } [HarmonyPatch(typeof(ItemDrop), "Interact")] private static class ItemDrop_Interact_Block { private static bool Prefix(Humanoid character, ref bool __result) { try { if (!BiomeLockPlugin.CE_SE_Block_ItemDropInteract.Value) { return true; } Player val = (Player)(object)((character is Player) ? character : null); if ((Object)(object)val == (Object)null) { return true; } if (ShouldBlock(val)) { __result = false; return false; } return true; } catch { return true; } } } [HarmonyPatch(typeof(Pickable), "Interact")] private static class Pickable_Interact_Block { private static bool Prefix(Humanoid character, ref bool __result) { try { if (!BiomeLockPlugin.CE_SE_Block_PickableInteract.Value) { return true; } Player val = (Player)(object)((character is Player) ? character : null); if ((Object)(object)val == (Object)null) { return true; } if (ShouldBlock(val)) { __result = false; return false; } return true; } catch { return true; } } } [HarmonyPatch(typeof(Container), "Interact")] private static class Container_Interact_Block { private static bool Prefix(Container __instance, Humanoid character, ref bool __result) { try { if (!BiomeLockPlugin.CE_SE_Block_ContainerInteract.Value) { return true; } Player val = (Player)(object)((character is Player) ? character : null); if ((Object)(object)val == (Object)null) { return true; } if (!ShouldBlock(val)) { return true; } if (IsAllowedInteractableGO(((Component)__instance).gameObject)) { return true; } __result = false; return false; } catch { return true; } } } [HarmonyPatch(typeof(Minimap), "ShowPinNameInput")] private static class Minimap_ShowPinNameInput_Block_When_SE_Active { private static bool Prefix(Vector3 pos) { try { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return true; } SEMan sEMan = ((Character)localPlayer).GetSEMan(); if (sEMan == null || !sEMan.HaveStatusEffect(SE_HASH)) { return true; } ((Character)localPlayer).Message((MessageType)2, "$biomelock_map_pin_blocked", 0, (Sprite)null); return false; } catch { return true; } } } [HarmonyPatch(typeof(Minimap), "UpdateExplore")] private static class Minimap_UpdateExplore_Block { private static bool Prefix(Minimap __instance, Player player) { try { if (!BiomeLockPlugin.CE_SE_Block_MapExplore.Value) { return true; } if ((Object)(object)player == (Object)null) { return true; } if (!ShouldBlock(player)) { return true; } __instance.m_exploreTimer = 0f; return false; } catch { return true; } } } [HarmonyPatch(typeof(StoreGui), "Show", new Type[] { typeof(Trader) })] private static class StoreGui_Show_Block { private static bool Prefix(StoreGui __instance, Trader trader) { try { if (BiomeLockPlugin.CE_SE_AdminBypass.Value && BiomeLockPlugin.IsLocalPlayerAdmin()) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return true; } if (!HasBiomeLockSE(localPlayer)) { return true; } if (TraderAllowedByApiRule(trader)) { return true; } MessageHud instance = MessageHud.instance; if (instance != null) { instance.ShowMessage((MessageType)2, "$bl_se_trader_blocked", 0, (Sprite)null, false); } return false; } catch { return true; } } } [HarmonyPatch(typeof(Heightmap), "ApplyModifier")] private static class Heightmap_ApplyModifier_Block_PlayerTerrain { private static bool Prefix(Heightmap __instance, TerrainModifier modifier, float[] baseHeights, float[] levelOnly) { try { if (!BiomeLockPlugin.CE_SE_Block_TerrainHoe.Value) { return true; } Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { return true; } if (!ShouldBlock(localPlayer)) { return true; } if ((Object)(object)modifier == (Object)null) { return true; } if (!modifier.m_playerModifiction) { return true; } return false; } catch { return true; } } } [HarmonyPatch(typeof(SpawnSystem), "GetPlayersInZone")] private static class SpawnSystem_GetPlayersInZone_FilterRestrictedPlayers { private static void Postfix(List<Player> players) { try { if (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) && HasBiomeLockSE(val)) { players.RemoveAt(num); } } } catch { } } } [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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) try { List<Player> allPlayers = Player.GetAllPlayers(); if (allPlayers == null || allPlayers.Count == 0) { __result = false; return false; } float num = range * range; for (int i = 0; i < allPlayers.Count; i++) { Player val = allPlayers[i]; if (!((Object)(object)val == (Object)null) && !HasBiomeLockSE(val)) { Vector3 val2 = ((Component)val).transform.position - point; if (((Vector3)(ref val2)).sqrMagnitude <= num) { __result = true; return false; } } } __result = false; return false; } catch { return true; } } } private static Biome _blockedBiomesCache = (Biome)0; private static string _blockedBiomesRaw = ""; private const string SE_Name = "SE_BiomeLock"; private static readonly int SE_Hash = StringExtensionMethods.GetStableHashCode("SE_BiomeLock"); 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" }; internal const string SE_NAME = "SE_BiomeLock"; internal static readonly int SE_HASH = StringExtensionMethods.GetStableHashCode("SE_BiomeLock"); private static readonly HashSet<string> AllowedInteractables = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "TombStone", "ShipControlls", "Ladder", "Saddle", "Sadle", "Chair" }; private const string MapPinBlockedToken = "$biomelock_map_pin_blocked"; internal static readonly Dictionary<Biome, string> BiomeRequirement = new Dictionary<Biome, string> { { (Biome)8, "defeated_eikthyr" }, { (Biome)256, "defeated_eikthyr" }, { (Biome)2, "defeated_gdking" }, { (Biome)4, "defeated_bonemass" }, { (Biome)16, "defeated_dragon" }, { (Biome)512, "defeated_goblinking" }, { (Biome)32, "defeated_queen" }, { (Biome)64, "defeated_fader" } }; private static bool IsHildirMapTable(Vegvisir v) { return v.m_locations != null && v.m_locations.Count > 1; } private static Biome GetBlockedBiomes() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) string text = BiomeLockPlugin.CE_SE_BlockedBiomes.Value ?? ""; if (string.Equals(text, _blockedBiomesRaw, StringComparison.Ordinal)) { return _blockedBiomesCache; } _blockedBiomesRaw = text; _blockedBiomesCache = (Biome)0; string[] array = text.Split(new char[6] { ',', ';', ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { if (Enum.TryParse<Biome>(array[i], ignoreCase: true, out Biome result)) { _blockedBiomesCache |= result; } } return _blockedBiomesCache; } private static bool IsBiomeBlockedByConfig(Biome biome) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 return (GetBlockedBiomes() & biome) > 0; } internal static void ApplyOrRemove(Player p) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)p == (Object)null || ((Character)p).InIntro() || ((Character)p).IsDead() || ((Character)p).InCutscene() || ((Character)p).IsTeleporting() || p.m_isLoading || (Object.op_Implicit((Object)(object)((Character)p).m_nview) && !((Character)p).m_nview.IsOwner())) { return; } Biome currentBiome = p.GetCurrentBiome(); bool flag = IsBiomeBlockedByConfig(currentBiome) && NeedsRestriction(p, currentBiome); SEMan sEMan = ((Character)p).GetSEMan(); if (sEMan == null) { return; } bool flag2 = sEMan.HaveStatusEffect(SE_HASH); if (flag) { if (!flag2) { EnsureSERegistered(); sEMan.AddStatusEffect(SE_HASH, true, 0, 0f); } } else if (flag2) { sEMan.RemoveStatusEffect(SE_HASH, true); } } internal static void EnsureSERegistered() { if (Object.op_Implicit((Object)(object)ObjectDB.instance)) { StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect(SE_HASH); if (!((Object)(object)statusEffect != (Object)null)) { StatusEffect val = ScriptableObject.CreateInstance<StatusEffect>(); ((Object)val).name = "SE_BiomeLock"; val.m_name = "$se_biome_lock"; val.m_category = "BiomeLock"; val.m_tooltip = "$biomelock_se_tooltip"; val.m_ttl = 0f; val.m_startMessage = ""; val.m_stopMessage = ""; val.m_repeatMessage = ""; val.m_repeatInterval = 0f; val.m_icon = AssetLoader.GetSprite("biomelock_icon"); ObjectDB.instance.m_StatusEffects.Add(val); } } } private static bool IsAllowedInteractableGO(GameObject go) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown try { if ((Object)(object)go == (Object)null) { return false; } if ((Object)(object)go.GetComponent<TombStone>() != (Object)null) { return true; } if ((Object)(object)go.GetComponentInParent<TombStone>() != (Object)null) { return true; } Interactable val = go.GetComponent<Interactable>() ?? go.GetComponentInParent<Interactable>(); if ((Object)val == (Object)null) { return false; } return AllowedInteractables.Contains(((object)val).GetType().Name); } catch { return false; } } private static bool ShouldBlock(Player p) { int result; if ((Object)(object)p == (Object)(object)Player.m_localPlayer) { SEMan sEMan = ((Character)p).GetSEMan(); result = ((sEMan != null && sEMan.HaveStatusEffect(SE_HASH)) ? 1 : 0); } else { result = 0; } return (byte)result != 0; } internal static bool NeedsRestriction(Player p, Biome biome) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) if (BiomeLockPlugin.CE_SE_AdminBypass.Value && BiomeLockPlugin.IsLocalPlayerAdmin()) { return false; } if (!BiomeRequirement.TryGetValue(biome, out string value)) { return false; } if (string.IsNullOrEmpty(value)) { return false; } return !BiomeLockAPI.HasPrivateKey(value); } private static string GetPrefabName(GameObject go) { try { if ((Object)(object)go == (Object)null) { return string.Empty; } ZNetView component = go.GetComponent<ZNetView>(); if ((Object)(object)component == (Object)null) { return string.Empty; } ZDO zDO = component.GetZDO(); if (zDO == null) { return string.Empty; } int prefab = zDO.GetPrefab(); if (prefab == 0 || (Object)(object)ZNetScene.instance == (Object)null) { return string.Empty; } GameObject prefab2 = ZNetScene.instance.GetPrefab(prefab); return ((Object)(object)prefab2 != (Object)null) ? ((Object)prefab2).name : string.Empty; } catch { return string.Empty; } } private static bool TraderAllowedByApiRule(Trader t) { try { if ((Object)(object)t == (Object)null) { return true; } string text = GetPrefabName(((Component)t).gameObject); if (string.IsNullOrEmpty(text)) { text = ((Object)t).name ?? ((Object)((Component)t).gameObject).name; } if (!string.IsNullOrEmpty(text) && text.EndsWith("(Clone)", StringComparison.Ordinal)) { text = text.Replace("(Clone)", string.Empty); } if (text == "Haldor") { return BiomeLockAPI.HasPrivateKey("defeated_eikthyr"); } if (text == "BogWitch") { return BiomeLockAPI.HasPrivateKey("defeated_gdking"); } return true; } catch { return true; } } private static bool HasBiomeLockSE(Player p) { try { if (!BiomeLockPlugin.CE_SE_Block_SpawnBlock.Value) { return false; } if ((Object)(object)p == (Object)null) { return false; } SEMan sEMan = ((Character)p).GetSEMan(); return sEMan != null && sEMan.HaveStatusEffect(SE_HASH); } catch { return false; } } } [HarmonyPatch] internal static class BiomeLock_ZoneSystem_GetGlobalKey_RedirectPrivateKeys { private static readonly HashSet<string> RedirectedKeys = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "defeated_eikthyr", "defeated_gdking", "defeated_bonemass", "defeated_dragon", "defeated_goblinking", "defeated_queen", "defeated_fader", "defeated_serpent", "KilledTroll", "killed_surtling", "KilledBat", "Hildir1", "Hildir2", "Hildir3" }; private static MethodBase TargetMethod() { return AccessTools.Method(typeof(ZoneSystem), "GetGlobalKey", new Type[2] { typeof(string), typeof(string).MakeByRefType() }, (Type[])null); } private static bool Prefix(string name, ref string value, ref bool __result) { try { 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 (BiomeLockPlugin.CE_SE_AdminBypass.Value && BiomeLockPlugin.IsLocalPlayerAdmin()) { return true; } if (!RedirectedKeys.Contains(name)) { return true; } __result = BiomeLockAPI.HasPrivateKey(name); value = string.Empty; return false; } catch { return true; } } } internal static class BiomeLock_KeyRefresh { private static bool _pending; private static float _nextRunAt; private static MethodInfo? _miStoreGui_FillList; private static MethodInfo? _miInventoryGui_UpdateCraftingPanel; private static MethodInfo? _miInventoryGui_UpdateRecipeList; private static MethodInfo? _miPlayer_UpdateKnownRecipesList; private static MethodInfo? _miPlayer_UpdateAvailablePiecesList; internal static void NotifyKeysChanged() { try { _pending = true; float time = Time.time; if (_nextRunAt < time) { _nextRunAt = time + 0.05f; } } catch { } } private static void EnsureMethods() { if (_miStoreGui_FillList == null) { _miStoreGui_FillList = AccessTools.Method(typeof(StoreGui), "FillList", (Type[])null, (Type[])null); } if (_miInventoryGui_UpdateCraftingPanel == null) { _miInventoryGui_UpdateCraftingPanel = AccessTools.Method(typeof(InventoryGui), "UpdateCraftingPanel", (Type[])null, (Type[])null); } if (_miInventoryGui_UpdateRecipeList == null) { _miInventoryGui_UpdateRecipeList = AccessTools.Method(typeof(InventoryGui), "UpdateRecipeList", (Type[])null, (Type[])null); } if (_miPlayer_UpdateKnownRecipesList == null) { _miPlayer_UpdateKnownRecipesList = AccessTools.Method(typeof(Player), "UpdateKnownRecipesList", (Type[])null, (Type[])null); } if (_miPlayer_UpdateAvailablePiecesList == null) { _miPlayer_UpdateAvailablePiecesList = AccessTools.Method(typeof(Player), "UpdateAvailablePiecesList", (Type[])null, (Type[])null); } } internal static void TryRunPending() { try { if (!_pending || Time.time < _nextRunAt) { return; } _pending = false; if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsDedicated() || (Object)(object)Player.m_localPlayer == (Object)null) { return; } EnsureMethods(); Player localPlayer = Player.m_localPlayer; try { if (_miPlayer_UpdateKnownRecipesList != null) { _miPlayer_UpdateKnownRecipesList.Invoke(localPlayer, Array.Empty<object>()); } if (_miPlayer_UpdateAvailablePiecesList != null) { _miPlayer_UpdateAvailablePiecesList.Invoke(localPlayer, Array.Empty<object>()); } } catch { } try { localPlayer.UpdateEvents(); } catch { } try { if ((Object)(object)InventoryGui.instance != (Object)null) { if (_miInventoryGui_UpdateCraftingPanel != null) { _miInventoryGui_UpdateCraftingPanel.Invoke(InventoryGui.instance, Array.Empty<object>()); } if (_miInventoryGui_UpdateRecipeList != null) { _miInventoryGui_UpdateRecipeList.Invoke(InventoryGui.instance, Array.Empty<object>()); } } } catch { } try { if ((Object)(object)StoreGui.instance != (Object)null && StoreGui.IsVisible() && _miStoreGui_FillList != null) { _miStoreGui_FillList.Invoke(StoreGui.instance, Array.Empty<object>()); } } catch { } } catch { } } } [HarmonyPatch(typeof(Hud), "Update")] internal static class BL_KeyRefresh_HudUpdate { private static void Postfix() { BiomeLock_KeyRefresh.TryRunPending(); } } [HarmonyPatch] internal static class BL_KeyRefresh_RPC_SetPrivateKey { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(BiomeLockPrivateKeys), "RPC_BL_SetPrivateKey", (Type[])null, (Type[])null); } private static void Postfix() { BiomeLock_KeyRefresh.NotifyKeysChanged(); } } [HarmonyPatch] internal static class BL_KeyRefresh_RPC_RemovePrivateKey { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(BiomeLockPrivateKeys), "RPC_BL_RemovePrivateKey", (Type[])null, (Type[])null); } private static void Postfix() { BiomeLock_KeyRefresh.NotifyKeysChanged(); } } [HarmonyPatch] internal static class BL_KeyRefresh_RPC_ResetPrivateKeys { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(BiomeLockPrivateKeys), "RPC_BL_ResetPrivateKeys", (Type[])null, (Type[])null); } private static void Postfix() { BiomeLock_KeyRefresh.NotifyKeysChanged(); } } [HarmonyPatch] internal static class BL_KeyRefresh_LoadKeysFromPlayer { private static MethodBase TargetMethod() { return AccessTools.Method(typeof(BiomeLockPrivateKeys), "LoadKeysFromPlayer", (Type[])null, (Type[])null); } private static void Postfix() { BiomeLock_KeyRefresh.NotifyKeysChanged(); } } internal static class BiomeLock_SkillCapBoss { internal static void Init() { } internal static int GetEffectiveSkillCap() { int cap = 0; ApplyCapIfMissing("defeated_eikthyr", BiomeLockPlugin.CE_SkillCap_Eikthyr.Value); ApplyCapIfMissing("defeated_gdking", BiomeLockPlugin.CE_SkillCap_Elder.Value); ApplyCapIfMissing("defeated_bonemass", BiomeLockPlugin.CE_SkillCap_Bonemass.Value); ApplyCapIfMissing("defeated_dragon", BiomeLockPlugin.CE_SkillCap_Moder.Value); ApplyCapIfMissing("defeated_goblinking", BiomeLockPlugin.CE_SkillCap_Yagluth.Value); ApplyCapIfMissing("defeated_queen", BiomeLockPlugin.CE_SkillCap_Queen.Value); ApplyCapIfMissing("defeated_fader", BiomeLockPlugin.CE_SkillCap_Fader.Value); return cap; void ApplyCapIfMissing(string bossKey, int bossCap) { if (bossCap > 0 && !BiomeLockAPI.HasPrivateKey(bossKey)) { if (cap <= 0) { cap = bossCap; } else { cap = Mathf.Min(cap, bossCap); } } } } } [HarmonyPatch(typeof(Skills), "RaiseSkill")] internal static class BiomeLock_SkillCapBoss_RaiseSkill_Patch { 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; } } } } internal static class BiomeLock_GuardianPowerKey { [HarmonyPatch(typeof(ItemStand), "DelayedPowerActivation")] private static class Patch_ItemStand_DelayedPowerActivation { [HarmonyPriority(100)] private static bool Prefix(ItemStand __instance) { try { if (ShouldBlock(__instance)) { NotifyBlocked(); return false; } return true; } catch { return true; } } } private static string GetNameSafe(Object? obj) { try { if (obj == (Object)null) { return string.Empty; } string text = obj.name ?? string.Empty; int num = text.IndexOf("(Clone)", StringComparison.Ordinal); if (num >= 0) { text = text.Substring(0, num); } return text.Trim(); } catch { return string.Empty; } } private static string GetRequiredGuardianPowerGlobalKeyLower(string guardianPowerName) { if (guardianPowerName.Length == 0) { return string.Empty; } if (guardianPowerName.Equals("GP_Eikthyr", StringComparison.OrdinalIgnoreCase)) { return "defeated_eikthyr"; } if (guardianPowerName.Equals("GP_TheElder", StringComparison.OrdinalIgnoreCase)) { return "defeated_gdking"; } if (guardianPowerName.Equals("GP_Bonemass", StringComparison.OrdinalIgnoreCase)) { return "defeated_bonemass"; } if (guardianPowerName.Equals("GP_Moder", StringComparison.OrdinalIgnoreCase)) { return "defeated_dragon"; } if (guardianPowerName.Equals("GP_Yagluth", StringComparison.OrdinalIgnoreCase)) { return "defeated_goblinking"; } if (guardianPowerName.Equals("GP_Queen", StringComparison.OrdinalIgnoreCase)) { return "defeated_queen"; } if (guardianPowerName.Equals("GP_Fader", StringComparison.OrdinalIgnoreCase)) { return "defeated_fader"; } return string.Empty; } public static bool ShouldBlock(ItemStand stand) { try { if ((Object)(object)Player.m_localPlayer == (Object)null) { return false; } if (BiomeLockPlugin.CE_SE_AdminBypass.Value && BiomeLockPlugin.IsLocalPlayerAdmin()) { return false; } if ((Object)(object)stand == (Object)null) { return false; } string nameSafe = GetNameSafe((Object?)(object)stand.m_guardianPower); string requiredGuardianPowerGlobalKeyLower = GetRequiredGuardianPowerGlobalKeyLower(nameSafe); if (requiredGuardianPowerGlobalKeyLower.Length == 0) { return false; } return !BiomeLockAPI.HasPrivateKey(requiredGuardianPowerGlobalKeyLower); } catch { return false; } } private static void NotifyBlocked() { try { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { ((Character)localPlayer).Message((MessageType)2, Localization.instance.Localize("$biomelock_guardian_power_locked"), 0, (Sprite)null); } } catch { } } } internal static class BiomeLock_BossSummonDay { [HarmonyPatch(typeof(OfferingBowl), "InitiateSpawnBoss")] private static class Patch_OfferingBowl_InitiateSpawnBoss { [HarmonyPriority(200)] private static bool Prefix(OfferingBowl __instance) { try { if (ShouldBlock(__instance, out var requiredDay, out var currentDay)) { NotifyBlocked(requiredDay, currentDay); return false; } return true; } catch { return true; } } } private static string GetPrefabNameSafe(GameObject? go) { try { if ((Object)(object)go == (Object)null) { return string.Empty; } string text = ((Object)go).name ?? string.Empty; int num = text.IndexOf("(Clone)", StringComparison.Ordinal); if (num >= 0) { text = text.Substring(0, num); } return text.Trim(); } catch { return string.Empty; } } private static int GetCurrentDaySafe() { try { if ((Object)(object)EnvMan.instance == (Object)null) { return 0; } return EnvMan.instance.GetDay(); } catch { return 0; } } private static int GetRequiredDayForBoss(string bossPrefabName) { if (bossPrefabName.Length == 0) { return 0; } if (bossPrefabName.Equals("Eikthyr", StringComparison.OrdinalIgnoreCase)) { return BiomeLockPlugin.CE_BossDay_Eikthyr.Value; } if (bossPrefabName.Equals("gd_king", StringComparison.OrdinalIgnoreCase)) { return BiomeLockPlugin.CE_BossDay_Elder.Value; } if (bossPrefabName.Equals("Bonemass", StringComparison.OrdinalIgnoreCase)) { return BiomeLockPlugin.CE_BossDay_Bonemass.Value; } if (bossPrefabName.Equals("Dragon", StringComparison.OrdinalIgnoreCase)) { return BiomeLockPlugin.CE_BossDay_Moder.Value; } if (bossPrefabName.Equals("GoblinKing", StringComparison.OrdinalIgnoreCase)) { return BiomeLockPlugin.CE_BossDay_Yagluth.Value; } if (bossPrefabName.Equals("SeekerQueen", StringComparison.OrdinalIgnoreCase)) { return BiomeLockPlugin.CE_BossDay_Queen.Value; } if (bossPrefabName.Equals("Fader", StringComparison.OrdinalIgnoreCase)) { return BiomeLockPlugin.CE_BossDay_Fader.Value; } return 0; } public static bool ShouldBlock(OfferingBowl bowl, out int requiredDay, out int currentDay) { requiredDay = 0; currentDay = 0; try { if ((Object)(object)Player.m_localPlayer == (Object)null) { return false; } if (!BiomeLockPlugin.CE_BossDay_Enabled.Value) { return false; } if (BiomeLockPlugin.CE_SE_AdminBypass.Value && BiomeLockPlugin.IsLocalPlayerAdmin()) { return false; } if ((Object)(object)bowl == (Object)null) { return false; } if ((Object)(object)bowl.m_bossPrefab == (Object)null) { return false; } string prefabNameSafe = GetPrefabNameSafe(bowl.m_bossPrefab); requiredDay = GetRequiredDayForBoss(prefabNameSafe); if (requiredDay <= 0) { return false; } currentDay = GetCurrentDaySafe(); return currentDay < requiredDay; } catch { return false; } } private static void NotifyBlocked(int requiredDay, int currentDay) { try { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { ((Character)localPlayer).Message((MessageType)2, string.Format(Localization.instance.Localize("$biomelock_boss_day_locked"), requiredDay, currentDay), 0, (Sprite)null); } } catch { } } } internal static class BiomeLock_BossSummonKey { [HarmonyPatch(typeof(OfferingBowl), "InitiateSpawnBoss")] private static class Patch_OfferingBowl_InitiateSpawnBoss { [HarmonyPriority(100)] private static bool Prefix(OfferingBowl __instance) { try { if (ShouldBlock(__instance)) { NotifyBlocked(); return false; } return true; } catch { return true; } } } private static string GetPrefabNameSafe(GameObject? go) { try { if ((Object)(object)go == (Object)null) { return string.Empty; } string text = ((Object)go).name ?? string.Empty; int num = text.IndexOf("(Clone)", StringComparison.Ordinal); if (num >= 0) { text = text.Substring(0, num); } return text.Trim(); } catch { return string.Empty; } } private static string GetRequiredPreviousBossGlobalKeyLower(string bossPrefabName) { if (bossPrefabName.Length == 0) { return string.Empty; } if (bossPrefabName.Equals("Eikthyr", StringComparison.OrdinalIgnoreCase)) { return string.Empty; } if (bossPrefabName.Equals("gd_king", StringComparison.OrdinalIgnoreCase)) { return "defeated_eikthyr"; } if (bossPrefabName.Equals("Bonemass", StringComparison.OrdinalIgnoreCase)) { return "defeated_gdking"; } if (bossPrefabName.Equals("Dragon", StringComparison.OrdinalIgnoreCase)) { return "defeated_bonemass"; } if (bossPrefabName.Equals("GoblinKing", StringComparison.OrdinalIgnoreCase)) { return "defeated_dragon"; } if (bossPrefabName.Equals("SeekerQueen", StringComparison.OrdinalIgnoreCase)) { return "defeated_goblinking"; } if (bossPrefabName.Equals("Fader", StringComparison.OrdinalIgnoreCase)) { return "defeated_queen"; } return string.Empty; } public static bool ShouldBlock(OfferingBowl bowl) { try { if ((Object)(object)Player.m_localPlayer == (Object)null) { return false; } if (!BiomeLockPlugin.CE_BossPrevKey_Enabled.Value) { return false; } if (BiomeLockPlugin.CE_SE_AdminBypass.Value && BiomeLockPlugin.IsLocalPlayerAdmin()) { return false; } if ((Object)(object)bowl == (Object)null) { return false; } if ((Object)(object)bowl.m_bossPrefab == (Object)null) { return false; } if (BiomeLock_BossSummonDay.ShouldBlock(bowl, out var _, out var _)) { return false; } string prefabNameSafe = GetPrefabNameSafe(bowl.m_bossPrefab); string requiredPreviousBossGlobalKeyLower = GetRequiredPreviousBossGlobalKeyLower(prefabNameSafe); if (requiredPreviousBossGlobalKeyLower.Length == 0) { return false; } return !BiomeLockAPI.HasPrivateKey(requiredPreviousBossGlobalKeyLower); } catch { return false; } } private static void NotifyBlocked() { try { Player localPlayer = Player.m_localPlayer; if (!((Object)(object)localPlayer == (Object)null)) { ((Character)localPlayer).Message((MessageType)2, Localization.instance.Localize("$biomelock_boss_prev_key_locked"), 0, (Sprite)null); } } catch { } } } [HarmonyPatch(typeof(Terminal), "InitTerminal")] internal static class BL_Commands { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static ConsoleEvent <>9__1_0; public static ConsoleEvent <>9__1_1; public static ConsoleEvent <>9__1_2; public static ConsoleEvent <>9__1_3; internal void <Postfix>b__1_0(ConsoleEventArgs args) { if (!RequireAdmin(args)) { return; } if (args.Length < 2) { args.Context.AddString("Syntax: bl_setkey bl_<key> [optional: player name]"); return; } if (!TryGetPrivateKeyArg(args[1], out string privateKey, out string error)) { args.Context.AddString(error); return; } long uid = 0L; string text = ""; bool flag = true; if (args.Length >= 3) { string text2 = JoinName(args, 2).Trim(); text = text2; flag = IsLocalPlayerName(text2); if (!flag && !BiomeLockPrivateKeys.TryResolveUidByPlayerName(text2, out uid)) { args.Context.AddString("Player not found: " + text2); return; } } if (ZRoutedRpc.instance == null) { args.Context.AddString("ZRoutedRpc not ready."); return; } if (uid == 0) { uid = ZNet.GetUID(); } ZRoutedRpc.instance.InvokeRoutedRPC(uid, "BL_SetPrivateKey", new object[1] { privateKey }); args.Context.AddString(flag ? ("Key added to you: " + privateKey) : ("Key added to player: " + text + " -> " + privateKey)); } internal void <Postfix>b__1_1(ConsoleEventArgs args) { if (!RequireAdmin(args)) { return; } if (args.Length < 2) { args.Context.AddString("Syntax: bl_removekey bl_<key> [optional: player name]"); return; } if (!TryGetPrivateKeyArg(args[1], out string privateKey, out string error)) { args.Context.AddString(error); return; } long uid = 0L; string text = ""; bool flag = true; if (args.Length >= 3) { string text2 = JoinName(args, 2).Trim(); text = text2; flag = IsLocalPlayerName(text2); if (!flag && !BiomeLockPrivateKeys.TryResolveUidByPlayerName(text2, out uid)) { args.Context.AddString("Player not found: " + text2); return; } } if (ZRoutedRpc.instance == null) { args.Context.AddString("ZRoutedRpc not ready."); return; } if (uid == 0) { uid = ZNet.GetUID(); } ZRoutedRpc.instance.InvokeRoutedRPC(uid, "BL_RemovePrivateKey", new object[1] { privateKey }); args.Context.AddString(flag ? ("Key removed from you: " + privateKey) : ("Key removed from player: " + text + " -> " + privateKey)); } internal void <Postfix>b__1_2(ConsoleEventArgs args) { if (!RequireAdmin(args)) { return; } long uid = 0L; string text = ""; bool flag = true; if (args.Length >= 2) { string text2 = JoinName(args, 1).Trim(); text = text2; flag = IsLocalPlayerName(text2); if (!flag && !BiomeLockPrivateKeys.TryResolveUidByPlayerName(text2, out uid)) { args.Context.AddString("Player not found: " + text2); return; } } if (ZRoutedRpc.instance == null) { args.Context.AddString("ZRoutedRpc not ready."); return; } if (uid == 0) { uid = ZNet.GetUID(); } ZRoutedRpc.instance.InvokeRoutedRPC(uid, "BL_ResetPrivateKeys", Array.Empty<object>()); args.Context.AddString(flag ? "Keys reset for you." : ("Keys reset for player: " + text + ".")); } internal void <Postfix>b__1_3(ConsoleEventArgs args) { if (!RequireAdmin(args)) { return; } if (args.Length == 1) { args.Context.AddString("Listing local keys:"); args.Context.AddString("Total Keys: " + BiomeLockPrivateKeys.PrivateKeys.Count); { foreach (string privateKey in BiomeLockPrivateKeys.PrivateKeys) { args.Context.AddString(privateKey); } return; } } string text = JoinName(args, 1).Trim(); if (IsLocalPlayerName(text)) { args.Context.AddString("Listing local keys:"); args.Context.AddString("Total Keys: " + BiomeLockPrivateKeys.PrivateKeys.Count); { foreach (string privateKey2 in BiomeLockPrivateKeys.PrivateKeys) { args.Context.AddString(privateKey2); } return; } } if (!BiomeLockPrivateKeys.TryResolveUidByPlayerName(text, out var uid)) { args.Context.AddString("Player not found: " + text); return; } if (ZRoutedRpc.instance == null) { args.Context.AddString("ZRoutedRpc not ready."); return; } ZRoutedRpc.instance.InvokeRoutedRPC("BL_ServerListKeys", new object[1] { uid }); } } [HarmonyPriority(800)] private static void Prefix(out bool __state) { __state = Terminal.m_terminalInitialized; } private static void Postfix(bool __state) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_00ad: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown if (__state) { return; } object obj = <>c.<>9__1_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { if (RequireAdmin(args)) { string privateKey2; string error2; if (args.Length < 2) { args.Context.AddString("Syntax: bl_setkey bl_<key> [optional: player name]"); } else if (!TryGetPrivateKeyArg(args[1], out privateKey2, out error2)) { args.Context.AddString(error2); } else { long uid4 = 0L; string text6 = ""; bool flag3 = true; if (args.Length >= 3) { string text7 = JoinName(args, 2).Trim(); text6 = text7; flag3 = IsLocalPlayerName(text7); if (!flag3 && !BiomeLockPrivateKeys.TryResolveUidByPlayerName(text7, out uid4)) { args.Context.AddString("Player not found: " + text7); return; } } if (ZRoutedRpc.instance == null) { args.Context.AddString("ZRoutedRpc not ready."); } else { if (uid4 == 0) { uid4 = ZNet.GetUID(); } ZRoutedRpc.instance.InvokeRoutedRPC(uid4, "BL_SetPrivateKey", new object[1] { privateKey2 }); args.Context.AddString(flag3 ? ("Key added to you: " + privateKey2) : ("Key added to player: " + text6 + " -> " + privateKey2)); } } } }; <>c.<>9__1_0 = val; obj = (object)val; } new ConsoleCommand("bl_setkey", "[bl_key] [optional: player name]", (ConsoleEvent)obj, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj2 = <>c.<>9__1_1; if (obj2 == null) { ConsoleEvent val2 = delegate(ConsoleEventArgs args) { if (RequireAdmin(args)) { string privateKey; string error; if (args.Length < 2) { args.Context.AddString("Syntax: bl_removekey bl_<key> [optional: player name]"); } else if (!TryGetPrivateKeyArg(args[1], out privateKey, out error)) { args.Context.AddString(error); } else { long uid3 = 0L; string text4 = ""; bool flag2 = true; if (args.Length >= 3) { string text5 = JoinName(args, 2).Trim(); text4 = text5; flag2 = IsLocalPlayerName(text5); if (!flag2 && !BiomeLockPrivateKeys.TryResolveUidByPlayerName(text5, out uid3)) { args.Context.AddString("Player not found: " + text5); return; } } if (ZRoutedRpc.instance == null) { args.Context.AddString("ZRoutedRpc not ready."); } else { if (uid3 == 0) { uid3 = ZNet.GetUID(); } ZRoutedRpc.instance.InvokeRoutedRPC(uid3, "BL_RemovePrivateKey", new object[1] { privateKey }); args.Context.AddString(flag2 ? ("Key removed from you: " + privateKey) : ("Key removed from player: " + text4 + " -> " + privateKey)); } } } }; <>c.<>9__1_1 = val2; obj2 = (object)val2; } new ConsoleCommand("bl_removekey", "[bl_key] [optional: player name]", (ConsoleEvent)obj2, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj3 = <>c.<>9__1_2; if (obj3 == null) { ConsoleEvent val3 = delegate(ConsoleEventArgs args) { if (RequireAdmin(args)) { long uid2 = 0L; string text2 = ""; bool flag = true; if (args.Length >= 2) { string text3 = JoinName(args, 1).Trim(); text2 = text3; flag = IsLocalPlayerName(text3); if (!flag && !BiomeLockPrivateKeys.TryResolveUidByPlayerName(text3, out uid2)) { args.Context.AddString("Player not found: " + text3); return; } } if (ZRoutedRpc.instance == null) { args.Context.AddString("ZRoutedRpc not ready."); } else { if (uid2 == 0) { uid2 = ZNet.GetUID(); } ZRoutedRpc.instance.InvokeRoutedRPC(uid2, "BL_ResetPrivateKeys", Array.Empty<object>()); args.Context.AddString(flag ? "Keys reset for you." : ("Keys reset for player: " + text2 + ".")); } } }; <>c.<>9__1_2 = val3; obj3 = (object)val3; } new ConsoleCommand("bl_resetkeys", "[optional: player name]", (ConsoleEvent)obj3, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj4 = <>c.<>9__1_3; if (obj4 == null) { ConsoleEvent val4 = delegate(ConsoleEventArgs args) { if (RequireAdmin(args)) { if (args.Length == 1) { args.Context.AddString("Listing local keys:"); args.Context.AddString("Total Keys: " + BiomeLockPrivateKeys.PrivateKeys.Count); { foreach (string privateKey3 in BiomeLockPrivateKeys.PrivateKeys) { args.Context.AddString(privateKey3); } return; } } string text = JoinName(args, 1).Trim(); if (IsLocalPlayerName(text)) { args.Context.AddString("Listing local keys:"); args.Context.AddString("Total Keys: " + BiomeLockPrivateKeys.PrivateKeys.Count); { foreach (string privateKey4 in BiomeLockPrivateKeys.PrivateKeys) { args.Context.AddString(privateKey4); } return; } } if (!BiomeLockPrivateKeys.TryResolveUidByPlayerName(text, out var uid)) { args.Context.AddString("Player not found: " + text); } else if (ZRoutedRpc.instance == null) { args.Context.AddString("ZRoutedRpc not ready."); } else { ZRoutedRpc.instance.InvokeRoutedRPC("BL_ServerListKeys", new object[1] { uid }); } } }; <>c.<>9__1_3 = val4; obj4 = (object)val4; } new ConsoleCommand("bl_listkeys", "[optional: player name]", (ConsoleEvent)obj4, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } private static bool IsLocalPlayerName(string name) { try { if ((Object)(object)Player.m_localPlayer == (Object)null) { return false; } string playerName = Player.m_localPlayer.GetPlayerName(); if (string.IsNullOrEmpty(playerName)) { return false; } return string.Equals(playerName, name, StringComparison.OrdinalIgnoreCase); } catch { return false; } } private static bool RequireAdmin(ConsoleEventArgs args) { bool flag = false; try { flag = BiomeLockPlugin.IsLocalPlayerAdmin(); } catch { } if (!flag) { flag = IsVanillaAdmin(); } if (!flag) { args.Context.AddString("Admin only."); } return flag; } private static bool IsVanillaAdmin() { try { if ((Object)(object)ZNet.instance == (Object)null) { return false; } if ((Object)(object)Player.m_localPlayer != (Object)null) { return ZNet.instance.IsAdmin(Player.m_localPlayer.GetPlayerName()); } return false; } catch { return false; } } private static string JoinName(ConsoleEventArgs args, int startIndex) { string text = args[startIndex]; for (int i = startIndex + 1; i < args.Length; i++) { text = text + " " + args[i]; } return text; } private static bool TryGetPrivateKeyArg(string arg, out string privateKey, out string error) { privateKey = ""; error = ""; string text = BiomeLockPrivateKeys.NormalizeKey(arg); if (!text.StartsWith("bl_", StringComparison.Ordinal)) { error = "Key must include prefix. Example: bl_defeated_eikthyr"; return false; } string text2 = text.Substring("bl_".Length); if (string.IsNullOrEmpty(text2)) { error = "Invalid key."; return false; } if (!BiomeLockPrivateKeys.IsBossGlobalKey(text2)) { error = "Invalid key: " + text; return false; } privateKey = text; return true; } } [BepInPlugin("radamanto.BiomeLock", "BiomeLock", "1.0.9")] public class BiomeLockPlugin : BaseUnityPlugin { private class ConfigurationManagerAttributes { public bool? Browsable = false; } [CompilerGenerated] private sealed class <ReloadConfigAfterQuietPeriod>d__58 : IEnumerator<object>, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public float quietSeconds; public BiomeLockPlugin <>4__this; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <ReloadConfigAfterQuietPeriod>d__58(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if ((DateTime.UtcNow - <>4__this._lastCfgWriteUtc).TotalSeconds < (double)quietSeconds) { <>2__current = null; <>1__state = 1; return true; } try { if (<>4__this._configWatcher == null || !<>4__this._watcherReady) { return false; } <>4__this._configWatcher.EnableRaisingEvents = false; if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { ((BaseUnityPlugin)<>4__this).Config.Reload(); <>4__this._ignoreEventsUntilUtc = DateTime.UtcNow.AddSeconds(1.0); ((BaseUnityPlugin)<>4__this).Config.Save(); } } catch { } finally { if (<>4__this._configWatcher != null) { <>4__this._configWatcher.EnableRaisingEvents = true; } <>4__this._reloadScheduled = false; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } internal const string ModGUID = "radamanto.BiomeLock"; internal const string ModName = "BiomeLock"; internal const string ModVersion = "1.0.9"; 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_GenericInteract; internal static ConfigEntry<bool> CE_SE_Block_ItemDropInteract; internal static ConfigEntry<bool> CE_SE_Block_PickableInteract; internal static ConfigEntry<bool> CE_SE_Block_ContainerInteract; 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_Broadcast_Enabled; internal static ConfigEntry<float> CE_SE_Broadcast_Interval; 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<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 ConfigSync? ConfigSync; private static ConfigEntry<bool>? _serverConfigLocked; private FileSystemWatcher? _configWatcher; private DateTime _lastCfgWriteUtc = DateTime.MinValue; private bool _reloadScheduled; private bool _watcherReady; private DateTime _ignoreEventsUntilUtc = DateTime.MinValue; private void Awake() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown Localizer.Load(); Log = ((BaseUnityPlugin)this).Logger; _harmony = new Harmony("radamanto.BiomeLock"); SetupServerSyncAndWatcher(); SetupSEBinds(); _harmony.PatchAll(); } public static bool IsLocalPlayerAdmin() { return ConfigSync != null && ConfigSync.IsAdmin; } private void SetupSEBinds() { 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 interactions."); CE_SE_Block_ItemDropInteract = Cfg("04 - SE Blocks", "04.06 - ItemDropInteract", defaultValue: true, "If true, blocks item drop interactions."); CE_SE_Block_PickableInteract = Cfg("04 - SE Blocks", "04.07 - PickableInteract", defaultValue: true, "If true, blocks pickable interactions."); CE_SE_Block_ContainerInteract = Cfg("04 - SE Blocks", "04.08 - ContainerInteract", defaultValue: true, "If true, blocks container interactions."); CE_SE_Block_AttackBlock = Cfg("04 - SE Blocks", "04.09 - AttackBlock", defaultValue: true, "If true, blocks all player attacks."); 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_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_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)"); } public void SetupServerSyncAndWatcher() { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown bool flag = false; try { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; 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() }; _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); SetupConfigWatcher(); flag = true; } catch { } finally { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; if (flag) { ((BaseUnityPlugin)this).Config.Save(); } } } protected ConfigEntry<T> Cfg<T>(string section, string key, T defaultValue, string description, bool synced = true) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown return config(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()), synced); } private ConfigEntry<T> config<T>(string group, string name, T value, ConfigDescription description, bool synchronizedSetting = true) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown ConfigDescription val = new ConfigDescription(description.Description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"), description.AcceptableValues, description.Tags); ConfigEntry<T> val2 = ((BaseUnityPlugin)this).Config.Bind<T>(group, name, value, val); try { SyncedConfigEntry<T> syncedConfigEntry = ((ConfigSync != null) ? ConfigSync.AddConfigEntry<T>(val2) : null); if (syncedConfigEntry != null) { syncedConfigEntry.SynchronizedConfig = synchronizedSetting; } } catch { } return val2; } private void SetupConfigWatcher() { try { if (_configWatcher != null) { _configWatcher.Dispose(); } string configPath = Paths.ConfigPath; string fileName = Path.GetFileName(((BaseUnityPlugin)this).Config.ConfigFilePath); _configWatcher = new FileSystemWatcher(configPath, fileName) { IncludeSubdirectories = false, NotifyFilter = (NotifyFilters.FileName | NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime) }; FileSystemEventHandler onChanged = delegate { if (!(DateTime.UtcNow < _ignoreEventsUntilUtc)) { _lastCfgWriteUtc = DateTime.UtcNow; if (!_reloadScheduled) { _reloadScheduled = true; ((MonoBehaviour)this).StartCoroutine(ReloadConfigAfterQuietPeriod(0.75f)); } } }; _configWatcher.Changed += onChanged; _configWatcher.Created += onChanged; _configWatcher.Renamed += delegate(object _, RenamedEventArgs __) { onChanged(_, __); }; _configWatcher.EnableRaisingEvents = true; _watcherReady = true; } catch { } } [IteratorStateMachine(typeof(<ReloadConfigAfterQuietPeriod>d__58))] private IEnumerator ReloadConfigAfterQuietPeriod(float quietSeconds) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <ReloadConfigAfterQuietPeriod>d__58(0) { <>4__this = this, quietSeconds = quietSeconds }; } } internal static class BiomeLockPrivateKeys { internal const string PrivatePrefix = "bl_"; 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_ClientListKeysEnd = "BL_ClientListKeysEnd"; 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 float ShareRadiusMeters = 120f; internal static HashSet<string> PrivateKeys = new HashSet<string>(StringComparer.Ordinal); internal static readonly Dictionary<long, HashSet<string>> ServerPrivateKeysByUid = new Dictionary<long, HashSet<string>>(); private static readonly HashSet<string> BossGlobalKeys = new HashSet<string>(StringComparer.Ordinal) { "defeated_eikthyr", "defeated_gdking", "defeated_bonemass", "defeated_dragon", "defeated_goblinking", "defeated_queen", "defeated_fader", "defeated_serpent", "KilledTroll", "killed_surtling", "KilledBat", "Hildir1", "Hildir2", "Hildir3" }; internal static bool IsInMainScene() { try { return (Object)(object)ZNetScene.instance != (Object)null && (Object)(object)Player.m_localPlayer != (Object)null; } catch { return false; } } internal static string NormalizeKey(string key) { return (key ?? string.Empty).Trim().ToLowerInvariant(); } internal static bool IsBossGlobalKey(string globalKeyLower) { return BossGlobalKeys.Contains(globalKeyLower); } internal static string ToPrivateKey(string globalKeyLower) { return "bl_" + globalKeyLower; } internal static void EnsurePlayerRpcRegistered() { if (ZRoutedRpc.instance == null) { return; } try { ZRoutedRpc.instance.Register<string>("BL_SetPrivateKey", (Action<long, string>)RPC_BL_SetPrivateKey); ZRoutedRpc.instance.Register<string>("BL_RemovePrivateKey", (Action<long, string>)RPC_BL_RemovePrivateKey); ZRoutedRpc.instance.Register("BL_ResetPrivateKeys", (Action<long>)RPC_BL_ResetPrivateKeys); ZRoutedRpc.instance.Register<long, int>("BL_ClientListKeysBegin", (Action<long, long, int>)RPC_BL_ClientListKeysBegin); ZRoutedRpc.instance.Register<long, string>("BL_ClientListKeysLine", (Action<long, long, string>)RPC_BL_ClientListKeysLine); ZRoutedRpc.instance.Register<long>("BL_ClientListKeysEnd", (Action<long, long>)RPC_BL_ClientListKeysEnd); } catch { } } internal static void EnsureServerRpcRegistered() { if (ZRoutedRpc.instance == null || (Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } try { ZRoutedRpc.instance.Register<long>("BL_ServerListKeys", (Action<long, long>)RPC_BL_ServerListKeys); ZRoutedRpc.instance.Register<string, long>("BL_ServerSetPrivateKeys", (Action<long, string, long>)RPC_BL_ServerSetPrivateKeys); ZRoutedRpc.instance.Register<string, long>("BL_ServerSetPrivateKey", (Action<long, string, long>)RPC_BL_ServerSetPrivateKey); ZRoutedRpc.instance.Register<string, long>("BL_ServerRemovePrivateKey", (Action<long, string, long>)RPC_BL_ServerRemovePrivateKey); } catch