Decompiled source of WayhomeCoins v1.0.1

BepInEx/plugins/WayhomeCoins/WayhomeCoins.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.NET.Common;
using Candide;
using Candide.CandideUI;
using Candide.CandideUI.Components;
using Candide.CandideUI.Components.Buttons;
using Candide.CandideUI.Containers;
using Candide.CandideUI.UiInput;
using Candide.CandideUI.Windows;
using Candide.CandideUI.WorldOverview;
using Candide.GameModels;
using Candide.GameModels.Managers;
using Candide.GameModels.Models;
using Candide.GameModels.Models.Constructions;
using Candide.Input.InputProviders.Native;
using Candide.Multiplayer.Chat;
using Candide.Multiplayer.Network;
using Candide.Sound;
using Candide.Terminal;
using CandideCreator.Shared.Graphics;
using CandideCreator.Shared.Helpers;
using CandideServer;
using CandideServer.Entities;
using CandideServer.EventBus;
using CandideServer.MessageModels;
using CandideServer.Models;
using CandideServer.Models.Player;
using CandideServer.Models.Spells;
using CandideServer.Models.Town;
using CandideServer.Server;
using CandideServer.ServerManagers;
using CandideServer.ServerServices;
using CandideServer.SimulationModels;
using CandideServer.SyncStrategies;
using CandideServer.Toolkit;
using FontStashSharp.RichText;
using HarmonyLib;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;
using ModSettingsMenu.Api;
using RomesteadContentFramework.Api;
using RomesteadLocalizationAPI.Api;
using Shared;
using Shared.Combat.Projectiles;
using Shared.Combat.Spells;
using Shared.Combat.Spells.Casting;
using Shared.Combat.Spells.Parameters;
using Shared.Data;
using Shared.Entity;
using Shared.Entity.Components;
using Shared.Helpers;
using Shared.Models.Construction;
using Shared.Models.Items;
using Shared.Models.Shops;
using Shared.Text;
using WayhomeCoins.Configuration;
using WayhomeCoins.Features;
using WayhomeCoins.Networking;
using WayhomeCoins.Patches;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("WayhomeCoins")]
[assembly: AssemblyDescription("Wayhome Coins For Romestead by Ice Box Studio")]
[assembly: AssemblyCompany("Ice Box Studio")]
[assembly: AssemblyProduct("WayhomeCoins")]
[assembly: AssemblyCopyright("Copyright (C) 2026 Ice Box Studio All rights reserved.")]
[assembly: ComVisible(false)]
[assembly: Guid("ca545aa6-4c2b-4eb7-88da-9f09f0b9c884")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: TargetFramework(".NETCoreApp,Version=v8.0", FrameworkDisplayName = ".NET 8.0")]
[assembly: AssemblyVersion("1.0.1.0")]
[module: RefSafetyRules(11)]
namespace WayhomeCoins
{
	internal static class I18n
	{
		internal const string MarketCoinNameKey = "wayhomecoins:market_wayhome_coin*item:name";

		internal const string MarketCoinDescriptionKey = "wayhomecoins:market_wayhome_coin*item:description";

		public static readonly RomesteadLocalizer L = RomesteadLocalization.For("IceBoxStudio.Romestead.WayhomeCoins");

		public static void RegisterJson(string path)
		{
			L.RegisterJson(path);
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "IceBoxStudio.Romestead.WayhomeCoins";

		public const string PLUGIN_NAME = "WayhomeCoins";

		public const string PLUGIN_VERSION = "1.0.1";

		public const string PLUGIN_AUTHOR = "Ice Box Studio";

		public const string PLUGIN_AUTHOR_URL = "https://steamcommunity.com/id/ibox666/";

		public const int NEXUS_MODS_ID = 108;

		public const string THUNDERSTORE_TEAM = "Ice_Box_Studio_Romestead";

		public const string THUNDERSTORE_MOD_NAME = "WayhomeCoins";

		public const string UPDATE_MANIFEST_URL = "https://cdn.jsdelivr.net/gh/ibox233/MyMod_Version@main/WayhomeCoins.json";
	}
	[BepInPlugin("IceBoxStudio.Romestead.WayhomeCoins", "WayhomeCoins", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public sealed class WayhomeCoins : BasePlugin
	{
		private Harmony _harmony;

		public static WayhomeCoins Instance { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		public override void Load()
		{
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Expected O, but got Unknown
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Expected O, but got Unknown
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Expected O, but got Unknown
			Instance = this;
			Logger = ((BasePlugin)this).Log;
			bool flag = default(bool);
			try
			{
				Logger.LogInfo((object)"=============================================");
				ManualLogSource logger = Logger;
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(16, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("WayhomeCoins");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" initializing...");
				}
				logger.LogInfo(val);
				ManualLogSource logger2 = Logger;
				val = new BepInExInfoLogInterpolatedStringHandler(10, 2, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Author: ");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("Ice Box Studio");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("(");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("https://steamcommunity.com/id/ibox666/");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")");
				}
				logger2.LogInfo(val);
				I18n.RegisterJson(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Localization.json"));
				ConfigManager.Init(((BasePlugin)this).Config);
				ModSettingsMenuRegistration.Register(((BasePlugin)this).Config);
				BaseServer.Instance.NetworkEventBusManager.Subscribe(Assembly.GetExecutingAssembly(), (string)null);
				ConfigManager.MarketSettingsChanged += OnMarketSettingsChanged;
				_harmony = new Harmony("IceBoxStudio.Romestead.WayhomeCoins");
				_harmony.PatchAll(Assembly.GetExecutingAssembly());
				ItemDataBasePatch.RegisterMarketCoin();
				ShopDataBasePatch.EnsureMarketShopRegistered();
				ManualLogSource logger3 = Logger;
				val = new BepInExInfoLogInterpolatedStringHandler(13, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>("WayhomeCoins");
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" initialized.");
				}
				logger3.LogInfo(val);
				Logger.LogInfo((object)"=============================================");
			}
			catch (Exception ex)
			{
				ManualLogSource logger4 = Logger;
				BepInExErrorLogInterpolatedStringHandler val2 = new BepInExErrorLogInterpolatedStringHandler(24, 3, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>("WayhomeCoins");
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" initialization error: ");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.Message);
					((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("\n");
					((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(ex.StackTrace);
				}
				logger4.LogError(val2);
			}
		}

		private static void OnMarketSettingsChanged()
		{
			ItemDataBasePatch.RegisterMarketCoin();
			ShopDataBasePatch.RefreshMarketShop();
		}
	}
}
namespace WayhomeCoins.Patches
{
	[HarmonyPatch(typeof(CandideEngine), "Update")]
	internal static class CandideEngineUpdatePatch
	{
		private static void Postfix()
		{
			WayhomeClient.UpdateHotkeys();
		}
	}
	[HarmonyPatch(typeof(ItemDataBase), "AddItems")]
	internal static class ItemDataBasePatch
	{
		private static void Postfix(List<ItemData> itemDataList)
		{
			ApplyCooldown((IEnumerable<ItemData>)itemDataList);
			if (ItemDataBase.DataMap.TryGetValue("consumable:travelers_coin", out var value))
			{
				ApplyCooldown(value);
			}
		}

		public static void RegisterMarketCoin()
		{
			RomesteadContent.Items.Register("wayhomecoins:market_wayhome_coin", I18n.L.Text("wayhomecoins:market_wayhome_coin*item:name", Array.Empty<object>()), I18n.L.Text("wayhomecoins:market_wayhome_coin*item:description", Array.Empty<object>()), (Action<ItemData>)delegate(ItemData item)
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_0038: Expected O, but got Unknown
				//IL_003b: 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_004e: 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_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_0066: Unknown result type (might be due to invalid IL or missing references)
				//IL_006b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				//IL_0082: Expected O, but got Unknown
				item.Icon = "sell";
				item.MaxStackSize = ConfigManager.MarketStackSize;
				item.Tier = 1;
				item.Tradable = new TradableItem
				{
					Price = ConfigManager.MarketPrice
				};
				item.Worship = new ItemWorshipData
				{
					AssociatedGodId = string.Empty
				};
				item.Usable = new UsableItem
				{
					SpellId = "item:teleport_home:start",
					Type = (UsableType)0,
					UsesMax = 1,
					Cooldown = ConfigManager.CooldownSeconds
				};
			});
		}

		private static void ApplyCooldown(IEnumerable<ItemData> items)
		{
			if (items == null)
			{
				return;
			}
			foreach (ItemData item in items)
			{
				if (item?.Id == "consumable:travelers_coin")
				{
					ApplyCooldown(item);
				}
			}
		}

		private static void ApplyCooldown(ItemData item)
		{
			if (item?.Usable != null)
			{
				item.Usable.Cooldown = ConfigManager.CooldownSeconds;
			}
		}
	}
	[HarmonyPatch(typeof(ItemInstanceManager), "TryUseItem")]
	internal static class ItemInstanceManagerPatch
	{
		private static bool Prefix(ItemInstanceModel item, ref bool __result)
		{
			if (!ConfigManager.Active || item == null || !WayhomeServer.IsWayhomeCoinId(item.BaseDataId) || !NetworkManager.ClientActive)
			{
				return true;
			}
			WayhomeClient.ShowMenu();
			__result = true;
			return false;
		}
	}
	[HarmonyPatch(typeof(LocalizationManager), "SetLocalization")]
	[HarmonyAfter(new string[] { "IceBoxStudio.Romestead.RomesteadContentFramework" })]
	internal static class LocalizationManagerPatch
	{
		private static void Postfix()
		{
			ItemDataBasePatch.RegisterMarketCoin();
		}
	}
	[HarmonyPatch(typeof(OfferingsServerManager), "TryHandInOffering", new Type[]
	{
		typeof(Guid),
		typeof(Guid?)
	})]
	internal static class OfferingsServerManagerPatch
	{
		private static bool Prefix(Guid altarBuildingId, Guid? characterEntityId)
		{
			BuildingSimulationModel val = default(BuildingSimulationModel);
			if (!ServerGameState.TryGetBuilding(altarBuildingId, ref val) || !val.InstanceModel.StorageInventoryId.HasValue)
			{
				return true;
			}
			SharedInventoryModel val2 = default(SharedInventoryModel);
			if (!ServerGameState.TryGetInventory(val.InstanceModel.StorageInventoryId.Value, ref val2))
			{
				return true;
			}
			if (val2.GetItemCount("wayhomecoins:market_wayhome_coin") <= 0)
			{
				return true;
			}
			SendBlockedMessage(characterEntityId);
			return false;
		}

		private static void SendBlockedMessage(Guid? characterEntityId)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (characterEntityId.HasValue && TryGetPlayer(characterEntityId.Value, out var player))
			{
				BaseServer.Instance.SendHostMessage("wayhome-coins-teleport-failed", (object)new WayhomeResultMessage
				{
					MessageKey = "status.market_coin_not_offering"
				}, player.Peer);
			}
		}

		private static bool TryGetPlayer(Guid characterEntityId, out ServerJoinedPlayerModel player)
		{
			foreach (ServerJoinedPlayerModel value in PlayerServerService.JoinedPlayers.Values)
			{
				if (value != null && value.CharacterModel?.Character?.EntityId == characterEntityId)
				{
					player = value;
					return true;
				}
			}
			player = null;
			return false;
		}
	}
	[HarmonyPatch(typeof(ServerScriptedSpell))]
	internal static class ServerScriptedSpellPatch
	{
		[HarmonyPatch("CanCast")]
		[HarmonyPrefix]
		private static bool CanCastPrefix(ServerSpellCastingContext context, ref CanCastSpellResult __result)
		{
			//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)
			if (!IsTeleportHome(context.Context, out var player))
			{
				return true;
			}
			if (!ConfigManager.Active || !WayhomeServer.IsTeleportHomeOnCooldown(player))
			{
				return true;
			}
			__result = (CanCastSpellResult)1;
			return false;
		}

		[HarmonyPatch("DoCast")]
		[HarmonyPostfix]
		private static void DoCastPostfix(ProjectileSystem projectileSystem, ServerSpellCastingContext context, CastSpellArgs castSpellArgs)
		{
			//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)
			if (IsTeleportHome(context.Context, out var player))
			{
				WayhomeServer.SetCooldown(player);
			}
		}

		private static bool IsTeleportHome(SpellCastingContext context, out ServerPlayerCharacter player)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			player = null;
			object spellTypeArgs = context.SpellTypeArgs;
			ScriptedSpellArgs val = (ScriptedSpellArgs)((spellTypeArgs is ScriptedSpellArgs) ? spellTypeArgs : null);
			if (val == null || val.Script != "player-teleport-home")
			{
				return false;
			}
			if (context.Target.HasValue)
			{
				return ServerGameState.TryGetPlayerCharacter(context.Target.Value, ref player);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(ShopDataBase), "AddData")]
	internal static class ShopDataBasePatch
	{
		private static void Postfix(List<Shop> shops)
		{
			EnsureMarketShopRegistered();
		}

		public static void EnsureMarketShopRegistered()
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			if (ConfigManager.Active)
			{
				ConfigEntry<bool> marketSalesEnabled = ConfigManager.MarketSalesEnabled;
				if (marketSalesEnabled != null && marketSalesEnabled.Value)
				{
					Dictionary<string, Shop> shopDataMap = ShopDataBase.ShopDataMap;
					Shop val = new Shop();
					val.Id = "wayhomecoins:market_wayhome_shop";
					val.ItemIds = new string[1] { "wayhomecoins:market_wayhome_coin" };
					val.MerchantLevel = ConfigManager.MerchantLevel;
					shopDataMap["wayhomecoins:market_wayhome_shop"] = val;
					return;
				}
			}
			ShopDataBase.ShopDataMap.Remove("wayhomecoins:market_wayhome_shop");
		}

		public static void RefreshMarketShop()
		{
			EnsureMarketShopRegistered();
		}
	}
	[HarmonyPatch(typeof(WorldOverviewWindow), "CursorClickOnMap", new Type[] { typeof(Vector2) })]
	internal static class WorldOverviewWindowPatch
	{
		private static bool Prefix(WorldOverviewWindow __instance, Vector2 tilePosition, ref bool __result)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if (!WayhomeClient.TryOpenMapShortcut(tilePosition, (CandideWindow)(object)__instance))
			{
				return true;
			}
			__result = false;
			return false;
		}
	}
}
namespace WayhomeCoins.Networking
{
	internal static class WayhomeEventKeys
	{
		public const string GetTargets = "wayhome-coins-get-targets";

