Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of AdjustablePortals v0.3.0
plugins/AdjustablePortals.dll
Decompiled 2 weeks agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Permissions; using AdjustablePortals.common; using AdjustablePortals.modules; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("AdjustablePortals")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("AdjustablePortals")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.3.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.3.0.0")] namespace AdjustablePortals { [BepInPlugin("MidnightsFX.AdjustablePortals", "AdjustablePortals", "0.3.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] internal class AdjustablePortals : BaseUnityPlugin { public const string PluginGUID = "MidnightsFX.AdjustablePortals"; public const string PluginName = "AdjustablePortals"; public const string PluginVersion = "0.3.0"; internal static Harmony Harmony = new Harmony("MidnightsFX.AdjustablePortals"); public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization(); internal static ManualLogSource Log; public void Awake() { Log = ((BaseUnityPlugin)this).Logger; new ValConfig(((BaseUnityPlugin)this).Config); TeleportItems.SetupTeleportLists(); Compatibility.CheckModCompat(); Assembly executingAssembly = Assembly.GetExecutingAssembly(); Harmony.PatchAll(executingAssembly); Compatibility.TargetPortalCompat(); } } internal class Logger { public static LogLevel Level = (LogLevel)16; public static void enableDebugLogging(object sender, EventArgs e) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (ValConfig.EnableDebugMode.Value) { Level = (LogLevel)32; } else { Level = (LogLevel)16; } } public static void setDebugLogging(bool state) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (state) { Level = (LogLevel)32; } else { Level = (LogLevel)16; } } public static void LogDebug(string message) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)Level >= 32) { AdjustablePortals.Log.LogInfo((object)message); } } public static void LogInfo(string message) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 if ((int)Level >= 16) { AdjustablePortals.Log.LogInfo((object)message); } } public static void LogWarning(string message) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level >= 4) { AdjustablePortals.Log.LogWarning((object)message); } } public static void LogError(string message) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level >= 2) { AdjustablePortals.Log.LogError((object)message); } } } internal class ValConfig { public static ConfigFile cfg; public static ConfigEntry<bool> EnableDebugMode; public static ConfigEntry<float> PortalPieceActivationDistance; public static ConfigEntry<int> PortalNearbyPiecesForActivation; public static ConfigEntry<string> DefeatedEikthyrAllowedItems; public static ConfigEntry<string> DefeatedElderAllowedItems; public static ConfigEntry<string> DefeatedBonemassAllowedItems; public static ConfigEntry<string> DefeatedModerAllowItems; public static ConfigEntry<string> DefeatedYagluthAllowItems; public static ConfigEntry<string> DefeatedQueenAllowItems; public static ConfigEntry<string> DefeatedFaderAllowItems; public static ConfigEntry<bool> EnablePortalPieceRequirements; public static ConfigEntry<bool> EnablePortalRequireFuel; public static ConfigEntry<int> PortalFuelUsagesPerBatch; public static ConfigEntry<int> PortalFuelBatchSize; public static ConfigEntry<string> PortalFuelPrefab; public ValConfig(ConfigFile cf) { cfg = cf; cfg.SaveOnConfigSet = true; CreateConfigValues(cf); Logger.setDebugLogging(EnableDebugMode.Value); SetupMainFileWatcher(); } private void CreateConfigValues(ConfigFile Config) { //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_002d: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown EnableDebugMode = Config.Bind<bool>("Client config", "EnableDebugMode", false, new ConfigDescription("Enables Debug logging.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdvanced = true } })); EnableDebugMode.SettingChanged += Logger.enableDebugLogging; EnablePortalPieceRequirements = BindServerConfig("PortalActivation", "EnablePortalPieceRequirements", value: true, "When enabled, portals require a set number of building pieces around them in order to activate"); PortalNearbyPiecesForActivation = BindServerConfig("PortalActivation", "PortalNearbyPiecesForActivation", 1000, "The number of building pieces required nearby in order for a portal to be activated.", advanced: false, 0, 10000); PortalPieceActivationDistance = BindServerConfig("PortalActivation", "PortalPieceActivationDistance", 100f, "The distance that will be checked for nearby building pieces to meet the required structures nearby."); EnablePortalRequireFuel = BindServerConfig("PortalActivation", "EnablePortalRequireFuel", value: false, "When enabled, portals require a fuel item to teleport users"); PortalFuelUsagesPerBatch = BindServerConfig("PortalActivation", "PortalFuelUsagesPerBatch", 20, "The number of usages that one batch of the fuel type provides"); PortalFuelBatchSize = BindServerConfig("PortalActivation", "PortalFuelBatchSize", 1, "The number of the portal fuel required for activation."); PortalFuelPrefab = BindServerConfig("PortalActivation", "PortalFuelPrefab", "SurtlingCore", "The prefab name that will be used for the portal costs."); DefeatedEikthyrAllowedItems = BindServerConfig("PortalProgression", "DefeatedEikthyrAllowedItems", "", "Comma seperated list of prefab items that will be allowed to teleported once Eikthyr is defeated."); DefeatedEikthyrAllowedItems.SettingChanged += TeleportItems.EikthyrAllowedTeleportsChanged; DefeatedElderAllowedItems = BindServerConfig("PortalProgression", "DefeatedElderAllowedItems", "", "Comma seperated list of prefab items that will be allowed to be teleported once The Elder is defeated."); DefeatedElderAllowedItems.SettingChanged += TeleportItems.ElderAllowedTeleportsChanged; DefeatedBonemassAllowedItems = BindServerConfig("PortalProgression", "DefeatedBonemassAllowedItems", "Bronze,Copper,Tin,CopperOre,TinOre,BronzeScrap", "Comma seperated list of prefab items that will be allowed to be teleported once Bonemass is defeated."); DefeatedBonemassAllowedItems.SettingChanged += TeleportItems.BonemassAllowedTeleportsChanged; DefeatedModerAllowItems = BindServerConfig("PortalProgression", "DefeatedModerAllowItems", "Iron,IronOre,Ironpit,IronScrap,chest_hildir1,chest_hildir2,chest_hildir3", "Comma seperated list of prefab items that will be allowed to be teleported once Moder is defeated."); DefeatedModerAllowItems.SettingChanged += TeleportItems.ModerAllowedTeleportsChanged; DefeatedYagluthAllowItems = BindServerConfig("PortalProgression", "DefeatedYagluthAllowItems", "Silver,SilverOre,DragonEgg", "Comma seperated list of prefab items that will be allowed to be teleported once Yagluth is defeated."); DefeatedYagluthAllowItems.SettingChanged += TeleportItems.YagluthAllowedTeleportsChanged; DefeatedQueenAllowItems = BindServerConfig("PortalProgression", "DefeatedQueenAllowItems", "MechanicalSpring,BlackMetal,BlackMetalScrap", "Comma seperated list of prefab items that will be allowed to be teleported once The Seeker Queen is defeated."); DefeatedQueenAllowItems.SettingChanged += TeleportItems.QueenAllowedTeleportsChanged; DefeatedFaderAllowItems = BindServerConfig("PortalProgression", "DefeatedFaderAllowItems", "DvergrNeedle", "Comma seperated list of prefab items that will be allowed to be teleported once Fader is defeated."); DefeatedFaderAllowItems.SettingChanged += TeleportItems.FaderAllowedTeleportsChanged; } internal static void SetupMainFileWatcher() { FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(); fileSystemWatcher.NotifyFilter = NotifyFilters.LastWrite; fileSystemWatcher.Path = Path.GetDirectoryName(cfg.ConfigFilePath); fileSystemWatcher.Filter = "MidnightsFX.ImpactfulSkills.cfg"; fileSystemWatcher.Changed += OnConfigFileChanged; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private static void OnConfigFileChanged(object sender, FileSystemEventArgs e) { if (ZNet.instance.IsServer()) { Logger.LogInfo("Configuration file has been changed, reloading settings."); cfg.Reload(); } } public static ConfigEntry<List<string>> BindServerConfig(string catagory, string key, List<string> value, string description, bool advanced = false) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_002e: Expected O, but got Unknown //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown return cfg.Bind<List<string>>(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<float[]> BindServerConfig(string catagory, string key, float[] value, string description, bool advanced = false, float valmin = 0f, float valmax = 150f) { //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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown return cfg.Bind<float[]>(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(valmin, valmax), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<bool> BindServerConfig(string catagory, string key, bool value, string description, AcceptableValueBase acceptableValues = null, bool advanced = false) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown return cfg.Bind<bool>(catagory, key, value, new ConfigDescription(description, acceptableValues, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<int> BindServerConfig(string catagory, string key, int value, string description, bool advanced = false, int valmin = 0, int valmax = 150) { //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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown return cfg.Bind<int>(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<int>(valmin, valmax), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<float> BindServerConfig(string catagory, string key, float value, string description, bool advanced = false, float valmin = 0f, float valmax = 150f) { //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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown return cfg.Bind<float>(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<float>(valmin, valmax), new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } public static ConfigEntry<string> BindServerConfig(string catagory, string key, string value, string description, AcceptableValueList<string> acceptableValues = null, bool advanced = false) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Expected O, but got Unknown return cfg.Bind<string>(catagory, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)acceptableValues, new object[1] { (object)new ConfigurationManagerAttributes { IsAdminOnly = true, IsAdvanced = advanced } })); } } } namespace AdjustablePortals.modules { internal static class ActivationRequirements { [HarmonyPatch(typeof(TeleportWorld))] internal static class PortalInstanceActivatable { private static readonly int pieceMask = LayerMask.GetMask(new string[1] { "piece" }); private static readonly string fuelKey = "AJP_FUEL"; private static readonly string nearbyPiecesKey = "AJP_PORT_BUILD_NEARBY"; private static float update_timer = 0f; private static float current_update_time = 0f; private static Dictionary<uint, int> nearbyPiecesByPortal = new Dictionary<uint, int>(); private static int GetCurrentPiecesForSpecificPortal(ZDO portalZDO) { uint iD = ((ZDOID)(ref portalZDO.m_uid)).ID; int num; if (nearbyPiecesByPortal.ContainsKey(iD)) { num = nearbyPiecesByPortal[iD]; } else { num = portalZDO.GetInt(nearbyPiecesKey, 1); nearbyPiecesByPortal.Add(iD, num); } return num; } [HarmonyPatch(typeof(TeleportWorld), "HaveTarget")] [HarmonyBefore(new string[] { "org.bepinex.plugins.targetportal" })] [HarmonyPrefix] internal static bool Activator(TeleportWorld __instance, ref bool __result) { return CheckActivationRequirements(__instance, ref __result); } public static void ConsumeFuel(TeleportWorld instance) { if (!((Object)(object)instance.m_nview == (Object)null) && instance.m_nview.IsValid() && ValConfig.EnablePortalRequireFuel.Value) { int @int = instance.m_nview.GetZDO().GetInt(fuelKey, 0); if (@int > 0) { @int--; instance.m_nview.GetZDO().Set(fuelKey, @int); Logger.LogDebug("Consumed 1 usage of portal fuel."); } } } public static bool AreActivationRequirementsMet(TeleportWorld instance, out string reason) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) reason = ""; bool result = true; if ((Object)(object)instance.m_nview == (Object)null || !instance.m_nview.IsValid()) { return result; } if (ValConfig.EnablePortalPieceRequirements.Value) { ZDO zDO = instance.m_nview.GetZDO(); int num = GetCurrentPiecesForSpecificPortal(zDO); current_update_time += Time.fixedDeltaTime; if (update_timer <= current_update_time) { num = instance.m_nview.GetZDO().GetInt(nearbyPiecesKey, 0); update_timer = current_update_time + 10f; Collider[] array = Physics.OverlapSphere(((Component)instance).transform.position, ValConfig.PortalPieceActivationDistance.Value, pieceMask); num = array.Length; nearbyPiecesByPortal[((ZDOID)(ref zDO.m_uid)).ID] = num; zDO.Set(nearbyPiecesKey, num); } if (num < ValConfig.PortalNearbyPiecesForActivation.Value) { reason = $"More nearby structures required ({num}/{ValConfig.PortalNearbyPiecesForActivation.Value})"; result = false; } } if (ValConfig.EnablePortalRequireFuel.Value && instance.m_nview.GetZDO().GetInt(fuelKey, 0) == 0) { reason = $"Fuel is required, add {ValConfig.PortalFuelPrefab.Value} x {ValConfig.PortalFuelBatchSize.Value}"; result = false; } return result; } public static bool CheckActivationRequirements(TeleportWorld __instance, ref bool __result) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsValid()) { return true; } if (!Compatibility.IsTargetPortalInstalled && __instance.m_nview.GetZDO().GetConnectionZDOID((ConnectionType)1) == ZDOID.None) { __result = false; return false; } __result = AreActivationRequirementsMet(__instance, out var reason); if (!__result) { Logger.LogDebug($"Is portal active? {__result} {reason}"); } return false; } [HarmonyPatch(typeof(TeleportWorld), "GetHoverText")] [HarmonyPostfix] internal static void OnHoverHelp(TeleportWorld __instance, ref string __result) { if ((Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsValid()) { return; } if (ValConfig.EnablePortalPieceRequirements.Value) { int currentPiecesForSpecificPortal = GetCurrentPiecesForSpecificPortal(__instance.m_nview.GetZDO()); if (currentPiecesForSpecificPortal < ValConfig.PortalNearbyPiecesForActivation.Value) { __result += Localization.instance.Localize($"\nMore nearby structures required ({currentPiecesForSpecificPortal}/{ValConfig.PortalNearbyPiecesForActivation.Value})"); } } if (ValConfig.EnablePortalRequireFuel.Value) { int @int = __instance.m_nview.GetZDO().GetInt(fuelKey, 0); if (@int == 0) { __result += Localization.instance.Localize($"\nFuel is required, add <color=red>{ValConfig.PortalFuelPrefab.Value}</color> x {ValConfig.PortalFuelBatchSize.Value}"); } else { __result += Localization.instance.Localize($"\nCurrent Fuel {@int}."); } } } [HarmonyPatch(typeof(TeleportWorld), "TargetFound")] [HarmonyPostfix] internal static void TargetFoundPrevention(TeleportWorld __instance, ref bool __result) { if (!((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid() && ValConfig.EnablePortalPieceRequirements.Value) { CheckActivationRequirements(__instance, ref __result); } } [HarmonyPatch(typeof(TeleportWorld), "UseItem")] [HarmonyPrefix] internal static bool TeleportCost(TeleportWorld __instance, Humanoid user, ItemData item, ref bool __result) { if ((Object)(object)__instance.m_nview == (Object)null || !__instance.m_nview.IsValid() || !ValConfig.EnablePortalRequireFuel.Value) { return true; } int @int = __instance.m_nview.GetZDO().GetInt(fuelKey, 0); if ((Object)(object)item.m_dropPrefab != (Object)null && ((Object)item.m_dropPrefab).name == ValConfig.PortalFuelPrefab.Value) { if (item.m_stack >= ValConfig.PortalFuelBatchSize.Value) { user.m_inventory.RemoveItemByPrefab(ValConfig.PortalFuelPrefab.Value, ValConfig.PortalFuelBatchSize.Value); @int += ValConfig.PortalFuelUsagesPerBatch.Value; __instance.m_nview.GetZDO().Set(fuelKey, @int); ((Character)user).Message((MessageType)2, $"Added {ValConfig.PortalFuelPrefab.Value}x{ValConfig.PortalFuelBatchSize.Value} for {ValConfig.PortalFuelUsagesPerBatch.Value} fuel.", 0, (Sprite)null); } else { ((Character)user).Message((MessageType)2, $"Requires at least {ValConfig.PortalFuelPrefab.Value}x{ValConfig.PortalFuelBatchSize.Value}.", 0, (Sprite)null); } __result = true; return false; } return true; } [HarmonyPatch(typeof(TeleportWorld), "Teleport")] [HarmonyPostfix] internal static void TeleportCost(TeleportWorld __instance) { if (!((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid() && ValConfig.EnablePortalRequireFuel.Value) { int @int = __instance.m_nview.GetZDO().GetInt(fuelKey, 0); if (@int > 0) { @int--; __instance.m_nview.GetZDO().Set(fuelKey, @int); Logger.LogDebug("Consumed 1 usage of portal fuel."); } } } } } internal static class Compatibility { public static bool IsTargetPortalInstalled; private static TeleportWorld activeSourcePortal; internal static void CheckModCompat() { try { Dictionary<string, BaseUnityPlugin> plugins = BepInExUtils.GetPlugins(false); if (plugins != null && plugins.Keys.Contains("org.bepinex.plugins.targetportal")) { IsTargetPortalInstalled = true; } } catch { Logger.LogWarning("Unable to check mod compatibility. Ensure that Bepinex can load."); } } internal static void TargetPortalCompat() { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown if (IsTargetPortalInstalled) { Logger.LogInfo("TargetPortal detected, applying compatibility patches..."); Type type = AccessTools.TypeByName("TargetPortal.Map")?.GetNestedType("OpenMapOnPortalEnter", AccessTools.all); MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "Prefix", (Type[])null, (Type[])null) : null); if (methodInfo == null) { Logger.LogWarning("Could not find TargetPortal.Map.OpenMapOnPortalEnter.Prefix - TargetPortal compatibility patches will not be applied."); return; } HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(Compatibility), "BlockOrTrackPortalEntry", (Type[])null, (Type[])null)); AdjustablePortals.Harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo2 = AccessTools.Method(typeof(Player), "TeleportTo", (Type[])null, (Type[])null); HarmonyMethod val2 = new HarmonyMethod(AccessTools.Method(typeof(Compatibility), "TeleportToPostfix", (Type[])null, (Type[])null)); AdjustablePortals.Harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Logger.LogInfo("TargetPortal compatibility patches applied."); } } private static bool BlockOrTrackPortalEntry(TeleportWorldTrigger __0) { if ((Object)(object)__0 == (Object)null || (Object)(object)__0.m_teleportWorld == (Object)null) { return true; } if (!ActivationRequirements.PortalInstanceActivatable.AreActivationRequirementsMet(__0.m_teleportWorld, out var reason)) { ((Character)Player.m_localPlayer).Message((MessageType)2, reason, 0, (Sprite)null); return false; } activeSourcePortal = __0.m_teleportWorld; return true; } private static void TeleportToPostfix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !((Object)(object)activeSourcePortal == (Object)null)) { ActivationRequirements.PortalInstanceActivatable.ConsumeFuel(activeSourcePortal); activeSourcePortal = null; } } } public static class TeleportItems { [HarmonyPatch(typeof(Humanoid))] private static class AllowConfiguredTeleportableItems { [HarmonyPatch("IsTeleportable")] private static void Postfix(Humanoid __instance, ref bool __result) { if (__result) { return; } List<ItemData> list = (from x in __instance.m_inventory.GetAllItems() where !x.m_shared.m_teleportable select x).Distinct().ToList(); List<string> list2 = new List<string>(); foreach (ItemData item in list) { if (!PerPlayerTeleportableItems.IsItemTeleportable(item)) { list2.Add(((Object)item.m_dropPrefab).name); } } if (list2.Count == 0) { __result = true; return; } Logger.LogDebug("The following items are not teleportable " + string.Join(", ", list2)); __result = false; } } [HarmonyPatch(typeof(ZoneSystem))] public static class ClearTeleportableCache { [HarmonyPostfix] [HarmonyPatch(typeof(ZoneSystem), "SetGlobalKey", new Type[] { typeof(string) })] private static void ClearGlobalKeyReset(string name) { PlayerItemsAllowTeleport.Clear(); } } [HarmonyPatch(typeof(Player))] public static class ClearTeleportableCachePrivateKeys { [HarmonyPostfix] [HarmonyPatch(typeof(Player), "AddUniqueKey", new Type[] { typeof(string) })] private static void ClearPrivateKeyReset(string name) { PlayerItemsAllowTeleport.Clear(); } } [HarmonyPatch(typeof(InventoryGrid))] public static class PerPlayerTeleportableItems { [HarmonyTranspiler] [HarmonyPatch("UpdateGui")] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((OpCode?)OpCodes.Ldloc_S, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Ldfld, (object)AccessTools.Field(typeof(SharedData), "m_teleportable"), (string)null) }).RemoveInstructions(3).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldloc_S, (object)18), Transpilers.EmitDelegate<Func<ItemData, bool>>((Func<ItemData, bool>)IsItemTeleportable) }) .ThrowIfNotMatch("Unable to patch item teleport visual display.", Array.Empty<CodeMatch>()); return val.Instructions(); } public static bool IsItemTeleportable(ItemData item) { if (item == null || item.m_shared == null || (Object)(object)item.m_dropPrefab == (Object)null) { return true; } string name = ((Object)item.m_dropPrefab).name; if (PlayerItemsAllowTeleport.ContainsKey(name)) { return PlayerItemsAllowTeleport[name]; } bool flag = item.m_shared.m_teleportable; if (!flag && ZoneSystem.instance.GetGlobalKey((GlobalKeys)33) && EikthyrAllowedTeleports.Contains(name)) { flag = true; } if (!flag && ZoneSystem.instance.GetGlobalKey((GlobalKeys)36) && ElderAllowedTeleports.Contains(name)) { flag = true; } if (!flag && ZoneSystem.instance.GetGlobalKey((GlobalKeys)37) && BonemassAllowedTeleports.Contains(name)) { flag = true; } if (!flag && ZoneSystem.instance.GetGlobalKey((GlobalKeys)34) && ModerAllowedTeleports.Contains(name)) { flag = true; } if (!flag && ZoneSystem.instance.GetGlobalKey((GlobalKeys)35) && YagluthAllowedTeleports.Contains(name)) { flag = true; } if (!flag && ZoneSystem.instance.GetGlobalKey("defeated_queen") && QueenAllowedTeleports.Contains(name)) { flag = true; } if (!flag && ZoneSystem.instance.GetGlobalKey("defeated_fader") && FaderAllowedTeleports.Contains(name)) { flag = true; } Logger.LogInfo($"Item is teleportable? {name} - {flag}"); if (!PlayerItemsAllowTeleport.ContainsKey(name)) { PlayerItemsAllowTeleport.Add(name, flag); } return false; } } internal static List<string> EikthyrAllowedTeleports = new List<string>(); internal static List<string> ElderAllowedTeleports = new List<string>(); internal static List<string> BonemassAllowedTeleports = new List<string>(); internal static List<string> ModerAllowedTeleports = new List<string>(); internal static List<string> YagluthAllowedTeleports = new List<string>(); internal static List<string> QueenAllowedTeleports = new List<string>(); internal static List<string> FaderAllowedTeleports = new List<string>(); private static Dictionary<string, bool> PlayerItemsAllowTeleport = new Dictionary<string, bool>(); internal static void SetupTeleportLists() { ConfigListChanged(EikthyrAllowedTeleports, ValConfig.DefeatedEikthyrAllowedItems.Value); ConfigListChanged(ElderAllowedTeleports, ValConfig.DefeatedElderAllowedItems.Value); ConfigListChanged(BonemassAllowedTeleports, ValConfig.DefeatedBonemassAllowedItems.Value); ConfigListChanged(ModerAllowedTeleports, ValConfig.DefeatedModerAllowItems.Value); ConfigListChanged(YagluthAllowedTeleports, ValConfig.DefeatedYagluthAllowItems.Value); ConfigListChanged(QueenAllowedTeleports, ValConfig.DefeatedQueenAllowItems.Value); ConfigListChanged(FaderAllowedTeleports, ValConfig.DefeatedFaderAllowItems.Value); } internal static void EikthyrAllowedTeleportsChanged(object s, EventArgs e) { ConfigListChanged(EikthyrAllowedTeleports, ValConfig.DefeatedEikthyrAllowedItems.Value); } internal static void ElderAllowedTeleportsChanged(object s, EventArgs e) { ConfigListChanged(ElderAllowedTeleports, ValConfig.DefeatedElderAllowedItems.Value); } internal static void BonemassAllowedTeleportsChanged(object s, EventArgs e) { ConfigListChanged(BonemassAllowedTeleports, ValConfig.DefeatedBonemassAllowedItems.Value); } internal static void ModerAllowedTeleportsChanged(object s, EventArgs e) { ConfigListChanged(ModerAllowedTeleports, ValConfig.DefeatedModerAllowItems.Value); } internal static void YagluthAllowedTeleportsChanged(object s, EventArgs e) { ConfigListChanged(YagluthAllowedTeleports, ValConfig.DefeatedYagluthAllowItems.Value); } internal static void QueenAllowedTeleportsChanged(object s, EventArgs e) { ConfigListChanged(QueenAllowedTeleports, ValConfig.DefeatedQueenAllowItems.Value); } internal static void FaderAllowedTeleportsChanged(object s, EventArgs e) { ConfigListChanged(FaderAllowedTeleports, ValConfig.DefeatedFaderAllowItems.Value); } private static void ConfigListChanged(List<string> targetList, string configValue) { PlayerItemsAllowTeleport.Clear(); try { List<string> list = new List<string>(); string[] array = configValue.Split(new char[1] { ',' }); foreach (string item in array) { list.Add(item); } if (list.Count > 0) { targetList.Clear(); targetList.AddRange(list); } } catch (Exception arg) { Logger.LogWarning($"Error parsing ConfigList: {arg}"); } } } } namespace AdjustablePortals.common { internal static class Extensions { public static bool RemoveItemByPrefab(this Inventory inv, string prefab, int countToRemove) { List<ItemData> allItems = inv.GetAllItems(); int num = countToRemove; List<ItemData> list = new List<ItemData>(); foreach (ItemData item in allItems) { if (!(((Object)item.m_dropPrefab).name == prefab)) { continue; } if (item.m_stack > 0) { if (num < item.m_stack) { item.m_stack -= num; break; } if (item.m_stack <= num) { list.Add(item); num -= item.m_stack; } else { item.m_stack -= num; num = 0; } } else { list.Add(item); } } foreach (ItemData item2 in list) { inv.RemoveItem(item2); } Logger.LogDebug($"Remove summary: {prefab}x{countToRemove} successfully removed: {countToRemove - num}"); return num == 0; } } }