using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; 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; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using JetBrains.Annotations; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using Splatform; using UnityEngine; using UnityEngine.SceneManagement; using VentureValheim.MultiplayerTweaks; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("VentureValheim.TravelTotems")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("VentureValheim.TravelTotems")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("D150132C-BA5F-41DA-9A9C-29FD189CDE71")] [assembly: AssemblyFileVersion("0.1.0")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] [module: UnverifiableCode] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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; } } } namespace VentureValheim.TravelTotems { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [BepInPlugin("com.orianaventure.mod.TravelTotems", "TravelTotems", "0.1.0")] public class TravelTotemsPlugin : BaseUnityPlugin { private const string ModName = "TravelTotems"; private const string ModVersion = "0.1.0"; private const string Author = "com.orianaventure.mod"; private const string ModGUID = "com.orianaventure.mod.TravelTotems"; private static string ConfigFileName = "com.orianaventure.mod.TravelTotems.cfg"; private static string ConfigFileFullPath; private const string VVMTGUID = "com.orianaventure.mod.MultiplayerTweaks"; private const string VVMTAPI = "VentureValheim.MultiplayerTweaks.API"; private readonly Harmony HarmonyInstance = new Harmony("com.orianaventure.mod.TravelTotems"); public static readonly ManualLogSource TravelTotemsLogger; private static ConfigEntry CE_AdminBypass; private static ConfigEntry CE_ShowTotemID; private static ConfigEntry CE_TotemNamingAccess; private static ConfigEntry CE_ShowMapPins; private static ConfigEntry CE_TotemAccessDefault; private static ConfigEntry CE_TotemUnlockRequirementsString; private static ConfigEntry CE_AllowSelectDefaultSpawn; private static ConfigEntry CE_AllowSelectTraders; private static ConfigEntry CE_AllowSelectBed; private static ConfigEntry CE_AllowTotemClaiming; private static ConfigEntry CE_TradersSellTotemBomb; private static ConfigEntry CE_TradersSellTotemBombCost; private static ConfigEntry CE_LocationAmountDefault; private static ConfigEntry CE_LocationAmountMeadows; private static ConfigEntry CE_LocationAmountBlackForest; private static ConfigEntry CE_LocationAmountSwamp; private static ConfigEntry CE_LocationAmountMountain; private static ConfigEntry CE_LocationAmountPlains; private static ConfigEntry CE_LocationAmountMistlands; private static ConfigEntry CE_LocationAmountAshlands; private static ConfigEntry CE_LocationSpacing; private static ConfigEntry CE_PieceRecipesEnabled; private static ConfigEntry CE_TravelTotemPieceCost; private static ConfigEntry CE_TravelTotemPieceMistlandsCost; private static ConfigEntry CE_TravelTotemPieceAshlandsCost; private static ConfigEntry CE_ItemRecipesEnabled; private static ConfigEntry CE_TotemBombCraftCost; private readonly ConfigurationManagerAttributes AdminConfig = new ConfigurationManagerAttributes { IsAdminOnly = true }; private readonly ConfigurationManagerAttributes ClientConfig = new ConfigurationManagerAttributes { IsAdminOnly = false }; private DateTime _lastReloadTime; private const long RELOAD_DELAY = 10000000L; public static bool MultiplayerTweaksInstalled { get; private set; } internal static AssetBundle TotemBundle { get; private set; } private static bool AdminAccess() { if (CE_AdminBypass.Value) { return SynchronizationManager.Instance.PlayerIsAdmin; } return false; } public static bool GetOverrideTotemAccess(bool isCreator) { if (isCreator || AdminAccess()) { return true; } return false; } public static bool GetTotemNamingAccess(bool isCreator, bool isPublic) { if (isCreator || AdminAccess() || (CE_TotemNamingAccess.Value && isPublic)) { return true; } return false; } public static bool GetShowMapPins() { return CE_ShowMapPins.Value; } public static bool GetShowTotemID() { return CE_ShowTotemID.Value; } public static TravelTotemType GetTravelTotemType() { return CE_TotemAccessDefault.Value.ToLower() switch { "alwaysunlock" => TravelTotemType.AlwaysUnlock, "alwayslock" => TravelTotemType.AlwaysLock, "findunlock" => TravelTotemType.FindUnlock, _ => TravelTotemType.Undefined, }; } public static string GetTotemUnlockRequirementsString() { return CE_TotemUnlockRequirementsString.Value; } public static bool GetAllowSelectDefaultSpawn() { return CE_AllowSelectDefaultSpawn.Value; } public static bool GetAllowSelectTraders() { return CE_AllowSelectTraders.Value; } public static bool GetAllowSelectBed() { return CE_AllowSelectBed.Value; } public static bool GetAllowTotemClaiming() { return CE_AllowTotemClaiming.Value; } public static bool GetTradersSellTotemBomb() { return CE_TradersSellTotemBomb.Value; } public static int GetTradersSellTotemBombCost() { return CE_TradersSellTotemBombCost.Value; } public static int GetLocationAmountDefault() { return CE_LocationAmountDefault.Value; } public static int GetLocationAmountMeadows() { return CE_LocationAmountMeadows.Value; } public static int GetLocationAmountBlackForest() { return CE_LocationAmountBlackForest.Value; } public static int GetLocationAmountSwamp() { return CE_LocationAmountSwamp.Value; } public static int GetLocationAmountMountain() { return CE_LocationAmountMountain.Value; } public static int GetLocationAmountPlains() { return CE_LocationAmountPlains.Value; } public static int GetLocationAmountMistlands() { return CE_LocationAmountMistlands.Value; } public static int GetLocationAmountAshlands() { return CE_LocationAmountAshlands.Value; } public static int GetLocationSpacing() { return CE_LocationSpacing.Value; } public static bool GetTravelTotemPieceRecipesEnabled() { return CE_PieceRecipesEnabled.Value; } public static string GetTravelTotemPieceCost() { return CE_TravelTotemPieceCost.Value; } public static string GetTravelTotemPieceMistlandsCost() { return CE_TravelTotemPieceMistlandsCost.Value; } public static string GetTravelTotemPieceAshlandsCost() { return CE_TravelTotemPieceAshlandsCost.Value; } public static bool GetTotemItemRecipesEnabled() { return CE_ItemRecipesEnabled.Value; } public static string GetTotemBombItemCost() { return CE_TotemBombCraftCost.Value; } private void AddConfig(string key, string section, string description, bool synced, T value, ref ConfigEntry configEntry) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown string extendedDescription = GetExtendedDescription(description, synced); configEntry = ((BaseUnityPlugin)this).Config.Bind(section, key, value, new ConfigDescription(extendedDescription, (AcceptableValueBase)null, new object[1] { synced ? AdminConfig : ClientConfig })); } public string GetExtendedDescription(string description, bool synchronizedSetting) { return description + (synchronizedSetting ? " [Synced with Server]" : " [Not Synced with Server]"); } public void Awake() { AddConfig("TotemNamingAccess", "General", "When false allow only admins (using AdminBypass) to rename public travel totems (boolean).", synced: true, value: false, ref CE_TotemNamingAccess); AddConfig("TotemAccessDefault", "General", "Default access type for new totems: AlwaysUnlock, FindUnlock, AlwaysLock (string).", synced: true, "FindUnlock", ref CE_TotemAccessDefault); AddConfig("TotemUnlockRequirements", "General", "Prefab amount pairs of required items to unlock a portal when access is set to TouchUnlock. For example: Wood:2,SurtlingCore:2 (A comma-separated list of ITEM:QUANTITY pairs).", synced: true, "", ref CE_TotemUnlockRequirementsString); AddConfig("AllowSelectDefaultSpawn", "General", "When true allow teleporting to the starting stones icon when using totems (boolean).", synced: true, value: true, ref CE_AllowSelectDefaultSpawn); AddConfig("AllowSelectTraders", "General", "When true allow teleporting to discovered trader icons when using totems (boolean).", synced: true, value: true, ref CE_AllowSelectTraders); AddConfig("AllowSelectBed", "General", "When true allow teleporting to bed icons when using totems (boolean).", synced: true, value: true, ref CE_AllowSelectBed); AddConfig("AllowTotemClaiming", "General", "When true allow players to claim public totems they unlock as if they built them (boolean).", synced: true, value: false, ref CE_AllowTotemClaiming); AddConfig("AdminBypass", "Client", "Allow local admins to access and change all travel totems at all times (boolean).", synced: false, value: false, ref CE_AdminBypass); AddConfig("ShowMapPins", "Client", "Always show map pins of available Totems on the Player minimap (boolean).", synced: false, value: true, ref CE_ShowMapPins); AddConfig("ShowTotemID", "Client", "Display the Totem ID when looking at a Totem (boolean).", synced: false, value: false, ref CE_ShowTotemID); AddConfig("TradersSellTotemBomb", "Trader", "Adds Totem Bombs for sale by the traders (boolean).", synced: false, value: true, ref CE_TradersSellTotemBomb); AddConfig("TradersSellTotemBombCost", "Trader", "Coins cost of the Totem Bomb (boolean).", synced: false, 100, ref CE_TradersSellTotemBombCost); AddConfig("LocationAmountDefault", "Location", "Maximum number of undecorated, biome universal locations to add during world generation. Set to 0 to disable (int).", synced: true, 0, ref CE_LocationAmountDefault); AddConfig("LocationAmountMeadows", "Location", "Maximum number of Meadows locations to add during world generation. Set to 0 to disable (int).", synced: true, 20, ref CE_LocationAmountMeadows); AddConfig("LocationAmountBlackForest", "Location", "Maximum number of BlackForest locations to add during world generation. Set to 0 to disable (int).", synced: true, 20, ref CE_LocationAmountBlackForest); AddConfig("LocationAmountSwamp", "Location", "Maximum number of Swamp locations to add during world generation. Set to 0 to disable (int).", synced: true, 20, ref CE_LocationAmountSwamp); AddConfig("LocationAmountMountain", "Location", "Maximum number of Mountain locations to add during world generation. Set to 0 to disable (int).", synced: true, 20, ref CE_LocationAmountMountain); AddConfig("LocationAmountPlains", "Location", "Maximum number of Plains locations to add during world generation. Set to 0 to disable (int).", synced: true, 20, ref CE_LocationAmountPlains); AddConfig("LocationAmountMistlands", "Location", "Maximum number of Mistlands locations to add during world generation. Set to 0 to disable (int).", synced: true, 20, ref CE_LocationAmountMistlands); AddConfig("LocationAmountAshlands", "Location", "Maximum number of Ashlands locations to add during world generation. Set to 0 to disable (int).", synced: true, 10, ref CE_LocationAmountAshlands); AddConfig("LocationSpacing", "Location", "Minimum world distance between similar totems. Setting also commonly known as \"MinDistanceFromSimilar\" (int).", synced: true, 1500, ref CE_LocationSpacing); AddConfig("PieceRecipeOverridesEnabled", "Pieces", "True to use these cost configurations. Set to false if using another mod to customize this (boolean).", synced: true, value: true, ref CE_PieceRecipesEnabled); AddConfig("PieceCost", "Pieces", "Default Totem build cost, if left blank will be disabled (A comma-separated list of ITEM:QUANTITY pairs).", synced: true, AssetManager.TravelTotemPiece_Cost, ref CE_TravelTotemPieceCost); AddConfig("PieceMistlandsCost", "Pieces", "Mistlands Totem build cost, if left blank will be disabled (A comma-separated list of ITEM:QUANTITY pairs).", synced: true, AssetManager.TravelTotemPieceMistlands_Cost, ref CE_TravelTotemPieceMistlandsCost); AddConfig("PieceAshlandsCost", "Pieces", "Ashlands Totem build cost, if left blank will be disabled (A comma-separated list of ITEM:QUANTITY pairs).", synced: true, AssetManager.TravelTotemPieceAshlands_Cost, ref CE_TravelTotemPieceAshlandsCost); AddConfig("ItemRecipeOverridesEnabled", "Items", "True to use these cost configurations. Set to false if using another mod to customize this (boolean).", synced: true, value: true, ref CE_ItemRecipesEnabled); AddConfig("TotemBombCraftCost", "Items", "Totem Bomb crafting cost, if left blank will be disabled (A comma-separated list of ITEM:QUANTITY pairs).", synced: true, AssetManager.TotemBombCraft_Cost, ref CE_TotemBombCraftCost); TravelTotemsLogger.LogInfo((object)"Praise be to the gods."); CheckForMultiplayerTweaks(); ZoneManager.OnVanillaLocationsAvailable += AssetManager.AddTotemLocations; PrefabManager.OnVanillaPrefabsAvailable += AssetManager.AddPrefabs; Assembly executingAssembly = Assembly.GetExecutingAssembly(); HarmonyInstance.PatchAll(executingAssembly); SetupWatcher(); TotemBundle = AssetUtils.LoadAssetBundleFromResources("vv_traveltotems", Assembly.GetExecutingAssembly()); ItemManager.OnItemsRegistered += AssetManager.UpdateItemConfigurations; PieceManager.OnPiecesRegistered += AssetManager.UpdatePieceConfigurations; } [MethodImpl(MethodImplOptions.NoInlining)] private void CheckForMultiplayerTweaks() { try { MultiplayerTweaksInstalled = Chainloader.PluginInfos.TryGetValue("com.orianaventure.mod.MultiplayerTweaks", out var value); if (MultiplayerTweaksInstalled) { Type type = Assembly.GetAssembly(((object)value.Instance).GetType()).GetType("VentureValheim.MultiplayerTweaks.API"); if (type != null && AccessTools.Method(type, "GetHaldorPinIndex", (Type[])null, (Type[])null) != null) { TravelTotemsLogger.LogInfo((object)"Multiplayer Tweaks installed. Personal Trader pins can be tracked for teleportation!"); return; } MultiplayerTweaksInstalled = false; TravelTotemsLogger.LogWarning((object)"Multiplayer Tweaks version mismatch! Please update Multiplayer Tweaks."); } } catch { MultiplayerTweaksInstalled = false; } if (!MultiplayerTweaksInstalled) { TravelTotemsLogger.LogDebug((object)"Multiplayer Tweaks is not installed. Will not check pins for compatibility."); } } private void OnDestroy() { ((BaseUnityPlugin)this).Config.Save(); } private void SetupWatcher() { _lastReloadTime = DateTime.Now; FileSystemWatcher fileSystemWatcher = new FileSystemWatcher(Paths.ConfigPath, ConfigFileName); fileSystemWatcher.Changed += ReadConfigValues; fileSystemWatcher.Created += ReadConfigValues; fileSystemWatcher.Renamed += ReadConfigValues; fileSystemWatcher.IncludeSubdirectories = true; fileSystemWatcher.SynchronizingObject = ThreadingHelper.SynchronizingObject; fileSystemWatcher.EnableRaisingEvents = true; } private void ReadConfigValues(object sender, FileSystemEventArgs e) { DateTime now = DateTime.Now; long num = now.Ticks - _lastReloadTime.Ticks; if (!File.Exists(ConfigFileFullPath) || num < 10000000) { return; } try { TravelTotemsLogger.LogInfo((object)"Attempting to reload configuration..."); ((BaseUnityPlugin)this).Config.Reload(); } catch { TravelTotemsLogger.LogError((object)("There was an issue loading " + ConfigFileName)); return; } _lastReloadTime = now; if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsDedicated()) { TravelTotems.UpdateSettings(); AssetManager.UpdateConfigurations(); TravelTotemMap.RefreshMapPins(); if (Object.op_Implicit((Object)(object)ZoneSystem.instance)) { TravelTotemMap.RefreshLocationIcons(); } } } public static bool IsInTheMainScene() { //IL_0000: 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) Scene activeScene = SceneManager.GetActiveScene(); return ((Scene)(ref activeScene)).name.Equals("main"); } static TravelTotemsPlugin() { string configPath = Paths.ConfigPath; char directorySeparatorChar = Path.DirectorySeparatorChar; ConfigFileFullPath = configPath + directorySeparatorChar + ConfigFileName; TravelTotemsLogger = Logger.CreateLogSource("TravelTotems"); CE_AdminBypass = null; CE_ShowTotemID = null; CE_TotemNamingAccess = null; CE_ShowMapPins = null; CE_TotemAccessDefault = null; CE_TotemUnlockRequirementsString = null; CE_AllowSelectDefaultSpawn = null; CE_AllowSelectTraders = null; CE_AllowSelectBed = null; CE_AllowTotemClaiming = null; CE_TradersSellTotemBomb = null; CE_TradersSellTotemBombCost = null; CE_LocationAmountDefault = null; CE_LocationAmountMeadows = null; CE_LocationAmountBlackForest = null; CE_LocationAmountSwamp = null; CE_LocationAmountMountain = null; CE_LocationAmountPlains = null; CE_LocationAmountMistlands = null; CE_LocationAmountAshlands = null; CE_LocationSpacing = null; CE_PieceRecipesEnabled = null; CE_TravelTotemPieceCost = null; CE_TravelTotemPieceMistlandsCost = null; CE_TravelTotemPieceAshlandsCost = null; CE_ItemRecipesEnabled = null; CE_TotemBombCraftCost = null; } } public class AssetManager { public static string TravelTotemTrackerPrefabName = "VV_TravelTotemTracker"; public static int TravelTotemTrackerHash = StringExtensionMethods.GetStableHashCode(TravelTotemTrackerPrefabName); private static string TravelTotem_PrefabName = "VV_TravelTotem"; private static string TravelTotemMistlands_PrefabName = "VV_TravelTotemMistlands"; private static string TravelTotemAshlands_PrefabName = "VV_TravelTotemAshlands"; private static int TravelTotemHash = StringExtensionMethods.GetStableHashCode(TravelTotem_PrefabName); private static int TravelTotemMistlandsHash = StringExtensionMethods.GetStableHashCode(TravelTotemMistlands_PrefabName); private static int TravelTotemAshlandsHash = StringExtensionMethods.GetStableHashCode(TravelTotemAshlands_PrefabName); private static string TravelTotemPiece_PrefabName = "VV_TravelTotemPiece"; private static string TravelTotemPieceMistlands_PrefabName = "VV_TravelTotemPieceMistlands"; private static string TravelTotemPieceAshlands_PrefabName = "VV_TravelTotemPieceAshlands"; private static int TravelTotemPieceHash = StringExtensionMethods.GetStableHashCode(TravelTotemPiece_PrefabName); private static int TravelTotemPieceMistlandsHash = StringExtensionMethods.GetStableHashCode(TravelTotemPieceMistlands_PrefabName); private static int TravelTotemPieceAshlandsHash = StringExtensionMethods.GetStableHashCode(TravelTotemPieceAshlands_PrefabName); public static string TravelTotemPiece_Cost = "GreydwarfEye:10,Stone:20,SurtlingCore:5"; public static string TravelTotemPieceMistlands_Cost = "GreydwarfEye:10,BlackMarble:20,SurtlingCore:5"; public static string TravelTotemPieceAshlands_Cost = "GreydwarfEye:10,Grausten:20,SurtlingCore:5"; private static string TravelTotemArea_PrefabName = "VV_TravelTotemArea"; public static string TravelTotemBomb_PrefabName = "VV_BombTotem"; private static string TravelTotemBombSpawn_PrefabName = "VV_BombTotem_projectile"; public static string TotemBombCraft_Cost = "GreydwarfEye:10,Resin:10,SurtlingCore:2"; private static string TotemMapSprite_Name = "VV_TravelTotemMapSprite"; public static Material TotemMaterialDefault { get; private set; } public static Material TotemMaterialMistlands { get; private set; } public static Material TotemMaterialAshlands { get; private set; } public static Sprite TotemMapSprite { get; private set; } public static bool IsTravelTotem(int prefabHash) { if (prefabHash != TravelTotemHash && prefabHash != TravelTotemMistlandsHash && prefabHash != TravelTotemAshlandsHash && prefabHash != TravelTotemPieceHash && prefabHash != TravelTotemPieceMistlandsHash) { return prefabHash == TravelTotemPieceAshlandsHash; } return true; } public static bool IsTravelTotemTracker(int prefabHash) { return prefabHash == TravelTotemTrackerHash; } public static void AddPrefabs() { CreateMaterials(); AddPrefab(TravelTotem_PrefabName); AddPrefab(TravelTotemMistlands_PrefabName); AddPrefab(TravelTotemAshlands_PrefabName); AddPrefab(TravelTotemTrackerPrefabName); CreatePieces(); CreateItems(); TotemMapSprite = TravelTotemsPlugin.TotemBundle.LoadAsset(TotemMapSprite_Name); PrefabManager.OnVanillaPrefabsAvailable -= AddPrefabs; } private static void AddPrefab(string name) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown CustomPrefab val = new CustomPrefab(TravelTotemsPlugin.TotemBundle, name, true); PrefabManager.Instance.AddPrefab(val); } private static void CreateItems() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_0074: Expected O, but got Unknown //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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown AddPrefab(TravelTotemArea_PrefabName); AddPrefab(TravelTotemBombSpawn_PrefabName); GameObject val = TravelTotemsPlugin.TotemBundle.LoadAsset(TravelTotemBomb_PrefabName); ItemConfig val2 = new ItemConfig(); val2.Name = "Totem Bomb"; val2.Description = "An unstable burst energy that can temporarily access a teleportation network."; val2.CraftingStation = CraftingStations.Workbench; val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig { Item = "GreydwarfEye", Amount = 10, Recover = true }, new RequirementConfig { Item = "Resin", Amount = 10, Recover = true }, new RequirementConfig { Item = "SurtlingCore", Amount = 2, Recover = true } }; ItemConfig val3 = val2; CustomItem val4 = new CustomItem(val, true, val3); ItemManager.Instance.AddItem(val4); } private static void CreatePieces() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Expected O, but got Unknown //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Expected O, but got Unknown //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Expected O, but got Unknown //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Expected O, but got Unknown //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_018e: 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_019d: Expected O, but got Unknown //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Expected O, but got Unknown //IL_01cf: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Expected O, but got Unknown //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_023c: Expected O, but got Unknown //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Expected O, but got Unknown //IL_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Expected O, but got Unknown //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Expected O, but got Unknown GameObject val = TravelTotemsPlugin.TotemBundle.LoadAsset(TravelTotemPiece_PrefabName); PieceConfig val2 = new PieceConfig(); val2.PieceTable = PieceTables.Hammer; val2.Category = PieceCategories.Misc; val2.Name = "Travel Totem"; val2.Description = "A mystical relic that can form a teleportation network. CANNOT BE REMOVED ONCE PLACED!"; val2.CraftingStation = CraftingStations.Stonecutter; val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig { Item = "GreydwarfEye", Amount = 10, Recover = true }, new RequirementConfig { Item = "Stone", Amount = 20, Recover = true }, new RequirementConfig { Item = "SurtlingCore", Amount = 5, Recover = true } }; PieceConfig val3 = val2; CustomPiece val4 = new CustomPiece(val, true, val3); PieceManager.Instance.AddPiece(val4); GameObject val5 = TravelTotemsPlugin.TotemBundle.LoadAsset(TravelTotemPieceMistlands_PrefabName); val2 = new PieceConfig(); val2.PieceTable = PieceTables.Hammer; val2.Category = PieceCategories.Misc; val2.Name = "Travel Totem BlackMarble"; val2.Description = "A mystical relic that can form a teleportation network. CANNOT BE REMOVED ONCE PLACED!"; val2.CraftingStation = CraftingStations.Stonecutter; val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig { Item = "GreydwarfEye", Amount = 10, Recover = true }, new RequirementConfig { Item = "BlackMarble", Amount = 20, Recover = true }, new RequirementConfig { Item = "SurtlingCore", Amount = 5, Recover = true } }; PieceConfig val6 = val2; CustomPiece val7 = new CustomPiece(val5, true, val6); PieceManager.Instance.AddPiece(val7); GameObject val8 = TravelTotemsPlugin.TotemBundle.LoadAsset(TravelTotemPieceAshlands_PrefabName); val2 = new PieceConfig(); val2.PieceTable = PieceTables.Hammer; val2.Category = PieceCategories.Misc; val2.Name = "Travel Totem Grausten"; val2.Description = "A mystical relic that can form a teleportation network. CANNOT BE REMOVED ONCE PLACED!"; val2.CraftingStation = CraftingStations.Stonecutter; val2.Requirements = (RequirementConfig[])(object)new RequirementConfig[3] { new RequirementConfig { Item = "GreydwarfEye", Amount = 10, Recover = true }, new RequirementConfig { Item = "Grausten", Amount = 20, Recover = true }, new RequirementConfig { Item = "SurtlingCore", Amount = 5, Recover = true } }; PieceConfig val9 = val2; CustomPiece val10 = new CustomPiece(val8, true, val9); PieceManager.Instance.AddPiece(val10); } public static void UpdateConfigurations() { UpdatePieceConfigurations(); UpdateItemConfigurations(); } public static void UpdateItemConfigurations() { if (TravelTotemsPlugin.GetTotemItemRecipesEnabled()) { UpdateItemConfiguration(TravelTotemBomb_PrefabName, TravelTotemsPlugin.GetTotemBombItemCost()); } } public static void UpdatePieceConfigurations() { if (TravelTotemsPlugin.GetTravelTotemPieceRecipesEnabled()) { UpdatePieceConfiguration(TravelTotemPiece_PrefabName, TravelTotemsPlugin.GetTravelTotemPieceCost()); UpdatePieceConfiguration(TravelTotemPieceMistlands_PrefabName, TravelTotemsPlugin.GetTravelTotemPieceMistlandsCost()); UpdatePieceConfiguration(TravelTotemPieceAshlands_PrefabName, TravelTotemsPlugin.GetTravelTotemPieceAshlandsCost()); } } public static void UpdatePieceConfiguration(string name, string cost) { bool flag = !Utility.IsNullOrWhiteSpace(cost); Requirement[] resources = MakeRequirementFromConfig(name, cost).ToArray(); GameObject prefab = PrefabManager.Instance.GetPrefab(name); if ((Object)(object)prefab == (Object)null) { TravelTotemsPlugin.TravelTotemsLogger.LogError((object)("Could not find prefab for piece " + name + ".")); return; } Piece pieceComp = prefab.GetComponent(); if ((Object)(object)pieceComp == (Object)null) { TravelTotemsPlugin.TravelTotemsLogger.LogError((object)("Could not find Piece for piece " + name + ".")); return; } pieceComp.m_resources = resources; PieceTable val = null; GameObject prefab2 = PrefabManager.Instance.GetPrefab("Hammer"); ItemDrop val2 = default(ItemDrop); if ((Object)(object)prefab2 == (Object)null || !prefab2.TryGetComponent(ref val2)) { TravelTotemsPlugin.TravelTotemsLogger.LogWarning((object)"Hammer not found, will not add build piece."); return; } val = val2.m_itemData.m_shared.m_buildPieces; GameObject val3 = val.m_pieces.Find((GameObject x) => ((Object)x).name == Utils.GetPrefabName(((Object)pieceComp).name)); if (!flag && (Object)(object)val3 != (Object)null) { val.m_pieces.Remove(val3); } else if (flag && (Object)(object)val3 == (Object)null) { val.m_pieces.Add(prefab); } TravelTotemsPlugin.TravelTotemsLogger.LogDebug((object)("Updated piece " + name + ".")); } public static void UpdateItemConfiguration(string name, string recipe) { bool enabled = !Utility.IsNullOrWhiteSpace(recipe); Requirement[] resources = MakeRequirementFromConfig(name, recipe).ToArray(); Recipe val = ((IEnumerable)ObjectDB.instance.m_recipes).FirstOrDefault((Func)((Recipe x) => (Object)(object)x.m_item != (Object)null && (Object)(object)x.m_item.m_itemData.m_dropPrefab != (Object)null && ((Object)x.m_item.m_itemData.m_dropPrefab).name == name)); if ((Object)(object)val == (Object)null) { TravelTotemsPlugin.TravelTotemsLogger.LogError((object)("Could not find recipe for item " + name + ".")); return; } val.m_enabled = enabled; val.m_resources = resources; } public static List MakeRequirementFromConfig(string itemName, string configString) { List list = MakeRecipeFromConfig(configString); List list2 = new List(); foreach (RequirementConfig item in list) { Requirement requirement = item.GetRequirement(); GameObject prefab = PrefabManager.Instance.GetPrefab(item.Item); if ((Object)(object)prefab == (Object)null) { TravelTotemsPlugin.TravelTotemsLogger.LogError((object)("Could not add requirement " + item.Item + ", for " + itemName + ". Prefab not found.")); continue; } ItemDrop component = prefab.GetComponent(); if ((Object)(object)component != (Object)null) { requirement.m_resItem = component; list2.Add(requirement); continue; } TravelTotemsPlugin.TravelTotemsLogger.LogError((object)("Could not add requirement " + item.Item + ", for " + itemName + ".")); } return list2; } private static List MakeRecipeFromConfig(string configString) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown string[] array = configString.Replace(" ", "").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); List list = new List(); string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string[] array3 = array2[i].Split(new char[1] { ':' }, StringSplitOptions.RemoveEmptyEntries); if (array3.Length != 2) { PrintRecipeErrorMessage(configString); continue; } string item = array3[0]; if (!int.TryParse(array3[1], out var result)) { PrintRecipeErrorMessage(configString); continue; } list.Add(new RequirementConfig { Item = item, Amount = result, Recover = true }); } return list; } public static void PrintRecipeErrorMessage(string entry) { TravelTotemsPlugin.TravelTotemsLogger.LogError((object)("Incorrectly formatted recipe: " + entry + "! Should be 'ITEM:QUANITY,ITEM2:QUANTITY' etc.")); } public static void AddTotemLocations() { CreateMaterials(); int locationSpacing = TravelTotemsPlugin.GetLocationSpacing(); AddTotemLocation("VV_TravelTotemLocation_Default", (Biome)895, TravelTotemsPlugin.GetLocationAmountDefault(), locationSpacing); AddTotemLocation("VV_TravelTotemLocation_Meadows", (Biome)1, TravelTotemsPlugin.GetLocationAmountMeadows(), locationSpacing); AddTotemLocation("VV_TravelTotemLocation_BlackForest", (Biome)8, TravelTotemsPlugin.GetLocationAmountBlackForest(), locationSpacing); AddTotemLocation("VV_TravelTotemLocation_Swamp", (Biome)2, TravelTotemsPlugin.GetLocationAmountSwamp(), locationSpacing); AddTotemLocation("VV_TravelTotemLocation_Mountain", (Biome)4, TravelTotemsPlugin.GetLocationAmountMountain(), locationSpacing); AddTotemLocation("VV_TravelTotemLocation_Plains", (Biome)16, TravelTotemsPlugin.GetLocationAmountPlains(), locationSpacing); AddTotemLocation("VV_TravelTotemLocation_Mistlands", (Biome)512, TravelTotemsPlugin.GetLocationAmountMistlands(), locationSpacing, 15); AddTotemLocation("VV_TravelTotemLocation_Ashlands", (Biome)32, TravelTotemsPlugin.GetLocationAmountAshlands(), locationSpacing, 15, 5); ZoneManager.OnVanillaLocationsAvailable -= AddTotemLocations; } private static void AddTotemLocation(string locationName, Biome biome, int quantity, int distance, int radius = 7, int minAltitude = 3) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0017: 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_0071: Expected O, but got Unknown GameObject obj = ZoneManager.Instance.CreateLocationContainer(TravelTotemsPlugin.TotemBundle, locationName); LocationConfig val = new LocationConfig(); val.Biome = biome; val.Quantity = quantity; val.ExteriorRadius = radius; val.HasInterior = false; val.InteriorRadius = 5f; val.MinAltitude = minAltitude; val.MaxAltitude = 1000f; val.Priotized = true; val.MinDistanceFromSimilar = distance; val.ClearArea = true; CustomLocation val2 = new CustomLocation(obj, true, val); ZoneManager.Instance.AddCustomLocation(val2); } public static void CreateMaterials() { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Expected O, but got Unknown //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)TotemMaterialDefault != (Object)null) { return; } Material prefab = Cache.GetPrefab("startplatform"); if ((Object)(object)prefab == (Object)null) { TravelTotemsPlugin.TravelTotemsLogger.LogWarning((object)"Material \"startplatform\" could not be found. Could not replace."); return; } Texture val = TravelTotemsPlugin.TotemBundle.LoadAsset("VV_startstone_emission"); if ((Object)(object)val == (Object)null) { TravelTotemsPlugin.TravelTotemsLogger.LogWarning((object)"Could not load emission texture data."); } Vector4 val2 = default(Vector4); ((Vector4)(ref val2))..ctor(0f, 0f, 0f, 1f); Material prefab2 = Cache.GetPrefab("rock_mistlands"); Material prefab3 = Cache.GetPrefab("AshlandsRockTest_mat"); CreateDefaultMaterial(prefab, val, Vector4.op_Implicit(val2)); if ((Object)(object)prefab2 == (Object)null) { TotemMaterialMistlands = new Material(TotemMaterialDefault); ((Object)TotemMaterialMistlands).name = "VV_TotemMaterialMistlands"; TravelTotemsPlugin.TravelTotemsLogger.LogWarning((object)"Material \"rock_mistlands\" could not be found. Could not replace."); } else { CreateMistlandsMaterial(prefab, prefab2, val, Vector4.op_Implicit(val2)); } if ((Object)(object)prefab3 == (Object)null) { TotemMaterialAshlands = new Material(TotemMaterialDefault); ((Object)TotemMaterialAshlands).name = "VV_TotemMaterialAshlands"; TravelTotemsPlugin.TravelTotemsLogger.LogWarning((object)"Material \"AshlandsRockTest_mat\" could not be found. Could not replace."); } else { CreateAshlandsMaterial(prefab, prefab3, val, Vector4.op_Implicit(val2)); } AssetManager.Instance.AddAsset((Object)(object)TotemMaterialDefault); AssetManager.Instance.AddAsset((Object)(object)TotemMaterialMistlands); AssetManager.Instance.AddAsset((Object)(object)TotemMaterialAshlands); } private static void CreateDefaultMaterial(Material originalPlatform, Texture emission, Vector3 emissionColor) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) TotemMaterialDefault = new Material(originalPlatform); ((Object)TotemMaterialDefault).name = "VV_TotemMaterialDefault"; TotemMaterialDefault.SetTexture("_EmissiveTex", emission); TotemMaterialDefault.SetVector("_EmissionColor", Vector4.op_Implicit(emissionColor)); TotemMaterialDefault.SetFloat("_MossBlend", 5f); } private static void CreateMistlandsMaterial(Material originalPlatform, Material originalMaterial, Texture emission, Vector3 emissionColor) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) TotemMaterialMistlands = new Material(originalMaterial); ((Object)TotemMaterialMistlands).name = "VV_TotemMaterialMistlands"; CopyBasics(originalPlatform, TotemMaterialMistlands, emission, Vector4.op_Implicit(emissionColor)); CopyMoss(originalPlatform, TotemMaterialMistlands); TotemMaterialMistlands.SetVector("_Color", new Vector4(27f / 106f, 27f / 106f, 27f / 106f, 1f)); } private static void CreateAshlandsMaterial(Material originalPlatform, Material originalMaterial, Texture emission, Vector3 emissionColor) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) TotemMaterialAshlands = new Material(originalMaterial); ((Object)TotemMaterialAshlands).name = "VV_TotemMaterialAshlands"; CopyBasics(originalPlatform, TotemMaterialAshlands, emission, Vector4.op_Implicit(emissionColor)); TotemMaterialAshlands.SetVector("_Color", new Vector4(0.02f, 0.04f, 0.06f, 1f)); } private static void CopyBasics(Material original, Material newMaterial, Texture emission, Vector4 emissionColor) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) newMaterial.SetTexture("_MainTex", original.GetTexture("_MainTex")); newMaterial.SetTextureScale("_MainTex", original.GetTextureScale("_MainTex")); newMaterial.SetTextureOffset("_MainTex", original.GetTextureOffset("_MainTex")); newMaterial.SetTexture("_BumpMap", original.GetTexture("_BumpMap")); newMaterial.SetTextureScale("_BumpMap", original.GetTextureScale("_BumpMap")); newMaterial.SetTextureOffset("_BumpMap", original.GetTextureOffset("_BumpMap")); newMaterial.SetFloat("_BumpScale", original.GetFloat("_BumpScale")); newMaterial.SetTexture("_EmissiveTex", emission); newMaterial.SetVector("_EmissionColor", emissionColor); } private static void CopyMoss(Material original, Material material) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) material.SetTextureScale("_MossTex", original.GetTextureScale("_MossTex")); material.SetTextureOffset("_MossTex", original.GetTextureOffset("_MossTex")); material.SetFloat("_MossBlend", 5f); material.SetFloat("_MossNormal", original.GetFloat("_MossNormal")); material.SetFloat("_MossTransition", original.GetFloat("_MossTransition")); } } public static class CodeMatcherExtensions { public static CodeMatcher ExtractOperand(this CodeMatcher matcher, out object operand) { operand = matcher.Operand; return matcher; } } public class TerminalCommands { [HarmonyPatch(typeof(Terminal), "InitTerminal")] private static class Patch_Terminal_InitTerminal { [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; internal void b__1_0(ConsoleEventArgs args) { if (args.Length > 1) { TravelTotemPlayer.TryRemoveTotem(args[1]); } else { TravelTotemPlayer.ClearKnownTotems(); } } internal void b__1_1(ConsoleEventArgs args) { if (args.Length > 1) { TravelTotemPlayer.TryAddTotem(args[1]); } else { args.Context.AddString("Syntax: addknowntraveltotem [ID such as 0:4]"); } } } [HarmonyPriority(800)] private static void Prefix(out bool __state) { __state = Terminal.m_terminalInitialized; } private static void Postfix(bool __state) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown if (__state) { return; } TravelTotemsPlugin.TravelTotemsLogger.LogInfo((object)"Adding Terminal Commands for totem management."); try { object obj = <>c.<>9__1_0; if (obj == null) { ConsoleEvent val = delegate(ConsoleEventArgs args) { if (args.Length > 1) { TravelTotemPlayer.TryRemoveTotem(args[1]); } else { TravelTotemPlayer.ClearKnownTotems(); } }; <>c.<>9__1_0 = val; obj = (object)val; } new ConsoleCommand("clearknowntraveltotems", "[optional: ID]", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); object obj2 = <>c.<>9__1_1; if (obj2 == null) { ConsoleEvent val2 = delegate(ConsoleEventArgs args) { if (args.Length > 1) { TravelTotemPlayer.TryAddTotem(args[1]); } else { args.Context.AddString("Syntax: addknowntraveltotem [ID such as 0:4]"); } }; <>c.<>9__1_1 = val2; obj2 = (object)val2; } new ConsoleCommand("addknowntraveltotem", "[ID]", (ConsoleEvent)obj2, true, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } catch (Exception ex) { TravelTotemsPlugin.TravelTotemsLogger.LogWarning((object)"Error, could not add terminal command. This can happen when two mods add the same command. The rest of this mod should work as expected."); TravelTotemsPlugin.TravelTotemsLogger.LogWarning((object)ex); } } } } public class TraderPatches { [HarmonyPatch(typeof(Trader), "Start")] public static class Patch_Trader_Start { private static void Postfix(Trader __instance) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown if (!TravelTotemsPlugin.GetTradersSellTotemBomb()) { return; } GameObject prefab = Cache.GetPrefab(AssetManager.TravelTotemBomb_PrefabName); if (!Object.op_Implicit((Object)(object)prefab)) { TravelTotemsPlugin.TravelTotemsLogger.LogWarning((object)"Could not add Totem Bomb to trader: Prefab not found."); return; } ItemDrop component = prefab.GetComponent(); if (!Object.op_Implicit((Object)(object)component)) { TravelTotemsPlugin.TravelTotemsLogger.LogWarning((object)"Could not add Totem Bomb to trader: ItemDrop undefined."); return; } TradeItem item = new TradeItem { m_prefab = component, m_price = TravelTotemsPlugin.GetTradersSellTotemBombCost() }; __instance.m_items.Add(item); } } } public static class TravelTotemMap { [HarmonyPatch(typeof(Minimap), "UpdateDynamicPins")] public static class Patch_Minimap_UpdateDynamicPins { private static void Postfix() { UpdateMapPins(); } } [HarmonyPatch(typeof(Minimap), "UpdateMap")] private static class Patch_Minimap_UpdateMap { [HarmonyTranspiler] internal static IEnumerable MinimapUpdateMapTranspiler(IEnumerable instructions, ILGenerator generator) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown return new CodeMatcher(instructions, generator).Start().MatchStartForward((CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldstr, (object)"JoyTabLeft", (string)null), new CodeMatch((OpCode?)OpCodes.Call, (object)AccessTools.Method(typeof(ZInput), "GetButtonDown", (Type[])null, (Type[])null), (string)null) }).ThrowIfInvalid("Could not patch Minimap.UpdateMap!") .Advance(3) .InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[1] { new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(TravelTotemMap), "TryTriggerTeleportGamepad", (Type[])null, (Type[])null)) }) .InstructionEnumeration(); } } [HarmonyPatch(typeof(Minimap), "OnMapLeftClick")] private static class Patch_Minimap_OnMapLeftClick { private static bool Prefix() { //IL_000e: 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) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (!TravelMapActive) { return true; } TryTriggerTeleport(GetClosestTravelLocation(Minimap.instance.ScreenToWorldPoint(ZInput.mousePosition), Minimap.instance.m_removeRadius * (Minimap.instance.m_largeZoom * 2f), out var isTotem), isTotem); return false; } } private static bool TravelMapPinsAdded = false; private static List TotemMapPins = new List(); private static List LocationMapPins = new List(); private const string START_LOC = "StartTemple"; private const string HALDOR_LOC = "Vendor_BlackForest"; private const string HILDIR_LOC = "Hildir_camp"; private const string BOGWITCH_LOC = "BogWitch_Camp"; public static bool TravelMapActive { get; private set; } = false; public static bool TotemTeleportActive { get; private set; } = false; public static void SetTravelMapActive(bool active) { TravelMapActive = active; } public static void SetTotemTeleportActive(bool active) { TotemTeleportActive = active; } public static void AddMapPin(ZDO totem) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) if (totem != null && !((Object)(object)Minimap.instance == (Object)null)) { PinData item = Minimap.instance.AddPin(totem.GetPosition(), TravelTotemMapPin.GetTotemPinType(), totem.GetString("VV_TotemName", ""), false, false, 0L, default(PlatformUserID)); TotemMapPins.Add(item); } } public static void RefreshMapPins() { if (Object.op_Implicit((Object)(object)Minimap.instance)) { ClearPins(); UpdateMapPins(); } } private static void UpdateMapPins() { if ((TravelMapActive || TravelTotemsPlugin.GetShowMapPins()) && !TravelMapPinsAdded) { foreach (ZDO validTotem in TravelTotemPlayer.GetValidTotems()) { AddMapPin(validTotem); } TravelMapPinsAdded = true; } else if (!TravelMapActive && TravelMapPinsAdded && !TravelTotemsPlugin.GetShowMapPins()) { ClearPins(); } } private static void ClearPins() { //IL_0000: 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) //IL_001c: 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) PinType totemPinType = TravelTotemMapPin.GetTotemPinType(); foreach (PinData totemMapPin in TotemMapPins) { if (totemMapPin.m_type == totemPinType) { Minimap.instance.RemovePin(totemMapPin); } } TotemMapPins.Clear(); TravelMapPinsAdded = false; } public static void TryTriggerTeleportGamepad() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (TravelMapActive) { TryTriggerTeleport(GetClosestTravelLocation(Minimap.instance.ScreenToWorldPoint(new Vector3((float)(Screen.width / 2), (float)(Screen.height / 2))), Minimap.instance.m_removeRadius * (Minimap.instance.m_largeZoom * 2f), out var isTotem), isTotem); } } private static void TryTriggerTeleport(Vector3 position, bool isTotem) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: 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_001f: Unknown result type (might be due to invalid IL or missing references) if (!(position == Vector3.zero)) { StopTotemMap(); SetTotemTeleportActive(isTotem); ((Character)Player.m_localPlayer).TeleportTo(position, Quaternion.identity, true); } } private static bool AllowedPinType(int pinType) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between I4 and Unknown if (pinType == (int)TravelTotemMapPin.GetTotemPinType()) { return true; } if (pinType == 5) { return TravelTotemsPlugin.GetAllowSelectBed(); } if (TravelTotemsPlugin.GetAllowSelectTraders() && TravelTotemsPlugin.MultiplayerTweaksInstalled) { return IsMultiplayerTweaksTraderPin(pinType); } return false; } [MethodImpl(MethodImplOptions.NoInlining)] private static bool IsMultiplayerTweaksTraderPin(int pinType) { try { int haldorPinIndex = API.GetHaldorPinIndex(); int hildirPinIndex = API.GetHildirPinIndex(); int bogWitchPinIndex = API.GetBogWitchPinIndex(); if (pinType == haldorPinIndex || pinType == hildirPinIndex || pinType == bogWitchPinIndex) { return true; } } catch { TravelTotemsPlugin.TravelTotemsLogger.LogWarning((object)"Multiplayer Tweaks version mismatch! Update or contact the author for more help."); } return false; } private static Vector3 GetClosestTravelLocation(Vector3 pos, float radius, out bool isTotem) { //IL_0000: 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) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected I4, but got Unknown //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.zero; float num = 999999f; foreach (PinData pin in Minimap.instance.m_pins) { if (AllowedPinType((int)pin.m_type) && Object.op_Implicit((Object)(object)pin.m_uiElement) && ((Component)pin.m_uiElement).gameObject.activeInHierarchy) { float num2 = Utils.DistanceXZ(pos, pin.m_pos); if (num2 < radius && (num2 < num || val == Vector3.zero)) { val = pin.m_pos; num = num2; isTotem = pin.m_type == TravelTotemMapPin.GetTotemPinType(); } } } isTotem = false; if (LocationMapPins.Count > 0) { foreach (Vector3 locationMapPin in LocationMapPins) { float num3 = Utils.DistanceXZ(pos, locationMapPin); if (num3 < radius && num3 < num) { val = locationMapPin; num = num3; } } } return val; } public static void HandleTotemOnTriggerEnter(TravelTotemPortal totem = null) { if (TotemTeleportActive) { SetTotemTeleportActive(active: false); StopTotemMap(); } else if (Object.op_Implicit((Object)(object)totem) && !totem.TryTrackTotem(consumeResources: false)) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_blocked", 0, (Sprite)null); } else if (((Humanoid)Player.m_localPlayer).IsTeleportable()) { StartTotemMap(); } else { ((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_noteleport", 0, (Sprite)null); } } public static void HandleTotemOnTriggerExit(TravelTotemPortal totem = null) { StopTotemMap(); } public static void StartTotemMap() { RefreshLocationIcons(); SetTravelMapActive(active: true); SetMapMode((MapMode)2); } public static void StopTotemMap() { SetTravelMapActive(active: false); SetMapMode((MapMode)(!Game.m_noMap)); } private static void SetMapMode(MapMode mode) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) bool noMap = Game.m_noMap; Game.m_noMap = false; Minimap.instance.SetMapMode(mode); Game.m_noMap = noMap; } public static void RefreshLocationIcons() { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) Dictionary dictionary = new Dictionary(); ZoneSystem.instance.GetLocationIcons(dictionary); LocationMapPins.Clear(); foreach (KeyValuePair item in dictionary) { switch (item.Value) { case "StartTemple": if (TravelTotemsPlugin.GetAllowSelectDefaultSpawn()) { LocationMapPins.Add(item.Key); } break; case "Vendor_BlackForest": case "Hildir_camp": case "BogWitch_Camp": if (TravelTotemsPlugin.GetAllowSelectTraders()) { LocationMapPins.Add(item.Key); } break; } } } } public class TravelTotemMapPin { [HarmonyPatch(typeof(Minimap))] private static class Patch_Minimap_GetMapData { [HarmonyPriority(700)] [HarmonyPatch("GetSharedMapData")] [HarmonyPatch("GetMapData")] private static void Prefix(ref Minimap __instance) { TransformPinIdsToSave(ref __instance.m_pins); } [HarmonyPriority(100)] [HarmonyPatch("GetSharedMapData")] [HarmonyPatch("GetMapData")] private static void Postfix(ref Minimap __instance) { TransformPinIdsToPlay(ref __instance.m_pins); } } [HarmonyPatch(typeof(Minimap), "Start")] private static class Patch_Minimap_Start { [HarmonyPriority(100)] private static void Postfix(Minimap __instance) { bool[] array = new bool[__instance.m_visibleIconTypes.Length + 1]; for (int i = 0; i < __instance.m_visibleIconTypes.Length; i++) { array[i] = __instance.m_visibleIconTypes[i]; } TotemIndex = __instance.m_visibleIconTypes.Length; array[TotemIndex] = true; __instance.m_visibleIconTypes = array; } } [HarmonyPatch(typeof(Minimap), "AddPin")] private static class Patch_Minimap_AddPin { [HarmonyPriority(800)] private static void Prefix(ref PinType type) { if ((int)type == 126) { type = (PinType)TotemIndex; } if ((int)type >= Minimap.instance.m_visibleIconTypes.Length) { TravelTotemsPlugin.TravelTotemsLogger.LogWarning((object)"Minimap conversion type out of range of visible icons."); } else if ((int)type < 0) { TravelTotemsPlugin.TravelTotemsLogger.LogWarning((object)"Minimap conversion type less than icon 0."); } } } [HarmonyPatch(typeof(Minimap), "GetSprite")] private static class Patch_Minimap_GetSprite { [HarmonyPriority(800)] private static bool Prefix(ref PinType type, ref Sprite __result) { if ((int)type == TotemIndex) { __result = AssetManager.TotemMapSprite; return false; } __result = null; return true; } } private const int TOTEM_INT = 126; internal static int TotemIndex = -1; public static PinType GetTotemPinType() { return (PinType)TotemIndex; } private static void TransformPinIdsToSave(ref List pins) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 //IL_0022: Unknown result type (might be due to invalid IL or missing references) foreach (PinData pin in pins) { if ((int)pin.m_type == TotemIndex) { pin.m_type = (PinType)126; } } } private static void TransformPinIdsToPlay(ref List pins) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Invalid comparison between Unknown and I4 //IL_0022: Unknown result type (might be due to invalid IL or missing references) foreach (PinData pin in pins) { if ((int)pin.m_type == 126) { pin.m_type = (PinType)TotemIndex; } } } } public static class TravelTotemPlayer { private readonly struct FileData { public List TravelTotemIDs { get; } public FileData(List totems) { TravelTotemIDs = totems; } public FileData(string saveString) { TravelTotemIDs = new List(); if (saveString == null) { return; } string[] array = saveString.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); if (array == null) { return; } for (int i = 0; i < array.Length; i++) { if (int.TryParse(array[i], out var result)) { TravelTotemIDs.Add(result); continue; } TravelTotemsPlugin.TravelTotemsLogger.LogWarning((object)$"Unable to parse travel totem save data for bin: {i}"); TravelTotemIDs.Add(0); } } public override string ToString() { string text = ""; foreach (int travelTotemID in TravelTotemIDs) { text = text + travelTotemID + ";"; } return text; } } [HarmonyPatch(typeof(Player), "Save")] public static class Patch_Player_Save { private static void Prefix(Player __instance) { if (TravelTotemsPlugin.IsInTheMainScene()) { TravelTotemsPlugin.TravelTotemsLogger.LogDebug((object)("Attempting to save data with key: " + CurrentSaveString)); FileData data = new FileData(KnownTravelTotemIDs); SaveData(ref __instance, data); } } } [HarmonyPatch(typeof(Player), "Load")] public static class Patch_Player_Load { private static void Postfix(Player __instance) { if (!TravelTotemsPlugin.IsInTheMainScene()) { CurrentSaveString = string.Empty; return; } KnownTravelTotemIDs.Clear(); long uid = WorldGenerator.instance.m_world.m_uid; if (uid == 0L) { TravelTotemsPlugin.TravelTotemsLogger.LogError((object)"World key not set! Will not be able to retrieve saved data."); return; } CurrentSaveString = "VV_TD_" + uid; TravelTotemsPlugin.TravelTotemsLogger.LogDebug((object)("Attempting to load data with key: " + CurrentSaveString)); FileData? fileData = LoadData(ref __instance); if (!fileData.HasValue) { return; } FileData value = fileData.Value; if (value.TravelTotemIDs != null) { for (int i = 0; i < value.TravelTotemIDs.Count; i++) { KnownTravelTotemIDs.Add(value.TravelTotemIDs[i]); } } TravelTotemMap.RefreshMapPins(); } } private const string PLAYER_SAVE_KEY_PREFIX = "VV_TD_"; private static List KnownTravelTotemIDs = new List(); private static string CurrentSaveString = string.Empty; private static bool IsValid(int bin) { if (bin < 0 || bin >= KnownTravelTotemIDs.Count) { return false; } return true; } public static bool ContainsID(int bin, int id) { if (!IsValid(bin)) { return false; } return ContainsIDInternal(bin, id); } private static bool ContainsIDInternal(int bin, int id) { return (KnownTravelTotemIDs[bin] & id) != 0; } public static bool AddKnownTotem(int bin, int id) { if (bin < 0) { return false; } if (bin >= KnownTravelTotemIDs.Count) { for (int i = KnownTravelTotemIDs.Count; i <= bin; i++) { KnownTravelTotemIDs.Add(0); } } KnownTravelTotemIDs[bin] |= id; TravelTotemMap.RefreshMapPins(); return true; } public static void TryRemoveTotem(string idString) { if (TryGetTotemID(idString, out var bin, out var id)) { RemoveTotem(bin, id); } } public static void TryAddTotem(string idString) { idString.Split(new string[1] { ":" }, StringSplitOptions.RemoveEmptyEntries); if (TryGetTotemID(idString, out var bin, out var id)) { AddKnownTotem(bin, id); } } private static bool TryGetTotemID(string idString, out int bin, out int id) { string[] array = idString.Split(new string[1] { ":" }, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 2 && int.TryParse(array[0].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out bin) && int.TryParse(array[1].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out id)) { return true; } bin = -1; id = 0; return false; } public static bool RemoveTotem(int bin, int id) { if (!IsValid(bin)) { return false; } if (ContainsIDInternal(bin, id)) { KnownTravelTotemIDs[bin] -= id; } TravelTotemMap.RefreshMapPins(); return true; } public static void ClearKnownTotems() { KnownTravelTotemIDs.Clear(); ClearData(ref Player.m_localPlayer); TravelTotemMap.RefreshMapPins(); } public static bool TotemUnlocked(bool isCreator, TravelTotemType type, int bin, int id) { if (isCreator) { return true; } if (type == TravelTotemType.AlwaysUnlock) { return true; } return ContainsID(bin, id); } public static List GetValidTotems() { long playerID = Game.instance.GetPlayerProfile().GetPlayerID(); List list = new List(); foreach (ZDO travelTotem in TravelTotems.GetTravelTotems()) { if (travelTotem == null) { continue; } bool isCreator = travelTotem.GetLong(ZDOVars.s_creator, 0L) == playerID; if (!TravelTotemsPlugin.GetOverrideTotemAccess(isCreator)) { TravelTotemType totemType = TravelTotemPortal.GetTotemType(travelTotem); if (!TotemUnlocked(isCreator, totemType, travelTotem.GetInt("VV_TotemIDBin", 0), travelTotem.GetInt("VV_TotemID", 0))) { continue; } } list.Add(travelTotem); } return list; } private static void SaveData(ref Player player, FileData data) { if (!((Object)(object)player == (Object)null) && !Utility.IsNullOrWhiteSpace(CurrentSaveString) && data.TravelTotemIDs.Count >= 1) { if (player.m_customData.ContainsKey(CurrentSaveString)) { player.m_customData[CurrentSaveString] = data.ToString(); } else { player.m_customData.Add(CurrentSaveString, data.ToString()); } } } private static void ClearData(ref Player player) { if ((Object)(object)player != (Object)null && player.m_customData.ContainsKey(CurrentSaveString)) { player.m_customData[CurrentSaveString] = ""; } } private static FileData? LoadData(ref Player player) { if ((Object)(object)player != (Object)null && player.m_customData.ContainsKey(CurrentSaveString)) { return new FileData(player.m_customData[CurrentSaveString]); } return null; } } public class TravelTotemPortal : MonoBehaviour, Hoverable, Interactable, TextReceiver { public ZNetView ZNetView; public const string TOTEM_ID_BIN = "VV_TotemIDBin"; public const string TOTEM_ID = "VV_TotemID"; public const string TOTEM_NAME = "VV_TotemName"; public const string TOTEM_TYPE = "VV_TotemType"; public const string RPCNAME_SetupAccess = "VV_SetupAccess"; public EffectFade EnabledEffects; public EffectFade DisabledEffects; public EffectFade PortalEffects; public float ActivationRange = 5f; public Light UnlockedLight; public MeshRenderer EmissionRenderer; public Color EmissionColor; private float EmissionAlpha; private float LastUseTime = -1f; private bool IsPlacementGhost; private bool IsCreator; private bool IsPublic; private bool IsPiece; private void Awake() { ZNetView = ((Component)this).GetComponent(); ZNetView.Register("VV_SetupAccess", (Action)RPC_SetupAccess); IsPiece = (Object)(object)((Component)this).GetComponent() != (Object)null; } private void Start() { if (Player.IsPlacementGhost(((Component)this).gameObject)) { IsPlacementGhost = true; EnabledEffects.SetActive(false); DisabledEffects.SetActive(false); PortalEffects.SetActive(false); ((Component)UnlockedLight).gameObject.SetActive(false); return; } int num = ZNetView.GetZDO().GetInt("VV_TotemIDBin", -1); int num2 = ZNetView.GetZDO().GetInt("VV_TotemID", -1); if (num == -1 || num2 == -1) { TravelTotems.AssignTotemID(ZNetView.GetZDO()); } int num3 = 0; if (ZNetView.GetZDO().GetInt("VV_TotemType", num3) == num3) { SetTotemType(TravelTotemType.ServerDefault); } SnapToGround component = ((Component)this).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { component.Snap(); } UpdateEffects(); long creator = ZNetView.GetZDO().GetLong(ZDOVars.s_creator, 0L); SetupAccess(creator); TravelTotems.AddTotem(ZNetView.GetZDO()); TravelTotemMap.RefreshMapPins(); } private void Update() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (ZNetView.IsValid() && !IsPlacementGhost) { Player closestPlayer = Player.GetClosestPlayer(((Component)this).transform.position, ActivationRange); bool travelPossible = Object.op_Implicit((Object)(object)closestPlayer) && ((Humanoid)closestPlayer).IsTeleportable(); UpdateEffects(travelPossible); } } private void SetupAccess(long creator) { IsPublic = creator == 0; if (ZNet.instance.IsDedicated()) { IsCreator = false; } else { IsCreator = creator == Game.instance.GetPlayerProfile().GetPlayerID(); } } private void RPC_SetupAccess(long sender, long creator) { if (ZNetView.IsOwner()) { ZNetView.GetZDO().Set(ZDOVars.s_creator, creator); } SetupAccess(creator); } private void UpdateEffects(bool travelPossible = false) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) bool flag = Unlocked(); bool active = flag && !travelPossible; bool active2 = !flag; bool active3 = flag && travelPossible; EnabledEffects.SetActive(active); DisabledEffects.SetActive(active2); PortalEffects.SetActive(active3); EmissionAlpha = Mathf.MoveTowards(EmissionAlpha, flag ? 1f : 0f, Time.deltaTime); ((Renderer)EmissionRenderer).material.SetColor("_EmissionColor", Color.Lerp(Color.black, EmissionColor, EmissionAlpha)); ((Component)UnlockedLight).gameObject.SetActive(flag); } public string GetHoverText() { if (!ZNetView.IsValid()) { return ""; } bool num = Unlocked(); string text = (num ? "$piece_portal_connected" : "$piece_portal_unconnected"); string text2 = GetText() + "[" + text + "]"; if (TravelTotemsPlugin.GetOverrideTotemAccess(isCreator: false) || TravelTotemsPlugin.GetShowTotemID()) { text2 += $"[ID {GetTotemIDBin()}:{GetTotemID()}]"; } if (!num && GetTotemType() == TravelTotemType.FindUnlock) { text2 += "\n[$KEY_Use] Activate"; if (RequiresPayment()) { text2 = text2 + " [" + TravelTotemsPlugin.GetTotemUnlockRequirementsString() + "]"; } } if (TravelTotemsPlugin.GetTotemNamingAccess(IsCreator, IsPublic)) { string text3 = ((ZInput.IsNonClassicFunctionality() && ZInput.IsGamepadActive()) ? "$KEY_AltKeys" : "$KEY_AltPlace"); text2 = text2 + "\n[" + text3 + " + $KEY_Use] $piece_portal_settag"; } if (TravelTotemsPlugin.GetOverrideTotemAccess(IsCreator)) { text2 += $"\n[Hold $KEY_Use] Cycle Access: [{GetTotemType(resolveDefault: false)}]"; } return Localization.instance.Localize(text2); } public string GetHoverName() { return "TravelTotem"; } public bool Interact(Humanoid human, bool hold, bool alt) { if (!ZNetView.IsValid()) { return false; } if (hold) { if (TravelTotemsPlugin.GetOverrideTotemAccess(IsCreator) && Time.time - LastUseTime > 0.5f) { CycleTotemAccess(); LastUseTime = Time.time; return true; } return false; } LastUseTime = Time.time; if (alt) { if (TravelTotemsPlugin.GetTotemNamingAccess(IsCreator, IsPublic)) { TextInput.instance.RequestText((TextReceiver)(object)this, "$piece_sign_input", 50); } return true; } if (!TryTrackTotem(consumeResources: true)) { return false; } return true; } private void CycleTotemAccess() { switch (GetTotemType(resolveDefault: false)) { case TravelTotemType.AlwaysUnlock: SetTotemType(TravelTotemType.FindUnlock); break; case TravelTotemType.FindUnlock: SetTotemType(TravelTotemType.AlwaysLock); break; case TravelTotemType.AlwaysLock: SetTotemType(TravelTotemType.ServerDefault); break; case TravelTotemType.ServerDefault: SetTotemType(TravelTotemType.AlwaysUnlock); break; default: SetTotemType(TravelTotemType.ServerDefault); break; } } public bool UseItem(Humanoid user, ItemData item) { return false; } public string GetText() { string text = ZNetView.GetZDO().GetString("VV_TotemName", ""); if (!Utility.IsNullOrWhiteSpace(text)) { text += " "; } return text; } public void SetText(string name) { ZNetView.ClaimOwnership(); ZNetView.GetZDO().Set("VV_TotemName", name); } public void SetTotemType(TravelTotemType type) { ZNetView.ClaimOwnership(); ZNetView.GetZDO().Set("VV_TotemType", (int)type); } public bool Unlocked() { return TravelTotemPlayer.TotemUnlocked(IsCreator, GetTotemType(), GetTotemIDBin(), GetTotemID()); } public bool RequiresPayment() { if (!IsPiece && IsPublic) { return TravelTotems.HasUnlockRequirements(); } return false; } public int GetTotemIDBin() { return ZNetView.GetZDO().GetInt("VV_TotemIDBin", -1); } public int GetTotemID() { return ZNetView.GetZDO().GetInt("VV_TotemID", -1); } public static TravelTotemType GetTotemType(ZDO zdo) { return ResolveTotemType((TravelTotemType)zdo.GetInt("VV_TotemType", 0)); } public TravelTotemType GetTotemType(bool resolveDefault = true) { TravelTotemType travelTotemType = (TravelTotemType)ZNetView.GetZDO().GetInt("VV_TotemType", 0); if (resolveDefault) { travelTotemType = ResolveTotemType(travelTotemType); } return travelTotemType; } private static TravelTotemType ResolveTotemType(TravelTotemType type) { if (type == TravelTotemType.ServerDefault) { type = TravelTotemsPlugin.GetTravelTotemType(); } if (type == TravelTotemType.Undefined) { return TravelTotemType.FindUnlock; } return type; } public bool TryTrackTotem(bool consumeResources) { if (Unlocked()) { TryClaimTotem(); } else { TravelTotemType totemType = GetTotemType(); bool overrideTotemAccess = TravelTotemsPlugin.GetOverrideTotemAccess(isCreator: false); switch (totemType) { case TravelTotemType.AlwaysLock: if (!overrideTotemAccess) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$piece_noaccess", 0, (Sprite)null); } return overrideTotemAccess; case TravelTotemType.FindUnlock: if (RequiresPayment()) { if (!consumeResources) { return overrideTotemAccess; } if (!TravelTotems.TryConsumeUnlockRequirements()) { ((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_incompleteoffering", 0, (Sprite)null); return false; } } TryClaimTotem(); break; } } TravelTotemPlayer.AddKnownTotem(GetTotemIDBin(), GetTotemID()); return true; } public void TryClaimTotem() { if (!IsPiece && IsPublic && TravelTotemsPlugin.GetAllowTotemClaiming()) { long playerID = Game.instance.GetPlayerProfile().GetPlayerID(); RPC_SetupAccess(playerID, playerID); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.Everybody, "VV_SetupAccess", new object[1] { playerID }); } } } public class TravelTotemPortalArea : MonoBehaviour { private void Awake() { } private void OnTriggerEnter(Collider colliderIn) { Player component = ((Component)colliderIn).GetComponent(); if (Object.op_Implicit((Object)(object)component) && (Object)(object)Player.m_localPlayer == (Object)(object)component) { TravelTotemMap.HandleTotemOnTriggerEnter(); } } private void OnTriggerExit(Collider colliderIn) { Player component = ((Component)colliderIn).GetComponent(); if (Object.op_Implicit((Object)(object)component) && (Object)(object)Player.m_localPlayer == (Object)(object)component) { TravelTotemMap.HandleTotemOnTriggerExit(); } } } public class TravelTotemPortalTrigger : MonoBehaviour { private TravelTotemPortal Trigger; private void Awake() { Trigger = ((Component)this).GetComponentInParent(); } private void OnTriggerEnter(Collider colliderIn) { Player component = ((Component)colliderIn).GetComponent(); if (Object.op_Implicit((Object)(object)component) && (Object)(object)Player.m_localPlayer == (Object)(object)component) { TravelTotemMap.HandleTotemOnTriggerEnter(Trigger); } } private void OnTriggerExit(Collider colliderIn) { Player component = ((Component)colliderIn).GetComponent(); if (Object.op_Implicit((Object)(object)component) && (Object)(object)Player.m_localPlayer == (Object)(object)component) { TravelTotemMap.HandleTotemOnTriggerExit(); } } } public static class TravelTotems { [HarmonyPatch(typeof(ZNet), "Start")] private static class Patch_ZNet_Start { private static void Postfix() { StartTravelTotems(); } } [HarmonyPatch(typeof(ZDOMan), "RPC_ZDOData")] private static class Patch_ZDOMan_RPC_ZDOData { [HarmonyTranspiler] internal static IEnumerable ZDOManRPC_ZDODataTranspiler(IEnumerable instructions, ILGenerator generator) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown object operand; return new CodeMatcher(instructions, generator).Start().MatchStartForward((CodeMatch[])(object)new CodeMatch[2] { new CodeMatch((OpCode?)OpCodes.Ldloc_3, (object)null, (string)null), new CodeMatch((OpCode?)OpCodes.Callvirt, (object)AccessTools.Method(typeof(ZDO), "Deserialize", (Type[])null, (Type[])null), (string)null) }).MatchStartBackwards((CodeMatch[])(object)new CodeMatch[1] { new CodeMatch((OpCode?)OpCodes.Ldloc_S, (object)null, (string)null) }) .ExtractOperand(out operand) .ThrowIfInvalid("Could not patch ZDOMan.RPC_ZDOData!") .Advance(3) .InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2] { new CodeInstruction(OpCodes.Ldloc_S, operand), new CodeInstruction(OpCodes.Call, (object)AccessTools.Method(typeof(Patch_ZDOMan_RPC_ZDOData), "TryAddTotem", (Type[])null, (Type[])null)) }) .InstructionEnumeration(); } private static void TryAddTotem(ZDO zdoObject) { if (AssetManager.IsTravelTotem(zdoObject.m_prefab)) { AddTotem(zdoObject); } } } [HarmonyPatch(typeof(ZDOMan), "ShutDown")] private static class Patch_ZDOMan_ShutDown { private static void Postfix() { Reset(); } } [HarmonyPatch(typeof(ZDOPeer), "ShouldSend")] private static class Patch_ZDOMan_ZDOPeer_ShouldSend { private static bool Prefix(ZDO zdo, ref bool __result) { if (AssetManager.IsTravelTotem(zdo.m_prefab)) { __result = true; return false; } return true; } } [HarmonyPatch(typeof(ZDOPeer), "ZDOSectorInvalidated")] private static class Patch_ZDOMan_ZDOPeer_ZDOSectorInvalidated { private static bool Prefix(ZDO zdo) { if (AssetManager.IsTravelTotem(zdo.m_prefab)) { return false; } return true; } } [HarmonyPatch(typeof(ZDOMan), "HandleDestroyedZDO")] private static class Patch_ZDOMan_HandleDestroyedZDO { private static void Prefix(ZDOID uid) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) ZDO zDO = ZDOMan.instance.GetZDO(uid); if (zDO != null && AssetManager.IsTravelTotem(zDO.GetPrefab())) { RemoveTotem(zDO); } } } [HarmonyPatch(typeof(ZDOMan), "AddPeer")] private static class Patch_ZDOMan_AddPeer2 { private static void Postfix(ZNetPeer netPeer) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown if (ZNet.instance.IsServer()) { netPeer.m_rpc.Register("VV_RequestTotems", new Method(RPC_RequestTotems)); } if (!ZNet.instance.IsDedicated()) { netPeer.m_rpc.Register("VV_SendTotems", (Action)RPC_SendTotems); netPeer.m_rpc.Invoke("VV_RequestTotems", Array.Empty()); } } } [HarmonyPatch(typeof(Piece), "CanBeRemoved")] private static class Patch_Piece_CanBeRemoved { private static void Postfix(Piece __instance, ref bool __result) { if (__result) { ZDO zDO = __instance.m_nview.GetZDO(); if (zDO != null && AssetManager.IsTravelTotem(zDO.GetPrefab()) && !TravelTotemsPlugin.GetOverrideTotemAccess(__instance.IsCreator())) { __result = false; } } } } [HarmonyPatch(typeof(Game), "Start")] private static class Patch_Game_Start { private static void Postfix() { try { ZRoutedRpc.instance.Register("VV_ConsumeTotemID", (Action)RPC_ConsumeTotemID); ZRoutedRpc.instance.Register("VV_ConsumeTotemIDResponse", (Action)RPC_ConsumeTotemIDResponse); } catch { TravelTotemsPlugin.TravelTotemsLogger.LogDebug((object)"Totem RPCs have already been registered. Skipping."); } } } public const string TOTEM_MAX_ID_BIN = "VV_MaxTotemIDBin"; public const string TOTEM_MAX_ID = "VV_MaxTotemID"; public const string RPCNAME_RequestTotems = "VV_RequestTotems"; public const string RPCNAME_SendTotems = "VV_SendTotems"; public const string RPCNAME_ConsumeTotemID = "VV_ConsumeTotemID"; public const string RPCNAME_ConsumeTotemIDResponse = "VV_ConsumeTotemIDResponse"; private static List TravelTotemZDOs = new List(); private static Queue UnassignedTravelTotemZDOs = new Queue(); public static ZDO TravelTotemTrackerZDO; private static List TotemUnlockCost = new List(); private static void Reset() { TravelTotemZDOs.Clear(); TravelTotemTrackerZDO = null; UnassignedTravelTotemZDOs.Clear(); } public static void SetRecipeFromConfig(string configString) { TotemUnlockCost.Clear(); string[] array = configString.Replace(" ", "").Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split(new char[1] { ':' }, StringSplitOptions.RemoveEmptyEntries); if (array2.Length != 2) { AssetManager.PrintRecipeErrorMessage(configString); continue; } string prefabName = array2[0]; if (!int.TryParse(array2[1], out var result)) { AssetManager.PrintRecipeErrorMessage(configString); continue; } TotemUnlockCost.Add(new UnlockRequirement { PrefabName = prefabName, Amount = result }); } } public static void UpdateSettings() { SetRecipeFromConfig(TravelTotemsPlugin.GetTotemUnlockRequirementsString()); if (TravelTotemsPlugin.GetTravelTotemType() == TravelTotemType.Undefined) { TravelTotemsPlugin.TravelTotemsLogger.LogWarning((object)"Default totem type is undefined. Please check your configuration for spelling errors!New totems may behave strangely until fixed."); } } public static bool HasUnlockRequirements() { return TotemUnlockCost.Count > 0; } public static bool TryConsumeUnlockRequirements() { if (TotemUnlockCost.Count > 0) { foreach (UnlockRequirement item in TotemUnlockCost) { if (((Humanoid)Player.m_localPlayer).m_inventory.CountItems(item.GetItemDropName(), -1, true) < item.Amount) { return false; } } foreach (UnlockRequirement item2 in TotemUnlockCost) { ((Humanoid)Player.m_localPlayer).m_inventory.RemoveItem(item2.GetItemDropName(), item2.Amount, -1, true); } ((Character)Player.m_localPlayer).Message((MessageType)2, "$msg_offerdone", 0, (Sprite)null); } return true; } public static void AddTotem(ZDO totem) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (totem != null && !TravelTotemZDOs.Contains(totem)) { TravelTotemZDOs.Add(totem); if (ZNet.instance.IsServer()) { ZDOMan.instance.ForceSendZDO(totem.m_uid); } } } public static void RemoveTotem(ZDO totem) { if (totem != null) { TravelTotemZDOs.Remove(totem); } TravelTotemMap.RefreshMapPins(); } public static List GetTravelTotems() { return TravelTotemZDOs; } private static void StartTravelTotems() { TravelTotemsPlugin.TravelTotemsLogger.LogDebug((object)"Loading travel totems..."); if (ZNet.instance.IsServer()) { StartTravelTotemsServer(); if (!ZNet.instance.IsDedicated()) { UpdateSettings(); } } else { StartTravelTotemsClient(); } } private static void StartTravelTotemsClient() { Reset(); } public static void RPC_ConsumeTotemIDResponse(long sender, int bin, int id) { ZDO val = UnassignedTravelTotemZDOs.Dequeue(); if (val != null) { if (!val.IsOwner()) { val.SetOwner(ZDOMan.GetSessionID()); } val.Set("VV_TotemIDBin", bin); val.Set("VV_TotemID", id); val.Set("VV_TotemType", 4); } } public static void ProcessUnassignedTotems() { int count = UnassignedTravelTotemZDOs.Count; for (int i = 0; i < count; i++) { ZRoutedRpc.instance.InvokeRoutedRPC("VV_ConsumeTotemID", Array.Empty()); } } public static void AssignTotemID(ZDO zdo) { if (zdo != null) { UnassignedTravelTotemZDOs.Enqueue(zdo); ZRoutedRpc.instance.InvokeRoutedRPC("VV_ConsumeTotemID", Array.Empty()); } } public static void RPC_RequestTotems(ZRpc rpc) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) ZNetPeer peer = ZNet.instance.GetPeer(rpc); if (peer == null) { TravelTotemsPlugin.TravelTotemsLogger.LogWarning((object)"Recieved a request for totem data but peer was not found!"); return; } ZPackage val = new ZPackage(); val.Write(TravelTotemZDOs.Count); foreach (ZDO travelTotemZDO in TravelTotemZDOs) { val.Write(travelTotemZDO.m_uid); ZDOMan.instance.ForceSendZDO(peer.m_uid, travelTotemZDO.m_uid); } rpc.Invoke("VV_SendTotems", new object[1] { val }); } public static void RPC_SendTotems(ZRpc rpc, ZPackage package) { //IL_000e: 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) //IL_0019: 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) int num = package.ReadInt(); int num2 = 0; for (int i = 0; i < num; i++) { ZDOID val = package.ReadZDOID(); ZDO zDO = ZDOMan.instance.GetZDO(val); if (zDO == null) { ZDOMan.instance.RequestZDO(val); continue; } num2++; TravelTotemZDOs.Add(zDO); } } private static void StartTravelTotemsServer() { //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) bool flag = false; Reset(); foreach (KeyValuePair item in ZDOMan.instance.m_objectsByID) { int prefab = item.Value.GetPrefab(); if (AssetManager.IsTravelTotemTracker(prefab)) { flag = true; TravelTotemTrackerZDO = item.Value; } else if (AssetManager.IsTravelTotem(prefab)) { TravelTotemZDOs.Add(item.Value); int num = item.Value.GetInt("VV_TotemIDBin", -1); int num2 = item.Value.GetInt("VV_TotemID", -1); if (num == -1 || num2 == -1) { UnassignedTravelTotemZDOs.Enqueue(item.Value); } } } if (!flag) { Object.Instantiate(Cache.GetPrefab(AssetManager.TravelTotemTrackerPrefabName), Vector3.zero, Quaternion.identity); } else { InitializeTracker(); } TravelTotemsPlugin.TravelTotemsLogger.LogDebug((object)($"Tracking {TravelTotemZDOs.Count} travel totems. " + $"{UnassignedTravelTotemZDOs.Count} need assignment.")); ProcessUnassignedTotems(); } public static void InitializeTracker() { if (TravelTotemTrackerZDO == null) { TravelTotemsPlugin.TravelTotemsLogger.LogError((object)"Tracker is null! Will not be able to assign new totem ids."); return; } int num = TravelTotemTrackerZDO.GetInt("VV_MaxTotemIDBin", -1); int num2 = TravelTotemTrackerZDO.GetInt("VV_MaxTotemID", -1); if (num == -1 || num2 == -1) { FindMaxTotemID(out var maxBin, out var maxID); UpdateMaxTotemIndexes(maxBin, maxID); } } public static bool FindMaxTotemID(out int maxBin, out int maxID) { bool result = false; maxBin = 0; maxID = 0; foreach (KeyValuePair item in ZDOMan.instance.m_objectsByID) { if (AssetManager.IsTravelTotem(item.Value.GetPrefab())) { int num = item.Value.GetInt("VV_TotemIDBin", -1); int num2 = item.Value.GetInt("VV_TotemID", -1); if (num > maxBin) { result = true; maxBin = num; maxID = num2; } else if (num == maxBin && num2 > maxID) { result = true; maxID = num2; } } } return result; } private static void IncrementIDMax() { int num = GetMaxTotemIDBin(); int maxTotemID = GetMaxTotemID(); if (maxTotemID != 1073741824) { maxTotemID = ((maxTotemID <= 0) ? 1 : (maxTotemID << 1)); } else { num++; maxTotemID = 1; } UpdateMaxTotemIndexes(num, maxTotemID); } public static void RPC_ConsumeTotemID(long sender) { if (ZNet.instance.IsServer() && TravelTotemTrackerZDO != null) { IncrementIDMax(); ZRoutedRpc.instance.InvokeRoutedRPC(sender, "VV_ConsumeTotemIDResponse", new object[2] { GetMaxTotemIDBin(), GetMaxTotemID() }); } } private static void UpdateMaxTotemIndexes(int bin, int id) { if (TravelTotemTrackerZDO != null && TravelTotemTrackerZDO.IsValid()) { TravelTotemTrackerZDO.SetOwner(ZDOMan.GetSessionID()); TravelTotemTrackerZDO.Set("VV_MaxTotemIDBin", bin); TravelTotemTrackerZDO.Set("VV_MaxTotemID", id); } } public static int GetMaxTotemIDBin() { return TravelTotemTrackerZDO.GetInt("VV_MaxTotemIDBin", 0); } public static int GetMaxTotemID() { return TravelTotemTrackerZDO.GetInt("VV_MaxTotemID", 0); } } public class TravelTotemTracker : MonoBehaviour { public static TravelTotemTracker Instance; public ZNetView ZNetView; private void Awake() { ZNetView = ((Component)this).GetComponent(); if ((Object)(object)Instance == (Object)null) { Instance = this; } else { TravelTotemsPlugin.TravelTotemsLogger.LogWarning((object)"Multiple Totem trackers found! IDs may not be tracked accurately!"); } } private void Start() { if (TravelTotems.TravelTotemTrackerZDO == null) { TravelTotems.TravelTotemTrackerZDO = Instance.ZNetView.GetZDO(); TravelTotems.InitializeTracker(); } } private void OnDestroy() { Instance = null; } } [Flags] public enum TravelTotemType { Undefined = 0, AlwaysUnlock = 1, FindUnlock = 2, AlwaysLock = 3, ServerDefault = 4 } public struct UnlockRequirement { public string PrefabName; public int Amount; private string ItemDropName; public UnlockRequirement(string prefab, int amount) { PrefabName = prefab; Amount = amount; ItemDropName = null; } public string GetItemDropName() { if (ItemDropName == null) { GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(PrefabName); if ((Object)(object)itemPrefab == (Object)null) { return string.Empty; } ItemDrop component = itemPrefab.GetComponent(); if ((Object)(object)component == (Object)null) { return string.Empty; } ItemDropName = component.m_itemData.m_shared.m_name; } return ItemDropName; } } [PublicAPI] public class API { public static int GetTotemPinIndex() { return TravelTotemMapPin.TotemIndex; } } }