		public const string Teleport = "wayhome-coins-teleport";

		public const string TeleportSucceeded = "wayhome-coins-teleport-succeeded";

		public const string TeleportFailed = "wayhome-coins-teleport-failed";
	}
	public sealed class WayhomeTargetsRequest
	{
	}
	public sealed class WayhomeTargetsResponse
	{
		public WayhomeTargetInfo[] Targets = Array.Empty<WayhomeTargetInfo>();

		public int CoinCount;

		public float CooldownRemainingSeconds;
	}
	public sealed class WayhomeTargetInfo
	{
		public WayhomeTargetKind Kind;

		public Guid TargetId;

		public string Name;

		public string Icon;

		public int CoinCost = 1;
	}
	public sealed class WayhomeTeleportRequest
	{
		public WayhomeTargetKind Kind;

		public Guid TargetId;
	}
	public sealed class WayhomeResultMessage
	{
		public string MessageKey;
	}
}
namespace WayhomeCoins.Features
{
	internal static class WayhomeClient
	{
		private static CandideEngine _subscribedGame;

		private static CandideModalWindow _menuModal;

		private static bool _menuRequestPending;

		private static bool _mapShortcutRequestPending;

		private const int TargetListWidth = 260;

		private const int TargetButtonLabelWidth = 220;

		public static void UpdateHotkeys()
		{
			//IL_0012: 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)
			EnsureNetworkEventsSubscribed();
			if (CanUseHotkeys() && (int)ConfigManager.OpenMenuHotkey.Value != 0 && NativeInput.Pressed(ConfigManager.OpenMenuHotkey.Value))
			{
				ShowMenu();
			}
		}

		public static void ShowMenu()
		{
			EnsureNetworkEventsSubscribed();
			CandideDesktop desktop = CandideUiSystem.Desktop;
			if (desktop != null && ConfigManager.Active && NetworkManager.ClientActive && _menuModal == null && !_menuRequestPending)
			{
				_menuRequestPending = true;
				NetworkManager.Get<WayhomeTargetsResponse>("wayhome-coins-get-targets", (object)new WayhomeTargetsRequest(), (Action<WayhomeTargetsResponse>)delegate(WayhomeTargetsResponse response)
				{
					_menuRequestPending = false;
					ShowTargetsModal(desktop, response);
				}, 3f, (Action<byte>)delegate
				{
					_menuRequestPending = false;
					ShowError(Text("status.targets_failed"));
				}, true);
			}
		}

		public static bool TryOpenMapShortcut(Vector2 tilePosition, CandideWindow mapWindow)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			EnsureNetworkEventsSubscribed();
			if (((mapWindow != null) ? ((CandideUiElement)mapWindow).Desktop : null) != null && ConfigManager.Active)
			{
				ConfigEntry<bool> mapShortcutEnabled = ConfigManager.MapShortcutEnabled;
				if (mapShortcutEnabled != null && mapShortcutEnabled.Value && NetworkManager.ClientActive)
				{
					if (!TryFindMapShortcutTarget(tilePosition, out var kind, out var targetId))
					{
						return false;
					}
					if (_mapShortcutRequestPending)
					{
						return true;
					}
					RequestMapShortcut(mapWindow, kind, targetId);
					return true;
				}
			}
			return false;
		}

		[EventBus("wayhome-coins-teleport-succeeded", true, null)]
		public static void OnTeleportSucceeded(WayhomeResultMessage message)
		{
			ShowStatus(message?.MessageKey ?? "status.teleport.success");
		}

		[EventBus("wayhome-coins-teleport-failed", true, null)]
		public static void OnTeleportFailed(WayhomeResultMessage message)
		{
			ShowStatus(message?.MessageKey ?? "status.teleport.failed");
		}

