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.4.0
plugins/AdjustablePortals.dll
Decompiled 6 days agousing System; using System.Collections; 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.IgnoreSymbolStoreSequencePoints)] [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.4.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.4.0.0")] namespace AdjustablePortals { [BepInPlugin("MidnightsFX.AdjustablePortals", "AdjustablePortals", "0.4.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.4.0"; internal static Harmony Harmony = new Harmony("MidnightsFX.AdjustablePortals"); public static CustomLocalization Localization = LocalizationManager.Instance.GetLocalization(); internal static ManualLogSource Log; internal static AdjustablePortals Instance; public void Awake() { Log = ((BaseUnityPlugin)this).Logger; Instance = this; 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_000e: 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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0005: 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_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level >= 32) { AdjustablePortals.Log.LogInfo((object)message); } } public static void LogInfo(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)Level >= 16) { AdjustablePortals.Log.LogInfo((object)message); } } public static void LogWarning(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)Level >= 4) { AdjustablePortals.Log.LogWarning((object)message); } } public static void LogError(string message) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: 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 static ConfigEntry<bool> EnableTeleportMounts; public static ConfigEntry<bool> EnableTeleportTames; public static ConfigEntry<float> TeleportTamesRadius; public static ConfigEntry<int> TeleportTamesMaxCount; public static ConfigEntry<bool> TeleportTamesRequireFollowing; public static ConfigEntry<bool> EnableTeleportCarts; public static ConfigEntry<bool> ReattachCartAfterTeleport; private static FileSystemWatcher configWatcher; public ValConfig(ConfigFile cf) { cfg = cf; cfg.SaveOnConfigSet = true; CreateConfigValues(cf); Logger.setDebugLogging(EnableDebugMode.Value); SetupMainFileWatcher(); } private void CreateConfigValues(ConfigFile Config) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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", 300, "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."); EnableTeleportMounts = BindServerConfig("PortalCompanions", "EnableTeleportMounts", value: true, "When enabled, a player riding a mount into a portal takes the mount with them and is put back in the saddle on arrival."); EnableTeleportTames = BindServerConfig("PortalCompanions", "EnableTeleportTames", value: true, "When enabled, tamed creatures near the portal travel with the player to the destination."); TeleportTamesRadius = BindServerConfig("PortalCompanions", "TeleportTamesRadius", 5f, "The distance around the portal that tamed creatures are collected from.", advanced: false, 0f, 50f); TeleportTamesMaxCount = BindServerConfig("PortalCompanions", "TeleportTamesMaxCount", 5, "The most tamed creatures that one teleport will take along. The closest to the portal go first.", advanced: false, 0, 50); TeleportTamesRequireFollowing = BindServerConfig("PortalCompanions", "TeleportTamesRequireFollowing", value: true, "When enabled, only tames that have been told to follow the teleporting player travel with them. Turn this off to take every tame standing near the portal, penned livestock included."); EnableTeleportCarts = BindServerConfig("PortalCompanions", "EnableTeleportCarts", value: true, "When enabled, a cart the player is pulling travels with them. The cart may only hold items that the player themselves could teleport with, and blocks the teleport otherwise."); ReattachCartAfterTeleport = BindServerConfig("PortalCompanions", "ReattachCartAfterTeleport", value: true, "When enabled, a cart that travelled through a portal is hitched back up on arrival instead of being left loose at the destination.", null, advanced: true); 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() { configWatcher = new FileSystemWatcher(); configWatcher.NotifyFilter = NotifyFilters.LastWrite; configWatcher.Path = Path.GetDirectoryName(cfg.ConfigFilePath); configWatcher.Filter = Path.GetFileName(cfg.ConfigFilePath); configWatcher.Changed += OnConfigFileChanged; configWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; configWatcher.EnableRaisingEvents = true; } private static void OnConfigFileChanged(object sender, FileSystemEventArgs e) { if (!((Object)(object)ZNet.instance == (Object)null) && 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_0012: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_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_001f: 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 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_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_001f: 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 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 struct PortalPieceState { public int Pieces; public float NextScanTime; } private static readonly string fuelKey = "AJP_FUEL"; private static readonly string nearbyPiecesKey = "AJP_PORT_BUILD_NEARBY"; private const float ScanIntervalSeconds = 10f; private const float InitialGraceSeconds = 5f; private const float InitialScanSpreadSeconds = 10f; private const float StaleEntrySeconds = 60f; private const float PruneIntervalSeconds = 60f; private static readonly Dictionary<ZDOID, PortalPieceState> nearbyPiecesByPortal = new Dictionary<ZDOID, PortalPieceState>(); private static float nextPruneTime = 0f; private static readonly List<ZDOID> pruneBuffer = new List<ZDOID>(); private static TeleportWorld lastFuelChargePortal = null; private static int lastFuelChargeFrame = -1; private static int GetPieceCount(TeleportWorld instance) { //IL_000d: 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) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = instance.m_nview.GetZDO(); ZDOID uid = zDO.m_uid; if (nearbyPiecesByPortal.TryGetValue(uid, out var value)) { if (Time.time < value.NextScanTime) { return value.Pieces; } PruneUnloadedPortals(); value.Pieces = PieceProximity.CountWithin(((Component)instance).transform.position, ValConfig.PortalPieceActivationDistance.Value); value.NextScanTime = Time.time + 10f; nearbyPiecesByPortal[uid] = value; if (instance.m_nview.IsOwner()) { zDO.Set(nearbyPiecesKey, value.Pieces); } return value.Pieces; } value.Pieces = zDO.GetInt(nearbyPiecesKey, 0); value.NextScanTime = Time.time + 5f + Random.Range(0f, 10f); nearbyPiecesByPortal[uid] = value; return value.Pieces; } private static void PruneUnloadedPortals() { //IL_005e: 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) if (Time.time < nextPruneTime) { return; } nextPruneTime = Time.time + 60f; float num = Time.time - 60f; pruneBuffer.Clear(); foreach (KeyValuePair<ZDOID, PortalPieceState> item in nearbyPiecesByPortal) { if (item.Value.NextScanTime < num) { pruneBuffer.Add(item.Key); } } for (int i = 0; i < pruneBuffer.Count; i++) { nearbyPiecesByPortal.Remove(pruneBuffer[i]); } pruneBuffer.Clear(); } [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 == (Object)null) && !((Object)(object)instance.m_nview == (Object)null) && instance.m_nview.IsValid() && ValConfig.EnablePortalRequireFuel.Value && (!((Object)(object)lastFuelChargePortal == (Object)(object)instance) || lastFuelChargeFrame != Time.frameCount)) { int num = instance.m_nview.GetZDO().GetInt(fuelKey, 0); if (num > 0) { lastFuelChargePortal = instance; lastFuelChargeFrame = Time.frameCount; instance.m_nview.ClaimOwnership(); instance.m_nview.GetZDO().Set(fuelKey, num - 1); Logger.LogDebug("Consumed 1 usage of portal fuel."); } } } public static bool AreActivationRequirementsMet(TeleportWorld instance, out string reason) { reason = ""; bool result = true; if ((Object)(object)instance.m_nview == (Object)null || !instance.m_nview.IsValid()) { return result; } if (ValConfig.EnablePortalPieceRequirements.Value) { int pieceCount = GetPieceCount(instance); if (pieceCount < ValConfig.PortalNearbyPiecesForActivation.Value) { reason = $"More nearby structures required ({pieceCount}/{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_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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 (!ValConfig.EnablePortalPieceRequirements.Value && !ValConfig.EnablePortalRequireFuel.Value) { 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 pieceCount = GetPieceCount(__instance); if (pieceCount < ValConfig.PortalNearbyPiecesForActivation.Value) { __result += Localization.instance.Localize($"\nMore nearby structures required ({pieceCount}/{ValConfig.PortalNearbyPiecesForActivation.Value})"); } } if (ValConfig.EnablePortalRequireFuel.Value) { int num = __instance.m_nview.GetZDO().GetInt(fuelKey, 0); if (num <= 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 {num}."); } } } [HarmonyPatch(typeof(TeleportWorld), "TargetFound")] [HarmonyPostfix] internal static void TargetFoundPrevention(TeleportWorld __instance, ref bool __result) { if (__result && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid() && (ValConfig.EnablePortalPieceRequirements.Value || ValConfig.EnablePortalRequireFuel.Value) && !AreActivationRequirementsMet(__instance, out var reason)) { Logger.LogDebug("Portal blocked: " + reason); __result = false; } } [HarmonyPatch(typeof(TeleportWorld), "UseItem")] [HarmonyPrefix] internal static bool AddFuelOnUseItem(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; } if ((Object)(object)user == (Object)null || user.m_inventory == null || item == null || (Object)(object)item.m_dropPrefab == (Object)null || ((Object)item.m_dropPrefab).name != ValConfig.PortalFuelPrefab.Value) { return true; } int value = ValConfig.PortalFuelBatchSize.Value; if (user.m_inventory.CountItemsByPrefab(ValConfig.PortalFuelPrefab.Value) < value || !user.m_inventory.RemoveItemByPrefab(ValConfig.PortalFuelPrefab.Value, value)) { ((Character)user).Message((MessageType)2, $"Requires at least {ValConfig.PortalFuelPrefab.Value}x{value}.", 0, (Sprite)null, false); __result = true; return false; } __instance.m_nview.ClaimOwnership(); int num = __instance.m_nview.GetZDO().GetInt(fuelKey, 0) + ValConfig.PortalFuelUsagesPerBatch.Value; __instance.m_nview.GetZDO().Set(fuelKey, num); ((Character)user).Message((MessageType)2, $"Added {ValConfig.PortalFuelPrefab.Value}x{value} for {ValConfig.PortalFuelUsagesPerBatch.Value} fuel.", 0, (Sprite)null, false); __result = true; return false; } [HarmonyPatch(typeof(TeleportWorld), "Teleport")] [HarmonyPrefix] internal static void ConsumeFuelAfterTeleportPrefix(Player player, out bool __state) { __state = (Object)(object)player != (Object)null && ((Character)player).IsTeleporting(); } [HarmonyPatch(typeof(TeleportWorld), "Teleport")] [HarmonyPostfix] internal static void ConsumeFuelAfterTeleport(TeleportWorld __instance, Player player, bool __state) { if (!__state && !((Object)(object)player == (Object)null) && ((Character)player).IsTeleporting()) { ConsumeFuel(__instance); } } internal static void ClearPortalPieceCache() { nearbyPiecesByPortal.Clear(); pruneBuffer.Clear(); nextPruneTime = 0f; PieceProximity.Clear(); lastFuelChargePortal = null; lastFuelChargeFrame = -1; } } [HarmonyPatch(typeof(ZNetScene))] internal static class PortalCacheLifetime { [HarmonyPatch("Shutdown")] [HarmonyPostfix] private static void OnShutdown() { PortalInstanceActivatable.ClearPortalPieceCache(); TeleportCompanions.ClearSessionState(); } } } internal static class Compatibility { public static bool IsTargetPortalInstalled; private static TeleportWorld activeSourcePortal; private static float activeSourcePortalExpiry; private const float ActiveSourcePortalLifetime = 30f; internal static TeleportWorld GetActiveSourcePortal() { if ((Object)(object)activeSourcePortal == (Object)null || Time.time > activeSourcePortalExpiry) { return null; } return activeSourcePortal; } internal static void CheckModCompat() { try { Dictionary<string, BaseUnityPlugin> plugins = BepInExUtils.GetPlugins(false); if (plugins != null && Enumerable.Contains(plugins.Keys, "org.bepinex.plugins.targetportal")) { IsTargetPortalInstalled = true; } } catch { Logger.LogWarning("Unable to check mod compatibility. Ensure that Bepinex can load."); } } internal static void TargetPortalCompat() { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: 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)) { if ((Object)(object)Player.m_localPlayer != (Object)null) { ((Character)Player.m_localPlayer).Message((MessageType)2, reason, 0, (Sprite)null, false); } return false; } activeSourcePortal = __0.m_teleportWorld; activeSourcePortalExpiry = Time.time + 30f; return true; } private static void TeleportToPostfix(Player __instance) { if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !((Object)(object)activeSourcePortal == (Object)null)) { if (Time.time > activeSourcePortalExpiry) { activeSourcePortal = null; return; } ActivationRequirements.PortalInstanceActivatable.ConsumeFuel(activeSourcePortal); activeSourcePortal = null; } } } internal static class TeleportCompanions { private struct PortalTrip { public bool FromPortal; public Vector3 Center; public Vector3 Destination; public Character Mount; public Vagon Cart; public string CartBlockedBy; } [HarmonyPatch(typeof(TeleportWorld))] internal static class PortalTripSource { [HarmonyPatch("Teleport")] [HarmonyPrefix] private static bool OnPortalTeleport(TeleportWorld __instance, Player player) { vanillaSourcePortal = __instance; vanillaSourcePortalFrame = Time.frameCount; if (!ValConfig.EnableTeleportCarts.Value || (Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)Player.m_localPlayer) { return true; } Vagon attachedCart = GetAttachedCart(player); if ((Object)(object)attachedCart == (Object)null) { return true; } if (!__instance.TargetFound()) { return true; } if (IsCartTeleportable(attachedCart, __instance.m_allowAllItems, out var blockedBy)) { return true; } ((Character)player).Message((MessageType)2, Localization.instance.Localize("$msg_noteleport (" + blockedBy + ")"), 0, (Sprite)null, false); Logger.LogDebug("Teleport blocked, cart contains: " + blockedBy); return false; } } [HarmonyPatch(typeof(Humanoid))] internal static class LoadedCartBlocksTeleport { [HarmonyPatch("IsTeleportable")] [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(Humanoid __instance, bool allowAllItems, ref bool __result) { if (__result && ValConfig.EnableTeleportCarts.Value && !((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer)) { Vagon attachedCart = GetAttachedCart(Player.m_localPlayer); if (!((Object)(object)attachedCart == (Object)null) && !IsCartTeleportable(attachedCart, allowAllItems, out var _)) { __result = false; } } } } [HarmonyPatch(typeof(Player))] internal static class CarryCompanionsThroughPortal { [HarmonyPatch("TeleportTo")] [HarmonyPrefix] private static void Prefix(Player __instance, Vector3 pos, out PortalTrip __state) { //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: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) __state = default(PortalTrip); if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || (!ValConfig.EnableTeleportTames.Value && !ValConfig.EnableTeleportCarts.Value && !ValConfig.EnableTeleportMounts.Value)) { return; } TeleportWorld val = ResolveSourcePortal(); if ((Object)(object)val == (Object)null) { return; } __state.FromPortal = true; __state.Center = ((Component)val).transform.position; __state.Destination = pos; if (ValConfig.EnableTeleportMounts.Value) { __state.Mount = GetRiddenMount(__instance); } if (!ValConfig.EnableTeleportCarts.Value) { return; } Vagon attachedCart = GetAttachedCart(__instance); if ((Object)(object)attachedCart != (Object)null) { if (IsCartTeleportable(attachedCart, val.m_allowAllItems, out var blockedBy)) { __state.Cart = attachedCart; } else { __state.CartBlockedBy = blockedBy; } } } [HarmonyPatch("TeleportTo")] [HarmonyPostfix] private static void Postfix(Player __instance, bool __result, PortalTrip __state) { if (__state.FromPortal && __result) { if (!string.IsNullOrEmpty(__state.CartBlockedBy)) { ((Character)__instance).Message((MessageType)2, "Cart left behind (" + __state.CartBlockedBy + ")", 0, (Sprite)null, false); } CarryCompanions(__instance, __state); } } private static TeleportWorld ResolveSourcePortal() { if ((Object)(object)vanillaSourcePortal != (Object)null && vanillaSourcePortalFrame == Time.frameCount) { return vanillaSourcePortal; } return Compatibility.GetActiveSourcePortal(); } } private static TeleportWorld vanillaSourcePortal = null; private static int vanillaSourcePortalFrame = -1; private const float CompanionSpacing = 1.6f; private const float GoldenAngleDegrees = 137.5f; private const float ArrivalTimeoutSeconds = 20f; private const int MaxBlockingItemsListed = 3; private static readonly List<Character> tameBuffer = new List<Character>(); private static readonly List<string> blockedItemBuffer = new List<string>(); internal static void ClearSessionState() { vanillaSourcePortal = null; vanillaSourcePortalFrame = -1; tameBuffer.Clear(); blockedItemBuffer.Clear(); } private static Vector3 CompanionOffset(int index) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) float num = (float)index * 137.5f * ((float)Math.PI / 180f); float num2 = 1.6f * Mathf.Sqrt((float)(index + 1)); return new Vector3(Mathf.Cos(num) * num2, 0f, Mathf.Sin(num) * num2); } internal static Vagon GetAttachedCart(Player player) { if ((Object)(object)player == (Object)null || Vagon.m_instances == null) { return null; } GameObject gameObject = ((Component)player).gameObject; foreach (Vagon instance in Vagon.m_instances) { if (!((Object)(object)instance == (Object)null) && !((Object)(object)instance.m_attachJoin == (Object)null)) { if ((Object)(object)instance.m_attachedObject == (Object)(object)gameObject) { return instance; } if ((Object)(object)((Joint)instance.m_attachJoin).connectedBody != (Object)null && (Object)(object)((Component)((Joint)instance.m_attachJoin).connectedBody).gameObject == (Object)(object)gameObject) { return instance; } } } return null; } private static Character GetRiddenMount(Player player) { if ((Object)(object)player == (Object)null || !((Character)player).IsRiding()) { return null; } IDoodadController doodadController = player.GetDoodadController(); Sadle val = (Sadle)(object)((doodadController is Sadle) ? doodadController : null); if ((Object)(object)val == (Object)null) { return null; } Character character = val.GetCharacter(); if ((Object)(object)character == (Object)null || character.IsDead() || (Object)(object)character.m_nview == (Object)null || !character.m_nview.IsValid()) { return null; } return character; } internal static bool IsCartTeleportable(Vagon cart, bool allowAllItems, out string blockedBy) { blockedBy = ""; if ((Object)(object)cart == (Object)null || (Object)(object)cart.m_container == (Object)null) { return true; } Inventory inventory = cart.m_container.GetInventory(); if (inventory == null) { return true; } bool flag = (Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGlobalKey((GlobalKeys)35); blockedItemBuffer.Clear(); foreach (ItemData allItem in inventory.GetAllItems()) { if (allItem != null && allItem.m_shared != null && (allItem.m_shared.m_toolTier >= 1000 || (!(allowAllItems || flag) && !TeleportItems.PerPlayerTeleportableItems.IsItemTeleportable(allItem)))) { string item = Localization.instance.Localize(allItem.m_shared.m_name); if (!blockedItemBuffer.Contains(item)) { blockedItemBuffer.Add(item); } } } if (blockedItemBuffer.Count == 0) { return true; } int num = Mathf.Min(blockedItemBuffer.Count, 3); blockedBy = string.Join(", ", blockedItemBuffer.GetRange(0, num).ToArray()); if (blockedItemBuffer.Count > num) { blockedBy += $", +{blockedItemBuffer.Count - num}"; } blockedItemBuffer.Clear(); return false; } private static bool IsFollowing(Character tame, Player player) { MonsterAI component = ((Component)tame).GetComponent<MonsterAI>(); if ((Object)(object)component != (Object)null && (Object)(object)component.GetFollowTarget() == (Object)(object)((Component)player).gameObject) { return true; } ZDO zDO = tame.m_nview.GetZDO(); if (zDO != null) { return zDO.GetString(ZDOVars.s_follow, "") == player.GetPlayerName(); } return false; } private static void GatherTames(Player player, Vector3 center, Character exclude, List<Character> into) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) into.Clear(); float num = ValConfig.TeleportTamesRadius.Value * ValConfig.TeleportTamesRadius.Value; bool value = ValConfig.TeleportTamesRequireFollowing.Value; List<Character> allCharacters = Character.GetAllCharacters(); for (int i = 0; i < allCharacters.Count; i++) { Character val = allCharacters[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)exclude) && !val.IsPlayer() && !val.IsDead() && !((Object)(object)val.m_nview == (Object)null) && val.m_nview.IsValid() && val.IsTamed() && !(Utils.DistanceSqr(((Component)val).transform.position, center) > num)) { Sadle componentInChildren = ((Component)val).GetComponentInChildren<Sadle>(); if ((!((Object)(object)componentInChildren != (Object)null) || !componentInChildren.HaveValidUser()) && (!value || IsFollowing(val, player))) { into.Add(val); } } } into.Sort((Character a, Character b) => Utils.DistanceSqr(((Component)a).transform.position, center).CompareTo(Utils.DistanceSqr(((Component)b).transform.position, center))); int value2 = ValConfig.TeleportTamesMaxCount.Value; if (into.Count > value2) { into.RemoveRange(value2, into.Count - value2); } } private static void MoveToDestination(ZNetView nview, Transform transform, Vector3 destination) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) nview.ClaimOwnership(); transform.position = destination; nview.GetZDO().SetPosition(destination); } private static void MoveTame(Character tame, Vector3 destination) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) MoveToDestination(tame.m_nview, ((Component)tame).transform, destination); if ((Object)(object)tame.m_body != (Object)null) { tame.m_body.position = destination; tame.m_body.linearVelocity = Vector3.zero; tame.m_body.angularVelocity = Vector3.zero; } tame.m_maxAirAltitude = destination.y; } private static void MoveCart(Vagon cart, Vector3 destination) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) MoveToDestination(cart.m_nview, ((Component)cart).transform, destination); if (cart.m_bodies == null) { return; } Rigidbody[] bodies = cart.m_bodies; foreach (Rigidbody val in bodies) { if (!((Object)(object)val == (Object)null)) { val.position = ((Component)val).transform.position; val.linearVelocity = Vector3.zero; val.angularVelocity = Vector3.zero; } } } private static void CarryCompanions(Player player, PortalTrip trip) { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_007f: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: 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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) int num = 0; if ((Object)(object)trip.Mount != (Object)null && (Object)(object)trip.Mount.m_nview != (Object)null && trip.Mount.m_nview.IsValid()) { ZDOID uid = trip.Mount.m_nview.GetZDO().m_uid; player.StopDoodadControl(); MoveTame(trip.Mount, trip.Destination + CompanionOffset(num)); num++; Logger.LogDebug("Took a ridden mount through the portal."); StartArrivalCoroutine(player, uid, "Mount", Remount); } if (ValConfig.EnableTeleportTames.Value) { GatherTames(player, trip.Center, trip.Mount, tameBuffer); foreach (Character item in tameBuffer) { MoveTame(item, trip.Destination + CompanionOffset(num)); num++; } if (tameBuffer.Count > 0) { Logger.LogDebug($"Took {tameBuffer.Count} tamed creature(s) through the portal."); } tameBuffer.Clear(); } if ((Object)(object)trip.Cart != (Object)null && (Object)(object)trip.Cart.m_nview != (Object)null && trip.Cart.m_nview.IsValid()) { ZDOID uid2 = trip.Cart.m_nview.GetZDO().m_uid; trip.Cart.Detach(); MoveCart(trip.Cart, trip.Destination + CompanionOffset(num)); Logger.LogDebug("Took a cart through the portal."); StartArrivalCoroutine(player, uid2, "Cart", SettleCart); } } private static void StartArrivalCoroutine(Player player, ZDOID id, string what, Func<Player, GameObject, IEnumerator> arrived) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)AdjustablePortals.Instance != (Object)null) { ((MonoBehaviour)AdjustablePortals.Instance).StartCoroutine(AfterArrival(player, id, what, arrived)); } } private static IEnumerator AfterArrival(Player player, ZDOID id, string what, Func<Player, GameObject, IEnumerator> arrived) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) float deadline = Time.time + 20f; while (Time.time < deadline && (Object)(object)player != (Object)null && ((Character)player).IsTeleporting()) { yield return null; } GameObject instance = null; while (Time.time < deadline && (Object)(object)player != (Object)null) { instance = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.FindInstance(id) : null); if ((Object)(object)instance != (Object)null) { break; } yield return null; } if ((Object)(object)player == (Object)null || (Object)(object)instance == (Object)null) { Logger.LogDebug(what + " did not turn up at the destination in time, leaving it where it landed."); } else { yield return ((MonoBehaviour)AdjustablePortals.Instance).StartCoroutine(arrived(player, instance)); } } private static IEnumerator SettleCart(Player player, GameObject instance) { Vagon cart = instance.GetComponent<Vagon>(); if ((Object)(object)cart == (Object)null || (Object)(object)cart.m_nview == (Object)null || !cart.m_nview.IsValid()) { yield break; } Vector3 val = cart.m_attachPoint.position - ((Component)cart).transform.position; MoveCart(cart, ((Component)player).transform.position + cart.m_attachOffset - val); if (ValConfig.ReattachCartAfterTeleport.Value) { yield return null; if ((Object)(object)player != (Object)null && (Object)(object)cart != (Object)null && !((Character)player).IsTeleporting()) { cart.AttachTo(((Component)player).gameObject); } } } private static IEnumerator Remount(Player player, GameObject instance) { Sadle componentInChildren = instance.GetComponentInChildren<Sadle>(); if (!((Object)(object)componentInChildren == (Object)null) && !((Character)player).IsDead() && !((Character)player).IsAttached() && player.GetDoodadController() == null) { if (!componentInChildren.InUseDistance((Humanoid)(object)player)) { Logger.LogDebug("Mount landed out of reach of the player, leaving it unridden."); } else { componentInChildren.Interact((Humanoid)(object)player, false, false); } } yield break; } } public static class TeleportItems { [HarmonyPatch(typeof(Humanoid))] private static class AllowConfiguredTeleportableItems { [HarmonyPatch("IsTeleportable")] private static void Postfix(Humanoid __instance, ref bool __result) { if (__result || __instance.m_inventory.GetAllItems().Any((ItemData x) => x.m_shared.m_toolTier >= 1000)) { 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), "GlobalKeyAdd", new Type[] { typeof(string), typeof(bool) })] private static void GlobalKeyAdded(string keyStr) { PlayerItemsAllowTeleport.Clear(); } [HarmonyPostfix] [HarmonyPatch(typeof(ZoneSystem), "ClearGlobalKeys")] private static void GlobalKeysCleared() { PlayerItemsAllowTeleport.Clear(); } } [HarmonyPatch(typeof(InventoryGrid))] public static class PerPlayerTeleportableItems { [HarmonyTranspiler] [HarmonyPatch("UpdateGui")] private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown CodeMatcher val = new CodeMatcher(instructions, (ILGenerator)null); val.MatchStartForward((CodeMatch[])(object)new CodeMatch[3] { new CodeMatch((Func<CodeInstruction, bool>)((CodeInstruction instruction) => CodeInstructionExtensions.IsLdloc(instruction, (LocalBuilder)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) }).ThrowIfNotMatch("Unable to patch item teleport visual display.", Array.Empty<CodeMatch>()); CodeInstruction val2 = val.Instruction.Clone(); val.RemoveInstructions(3).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2] { val2, Transpilers.EmitDelegate<Func<ItemData, bool>>((Func<ItemData, bool>)IsItemTeleportable) }); 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)42) && EikthyrAllowedTeleports.Contains(name)) { flag = true; } if (!flag && ZoneSystem.instance.GetGlobalKey((GlobalKeys)45) && ElderAllowedTeleports.Contains(name)) { flag = true; } if (!flag && ZoneSystem.instance.GetGlobalKey((GlobalKeys)46) && BonemassAllowedTeleports.Contains(name)) { flag = true; } if (!flag && ZoneSystem.instance.GetGlobalKey((GlobalKeys)43) && ModerAllowedTeleports.Contains(name)) { flag = true; } if (!flag && ZoneSystem.instance.GetGlobalKey((GlobalKeys)44) && 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; } if (!PlayerItemsAllowTeleport.ContainsKey(name)) { PlayerItemsAllowTeleport.Add(name, flag); } return flag; } } 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 int CountItemsByPrefab(this Inventory inv, string prefab) { int num = 0; foreach (ItemData allItem in inv.GetAllItems()) { if ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == prefab && allItem.m_stack > 0) { num += allItem.m_stack; } } return num; } public static bool RemoveItemByPrefab(this Inventory inv, string prefab, int countToRemove) { if (countToRemove <= 0) { return true; } if (inv.CountItemsByPrefab(prefab) < countToRemove) { Logger.LogDebug($"Remove summary: {prefab}x{countToRemove} not available, removing nothing."); return false; } List<ItemData> list = new List<ItemData>(); foreach (ItemData allItem in inv.GetAllItems()) { if ((Object)(object)allItem.m_dropPrefab != (Object)null && ((Object)allItem.m_dropPrefab).name == prefab && allItem.m_stack > 0) { list.Add(allItem); } } int num = countToRemove; foreach (ItemData item in list) { if (num <= 0) { break; } int num2 = Mathf.Min(item.m_stack, num); inv.RemoveItem(item, num2); num -= num2; } Logger.LogDebug($"Remove summary: {prefab}x{countToRemove} successfully removed: {countToRemove - num}"); return num == 0; } } internal static class PieceProximity { private struct PieceRefs { public Piece Piece; public GameObject GameObject; public Transform Transform; } private const float CellSize = 32f; private const float SnapshotLifetimeSeconds = 10f; private static readonly Dictionary<long, List<Vector3>> cells = new Dictionary<long, List<Vector3>>(); private static PieceRefs[] known = Array.Empty<PieceRefs>(); private static int knownCount = 0; private static float nextRebuildTime = 0f; private static bool built = false; internal static int CountWithin(Vector3 center, float radius) { //IL_0013: 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: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) if (radius <= 0f) { return 0; } RebuildIfStale(); float num = radius * radius; int num2 = CellIndex(center.x - radius); int num3 = CellIndex(center.x + radius); int num4 = CellIndex(center.z - radius); int num5 = CellIndex(center.z + radius); int num6 = 0; for (int i = num2; i <= num3; i++) { for (int j = num4; j <= num5; j++) { if (!cells.TryGetValue(CellKey(i, j), out var value)) { continue; } for (int k = 0; k < value.Count; k++) { Vector3 val = value[k] - center; if (((Vector3)(ref val)).sqrMagnitude < num) { num6++; } } } } return num6; } internal static void Clear() { cells.Clear(); Array.Clear(known, 0, knownCount); knownCount = 0; nextRebuildTime = 0f; built = false; } private static void RebuildIfStale() { //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) float time = Time.time; if (built && time < nextRebuildTime) { return; } foreach (List<Vector3> value2 in cells.Values) { value2.Clear(); } int s_ghostLayer = Piece.s_ghostLayer; List<Piece> s_allPieces = Piece.s_allPieces; int count = s_allPieces.Count; if (known.Length < count) { Array.Resize(ref known, Mathf.Max(count, known.Length * 2)); } long num = 0L; List<Vector3> list = null; for (int i = 0; i < count; i++) { Piece val = s_allPieces[i]; GameObject gameObject; Transform transform; if (known[i].Piece == val) { gameObject = known[i].GameObject; transform = known[i].Transform; } else { gameObject = ((Component)val).gameObject; transform = ((Component)val).transform; known[i].Piece = val; known[i].GameObject = gameObject; known[i].Transform = transform; } if (gameObject.layer == s_ghostLayer) { continue; } Vector3 position = transform.position; long num2 = CellKey(CellIndex(position.x), CellIndex(position.z)); if (list != null && num2 == num) { list.Add(position); continue; } if (!cells.TryGetValue(num2, out var value)) { value = new List<Vector3>(16); cells[num2] = value; } value.Add(position); num = num2; list = value; } for (int j = count; j < knownCount; j++) { known[j] = default(PieceRefs); } knownCount = count; nextRebuildTime = time + 10f; built = true; } private static int CellIndex(float world) { return Mathf.FloorToInt(world / 32f); } private static long CellKey(int cellX, int cellZ) { return ((long)cellX << 32) | (uint)cellZ; } } }