		private static void ShowTargetsModal(CandideDesktop desktop, WayhomeTargetsResponse response)
		{
			if (_menuModal != null)
			{
				return;
			}
			if (response == null)
			{
				ShowError(Text("status.targets_failed"));
				return;
			}
			_menuModal = CandideModalWindow.ShowCustomModal(desktop, true, (Action<CandideModalWindow, CandideVerticalStackPanel>)delegate(CandideModalWindow modal, CandideVerticalStackPanel panel)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0006: Unknown result type (might be due to invalid IL or missing references)
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_002a: Expected O, but got Unknown
				//IL_002b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: 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_003a: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Expected O, but got Unknown
				//IL_004b: 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)
				//IL_0075: Unknown result type (might be due to invalid IL or missing references)
				//IL_0082: Expected O, but got Unknown
				//IL_0095: Unknown result type (might be due to invalid IL or missing references)
				//IL_009a: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d2: Expected O, but got Unknown
				//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f8: 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_013b: Unknown result type (might be due to invalid IL or missing references)
				//IL_014b: 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_0157: Unknown result type (might be due to invalid IL or missing references)
				//IL_0162: Expected O, but got Unknown
				//IL_0162: Unknown result type (might be due to invalid IL or missing references)
				//IL_0167: Unknown result type (might be due to invalid IL or missing references)
				//IL_0177: Unknown result type (might be due to invalid IL or missing references)
				//IL_0182: Unknown result type (might be due to invalid IL or missing references)
				//IL_018a: Expected O, but got Unknown
				//IL_0122: Unknown result type (might be due to invalid IL or missing references)
				//IL_0129: Unknown result type (might be due to invalid IL or missing references)
				//IL_0136: Expected O, but got Unknown
				//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
				//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
				//IL_01dc: Expected O, but got Unknown
				((CandideUiContainerMultipleItems)panel).AddChild((CandideUiElement)new CandideTextLabel
				{
					Text = Text("ui.title"),
					TextAlign = (TextHorizontalAlignment)1,
					HorizontalAlignment = (HorizontalAlignment)3
				}, false);
				((CandideUiContainerMultipleItems)panel).AddChild((CandideUiElement)new CandideHorizontalSeparator
				{
					HorizontalAlignment = (HorizontalAlignment)3,
					Padding = new CandideThickness(0, 6)
				}, false);
				((CandideUiContainerMultipleItems)panel).AddChild((CandideUiElement)new CandideTextLabel
				{
					Text = string.Format(Text("ui.coin_count"), response.CoinCount),
					HorizontalAlignment = (HorizontalAlignment)3
				}, false);
				if (response.CooldownRemainingSeconds > 0f)
				{
					((CandideUiContainerMultipleItems)panel).AddChild((CandideUiElement)new CandideTextLabel
					{
						Text = string.Format(Text("ui.cooldown_remaining"), Math.Ceiling(response.CooldownRemainingSeconds)),
						HorizontalAlignment = (HorizontalAlignment)3
					}, false);
				}
				if (response.CoinCount <= 0 || response.CooldownRemainingSeconds > 0f)
				{
					((CandideUiContainerMultipleItems)panel).AddChild((CandideUiElement)new CandideTextLabel
					{
						Text = ((response.CoinCount <= 0) ? Text("status.no_coin") : Text("status.cooldown")),
						Wrap = true,
						HorizontalAlignment = (HorizontalAlignment)3
					}, false);
				}
				CandideVerticalScrollViewer val = new CandideVerticalScrollViewer
				{
					MaxHeight = 300,
					HorizontalAlignment = (HorizontalAlignment)1,
					Margin = new CandideThickness(0, 8, 0, 0)
				};
				CandideVerticalStackPanel val2 = new CandideVerticalStackPanel
				{
					Width = 260,
					DefaultColumnProportion = Proportion.Fill,
					HorizontalAlignment = (HorizontalAlignment)3
				};
				((CandideUiContainerSingleItem)val).SetChild((CandideUiElement)(object)val2);
				((CandideUiContainerMultipleItems)panel).AddChild((CandideUiElement)(object)val, false);
				WayhomeTargetInfo[] array = response.Targets ?? Array.Empty<WayhomeTargetInfo>();
				if (array.Length == 0)
				{
					((CandideUiContainerMultipleItems)val2).AddChild((CandideUiElement)new CandideTextLabel
					{
						Text = Text("ui.no_targets"),
						Wrap = true,
						HorizontalAlignment = (HorizontalAlignment)3
					}, false);
				}
				else
				{
					WayhomeTargetInfo[] array2 = array;
					foreach (WayhomeTargetInfo wayhomeTargetInfo in array2)
					{
						AddTargetButton(modal, val2, wayhomeTargetInfo, response.CooldownRemainingSeconds <= 0f && response.CoinCount >= Math.Max(1, wayhomeTargetInfo.CoinCost));
					}
				}
			});
			((CandideWindow)_menuModal).Closed += delegate
			{
				_menuModal = null;
			};
		}

		private static void AddTargetButton(CandideModalWindow modal, CandideVerticalStackPanel list, WayhomeTargetInfo target, bool enabled)
		{
			//IL_0043: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_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: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			CandideGridIconLabelButton val = new CandideGridIconLabelButton(string.IsNullOrWhiteSpace(target.Icon) ? "sell" : target.Icon, (IconFlag)1, (int?)220)
			{
				Text = FormatTargetName(target),
				Enabled = enabled,
				HorizontalAlignment = (HorizontalAlignment)3,
				Padding = new CandideThickness(2, 2, 6, 4),
				Margin = new CandideThickness(0, 2, 0, 2)
			};
			((CandideTextLabel)val.TextLabel).TextAlign = (TextHorizontalAlignment)0;
			((CandideUiElement)val.TextLabel).Margin = new CandideThickness(4, 0, 0, -2);
			((CandideButtonBase)val).OnClickAction = delegate
			{
				CandideModalWindow.ShowConfirmationModal(((CandideUiElement)modal).Desktop, string.Format(Text("ui.confirm"), Math.Max(1, target.CoinCost), target.Name), (Action)delegate
				{
					((CandideWindow)modal).Close();
					PlayTeleportSound();
					SendTeleport(target.Kind, target.TargetId);
				}, (Action)null);
			};
			((CandideUiContainerMultipleItems)list).AddChild((CandideUiElement)(object)val, false);
		}

		private static void RequestMapShortcut(CandideWindow mapWindow, WayhomeTargetKind kind, Guid targetId)
		{
			_mapShortcutRequestPending = true;
			NetworkManager.Get<WayhomeTargetsResponse>("wayhome-coins-get-targets", (object)new WayhomeTargetsRequest(), (Action<WayhomeTargetsResponse>)delegate(WayhomeTargetsResponse response)
			{
				_mapShortcutRequestPending = false;
				ShowMapShortcutConfirmation(mapWindow, response, kind, targetId);
			}, 3f, (Action<byte>)delegate
			{
				_mapShortcutRequestPending = false;
				ShowError(Text("status.targets_failed"));
			}, true);
		}

		private static void ShowMapShortcutConfirmation(CandideWindow mapWindow, WayhomeTargetsResponse response, WayhomeTargetKind kind, Guid targetId)
		{
			CandideWindow obj = mapWindow;
			if (((obj != null) ? ((CandideUiElement)obj).Desktop : null) == null || response?.Targets == null)
			{
				ShowError(Text("status.targets_failed"));
				return;
			}
			WayhomeTargetInfo target = Array.Find(response.Targets, (WayhomeTargetInfo candidate) => candidate.Kind == kind && candidate.TargetId == targetId);
			if (target == null)
			{
				ShowStatus("status.target_unavailable");
				return;
			}
			int num = Math.Max(1, target.CoinCost);
			if (response.CooldownRemainingSeconds > 0f)
			{
				ShowStatus("status.cooldown");
				return;
			}
			if (response.CoinCount < num)
			{
				ShowStatus("status.no_coin");
				return;
			}
			CandideModalWindow.ShowConfirmationModal(((CandideUiElement)mapWindow).Desktop, string.Format(Text("ui.confirm"), num, target.Name), (Action)delegate
			{
				mapWindow.Close();
				PlayTeleportSound();
				SendTeleport(target.Kind, target.TargetId);
			}, (Action)null);
		}

		private static bool TryFindMapShortcutTarget(Vector2 tilePosition, out WayhomeTargetKind kind, out Guid targetId)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<bool> homeTargetEnabled = ConfigManager.HomeTargetEnabled;
			if (homeTargetEnabled != null && homeTargetEnabled.Value && TryFindMapTownTarget(tilePosition, out targetId))
			{
				kind = WayhomeTargetKind.Home;
				return true;
			}
			ConfigEntry<bool> altarTargetEnabled = ConfigManager.AltarTargetEnabled;
			if (altarTargetEnabled != null && altarTargetEnabled.Value && TryFindMapAltarTarget(tilePosition, out targetId))
			{
				kind = WayhomeTargetKind.Altar;
				return true;
			}
			kind = WayhomeTargetKind.Home;
			targetId = Guid.Empty;
			return false;
		}

		private static bool TryFindMapTownTarget(Vector2 tilePosition, out Guid townId)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			townId = Guid.Empty;
			Building building = default(Building);
			foreach (ClientTownModel value in GameState.Towns.Values)
			{
				if (GameState.TryGetBuilding((Guid?)value.Model.TownCoreId, ref building) && ContainsTile(building, tilePosition))
				{
					townId = value.Model.Id;
					return true;
				}
			}
			return false;
		}

		private static bool TryFindMapAltarTarget(Vector2 tilePosition, out Guid buildingId)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			buildingId = Guid.Empty;
			if (!WorldFlagsHelper.HasFlag(GameState.WorldFlags, "worship_flag:altar_teleport"))
			{
				return false;
			}
			foreach (Building value in GameState.Buildings.Values)
			{
				if (!(value.Model.BuildingTypeId != "altar") && ContainsTile(value, tilePosition))
				{
					ConstructionModel constructionOrNull = ConstructionDataBase.GetConstructionOrNull(value.Model.ConstructionId);
					if (constructionOrNull != null && constructionOrNull.UpgradeLevel >= 1)
					{
						buildingId = value.Model.Id;
						return true;
					}
				}
			}
			return false;
		}

		private static bool ContainsTile(Building building, Vector2 tilePosition)
		{
			//IL_000b: 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)
			return ((Rectangle)(ref building.Model.TileBounds)).Contains((int)Math.Floor(tilePosition.X), (int)Math.Floor(tilePosition.Y));
		}

		private static string FormatTargetName(WayhomeTargetInfo target)
		{
			int num = Math.Max(1, target.CoinCost);
			if (num > 1)
			{
				return string.Format(Text("ui.target_cost"), target.Name, num);
			}
			return target.Name;
		}

		private static void SendTeleport(WayhomeTargetKind kind, Guid targetId)
		{
			NetworkManager.SendMessage("wayhome-coins-teleport", (object)new WayhomeTeleportRequest
			{
				Kind = kind,
				TargetId = targetId
			}, (byte)2, true, false);
		}

		private static void PlayTeleportSound()
		{
			SoundPlayer.PlayEventOneShot("event:/interface/altar/ui_altar_teleport", 1f, 1f);
		}

		private static bool CanUseHotkeys()
		{
			if (!ConfigManager.Active || !NetworkManager.ClientActive)
			{
				return false;
			}
			if (UiInputSystem.InputFocusableElement != null)
			{
				return false;
			}
			CandideEngine game = Globals.Game;
			if (game != null)
			{
				GameTerminal terminal = game.Terminal;
				if (terminal == null)
				{
					return true;
				}
				return !terminal.Active;
			}
			return false;
		}

		private static void EnsureNetworkEventsSubscribed()
		{
			CandideEngine game = Globals.Game;
			if (game != null && _subscribedGame != game)
			{
				game.NetworkEventBusManager.Subscribe(Assembly.GetExecutingAssembly(), (string)null);
				_subscribedGame = game;
			}
		}

		private static void ShowError(string text)
		{
			CandideDesktop desktop = CandideUiSystem.Desktop;
			if (desktop != null)
			{
				CandideModalWindow.ShowErrorModal(desktop, text);
			}
			else
			{
				ShowStatusDirect(text);
			}
		}

		private static void ShowStatus(string messageKey)
		{
			ShowStatusDirect(Text(messageKey));
		}

		private static void ShowStatusDirect(string text)
		{
			ChatLogMessage obj = ChatLogMessage.DirectText(text, (ChatMessageType)4, (string)null);
			obj.Silent = true;
			ChatLogManager.SendLocalChatMessage(obj);
		}

		private static string Text(string key)
		{
			return I18n.L.Text(key, Array.Empty<object>());
		}
	}
	internal static class WayhomeServer
	{
		public const string TravelersCoinId = "consumable:travelers_coin";

		public const string MarketCoinId = "wayhomecoins:market_wayhome_coin";

		public const string MarketShopId = "wayhomecoins:market_wayhome_shop";

		private static readonly string[] SpendableCoinIds = new string[2] { "wayhomecoins:market_wayhome_coin", "consumable:travelers_coin" };

		private static readonly Guid TentBaseId = Guid.Parse("5a34399a-9a36-4447-ad3c-908ffbad824a");

		private static readonly Dictionary<Guid, double> NextReadyTimeByCharacter = new Dictionary<Guid, double>();

		[EventBus("wayhome-coins-get-targets", true, null)]
		public static void OnGetTargets(WayhomeTargetsRequest request, EventBusArgs args)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Expected O, but got Unknown
			try
			{
				if (!ConfigManager.Active || !TryGetPlayer(args, out var _, out var joinedPlayer, out var inventory))
				{
					BaseServer.Instance.SendGetResponseError(args, (byte)1);
					return;
				}
				BaseServer.Instance.SendGetResponseMessage(args, (object)new WayhomeTargetsResponse
				{
					Targets = GetTargets(joinedPlayer).ToArray(),
					CoinCount = GetCoinCount(inventory),
					CooldownRemainingSeconds = GetCooldownRemaining(joinedPlayer)
				}, true);
			}
			catch (Exception ex)
			{
				ManualLogSource logger = WayhomeCoins.Logger;
				if (logger != null)
				{
					bool flag = default(bool);
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(28, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Get wayhome targets failed: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
					}
					logger.LogError(val);
				}
				BaseServer.Instance.SendGetResponseError(args, (byte)1);
			}
		}

		[EventBus("wayhome-coins-teleport", true, null)]
		public static void OnTeleport(WayhomeTeleportRequest request, EventBusArgs args)
		{
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			try
			{
				if (TryTeleportFromMessage(request, args, out var failKey))
				{
					SendResult(args, "wayhome-coins-teleport-succeeded", "status.teleport.success");
				}
				else
				{
					SendResult(args, "wayhome-coins-teleport-failed", failKey);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource logger = WayhomeCoins.Logger;
				if (logger != null)
				{
					bool flag = default(bool);
					BepInExErrorLogInterpolatedStringHandler val = new BepInExErrorLogInterpolatedStringHandler(25, 1, ref flag);
					if (flag)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Wayhome teleport failed: ");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Exception>(ex);
					}
					logger.LogError(val);
				}
				SendResult(args, "wayhome-coins-teleport-failed", "status.teleport.failed");
			}
		}

		public static bool TryTeleportFromMessage(WayhomeTeleportRequest request, EventBusArgs args, out string failKey)
		{
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			failKey = "status.teleport.failed";
			if (request == null || !ConfigManager.Active)
			{
				return false;
			}
			if (!TryGetPlayer(args, out var _, out var joinedPlayer, out var inventory))
			{
				return false;
			}
			if (!IsTargetKindEnabled(request.Kind))
			{
				failKey = "status.target_disabled";
				return false;
			}
			if (!TryResolveTarget(joinedPlayer, request.Kind, request.TargetId, out var worldId, out var position))
			{
				failKey = "status.target_unavailable";
				return false;
			}
			if (!CanTeleportNow(joinedPlayer, out failKey))
			{
				return false;
			}
			int coinCost = GetCoinCost(joinedPlayer, worldId, position);
			return TrySpendAndMove(joinedPlayer, inventory, worldId, position, coinCost, out failKey);
		}

		public static float GetCooldownRemaining(ServerJoinedPlayerModel player)
		{
			if (player?.CharacterModel?.Character == null || !NextReadyTimeByCharacter.TryGetValue(player.CharacterModel.Character.EntityId, out var value))
			{
				return 0f;
			}
			double num = value - ServerGameState.GetWorldPlayTimeSeconds();
			if (!(num <= 0.0))
			{
				return (float)num;
			}
			return 0f;
		}

		private static List<WayhomeTargetInfo> GetTargets(ServerJoinedPlayerModel player)
		{
			List<WayhomeTargetInfo> list = new List<WayhomeTargetInfo>();
			ConfigEntry<bool> homeTargetEnabled = ConfigManager.HomeTargetEnabled;
			if (homeTargetEnabled != null && homeTargetEnabled.Value)
			{
				AddTownTargets(player, list);
			}
			ConfigEntry<bool> altarTargetEnabled = ConfigManager.AltarTargetEnabled;
			if (altarTargetEnabled != null && altarTargetEnabled.Value)
			{
				AddAltarTargets(list);
			}
			ConfigEntry<bool> tentTargetEnabled = ConfigManager.TentTargetEnabled;
			if (tentTargetEnabled != null && tentTargetEnabled.Value)
			{
				AddTentTargets(player, list);
			}
			ConfigEntry<bool> graveTargetEnabled = ConfigManager.GraveTargetEnabled;
			if (graveTargetEnabled != null && graveTargetEnabled.Value && TryResolveGrave(player, player.LastGraveId ?? Guid.Empty, out var _, out var _, out var grave))
			{
				list.Add(new WayhomeTargetInfo
				{
					Kind = WayhomeTargetKind.Grave,
					TargetId = grave.Id,
					Name = Text("target.grave"),
					Icon = "map_marker:gravestone"
				});
			}
			ConfigEntry<bool> playerTargetEnabled = ConfigManager.PlayerTargetEnabled;
			if (playerTargetEnabled != null && playerTargetEnabled.Value)
			{
				AddPlayerTargets(player, list);
			}
			ApplyTargetCosts(player, list);
			return list;
		}

		private static bool TryResolveTarget(ServerJoinedPlayerModel player, WayhomeTargetKind kind, Guid targetId, out Guid worldId, out Vector3 position)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			BuildingSimulationModel building;
			ServerEntityModel grave;
			switch (kind)
			{
			case WayhomeTargetKind.Home:
			{
				ServerTownModel town;
				return TryResolveTownCore(player, targetId, out town, out worldId, out position, out building);
			}
			case WayhomeTargetKind.Altar:
				return TryResolveAltar(targetId, out worldId, out position, out building);
			case WayhomeTargetKind.Grave:
				return TryResolveGrave(player, targetId, out worldId, out position, out grave);
			case WayhomeTargetKind.Tent:
				return TryResolveTent(player, targetId, out worldId, out position, out grave);
			case WayhomeTargetKind.Player:
			{
				ServerJoinedPlayerModel target;
				return TryResolvePlayer(player, targetId, out worldId, out position, out target);
			}
			default:
				worldId = Guid.Empty;
				position = default(Vector3);
				return false;
			}
		}

		private static void AddAltarTargets(List<WayhomeTargetInfo> result)
		{
			if (!WorldFlagsHelper.HasFlag(ServerGameState.WorldFlags, "worship_flag:altar_teleport"))
			{
				return;
			}
			foreach (ServerTownModel value in ServerGameState.Towns.Values)
			{
				foreach (Guid buildingId in value.Model.BuildingIds)
				{
					if (TryResolveAltar(buildingId, out var _, out var _, out var building))
					{
						result.Add(new WayhomeTargetInfo
						{
							Kind = WayhomeTargetKind.Altar,
							TargetId = building.InstanceModel.Id,
							Name = string.Format(Text("target.altar"), GetTownTargetName(value)),
							Icon = "altar"
						});
					}
				}
			}
		}

		private static bool TryResolveAltar(Guid targetId, out Guid worldId, out Vector3 position, out BuildingSimulationModel building)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			worldId = Guid.Empty;
			position = default(Vector3);
			building = null;
			if (targetId == Guid.Empty || !WorldFlagsHelper.HasFlag(ServerGameState.WorldFlags, "worship_flag:altar_teleport") || !ServerGameState.TryGetBuilding(targetId, ref building) || building.InstanceModel.BuildingTypeId != "altar")
			{
				return false;
			}
			ConstructionModel constructionOrNull = ConstructionDataBase.GetConstructionOrNull(building.InstanceModel.ConstructionId);
			if (constructionOrNull == null || constructionOrNull.UpgradeLevel < 1)
			{
				return false;
			}
			return TryResolveBuildingOutside(building, out worldId, out position, bottomCenter: true);
		}

		private static void AddTownTargets(ServerJoinedPlayerModel player, List<WayhomeTargetInfo> result)
		{
			Guid worldId;
			Vector3 position;
			BuildingSimulationModel building;
			if (CanUseAnyTownAndTentTargets())
			{
				foreach (ServerTownModel value in ServerGameState.Towns.Values)
				{
					if (TryResolveTownCore(value, out worldId, out position, out building))
					{
						result.Add(new WayhomeTargetInfo
						{
							Kind = WayhomeTargetKind.Home,
							TargetId = value.Model.Id,
							Name = GetTownTargetName(value),
							Icon = "town_core"
						});
					}
				}
				return;
			}
			if (TryResolvePlayerTownCore(player, out var town, out worldId, out position, out building))
			{
				result.Add(new WayhomeTargetInfo
				{
					Kind = WayhomeTargetKind.Home,
					TargetId = town.Model.Id,
					Name = GetTownTargetName(town),
					Icon = "town_core"
				});
			}
		}

		private static bool TryResolveTownCore(ServerJoinedPlayerModel player, Guid targetId, out ServerTownModel town, out Guid worldId, out Vector3 position, out BuildingSimulationModel building)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (CanUseAnyTownAndTentTargets() && targetId != Guid.Empty)
			{
				town = null;
				worldId = Guid.Empty;
				position = default(Vector3);
				building = null;
				if (ServerGameState.Towns.TryGetValue(targetId, out town))
				{
					return TryResolveTownCore(town, out worldId, out position, out building);
				}
				return false;
			}
			if (TryResolvePlayerTownCore(player, out town, out worldId, out position, out building))
			{
				if (!(targetId == Guid.Empty))
				{
					return town.Model.Id == targetId;
				}
				return true;
			}
			return false;
		}

		private static bool TryResolvePlayerTownCore(ServerJoinedPlayerModel player, out ServerTownModel town, out Guid worldId, out Vector3 position, out BuildingSimulationModel building)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			town = null;
			worldId = Guid.Empty;
			position = default(Vector3);
			building = null;
			if (player?.CharacterModel?.Character == null)
			{
				return false;
			}
			if (!TryGetPlayerTown(player, out town))
			{
				return false;
			}
			return TryResolveTownCore(town, out worldId, out position, out building);
		}

		private static bool TryResolveTownCore(ServerTownModel town, out Guid worldId, out Vector3 position, out BuildingSimulationModel building)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			worldId = Guid.Empty;
			position = default(Vector3);
			building = null;
			if (town?.Model == null)
			{
				return false;
			}
			if (!ServerGameState.Buildings.TryGetValue(town.Model.TownCoreId, out building))
			{
				return false;
			}
			return TryResolveBuildingOutside(building, out worldId, out position, bottomCenter: false);
		}

		private static bool TryResolveBuildingOutside(BuildingSimulationModel building, out Guid worldId, out Vector3 position, bool bottomCenter)
		{
			//IL_000c: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: 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)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			worldId = Guid.Empty;
			position = default(Vector3);
			if (building == null || !ServerGameState.Worlds.TryGetValue(building.InstanceModel.ExteriorWorldId, out var value) || !value.ParentWorldId.HasValue)
			{
				return false;
			}
			worldId = value.ParentWorldId.Value;
			Vector2 centeredPositionFromTileBounds = TileBoundsHelper.GetCenteredPositionFromTileBounds(building.InstanceModel.TileBounds);
			if (bottomCenter)
			{
				centeredPositionFromTileBounds.Y += ((float)building.InstanceModel.TileBounds.Height / 2f - 1f) * 16f;
			}
			position = VectorExtension.ToVector3Xy(centeredPositionFromTileBounds);
			return true;
		}

		private static bool TryGetPlayerTown(ServerJoinedPlayerModel player, out ServerTownModel town)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			town = null;
			(Guid, Vector3) characterSpawn = PlayerCharacterServerManager.GetCharacterSpawn(player.CharacterModel);
			BuildingSimulationModel val = default(BuildingSimulationModel);
			if (ServerGameState.Worlds.TryGetValue(characterSpawn.Item1, out var value) && (int)value.Type == 2 && (int)value.Interior == 0 && value.BuildingId.HasValue && ServerGameState.TryGetBuilding(value.BuildingId.Value, ref val) && val.InstanceModel.TownId.HasValue && ServerGameState.TryGetTown(val.InstanceModel.TownId.Value, ref town))
			{
				return true;
			}
			Guid entityId = player.CharacterModel.Character.EntityId;
			BuildingSimulationModel val2 = default(BuildingSimulationModel);
			foreach (ServerTownModel value3 in ServerGameState.Towns.Values)
			{
				if (ServerGameState.TryGetBuilding(value3.Model.TownCoreId, ref val2) && val2.InstanceModel.Parameters != null && val2.InstanceModel.Parameters.TryGetValue("owner_character_id", out var value2) && Guid.TryParse(value2, out var result) && result == entityId)
				{
					town = value3;
					return true;
				}
			}
			return false;
		}

		private static void AddPlayerTargets(ServerJoinedPlayerModel player, List<WayhomeTargetInfo> result)
		{
			foreach (ServerJoinedPlayerModel value in PlayerServerService.JoinedPlayers.Values)
			{
				if (CanTeleportToPlayer(player, value))
				{
					result.Add(new WayhomeTargetInfo
					{
						Kind = WayhomeTargetKind.Player,
						TargetId = value.CharacterModel.Character.EntityId,
						Name = string.Format(Text("target.player"), GetPlayerName(value)),
						Icon = "ui:citizen"
					});
				}
			}
		}

		private static bool TryResolvePlayer(ServerJoinedPlayerModel player, Guid targetId, out Guid worldId, out Vector3 position, out ServerJoinedPlayerModel target)
		{
			//IL_000c: 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)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			worldId = Guid.Empty;
			position = default(Vector3);
			target = null;
			if (targetId == Guid.Empty)
			{
				return false;
			}
			foreach (ServerJoinedPlayerModel value in PlayerServerService.JoinedPlayers.Values)
			{
				ServerPlayerCharacter characterModel = value.CharacterModel;
				if (characterModel != null)
				{
					Guid? guid = characterModel.Character?.EntityId;
					if (guid.HasValue && !(guid.GetValueOrDefault() != targetId) && CanTeleportToPlayer(player, value))
					{
						target = value;
						worldId = value.CharacterModel.Character.WorldId;
						position = value.CharacterModel.Character.Position + new Vector3(16f, 0f, 0f);
						return true;
					}
				}
			}
			return false;
		}

		private static bool TryResolveGrave(ServerJoinedPlayerModel player, Guid targetId, out Guid worldId, out Vector3 position, out ServerEntityModel grave)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			worldId = Guid.Empty;
			position = default(Vector3);
			grave = null;
			if (targetId == Guid.Empty || player.LastGraveId != targetId)
			{
				return false;
			}
			if (!ServerGameState.TryGetServerEntity(targetId, ref grave, "TryResolveGrave") || grave.BaseId != EntityIds.PlayerGrave)
			{
				return false;
			}
			if (!GraveBelongsToPlayer(grave, player.CharacterModel.Character.EntityId))
			{
				return false;
			}
			worldId = grave.WorldId;
			position = grave.Position + new Vector3(0f, 16f, 0f);
			return true;
		}

		private static void AddTentTargets(ServerJoinedPlayerModel player, List<WayhomeTargetInfo> result)
		{
			if (CanUseAnyTownAndTentTargets())
			{
				HashSet<Guid> hashSet = new HashSet<Guid>();
				{
					foreach (ServerEntityModel value in ServerGameState.Entities.Values)
					{
						if (IsTentEntity(value) && hashSet.Add(value.Id))
						{
							result.Add(new WayhomeTargetInfo
							{
								Kind = WayhomeTargetKind.Tent,
								TargetId = value.Id,
								Name = GetTentTargetName(value),
								Icon = "tent_red"
							});
						}
					}
					return;
				}
			}
			if (TryResolvePlayerTent(player, out var _, out var _, out var tentEntity))
			{
				result.Add(new WayhomeTargetInfo
				{
					Kind = WayhomeTargetKind.Tent,
					TargetId = tentEntity.Id,
					Name = GetTentTargetName(tentEntity),
					Icon = "tent_red"
				});
			}
		}

		private static bool TryResolveTent(ServerJoinedPlayerModel player, Guid targetId, out Guid worldId, out Vector3 position, out ServerEntityModel tentEntity)
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if (CanUseAnyTownAndTentTargets() && targetId != Guid.Empty)
			{
				worldId = Guid.Empty;
				position = default(Vector3);
				tentEntity = null;
				if (!ServerGameState.Entities.TryGetValue(targetId, out tentEntity) || !IsTentEntity(tentEntity))
				{
					return false;
				}
				worldId = tentEntity.WorldId;
				position = tentEntity.Position + new Vector3(0f, 16f, 0f);
				return true;
			}
			if (TryResolvePlayerTent(player, out worldId, out position, out tentEntity))
			{
				if (!(targetId == Guid.Empty))
				{
					return tentEntity.Id == targetId;
				}
				return true;
			}
			return false;
		}

		private static bool TryResolvePlayerTent(ServerJoinedPlayerModel player, out Guid worldId, out Vector3 position, out ServerEntityModel tentEntity)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			worldId = Guid.Empty;
			position = default(Vector3);
			tentEntity = null;
			ServerPlayerCharacter val = player?.CharacterModel;
			if (!val.SpawnPointEntityId.HasValue || !val.SpawnPosition.HasValue)
			{
				return false;
			}
			if (!ServerGameState.Entities.TryGetValue(val.SpawnPointEntityId.Value, out tentEntity) || !IsTentEntity(tentEntity))
			{
				return false;
			}
			worldId = val.SpawnWorldId;
			position = VectorExtension.ToVector3Xy(val.SpawnPosition.Value);
			return true;
		}

		private static bool TrySpendAndMove(ServerJoinedPlayerModel player, SharedInventoryModel inventory, Guid worldId, Vector3 position, int coinCost, out string failKey)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			failKey = "status.teleport.failed";
			if (GetCooldownRemaining(player) > 0f)
			{
				failKey = "status.cooldown";
				return false;
			}
			if (GetCoinCount(inventory) < coinCost)
			{
				failKey = "status.no_coin";
				return false;
			}
			if (!TrySpendCoins(inventory, coinCost))
			{
				failKey = "status.no_coin";
				return false;
			}
			DetachCarriedEntity(player);
			PlayerServerManager.MovePlayerCharacter(player, position, (Guid?)worldId, true);
			SetCooldown(player);
			return true;
		}

		private static bool TryGetPlayer(EventBusArgs args, out ServerPlayerCharacter character, out ServerJoinedPlayerModel joinedPlayer, out SharedInventoryModel inventory)
		{
			character = null;
			joinedPlayer = null;
			inventory = null;
			(ServerPlayerCharacter, ServerJoinedPlayerModel)? playerInfoFromPeerId = PlayerServerService.GetPlayerInfoFromPeerId((int)args.Peer.Id);
			if (!playerInfoFromPeerId.HasValue)
			{
				return false;
			}
			character = playerInfoFromPeerId.Value.Item1;
			joinedPlayer = playerInfoFromPeerId.Value.Item2;
			return ServerGameState.TryGetInventory(character.Character.CharacterInventoryModel.InventoryId, ref inventory);
		}

		public static bool IsWayhomeCoinId(string itemId)
		{
			if (!(itemId == "consumable:travelers_coin"))
			{
				return itemId == "wayhomecoins:market_wayhome_coin";
			}
			return true;
		}

		private static int GetCoinCount(SharedInventoryModel inventory)
		{
			if (inventory == null)
			{
				return 0;
			}
			int num = 0;
			for (int i = 0; i < SpendableCoinIds.Length; i++)
			{
				num += inventory.GetItemCount(SpendableCoinIds[i]);
			}
			return num;
		}

		private static bool TrySpendCoins(SharedInventoryModel inventory, int count)
		{
			if (count <= 0)
			{
				return true;
			}
			if (GetCoinCount(inventory) < count)
			{
				return false;
			}
			int num = count;
			for (int i = 0; i < SpendableCoinIds.Length; i++)
			{
				if (num <= 0)
				{
					break;
				}
				while (num > 0)
				{
					(int, ItemInstanceModel) tuple = inventory.FindFirstSlotIndexWithBaseId(SpendableCoinIds[i], false);
					if (tuple.Item1 < 0)
					{
						break;
					}
					int num2 = Math.Min(num, tuple.Item2.StackCount);
					if (!SimpleInventoryServerManager.TryExpendItem(inventory.Id, tuple.Item1, num2, false))
					{
						return false;
					}
					num -= num2;
				}
			}
			return num <= 0;
		}

		private static bool IsTargetKindEnabled(WayhomeTargetKind kind)
		{
			return kind switch
			{
				WayhomeTargetKind.Home => ConfigManager.HomeTargetEnabled?.Value ?? false, 
				WayhomeTargetKind.Altar => ConfigManager.AltarTargetEnabled?.Value ?? false, 
				WayhomeTargetKind.Grave => ConfigManager.GraveTargetEnabled?.Value ?? false, 
				WayhomeTargetKind.Tent => ConfigManager.TentTargetEnabled?.Value ?? false, 
				WayhomeTargetKind.Player => ConfigManager.PlayerTargetEnabled?.Value ?? false, 
				_ => false, 
			};
		}

		private static bool CanUseAnyTownAndTentTargets()
		{
			return ConfigManager.AnyTownAndTentTargetEnabled?.Value ?? false;
		}

		private static bool IsTentEntity(ServerEntityModel entity)
		{
			return entity?.BaseId == TentBaseId;
		}

		private static bool CanTeleportToPlayer(ServerJoinedPlayerModel player, ServerJoinedPlayerModel target)
		{
			if (player != null && target?.CharacterModel?.Character != null && !target.Dead)
			{
				return target.CharacterModel.Character.EntityId != player.CharacterModel.Character.EntityId;
			}
			return false;
		}

		private static bool CanTeleportNow(ServerJoinedPlayerModel player, out string failKey)
		{
			failKey = null;
			if (player == null)
			{
				failKey = "status.teleport.failed";
				return false;
			}
			if (player.Dead)
			{
				ConfigEntry<bool> allowTeleportWhileDead = ConfigManager.AllowTeleportWhileDead;
				if (allowTeleportWhileDead == null || !allowTeleportWhileDead.Value)
				{
					failKey = "status.restricted_dead";
					return false;
				}
			}
			EntityWrapper entity = player.Entity;
			if (entity != null && entity.CarriedId.HasValue)
			{
				ConfigEntry<bool> allowTeleportWhileCarrying = ConfigManager.AllowTeleportWhileCarrying;
				if (allowTeleportWhileCarrying == null || !allowTeleportWhileCarrying.Value)
				{
					failKey = "status.restricted_carrying";
					return false;
				}
			}
			if (IsInDungeon(player))
			{
				ConfigEntry<bool> allowTeleportInDungeon = ConfigManager.AllowTeleportInDungeon;
				if (allowTeleportInDungeon == null || !allowTeleportInDungeon.Value)
				{
					failKey = "status.restricted_dungeon";
					return false;
				}
			}
			if (IsInCombat(player))
			{
				ConfigEntry<bool> allowTeleportInCombat = ConfigManager.AllowTeleportInCombat;
				if (allowTeleportInCombat == null || !allowTeleportInCombat.Value)
				{
					failKey = "status.restricted_combat";
					return false;
				}
			}
			return true;
		}

		private static bool IsInDungeon(ServerJoinedPlayerModel player)
		{
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Invalid comparison between Unknown and I4
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Invalid comparison between Unknown and I4
			Guid? guid = player?.CharacterModel?.Character?.WorldId;
			if (guid.HasValue && ServerGameState.Worlds.TryGetValue(guid.Value, out var value) && (int)value.Type == 2)
			{
				return (int)value.Interior == 1;
			}
			return false;
		}

		private static bool IsInCombat(ServerJoinedPlayerModel player)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			EntityWrapper val = player?.Entity;
			if (val == null)
			{
				return false;
			}
			foreach (ServerEntityModel value in ServerGameState.Entities.Values)
			{
				EntityWrapper val2 = value?.EntityWrapper;
				if (val2 != null && !val2.Removed && ComponentExtension.HasFlags(val2.Mask, (Component)8) && val2.TargetOfAggro != null && val2.TargetOfAggro.Id == val.Id)
				{
					return true;
				}
			}
			return false;
		}

		private static void DetachCarriedEntity(ServerJoinedPlayerModel player)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			if (player != null && (player.EntityModel?.CarriedEntityId).HasValue)
			{
				EntityServerManager.Detach(player.EntityModel, (Vector3?)null, SyncStrategy.SendToAll, true);
			}
		}

		private static void ApplyTargetCosts(ServerJoinedPlayerModel player, List<WayhomeTargetInfo> targets)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			foreach (WayhomeTargetInfo target in targets)
			{
				target.CoinCost = ((!TryResolveTarget(player, target.Kind, target.TargetId, out var worldId, out var position)) ? 1 : GetCoinCost(player, worldId, position));
			}
		}

		private static int GetCoinCost(ServerJoinedPlayerModel player, Guid worldId, Vector3 position)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			ConfigEntry<bool> distanceCostEnabled = ConfigManager.DistanceCostEnabled;
			if (distanceCostEnabled == null || !distanceCostEnabled.Value)
			{
				return 1;
			}
			float distanceTiles = GetDistanceTiles(player, worldId, position);
			if (distanceTiles <= 0f)
			{
				return 1;
			}
			int num = (int)Math.Floor(distanceTiles / (float)ConfigManager.TilesPerExtraCoin);
			return Math.Clamp(1 + num, 1, ConfigManager.MaxDistanceCostCoins);
		}

		private static float GetDistanceTiles(ServerJoinedPlayerModel player, Guid worldId, Vector3 position)
		{
			//IL_00a5: 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_00b6: 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_00d2: 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_00d8: Unknown result type (might be due to invalid IL or missing references)
			if (!TryGetOutsidePosition(player?.CharacterModel?.Character?.WorldId ?? Guid.Empty, (player?.CharacterModel?.Character?.Position).GetValueOrDefault(), out var outsideWorldId, out var outsidePosition) || !TryGetOutsidePosition(worldId, position, out var outsideWorldId2, out var outsidePosition2) || outsideWorldId != outsideWorldId2)
			{
				return 0f;
			}
			return Vector2.Distance(VectorExtension.ToVector2(outsidePosition), VectorExtension.ToVector2(outsidePosition2)) / 16f;
		}

		private static bool TryGetOutsidePosition(Guid worldId, Vector3 position, out Guid outsideWorldId, out Vector3 outsidePosition)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Invalid comparison between Unknown and I4
			outsideWorldId = worldId;
			outsidePosition = position;
			if (!ServerGameState.Worlds.TryGetValue(worldId, out var value))
			{
				return false;
			}
			if ((int)value.Type != 2)
			{
				return true;
			}
			BuildingSimulationModel building = default(BuildingSimulationModel);
			if (value.BuildingId.HasValue && ServerGameState.TryGetBuilding(value.BuildingId.Value, ref building) && TryResolveBuildingOutside(building, out outsideWorldId, out outsidePosition, bottomCenter: false))
			{
				return true;
			}
			return false;
		}

		private static string GetPlayerName(ServerJoinedPlayerModel player)
		{
			string text = player?.CharacterModel?.Character?.Name;
			if (!string.IsNullOrWhiteSpace(text))
			{
				return text;
			}
			return Text("target.player_unknown");
		}

		private static string GetTentTargetName(ServerEntityModel tent)
		{
			if (tent?.Parameters != null && tent.Parameters.TryGetValue("owner_character_id", out var value) && Guid.TryParse(value, out var result) && TryGetCharacterName(result, out var name))
			{
				return string.Format(Text("target.tent_owner"), name);
			}
			return Text("target.tent");
		}

		private static bool TryGetCharacterName(Guid characterId, out string name)
		{
			if (ServerGameState.PlayerCharacters.TryGetValue(characterId, out var value) && !string.IsNullOrWhiteSpace(value.Character?.Name))
			{
				name = value.Character.Name;
				return true;
			}
			foreach (ServerJoinedPlayerModel value2 in PlayerServerService.JoinedPlayers.Values)
			{
				ServerPlayerCharacter characterModel = value2.CharacterModel;
				if (characterModel != null)
				{
					Guid? guid = characterModel.Character?.EntityId;
					if (guid.HasValue && guid.GetValueOrDefault() == characterId && !string.IsNullOrWhiteSpace(value2.CharacterModel.Character.Name))
					{
						name = value2.CharacterModel.Character.Name;
						return true;
					}
				}
			}
			name = null;
			return false;
		}

		private static bool GraveBelongsToPlayer(ServerEntityModel grave, Guid characterId)
		{
			if (grave.Parameters == null || !grave.Parameters.TryGetValue("character_id", out var value))
			{
				return true;
			}
			if (Guid.TryParse(value, out var result))
			{
				return result == characterId;
			}
			return false;
		}

		public static bool IsTeleportHomeOnCooldown(ServerPlayerCharacter character)
		{
			if (!ConfigManager.Active || character == null || !PlayerServerService.JoinedPlayers.TryGetValue(character.PlayerId, out var value))
			{
				return false;
			}
			return GetCooldownRemaining(value) > 0f;
		}

		public static void SetCooldown(ServerPlayerCharacter character)
		{
			if (ConfigManager.Active && character != null && PlayerServerService.JoinedPlayers.TryGetValue(character.PlayerId, out var value))
			{
				SetCooldown(value);
			}
		}

		private static void SetCooldown(ServerJoinedPlayerModel player)
		{
			float cooldownSeconds = ConfigManager.CooldownSeconds;
			if (cooldownSeconds <= 0f)
			{
				NextReadyTimeByCharacter.Remove(player.CharacterModel.Character.EntityId);
			}
			else
			{
				NextReadyTimeByCharacter[player.CharacterModel.Character.EntityId] = ServerGameState.GetWorldPlayTimeSeconds() + (double)cooldownSeconds;
			}
		}

		private static void SendResult(EventBusArgs args, string key, string messageKey)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			BaseServer.Instance.SendHostMessage(key, (object)new WayhomeResultMessage
			{
				MessageKey = messageKey
			}, args.Peer);
		}

		private static string Text(string key)
		{
			return I18n.L.Text(key, Array.Empty<object>());
		}

		private static string GetTownTargetName(ServerTownModel town)
		{
			object obj;
			if (town == null)
			{
				obj = null;
			}
			else
			{
				TownModel model = town.Model;
				obj = ((model != null) ? model.GetLocalizedName() : null);
			}
			string text = (string)obj;
			if (!string.IsNullOrWhiteSpace(text) && !text.StartsWith("<", StringComparison.Ordinal))
			{
				return text;
			}
			return Text("target.town_core");
		}
	}
	public enum WayhomeTargetKind : byte
	{
		Home,
		Altar,
		Grave,
		Tent,
		Player
	}
}
namespace WayhomeCoins.Configuration
{
	internal static class ConfigManager
	{
		private sealed class LocalizedSectionTag
		{
			private readonly string _displayNameKey;

			public string Section { get; }

			public string DisplayName => Text(_displayNameKey);

			public int? Order { get; }

			public LocalizedSectionTag(string section, string displayNameKey, int? order)
			{
				Section = section;
				_displayNameKey = displayNameKey;
				Order = order;
			}
		}

		private sealed class LocalizedEntryTag
		{
			private readonly string _displayNameKey;

			private readonly string _descriptionKey;

			public string DisplayName => Text(_displayNameKey);

			public string Description => Text(_descriptionKey);

			public int? Order { get; }

			public double? SliderStep { get; }

			public bool? Keybind { get; }

			public LocalizedEntryTag(string displayNameKey, string descriptionKey, int? order, double? sliderStep, bool keybind)
			{
				_displayNameKey = displayNameKey;
				_descriptionKey = descriptionKey;
				Order = order;
				SliderStep = sliderStep;
				Keybind = keybind;
			}
		}

		public const string GeneralSection = "General";

		public const string TargetsSection = "Targets";

		public const string MarketSection = "Market";

		public const string RestrictionsSection = "Restrictions";

		public const string CostSection = "Cost";

		public const string ControlsSection = "Controls";

		public static ConfigEntry<bool> Enabled { get; private set; }

		public static ConfigEntry<float> TeleportCooldownSeconds { get; private set; }

		public static ConfigEntry<bool> HomeTargetEnabled { get; private set; }

		public static ConfigEntry<bool> AltarTargetEnabled { get; private set; }

		public static ConfigEntry<bool> GraveTargetEnabled { get; private set; }

		public static ConfigEntry<bool> TentTargetEnabled { get; private set; }

		public static ConfigEntry<bool> AnyTownAndTentTargetEnabled { get; private set; }

		public static ConfigEntry<bool> PlayerTargetEnabled { get; private set; }

		public static ConfigEntry<bool> AllowTeleportWhileCarrying { get; private set; }

		public static ConfigEntry<bool> AllowTeleportWhileDead { get; private set; }

		public static ConfigEntry<bool> AllowTeleportInCombat { get; private set; }

		public static ConfigEntry<bool> AllowTeleportInDungeon { get; private set; }

		public static ConfigEntry<bool> DistanceCostEnabled { get; private set; }

		public static ConfigEntry<int> DistanceTilesPerExtraCoin { get; private set; }

		public static ConfigEntry<int> DistanceCostMaxCoins { get; private set; }

		public static ConfigEntry<bool> MapShortcutEnabled { get; private set; }

		public static ConfigEntry<bool> MarketSalesEnabled { get; private set; }

		public static ConfigEntry<int> MarketCoinPrice { get; private set; }

		public static ConfigEntry<int> MarketCoinStackSize { get; private set; }

		public static ConfigEntry<int> MarketMerchantLevel { get; private set; }

		public static ConfigEntry<Keys> OpenMenuHotkey { get; private set; }

		public static bool Active => Enabled?.Value ?? false;

		public static float CooldownSeconds => Math.Clamp(TeleportCooldownSeconds?.Value ?? 30f, 0f, 120f);

		public static ulong MarketPrice => (ulong)Math.Clamp(MarketCoinPrice?.Value ?? 200, 1, 1000);

		public static int MarketStackSize => Math.Clamp(MarketCoinStackSize?.Value ?? 100, 1, 100);

		public static int MerchantLevel => Math.Clamp(MarketMerchantLevel?.Value ?? 1, 1, 7);

		public static int TilesPerExtraCoin => Math.Clamp(DistanceTilesPerExtraCoin?.Value ?? 500, 50, 5000);

		public static int MaxDistanceCostCoins => Math.Clamp(DistanceCostMaxCoins?.Value ?? 5, 1, 100);

		public static event Action MarketSettingsChanged;

		public static void Init(ConfigFile config)
		{
			Enabled = config.Bind<bool>("General", "Enabled", true, Description("config.enabled.description", "entry.enabled", 1, "General", "section.general", 10));
			AcceptableValueBase acceptableValues = (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 120f);
			double? sliderStep = 1.0;
			TeleportCooldownSeconds = config.Bind<float>("General", "TeleportCooldownSeconds", 30f, Description("config.cooldown.description", "entry.cooldown", 2, null, null, null, acceptableValues, sliderStep));
			HomeTargetEnabled = config.Bind<bool>("Targets", "HomeTargetEnabled", true, Description("config.home_target.description", "entry.home_target", 1, "Targets", "section.targets", 20));
			AltarTargetEnabled = config.Bind<bool>("Targets", "AltarTargetEnabled", true, Description("config.altar_target.description", "entry.altar_target", 2));
			GraveTargetEnabled = config.Bind<bool>("Targets", "GraveTargetEnabled", true, Description("config.grave_target.description", "entry.grave_target", 3));
			TentTargetEnabled = config.Bind<bool>("Targets", "TentTargetEnabled", true, Description("config.tent_target.description", "entry.tent_target", 4));
			PlayerTargetEnabled = config.Bind<bool>("Targets", "PlayerTargetEnabled", true, Description("config.player_target.description", "entry.player_target", 5));
			AnyTownAndTentTargetEnabled = config.Bind<bool>("Targets", "AnyTownAndTentTargetEnabled", true, Description("config.any_town_tent_target.description", "entry.any_town_tent_target", 6));
			AllowTeleportWhileCarrying = config.Bind<bool>("Restrictions", "AllowTeleportWhileCarrying", false, Description("config.allow_carrying.description", "entry.allow_carrying", 1, "Restrictions", "section.restrictions", 30));
			AllowTeleportWhileDead = config.Bind<bool>("Restrictions", "AllowTeleportWhileDead", false, Description("config.allow_dead.description", "entry.allow_dead", 2));
			AllowTeleportInCombat = config.Bind<bool>("Restrictions", "AllowTeleportInCombat", false, Description("config.allow_combat.description", "entry.allow_combat", 3));
			AllowTeleportInDungeon = config.Bind<bool>("Restrictions", "AllowTeleportInDungeon", false, Description("config.allow_dungeon.description", "entry.allow_dungeon", 4));
			DistanceCostEnabled = config.Bind<bool>("Cost", "DistanceCostEnabled", false, Description("config.distance_cost.description", "entry.distance_cost", 1, "Cost", "section.cost", 40));
			acceptableValues = (AcceptableValueBase)(object)new AcceptableValueRange<int>(50, 5000);
			sliderStep = 50.0;
			DistanceTilesPerExtraCoin = config.Bind<int>("Cost", "DistanceTilesPerExtraCoin", 500, Description("config.distance_tiles_per_coin.description", "entry.distance_tiles_per_coin", 2, null, null, null, acceptableValues, sliderStep));
			acceptableValues = (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100);
			sliderStep = 1.0;
			DistanceCostMaxCoins = config.Bind<int>("Cost", "DistanceCostMaxCoins", 5, Description("config.distance_max_cost.description", "entry.distance_max_cost", 3, null, null, null, acceptableValues, sliderStep));
			MapShortcutEnabled = config.Bind<bool>("Controls", "MapShortcutEnabled", true, Description("config.map_shortcut.description", "entry.map_shortcut", 1, "Controls", "section.controls", 60));
			MarketSalesEnabled = config.Bind<bool>("Market", "MarketSalesEnabled", true, Description("config.market_sales.description", "entry.market_sales", 1, "Market", "section.market", 50));
			acceptableValues = (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 1000);
			sliderStep = 1.0;
			MarketCoinPrice = config.Bind<int>("Market", "MarketCoinPrice", 200, Description("config.market_price.description", "entry.market_price", 2, null, null, null, acceptableValues, sliderStep));
			acceptableValues = (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100);
			sliderStep = 1.0;
			MarketCoinStackSize = config.Bind<int>("Market", "MarketCoinStackSize", 100, Description("config.market_stack.description", "entry.market_stack", 3, null, null, null, acceptableValues, sliderStep));
			acceptableValues = (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 7);
			sliderStep = 1.0;
			MarketMerchantLevel = config.Bind<int>("Market", "MarketMerchantLevel", 1, Description("config.market_level.description", "entry.market_level", 4, null, null, null, acceptableValues, sliderStep));
			OpenMenuHotkey = config.Bind<Keys>("Controls", "OpenMenuHotkey", (Keys)79, Description("config.open_menu_hotkey.description", "entry.open_menu_hotkey", 2, null, null, null, null, null, keybind: true));
			MarketSalesEnabled.SettingChanged += delegate
			{
				RaiseMarketSettingsChanged();
			};
			MarketCoinPrice.SettingChanged += delegate
			{
				RaiseMarketSettingsChanged();
			};
			MarketCoinStackSize.SettingChanged += delegate
			{
				RaiseMarketSettingsChanged();
			};
			MarketMerchantLevel.SettingChanged += delegate
			{
				RaiseMarketSettingsChanged();
			};
		}

		private static ConfigDescription Description(string descriptionKey, string entryNameKey, int entryOrder, string section = null, string sectionNameKey = null, int? sectionOrder = null, AcceptableValueBase acceptableValues = null, double? sliderStep = null, bool keybind = false)
		{
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			List<object> list = new List<object>();
			if (!string.IsNullOrWhiteSpace(section))
			{
				list.Add(new LocalizedSectionTag(section, sectionNameKey, sectionOrder));
			}
			list.Add(new LocalizedEntryTag(entryNameKey, descriptionKey, entryOrder, sliderStep, keybind));
			return new ConfigDescription(Text(descriptionKey), acceptableValues, list.ToArray());
		}

		private static string Text(string key)
		{
			return I18n.L.Text(key, Array.Empty<object>());
		}

		private static void RaiseMarketSettingsChanged()
		{
			ConfigManager.MarketSettingsChanged?.Invoke();
		}
	}
	internal static class ModSettingsMenuRegistration
	{
		private static ConfigFile _config;

		private static string _locale;

		private static bool _subscribed;

		public static void Register(ConfigFile config)
		{
			_config = config;
			if (!_subscribed)
			{
				ModSettingsRegistry.RefreshRequested += Refresh;
				_subscribed = true;
			}
			RegisterCurrent(config);
		}

		private static void Refresh()
		{
			if (_config != null)
			{
				string currentLocale = I18n.L.CurrentLocale;
				ModSettingsRegistration val = default(ModSettingsRegistration);
				if (!(_locale == currentLocale) || !ModSettingsRegistry.TryGet("IceBoxStudio.Romestead.WayhomeCoins", ref val))
				{
					RegisterCurrent(_config);
				}
			}
		}

		private static void RegisterCurrent(ConfigFile config)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: 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_002b: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			ModSettingsRegistry.Register("IceBoxStudio.Romestead.WayhomeCoins", Text("mod.name"), config, new ModSettingsModOptions
			{
				Icon = "cog",
				Version = "1.0.1",
				Author = "Ice Box Studio",
				Description = Text("mod.description"),
				NexusModsId = 108,
				ThunderstoreTeam = "Ice_Box_Studio_Romestead",
				ThunderstoreModName = "WayhomeCoins",
				UpdateManifestUrl = "https://cdn.jsdelivr.net/gh/ibox233/MyMod_Version@main/WayhomeCoins.json",
				Order = -70
			});
			_locale = I18n.L.CurrentLocale;
		}

		private static string Text(string key)
		{
			return I18n.L.Text(key, Array.Empty<object>());
		}
	}
}