Decompiled source of Captain territorial v1.0.22

Captain_territorial.dll

Decompiled 19 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Captain_territorial
{
	public static class SimpleVFX
	{
		private class AutoCleanup : MonoBehaviour
		{
			private float _delay;

			public static void Schedule(GameObject target, float delay)
			{
				if (!((Object)(object)target == (Object)null))
				{
					target.AddComponent<AutoCleanup>()._delay = delay;
				}
			}

			private void Start()
			{
				((MonoBehaviour)this).StartCoroutine(Run());
			}

			private IEnumerator Run()
			{
				yield return (object)new WaitForSeconds(_delay);
				((Component)this).gameObject.SetActive(false);
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}
		}

		private static GameObject _cachedAuraPrefab;

		private static bool _initialized;

		public static void Initialize()
		{
			if (!_initialized)
			{
				_initialized = true;
				_cachedAuraPrefab = LoadEmbeddedPrefab("buff_03a_aura");
			}
		}

		private static GameObject LoadEmbeddedPrefab(string vfxName)
		{
			try
			{
				Assembly executingAssembly = Assembly.GetExecutingAssembly();
				string text = null;
				string[] manifestResourceNames = executingAssembly.GetManifestResourceNames();
				foreach (string text2 in manifestResourceNames)
				{
					if (text2.EndsWith("." + vfxName))
					{
						text = text2;
						break;
					}
				}
				if (text == null)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[SimpleVFX] '" + vfxName + "' 리소스 없음"));
					}
					return null;
				}
				AssetBundle val;
				using (Stream stream = executingAssembly.GetManifestResourceStream(text))
				{
					if (stream == null)
					{
						return null;
					}
					val = AssetBundle.LoadFromStream(stream);
				}
				GameObject[] array = (((Object)(object)val != (Object)null) ? val.LoadAllAssets<GameObject>() : null);
				return (array != null && array.Length != 0) ? array[0] : null;
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)("[SimpleVFX] '" + vfxName + "' 로드 실패: " + ex.Message));
				}
				return null;
			}
		}

		public static GameObject PlayAura(Vector3 position, float duration)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_cachedAuraPrefab == (Object)null)
			{
				return null;
			}
			GameObject val = InstantiateWithoutNetworking(_cachedAuraPrefab, position);
			AutoCleanup.Schedule(val, duration);
			return val;
		}

		public static void PlaySound(string sfxName, Vector3 position, float duration)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			PlayZNetScenePrefab(sfxName, position, duration, "sfx");
		}

		public static void PlayVFX(string vfxName, Vector3 position, float duration)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			PlayZNetScenePrefab(vfxName, position, duration, "vfx");
		}

		private static void PlayZNetScenePrefab(string prefabName, Vector3 position, float duration, string logTag)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			if (string.IsNullOrEmpty(prefabName) || (Object)(object)ZNetScene.instance == (Object)null)
			{
				return;
			}
			GameObject prefab = ZNetScene.instance.GetPrefab(prefabName);
			if ((Object)(object)prefab == (Object)null)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[SimpleVFX] " + logTag + " '" + prefabName + "' 프리팹 없음"));
				}
			}
			else
			{
				GameObject target = InstantiateWithoutNetworking(prefab, position);
				AutoCleanup.Schedule(target, duration);
			}
		}

		private static GameObject InstantiateWithoutNetworking(GameObject prefab, Vector3 position)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			bool activeSelf = prefab.activeSelf;
			prefab.SetActive(false);
			GameObject val = Object.Instantiate<GameObject>(prefab, position, Quaternion.identity);
			prefab.SetActive(activeSelf);
			ZNetView component = val.GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component);
			}
			ZSyncTransform component2 = val.GetComponent<ZSyncTransform>();
			if ((Object)(object)component2 != (Object)null)
			{
				Object.DestroyImmediate((Object)(object)component2);
			}
			val.SetActive(true);
			return val;
		}
	}
	public static class VFXManager
	{
		public static bool VFX_ENABLED = true;

		private static readonly Vector3[] ConsumeAuraOffsets = (Vector3[])(object)new Vector3[3]
		{
			new Vector3(-0.3f, 1.5f, 0f),
			new Vector3(0f, 1.8f, 0f),
			new Vector3(0.3f, 1.5f, 0f)
		};

		private const float ConsumeEffectDuration = 3f;

		private const float UpgradeEffectDuration = 3f;

		public static void Initialize()
		{
			SimpleVFX.Initialize();
		}

		public static void PlayVFXMultiplayer(string vfxName, string soundName, Vector3 position, float destroyAfter = 3f)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (VFX_ENABLED)
			{
				if (!string.IsNullOrEmpty(vfxName))
				{
					SimpleVFX.PlayAura(position, destroyAfter);
				}
				if (!string.IsNullOrEmpty(soundName))
				{
					SimpleVFX.PlaySound(soundName, position, destroyAfter);
				}
			}
		}

		public static void PlayIntrusionAlert(Vector3 position)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			if (VFX_ENABLED)
			{
				SimpleVFX.PlaySound("sfx_morgen_alert", position, 2f);
			}
		}

		public static void PlayWardConsumeEffect(Transform wardTransform)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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)
			if (VFX_ENABLED && !((Object)(object)wardTransform == (Object)null))
			{
				Vector3[] consumeAuraOffsets = ConsumeAuraOffsets;
				foreach (Vector3 val in consumeAuraOffsets)
				{
					SimpleVFX.PlayAura(wardTransform.TransformPoint(val), 3f);
				}
				SimpleVFX.PlaySound("sfx_dverger_heal_finish", wardTransform.position, 3f);
			}
		}

		public static void PlayUpgradeEffect(Vector3 position)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (VFX_ENABLED)
			{
				SimpleVFX.PlayVFX("vfx_shieldgenerator_refuel", position, 3f);
				SimpleVFX.PlaySound("sfx_fader_bell", position, 3f);
			}
		}
	}
	[HarmonyPatch(typeof(Player), "TryPlacePiece")]
	public static class Patch_Player_TryPlacePiece
	{
		private static readonly string[] s_alwaysAllowedPieces = new string[7] { "piece_workbench", "portal_wood", "Cart", "Raft", "Karve", "VikingShip", "VikingShip_Ashlands" };

		private static bool Prefix(Player __instance, ref bool __result)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			GameObject placementGhost = __instance.m_placementGhost;
			if ((Object)(object)placementGhost == (Object)null)
			{
				return true;
			}
			Vector3 position = placementGhost.transform.position;
			string name = ((Object)placementGhost).name;
			string[] array = s_alwaysAllowedPieces;
			foreach (string value in array)
			{
				if (name.Contains(value))
				{
					return true;
				}
			}
			if (name.Contains("territoryward"))
			{
				if (!TerritoryConfig.Enabled.Value)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_disabled", 0, (Sprite)null);
					__result = false;
					return false;
				}
				if (!TerritoryConfig.AdminBypass.Value && CountPlayerWards() >= TerritoryConfig.WardLimit.Value)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_limit_reached", 0, (Sprite)null);
					__result = false;
					return false;
				}
				if (TerritoryWard.IsInsideActiveWard(position))
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_no_overlap", 0, (Sprite)null);
					__result = false;
					return false;
				}
				return true;
			}
			if (!TerritoryWard.IsInsideActiveWard(position))
			{
				string text = (TerritoryWard.IsInsideDeactivatedWard(position) ? "$territoryward_must_activate" : "$territoryward_no_build");
				((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null);
				__result = false;
				return false;
			}
			return true;
		}

		private static int CountPlayerWards()
		{
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return 0;
			}
			long playerID = Player.m_localPlayer.GetPlayerID();
			int num = 0;
			foreach (PrivateArea s_ward in TerritoryWard.s_wards)
			{
				if (!((Object)(object)s_ward == (Object)null))
				{
					ZNetView component = ((Component)s_ward).GetComponent<ZNetView>();
					if ((Object)(object)component != (Object)null && component.IsValid() && component.GetZDO().GetLong("creator", 0L) == playerID)
					{
						num++;
					}
				}
			}
			return num;
		}
	}
	public static class TerritoryConfig
	{
		public struct FuelTier
		{
			public int Level;

			public string ItemA;

			public int AmountA;

			public string ItemB;

			public int AmountB;

			public string ItemC;

			public int AmountC;

			public float IntervalSeconds;
		}

		public struct UpgradeCostInfo
		{
			public string ItemA;

			public int ItemAAmount;

			public string ItemB;

			public int ItemBAmount;

			public int Coins;
		}

		public static ConfigEntry<bool> AdminBypass;

		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<int> WardLimit;

		public static ConfigEntry<KeyCode> UpgradeKey;

		public static ConfigEntry<KeyCode> ShieldKey;

		public static ConfigEntry<KeyCode> RangeRingKey;

		public static ConfigEntry<KeyCode> FuelStorageKey;

		public static ConfigEntry<float> Lv1Radius;

		public static ConfigEntry<string> Lv1FuelA;

		public static ConfigEntry<int> Lv1FuelAAmount;

		public static ConfigEntry<string> Lv1FuelB;

		public static ConfigEntry<int> Lv1FuelBAmount;

		public static ConfigEntry<float> Lv1IntervalMinutes;

		public static ConfigEntry<float> Lv2Radius;

		public static ConfigEntry<string> Lv2FuelA;

		public static ConfigEntry<int> Lv2FuelAAmount;

		public static ConfigEntry<string> Lv2FuelB;

		public static ConfigEntry<int> Lv2FuelBAmount;

		public static ConfigEntry<float> Lv2IntervalMinutes;

		public static ConfigEntry<float> Lv3Radius;

		public static ConfigEntry<string> Lv3FuelA;

		public static ConfigEntry<int> Lv3FuelAAmount;

		public static ConfigEntry<string> Lv3FuelB;

		public static ConfigEntry<int> Lv3FuelBAmount;

		public static ConfigEntry<float> Lv3IntervalMinutes;

		public static ConfigEntry<float> Lv4Radius;

		public static ConfigEntry<string> Lv4FuelA;

		public static ConfigEntry<int> Lv4FuelAAmount;

		public static ConfigEntry<string> Lv4FuelB;

		public static ConfigEntry<int> Lv4FuelBAmount;

		public static ConfigEntry<float> Lv4IntervalMinutes;

		public static ConfigEntry<float> Lv5Radius;

		public static ConfigEntry<string> Lv5FuelA;

		public static ConfigEntry<int> Lv5FuelAAmount;

		public static ConfigEntry<string> Lv5FuelB;

		public static ConfigEntry<int> Lv5FuelBAmount;

		public static ConfigEntry<float> Lv5IntervalMinutes;

		public static ConfigEntry<float> Lv6Radius;

		public static ConfigEntry<string> Lv6FuelA;

		public static ConfigEntry<int> Lv6FuelAAmount;

		public static ConfigEntry<string> Lv6FuelB;

		public static ConfigEntry<int> Lv6FuelBAmount;

		public static ConfigEntry<string> Lv6FuelC;

		public static ConfigEntry<int> Lv6FuelCAmount;

		public static ConfigEntry<float> Lv6IntervalMinutes;

		public static ConfigEntry<float> Lv7Radius;

		public static ConfigEntry<string> Lv7FuelA;

		public static ConfigEntry<int> Lv7FuelAAmount;

		public static ConfigEntry<string> Lv7FuelB;

		public static ConfigEntry<int> Lv7FuelBAmount;

		public static ConfigEntry<float> Lv7IntervalMinutes;

		public static ConfigEntry<float> Lv8Radius;

		public static ConfigEntry<string> Lv8FuelA;

		public static ConfigEntry<int> Lv8FuelAAmount;

		public static ConfigEntry<string> Lv8FuelB;

		public static ConfigEntry<int> Lv8FuelBAmount;

		public static ConfigEntry<string> Lv8FuelC;

		public static ConfigEntry<int> Lv8FuelCAmount;

		public static ConfigEntry<float> Lv8IntervalMinutes;

		public static ConfigEntry<string> Lv2UpgradeItemA;

		public static ConfigEntry<int> Lv2UpgradeItemAAmount;

		public static ConfigEntry<string> Lv2UpgradeItemB;

		public static ConfigEntry<int> Lv2UpgradeItemBAmount;

		public static ConfigEntry<int> Lv2UpgradeCoins;

		public static ConfigEntry<string> Lv3UpgradeItemA;

		public static ConfigEntry<int> Lv3UpgradeItemAAmount;

		public static ConfigEntry<string> Lv3UpgradeItemB;

		public static ConfigEntry<int> Lv3UpgradeItemBAmount;

		public static ConfigEntry<int> Lv3UpgradeCoins;

		public static ConfigEntry<string> Lv4UpgradeItemA;

		public static ConfigEntry<int> Lv4UpgradeItemAAmount;

		public static ConfigEntry<string> Lv4UpgradeItemB;

		public static ConfigEntry<int> Lv4UpgradeItemBAmount;

		public static ConfigEntry<int> Lv4UpgradeCoins;

		public static ConfigEntry<string> Lv5UpgradeItemA;

		public static ConfigEntry<int> Lv5UpgradeItemAAmount;

		public static ConfigEntry<string> Lv5UpgradeItemB;

		public static ConfigEntry<int> Lv5UpgradeItemBAmount;

		public static ConfigEntry<int> Lv5UpgradeCoins;

		public static ConfigEntry<string> Lv6UpgradeItemA;

		public static ConfigEntry<int> Lv6UpgradeItemAAmount;

		public static ConfigEntry<string> Lv6UpgradeItemB;

		public static ConfigEntry<int> Lv6UpgradeItemBAmount;

		public static ConfigEntry<int> Lv6UpgradeCoins;

		public static ConfigEntry<string> Lv7UpgradeItemA;

		public static ConfigEntry<int> Lv7UpgradeItemAAmount;

		public static ConfigEntry<string> Lv7UpgradeItemB;

		public static ConfigEntry<int> Lv7UpgradeItemBAmount;

		public static ConfigEntry<int> Lv7UpgradeCoins;

		public static ConfigEntry<string> Lv8UpgradeItemA;

		public static ConfigEntry<int> Lv8UpgradeItemAAmount;

		public static ConfigEntry<string> Lv8UpgradeItemB;

		public static ConfigEntry<int> Lv8UpgradeItemBAmount;

		public static ConfigEntry<int> Lv8UpgradeCoins;

		public static ConfigEntry<bool> DoorAutoCloseEnabled;

		public static ConfigEntry<float> DoorAutoCloseDelay;

		public static ConfigEntry<string> ShieldItemName;

		public static void Init(ConfigFile cfg)
		{
			AdminBypass = B<bool>("General", "admin_bypass", def: false, "관리자 전용: 켜면 설치 개수 제한·설치 재료비·업그레이드 재료/골드 비용을 모두 무시하고 즉시 설치·업그레이드할 수 있습니다 (연료 유지비는 그대로 적용됩니다).", 200);
			Enabled = B<bool>("General", "territorial_ward", def: true, "영토 와드 시스템 활성화 여부 (false = 비활성화)", 190);
			WardLimit = B<int>("General", "ward_limit", 2, "캐릭터 1명당 설치 가능한 영토 와드 수", 180);
			DoorAutoCloseEnabled = B<bool>("General", "door_auto_close", def: true, "와드 구역 내 문 자동 닫힘 활성화", 170);
			DoorAutoCloseDelay = B<float>("General", "door_auto_close_delay", 5f, "문 자동 닫힘 대기 시간 (초)", 160);
			ShieldItemName = B<string>("General", "shield_item", "SurtlingCore", "Lv5+ 데미지 보호 소모 아이템 (프리팹명)", 150);
			UpgradeKey = B<KeyCode>("General", "upgrade_key", (KeyCode)117, "영토 와드 업그레이드 키", 140);
			ShieldKey = B<KeyCode>("General", "shield_key", (KeyCode)107, "Lv5+ 영토 보호 실드 활성화/비활성화 키", 130);
			RangeRingKey = B<KeyCode>("General", "range_ring_key", (KeyCode)114, "범위 링 수동 토글 키", 120);
			FuelStorageKey = B<KeyCode>("General", "fuel_storage_key", (KeyCode)113, "연료 창고 열기 키", 110);
			Lv1Radius = B<float>("Level 1 - 초원", "radius", 10f, "레벨 1 반경 (미터)", 100);
			Lv1FuelA = B<string>("Level 1 - 초원", "fuel_primary", "Wood", "레벨 1 주 연료 — 나무 (프리팹명)", 90);
			Lv1FuelAAmount = B<int>("Level 1 - 초원", "fuel_primary_amount", 1, "레벨 1 주 연료 소모량", 89);
			Lv1FuelB = B<string>("Level 1 - 초원", "fuel_secondary", "Resin", "레벨 1 보조 연료 — 수지 (프리팹명)", 88);
			Lv1FuelBAmount = B<int>("Level 1 - 초원", "fuel_secondary_amount", 1, "레벨 1 보조 연료 소모량", 87);
			Lv1IntervalMinutes = B<float>("Level 1 - 초원", "fuel_interval_minutes", 3f, "레벨 1 연료 소모 간격 (분)", 80);
			Lv1Radius.SettingChanged += delegate
			{
				TerritoryLocalization.RefreshWardDescription();
			};
			Lv1FuelA.SettingChanged += delegate
			{
				TerritoryLocalization.RefreshWardDescription();
			};
			Lv1FuelAAmount.SettingChanged += delegate
			{
				TerritoryLocalization.RefreshWardDescription();
			};
			Lv1FuelB.SettingChanged += delegate
			{
				TerritoryLocalization.RefreshWardDescription();
			};
			Lv1FuelBAmount.SettingChanged += delegate
			{
				TerritoryLocalization.RefreshWardDescription();
			};
			Lv1IntervalMinutes.SettingChanged += delegate
			{
				TerritoryLocalization.RefreshWardDescription();
			};
			Lv2Radius = B<float>("Level 2 - 검은숲", "radius", 13f, "레벨 2 반경 (미터)", 100);
			Lv2FuelA = B<string>("Level 2 - 검은숲", "fuel_primary", "RoundLog", "레벨 2 주 연료 — 원목 (프리팹명)", 90);
			Lv2FuelAAmount = B<int>("Level 2 - 검은숲", "fuel_primary_amount", 1, "레벨 2 주 연료 소모량", 89);
			Lv2FuelB = B<string>("Level 2 - 검은숲", "fuel_secondary", "Resin", "레벨 2 보조 연료 — 수지 (프리팹명)", 88);
			Lv2FuelBAmount = B<int>("Level 2 - 검은숲", "fuel_secondary_amount", 1, "레벨 2 보조 연료 소모량", 87);
			Lv2IntervalMinutes = B<float>("Level 2 - 검은숲", "fuel_interval_minutes", 4f, "레벨 2 연료 소모 간격 (분)", 80);
			Lv2UpgradeItemA = B<string>("Level 2 - 검은숲", "upgrade_item_primary", "RoundLog", "Lv2 업그레이드 주 재료 (원목)", 70);
			Lv2UpgradeItemAAmount = B<int>("Level 2 - 검은숲", "upgrade_item_primary_amount", 10, "Lv2 업그레이드 주 재료 수량", 69);
			Lv2UpgradeItemB = B<string>("Level 2 - 검은숲", "upgrade_item_secondary", "GreydwarfEye", "Lv2 업그레이드 보조 재료 (그레이드워프 눈)", 68);
			Lv2UpgradeItemBAmount = B<int>("Level 2 - 검은숲", "upgrade_item_secondary_amount", 5, "Lv2 업그레이드 보조 재료 수량", 67);
			Lv2UpgradeCoins = B<int>("Level 2 - 검은숲", "upgrade_coins", 0, "Lv2 업그레이드 골드(Coins) 비용", 60);
			Lv3Radius = B<float>("Level 3 - 늪지", "radius", 16f, "레벨 3 반경 (미터)", 100);
			Lv3FuelA = B<string>("Level 3 - 늪지", "fuel_primary", "ElderBark", "레벨 3 주 연료 — 고대나무껍질 (프리팹명)", 90);
			Lv3FuelAAmount = B<int>("Level 3 - 늪지", "fuel_primary_amount", 2, "레벨 3 주 연료 소모량", 89);
			Lv3FuelB = B<string>("Level 3 - 늪지", "fuel_secondary", "Resin", "레벨 3 보조 연료 — 수지 (프리팹명)", 88);
			Lv3FuelBAmount = B<int>("Level 3 - 늪지", "fuel_secondary_amount", 1, "레벨 3 보조 연료 소모량", 87);
			Lv3IntervalMinutes = B<float>("Level 3 - 늪지", "fuel_interval_minutes", 5f, "레벨 3 연료 소모 간격 (분)", 80);
			Lv3UpgradeItemA = B<string>("Level 3 - 늪지", "upgrade_item_primary", "ElderBark", "Lv3 업그레이드 주 재료 (고대나무껍질)", 70);
			Lv3UpgradeItemAAmount = B<int>("Level 3 - 늪지", "upgrade_item_primary_amount", 15, "Lv3 업그레이드 주 재료 수량", 69);
			Lv3UpgradeItemB = B<string>("Level 3 - 늪지", "upgrade_item_secondary", "Entrails", "Lv3 업그레이드 보조 재료 (창자)", 68);
			Lv3UpgradeItemBAmount = B<int>("Level 3 - 늪지", "upgrade_item_secondary_amount", 8, "Lv3 업그레이드 보조 재료 수량", 67);
			Lv3UpgradeCoins = B<int>("Level 3 - 늪지", "upgrade_coins", 1000, "Lv3 업그레이드 골드(Coins) 비용", 60);
			Lv4Radius = B<float>("Level 4 - 산", "radius", 19f, "레벨 4 반경 (미터)", 100);
			Lv4FuelA = B<string>("Level 4 - 산", "fuel_primary", "Obsidian", "레벨 4 주 연료 — 흑요석 (산에는 지역 나무가 없어 대체) (프리팹명)", 90);
			Lv4FuelAAmount = B<int>("Level 4 - 산", "fuel_primary_amount", 2, "레벨 4 주 연료 소모량", 89);
			Lv4FuelB = B<string>("Level 4 - 산", "fuel_secondary", "Resin", "레벨 4 보조 연료 — 수지 (프리팹명)", 88);
			Lv4FuelBAmount = B<int>("Level 4 - 산", "fuel_secondary_amount", 1, "레벨 4 보조 연료 소모량", 87);
			Lv4IntervalMinutes = B<float>("Level 4 - 산", "fuel_interval_minutes", 6f, "레벨 4 연료 소모 간격 (분)", 80);
			Lv4UpgradeItemA = B<string>("Level 4 - 산", "upgrade_item_primary", "FreezeGland", "Lv4 업그레이드 주 재료 (얼음 분비선)", 70);
			Lv4UpgradeItemAAmount = B<int>("Level 4 - 산", "upgrade_item_primary_amount", 20, "Lv4 업그레이드 주 재료 수량", 69);
			Lv4UpgradeItemB = B<string>("Level 4 - 산", "upgrade_item_secondary", "Obsidian", "Lv4 업그레이드 보조 재료 (흑요석)", 68);
			Lv4UpgradeItemBAmount = B<int>("Level 4 - 산", "upgrade_item_secondary_amount", 11, "Lv4 업그레이드 보조 재료 수량", 67);
			Lv4UpgradeCoins = B<int>("Level 4 - 산", "upgrade_coins", 2000, "Lv4 업그레이드 골드(Coins) 비용", 60);
			Lv5Radius = B<float>("Level 5 - 평원", "radius", 22f, "레벨 5 반경 (미터)", 100);
			Lv5FuelA = B<string>("Level 5 - 평원", "fuel_primary", "FineWood", "레벨 5 주 연료 — 경목 (프리팹명)", 90);
			Lv5FuelAAmount = B<int>("Level 5 - 평원", "fuel_primary_amount", 3, "레벨 5 주 연료 소모량", 89);
			Lv5FuelB = B<string>("Level 5 - 평원", "fuel_secondary", "Resin", "레벨 5 보조 연료 — 수지 (프리팹명)", 88);
			Lv5FuelBAmount = B<int>("Level 5 - 평원", "fuel_secondary_amount", 1, "레벨 5 보조 연료 소모량", 87);
			Lv5IntervalMinutes = B<float>("Level 5 - 평원", "fuel_interval_minutes", 7f, "레벨 5 연료 소모 간격 (분)", 80);
			Lv5UpgradeItemA = B<string>("Level 5 - 평원", "upgrade_item_primary", "Barley", "Lv5 업그레이드 주 재료 (보리)", 70);
			Lv5UpgradeItemAAmount = B<int>("Level 5 - 평원", "upgrade_item_primary_amount", 25, "Lv5 업그레이드 주 재료 수량", 69);
			Lv5UpgradeItemB = B<string>("Level 5 - 평원", "upgrade_item_secondary", "Tar", "Lv5 업그레이드 보조 재료 (타르)", 68);
			Lv5UpgradeItemBAmount = B<int>("Level 5 - 평원", "upgrade_item_secondary_amount", 14, "Lv5 업그레이드 보조 재료 수량", 67);
			Lv5UpgradeCoins = B<int>("Level 5 - 평원", "upgrade_coins", 2500, "Lv5 업그레이드 골드(Coins) 비용", 60);
			Lv6Radius = B<float>("Level 6 - 바다", "radius", 25f, "레벨 6 반경 (미터)", 100);
			Lv6FuelA = B<string>("Level 6 - 바다", "fuel_primary", "Wood", "레벨 6 주 연료 — 나무 (바다에는 지역 나무가 없어 나무+원목으로 대체) (프리팹명)", 90);
			Lv6FuelAAmount = B<int>("Level 6 - 바다", "fuel_primary_amount", 2, "레벨 6 주 연료 소모량", 89);
			Lv6FuelB = B<string>("Level 6 - 바다", "fuel_secondary", "Resin", "레벨 6 보조 연료 — 수지 (프리팹명)", 88);
			Lv6FuelBAmount = B<int>("Level 6 - 바다", "fuel_secondary_amount", 1, "레벨 6 보조 연료 소모량", 87);
			Lv6FuelC = B<string>("Level 6 - 바다", "fuel_tertiary", "RoundLog", "레벨 6 추가 연료 — 원목 (프리팹명, 비워두면 미사용)", 86);
			Lv6FuelCAmount = B<int>("Level 6 - 바다", "fuel_tertiary_amount", 1, "레벨 6 추가 연료 소모량", 85);
			Lv6IntervalMinutes = B<float>("Level 6 - 바다", "fuel_interval_minutes", 8f, "레벨 6 연료 소모 간격 (분)", 80);
			Lv6UpgradeItemA = B<string>("Level 6 - 바다", "upgrade_item_primary", "Chitin", "Lv6 업그레이드 주 재료 (키틴)", 70);
			Lv6UpgradeItemAAmount = B<int>("Level 6 - 바다", "upgrade_item_primary_amount", 30, "Lv6 업그레이드 주 재료 수량", 69);
			Lv6UpgradeItemB = B<string>("Level 6 - 바다", "upgrade_item_secondary", "Ooze", "Lv6 업그레이드 보조 재료 (점액)", 68);
			Lv6UpgradeItemBAmount = B<int>("Level 6 - 바다", "upgrade_item_secondary_amount", 17, "Lv6 업그레이드 보조 재료 수량", 67);
			Lv6UpgradeCoins = B<int>("Level 6 - 바다", "upgrade_coins", 3000, "Lv6 업그레이드 골드(Coins) 비용", 60);
			Lv7Radius = B<float>("Level 7 - 미스트랜드", "radius", 28f, "레벨 7 반경 (미터)", 100);
			Lv7FuelA = B<string>("Level 7 - 미스트랜드", "fuel_primary", "YggdrasilWood", "레벨 7 주 연료 — 이그드라실 나무 (프리팹명)", 90);
			Lv7FuelAAmount = B<int>("Level 7 - 미스트랜드", "fuel_primary_amount", 4, "레벨 7 주 연료 소모량", 89);
			Lv7FuelB = B<string>("Level 7 - 미스트랜드", "fuel_secondary", "Resin", "레벨 7 보조 연료 — 수지 (프리팹명)", 88);
			Lv7FuelBAmount = B<int>("Level 7 - 미스트랜드", "fuel_secondary_amount", 1, "레벨 7 보조 연료 소모량", 87);
			Lv7IntervalMinutes = B<float>("Level 7 - 미스트랜드", "fuel_interval_minutes", 9f, "레벨 7 연료 소모 간격 (분)", 80);
			Lv7UpgradeItemA = B<string>("Level 7 - 미스트랜드", "upgrade_item_primary", "YggdrasilWood", "Lv7 업그레이드 주 재료 (이그드라실 나무)", 70);
			Lv7UpgradeItemAAmount = B<int>("Level 7 - 미스트랜드", "upgrade_item_primary_amount", 35, "Lv7 업그레이드 주 재료 수량", 69);
			Lv7UpgradeItemB = B<string>("Level 7 - 미스트랜드", "upgrade_item_secondary", "JotunPuffs", "Lv7 업그레이드 보조 재료 (요툰 버섯)", 68);
			Lv7UpgradeItemBAmount = B<int>("Level 7 - 미스트랜드", "upgrade_item_secondary_amount", 20, "Lv7 업그레이드 보조 재료 수량", 67);
			Lv7UpgradeCoins = B<int>("Level 7 - 미스트랜드", "upgrade_coins", 4000, "Lv7 업그레이드 골드(Coins) 비용", 60);
			Lv8Radius = B<float>("Level 8 - 애쉬랜드", "radius", 30f, "레벨 8 반경 (미터)", 100);
			Lv8FuelA = B<string>("Level 8 - 애쉬랜드", "fuel_primary", "Wood", "레벨 8 주 연료 — 나무 (애쉬랜드에는 지역 나무가 없어 나무+이그드라실 나무로 대체) (프리팹명)", 90);
			Lv8FuelAAmount = B<int>("Level 8 - 애쉬랜드", "fuel_primary_amount", 3, "레벨 8 주 연료 소모량", 89);
			Lv8FuelB = B<string>("Level 8 - 애쉬랜드", "fuel_secondary", "Resin", "레벨 8 보조 연료 — 수지 (프리팹명)", 88);
			Lv8FuelBAmount = B<int>("Level 8 - 애쉬랜드", "fuel_secondary_amount", 1, "레벨 8 보조 연료 소모량", 87);
			Lv8FuelC = B<string>("Level 8 - 애쉬랜드", "fuel_tertiary", "YggdrasilWood", "레벨 8 추가 연료 — 이그드라실 나무 (프리팹명, 비워두면 미사용)", 86);
			Lv8FuelCAmount = B<int>("Level 8 - 애쉬랜드", "fuel_tertiary_amount", 1, "레벨 8 추가 연료 소모량", 85);
			Lv8IntervalMinutes = B<float>("Level 8 - 애쉬랜드", "fuel_interval_minutes", 10f, "레벨 8 연료 소모 간격 (분)", 80);
			Lv8UpgradeItemA = B<string>("Level 8 - 애쉬랜드", "upgrade_item_primary", "CharredBone", "Lv8 업그레이드 주 재료 (불탄 뼈)", 70);
			Lv8UpgradeItemAAmount = B<int>("Level 8 - 애쉬랜드", "upgrade_item_primary_amount", 40, "Lv8 업그레이드 주 재료 수량", 69);
			Lv8UpgradeItemB = B<string>("Level 8 - 애쉬랜드", "upgrade_item_secondary", "Grausten", "Lv8 업그레이드 보조 재료 (그라우스텐 돌)", 68);
			Lv8UpgradeItemBAmount = B<int>("Level 8 - 애쉬랜드", "upgrade_item_secondary_amount", 23, "Lv8 업그레이드 보조 재료 수량", 67);
			Lv8UpgradeCoins = B<int>("Level 8 - 애쉬랜드", "upgrade_coins", 5000, "Lv8 업그레이드 골드(Coins) 비용", 60);
			ConfigEntry<T> B<T>(string section, string key, T def, string desc, int order = 0)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_0019: Unknown result type (might be due to invalid IL or missing references)
				//IL_0021: Unknown result type (might be due to invalid IL or missing references)
				//IL_002f: Expected O, but got Unknown
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Expected O, but got Unknown
				return cfg.Bind<T>(section, key, def, new ConfigDescription(desc, (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					IsAdminOnly = true,
					Order = order
				} }));
			}
		}

		public static float GetRadius(int level)
		{
			return level switch
			{
				2 => Lv2Radius.Value, 
				3 => Lv3Radius.Value, 
				4 => Lv4Radius.Value, 
				5 => Lv5Radius.Value, 
				6 => Lv6Radius.Value, 
				7 => Lv7Radius.Value, 
				8 => Lv8Radius.Value, 
				_ => Lv1Radius.Value, 
			};
		}

		private static FuelTier GetTier(int level)
		{
			return level switch
			{
				2 => new FuelTier
				{
					Level = 2,
					ItemA = Lv2FuelA.Value,
					AmountA = Lv2FuelAAmount.Value,
					ItemB = Lv2FuelB.Value,
					AmountB = Lv2FuelBAmount.Value,
					IntervalSeconds = Lv2IntervalMinutes.Value * 60f
				}, 
				3 => new FuelTier
				{
					Level = 3,
					ItemA = Lv3FuelA.Value,
					AmountA = Lv3FuelAAmount.Value,
					ItemB = Lv3FuelB.Value,
					AmountB = Lv3FuelBAmount.Value,
					IntervalSeconds = Lv3IntervalMinutes.Value * 60f
				}, 
				4 => new FuelTier
				{
					Level = 4,
					ItemA = Lv4FuelA.Value,
					AmountA = Lv4FuelAAmount.Value,
					ItemB = Lv4FuelB.Value,
					AmountB = Lv4FuelBAmount.Value,
					IntervalSeconds = Lv4IntervalMinutes.Value * 60f
				}, 
				5 => new FuelTier
				{
					Level = 5,
					ItemA = Lv5FuelA.Value,
					AmountA = Lv5FuelAAmount.Value,
					ItemB = Lv5FuelB.Value,
					AmountB = Lv5FuelBAmount.Value,
					IntervalSeconds = Lv5IntervalMinutes.Value * 60f
				}, 
				6 => new FuelTier
				{
					Level = 6,
					ItemA = Lv6FuelA.Value,
					AmountA = Lv6FuelAAmount.Value,
					ItemB = Lv6FuelB.Value,
					AmountB = Lv6FuelBAmount.Value,
					ItemC = Lv6FuelC.Value,
					AmountC = Lv6FuelCAmount.Value,
					IntervalSeconds = Lv6IntervalMinutes.Value * 60f
				}, 
				7 => new FuelTier
				{
					Level = 7,
					ItemA = Lv7FuelA.Value,
					AmountA = Lv7FuelAAmount.Value,
					ItemB = Lv7FuelB.Value,
					AmountB = Lv7FuelBAmount.Value,
					IntervalSeconds = Lv7IntervalMinutes.Value * 60f
				}, 
				8 => new FuelTier
				{
					Level = 8,
					ItemA = Lv8FuelA.Value,
					AmountA = Lv8FuelAAmount.Value,
					ItemB = Lv8FuelB.Value,
					AmountB = Lv8FuelBAmount.Value,
					ItemC = Lv8FuelC.Value,
					AmountC = Lv8FuelCAmount.Value,
					IntervalSeconds = Lv8IntervalMinutes.Value * 60f
				}, 
				_ => new FuelTier
				{
					Level = 1,
					ItemA = Lv1FuelA.Value,
					AmountA = Lv1FuelAAmount.Value,
					ItemB = Lv1FuelB.Value,
					AmountB = Lv1FuelBAmount.Value,
					IntervalSeconds = Lv1IntervalMinutes.Value * 60f
				}, 
			};
		}

		public static List<FuelTier> GetFuelTiers(int uptoLevel)
		{
			List<FuelTier> list = new List<FuelTier>(2) { GetTier(1) };
			if (uptoLevel > 1)
			{
				list.Add(GetTier(uptoLevel));
			}
			return list;
		}

		public static UpgradeCostInfo GetUpgradeCost(int targetLevel)
		{
			return targetLevel switch
			{
				2 => new UpgradeCostInfo
				{
					ItemA = Lv2UpgradeItemA.Value,
					ItemAAmount = Lv2UpgradeItemAAmount.Value,
					ItemB = Lv2UpgradeItemB.Value,
					ItemBAmount = Lv2UpgradeItemBAmount.Value,
					Coins = Lv2UpgradeCoins.Value
				}, 
				3 => new UpgradeCostInfo
				{
					ItemA = Lv3UpgradeItemA.Value,
					ItemAAmount = Lv3UpgradeItemAAmount.Value,
					ItemB = Lv3UpgradeItemB.Value,
					ItemBAmount = Lv3UpgradeItemBAmount.Value,
					Coins = Lv3UpgradeCoins.Value
				}, 
				4 => new UpgradeCostInfo
				{
					ItemA = Lv4UpgradeItemA.Value,
					ItemAAmount = Lv4UpgradeItemAAmount.Value,
					ItemB = Lv4UpgradeItemB.Value,
					ItemBAmount = Lv4UpgradeItemBAmount.Value,
					Coins = Lv4UpgradeCoins.Value
				}, 
				5 => new UpgradeCostInfo
				{
					ItemA = Lv5UpgradeItemA.Value,
					ItemAAmount = Lv5UpgradeItemAAmount.Value,
					ItemB = Lv5UpgradeItemB.Value,
					ItemBAmount = Lv5UpgradeItemBAmount.Value,
					Coins = Lv5UpgradeCoins.Value
				}, 
				6 => new UpgradeCostInfo
				{
					ItemA = Lv6UpgradeItemA.Value,
					ItemAAmount = Lv6UpgradeItemAAmount.Value,
					ItemB = Lv6UpgradeItemB.Value,
					ItemBAmount = Lv6UpgradeItemBAmount.Value,
					Coins = Lv6UpgradeCoins.Value
				}, 
				7 => new UpgradeCostInfo
				{
					ItemA = Lv7UpgradeItemA.Value,
					ItemAAmount = Lv7UpgradeItemAAmount.Value,
					ItemB = Lv7UpgradeItemB.Value,
					ItemBAmount = Lv7UpgradeItemBAmount.Value,
					Coins = Lv7UpgradeCoins.Value
				}, 
				8 => new UpgradeCostInfo
				{
					ItemA = Lv8UpgradeItemA.Value,
					ItemAAmount = Lv8UpgradeItemAAmount.Value,
					ItemB = Lv8UpgradeItemB.Value,
					ItemBAmount = Lv8UpgradeItemBAmount.Value,
					Coins = Lv8UpgradeCoins.Value
				}, 
				_ => default(UpgradeCostInfo), 
			};
		}
	}
	[HarmonyPatch(typeof(DamageText), "AddInworldText")]
	public static class Patch_DamageText_RichText
	{
		internal static readonly HashSet<TMP_Text> SlowRiseFields = new HashSet<TMP_Text>();

		private static void Postfix(DamageText __instance, string text)
		{
			if (!string.IsNullOrEmpty(text) && text.Contains("<color=") && __instance.m_worldTexts.Count != 0)
			{
				WorldTextInstance val = __instance.m_worldTexts[__instance.m_worldTexts.Count - 1];
				val.m_textField.richText = true;
				SlowRiseFields.Add(val.m_textField);
			}
		}
	}
	[HarmonyPatch(typeof(DamageText), "UpdateWorldTexts")]
	public static class Patch_DamageText_SlowRise
	{
		private const float SpeedFactor = 1f / 3f;

		private static void Postfix(DamageText __instance, float dt)
		{
			if (Patch_DamageText_RichText.SlowRiseFields.Count == 0)
			{
				return;
			}
			foreach (WorldTextInstance worldText in __instance.m_worldTexts)
			{
				if (Patch_DamageText_RichText.SlowRiseFields.Contains(worldText.m_textField))
				{
					worldText.m_worldPos.y -= dt * 0.6666666f;
					if (worldText.m_timer > __instance.m_textDuration)
					{
						Patch_DamageText_RichText.SlowRiseFields.Remove(worldText.m_textField);
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(Door), "Interact")]
	public static class Patch_Door_AutoClose
	{
		private static void Postfix(Door __instance)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			if (TerritoryConfig.DoorAutoCloseEnabled.Value && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsOwner() && __instance.m_nview.GetZDO().GetInt("state", 0) != 0 && TerritoryWard.IsInsideActiveWard(((Component)__instance).transform.position))
			{
				((MonoBehaviour)__instance).StartCoroutine(AutoCloseRoutine(__instance));
			}
		}

		private static IEnumerator AutoCloseRoutine(Door door)
		{
			yield return (object)new WaitForSeconds(TerritoryConfig.DoorAutoCloseDelay.Value);
			if (!((Object)(object)door == (Object)null) && !((Object)(object)door.m_nview == (Object)null) && door.m_nview.IsValid() && door.m_nview.GetZDO().GetInt("state", 0) != 0 && TerritoryWard.IsInsideActiveWard(((Component)door).transform.position))
			{
				door.m_nview.InvokeRPC(ZNetView.Everybody, "UseDoor", new object[1] { false });
			}
		}
	}
	[HarmonyPatch(typeof(Player), "Interact")]
	public static class Patch_Player_Interact
	{
		private static bool Prefix(Player __instance, GameObject go)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)go == (Object)null)
			{
				return true;
			}
			if (((Object)((Component)go.transform.root).gameObject).name.Contains("territoryward"))
			{
				return true;
			}
			Vector3 position = go.transform.position;
			if (TerritoryWard.IsInsideDeactivatedWard(position))
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_off_blocked", 0, (Sprite)null);
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Inventory), "AddItem", new Type[]
	{
		typeof(ItemData),
		typeof(int),
		typeof(int),
		typeof(int)
	})]
	public static class Patch_Inventory_AddItem_MaxStack
	{
		private static void Prefix(Inventory __instance, ItemData item, out int __state)
		{
			__state = item.m_shared.m_maxStackSize;
			if (WardInventoryHelper.IsWardStorage(__instance) && WardInventoryHelper.IsWardFuel(item.m_shared.m_name))
			{
				item.m_shared.m_maxStackSize = 999;
			}
		}

		private static void Postfix(ItemData item, int __state)
		{
			item.m_shared.m_maxStackSize = __state;
		}
	}
	[HarmonyPatch(typeof(Inventory), "CanAddItem", new Type[]
	{
		typeof(ItemData),
		typeof(int)
	})]
	public static class Patch_Inventory_CanAddItem_MaxStack
	{
		private static void Prefix(Inventory __instance, ItemData item, out int __state)
		{
			__state = item.m_shared.m_maxStackSize;
			if (WardInventoryHelper.IsWardStorage(__instance) && WardInventoryHelper.IsWardFuel(item.m_shared.m_name))
			{
				item.m_shared.m_maxStackSize = 999;
			}
		}

		private static void Postfix(ItemData item, int __state)
		{
			item.m_shared.m_maxStackSize = __state;
		}
	}
	[HarmonyPatch(typeof(PrivateArea), "Interact")]
	public static class Patch_PrivateArea_PermittedToggle
	{
		private static bool Prefix(PrivateArea __instance, Humanoid human, bool hold, bool alt)
		{
			if (!((Object)((Component)__instance).gameObject).name.Contains("territoryward"))
			{
				return true;
			}
			if (hold)
			{
				return true;
			}
			if (alt || Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303))
			{
				return false;
			}
			if (__instance.m_piece.IsCreator())
			{
				return true;
			}
			Player val = (Player)(object)((human is Player) ? human : null);
			if ((Object)(object)val == (Object)null)
			{
				return true;
			}
			if (__instance.IsPermitted(val.GetPlayerID()))
			{
				__instance.m_nview.InvokeRPC("ToggleEnabled", new object[1] { val.GetPlayerID() });
			}
			else
			{
				__instance.m_nview.InvokeRPC("TogglePermitted", new object[2]
				{
					val.GetPlayerID(),
					val.GetPlayerName()
				});
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(PrivateArea), "RPC_ToggleEnabled")]
	public static class Patch_PrivateArea_RPC_ToggleEnabled
	{
		private static bool Prefix(PrivateArea __instance, long uid, long playerID)
		{
			if (!((Object)((Component)__instance).gameObject).name.Contains("territoryward"))
			{
				return true;
			}
			if (!__instance.m_nview.IsOwner())
			{
				return true;
			}
			if (__instance.m_piece.GetCreator() == playerID)
			{
				return true;
			}
			if (!__instance.IsPermitted(playerID))
			{
				return true;
			}
			__instance.SetEnabled(!__instance.IsEnabled());
			return false;
		}
	}
	[HarmonyPatch(typeof(PrivateArea), "RPC_TogglePermitted")]
	public static class Patch_PrivateArea_RPC_TogglePermitted
	{
		private static bool Prefix(PrivateArea __instance, long uid, long playerID, string name)
		{
			if (!((Object)((Component)__instance).gameObject).name.Contains("territoryward"))
			{
				return true;
			}
			if (!__instance.m_nview.IsOwner())
			{
				return true;
			}
			if (__instance.m_piece.GetCreator() == uid)
			{
				return true;
			}
			FieldInfo field = typeof(PrivateArea).GetField("m_permittedPlayers", BindingFlags.Instance | BindingFlags.NonPublic);
			if (field == null)
			{
				return true;
			}
			if (!(field.GetValue(__instance) is List<KeyValuePair<long, string>> list))
			{
				return true;
			}
			int num = list.FindIndex((KeyValuePair<long, string> kv) => kv.Key == playerID);
			if (num >= 0)
			{
				list.RemoveAt(num);
			}
			else
			{
				list.Add(new KeyValuePair<long, string>(playerID, name));
			}
			typeof(PrivateArea).GetMethod("Save", BindingFlags.Instance | BindingFlags.NonPublic)?.Invoke(__instance, null);
			return false;
		}
	}
	[HarmonyPatch(typeof(PrivateArea), "GetHoverText")]
	public static class Patch_PrivateArea_HoverText
	{
		private const string Cyan = "#00FFFF";

		private const string Yellow = "yellow";

		private static void Postfix(PrivateArea __instance, ref string __result)
		{
			//IL_026c: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_045c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_052c: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)((Component)__instance).gameObject).name.Contains("territoryward"))
			{
				return;
			}
			TerritoryWardController component = ((Component)__instance).GetComponent<TerritoryWardController>();
			ZNetView val = component?.m_nview ?? ((Component)__instance).GetComponent<ZNetView>();
			int num = 1;
			if ((Object)(object)val != (Object)null && val.IsValid())
			{
				num = val.GetZDO().GetInt("tw_level", 1);
			}
			string arg = (__instance.IsEnabled() ? "<color=green>활성화</color>" : "<color=red>비활성화</color>");
			Player localPlayer = Player.m_localPlayer;
			bool flag = (Object)(object)localPlayer != (Object)null && __instance.m_piece.IsCreator();
			bool flag2 = (Object)(object)localPlayer != (Object)null && (Object)(object)val != (Object)null && val.IsValid() && __instance.IsPermitted(localPlayer.GetPlayerID());
			string text = Localization.instance.Localize("$KEY_Use");
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(string.Format("<size=22><b>[ 영토 와드 <color={0}>Lv{1}</color>({2}) ]</b></size>", "#00FFFF", num, arg));
			if ((Object)(object)component != (Object)null)
			{
				stringBuilder.Append("\n<color=yellow>연료</color> : " + component.GetFuelInfoText());
			}
			stringBuilder.Append(string.Format("\n<color={0}>범위</color> : {1:0}m", "yellow", __instance.m_radius));
			stringBuilder.Append("\n");
			object obj;
			if (val == null)
			{
				obj = null;
			}
			else
			{
				ZDO zDO = val.GetZDO();
				obj = ((zDO != null) ? zDO.GetString("creatorName", "???") : null);
			}
			if (obj == null)
			{
				obj = "???";
			}
			string text2 = (string)obj;
			string permittedNamesString = GetPermittedNamesString(__instance, val);
			stringBuilder.Append("\n<color=yellow>소유자</color> : <color=green>" + text2 + "</color>");
			stringBuilder.Append("\n<color=yellow>허용됨</color> : <color=#4FC3F7>" + permittedNamesString + "</color>");
			stringBuilder.Append("\n");
			if (flag || flag2)
			{
				stringBuilder.Append("\n[<color=yellow><b>" + text + "</b></color>] 와드 활성화 / 비활성화");
				if (flag2 && !flag)
				{
					stringBuilder.Append("\n[<color=yellow><b>Shift+" + text + "</b></color>] 멤버 탈퇴");
				}
			}
			else
			{
				stringBuilder.Append("\n[<color=yellow><b>" + text + "</b></color>] 멤버 가입");
				stringBuilder.Append("\n[<color=yellow><b>Shift+" + text + "</b></color>] 멤버 탈퇴");
			}
			stringBuilder.Append(string.Format("\n[<color={0}><b>{1}</b></color>] $territoryward_fuel_hint", "yellow", TerritoryConfig.FuelStorageKey.Value));
			stringBuilder.Append("\n");
			stringBuilder.Append(string.Format("\n[<color={0}><b>{1}</b></color>] $territoryward_upgrade_hint_key", "yellow", TerritoryConfig.UpgradeKey.Value));
			if ((Object)(object)component != (Object)null)
			{
				if (num < 8)
				{
					float? nextLevelRadius = component.GetNextLevelRadius();
					stringBuilder.Append(string.Format(" <color={0}>Lv{1}</color>→<color={2}><b>Lv{3}</b></color>", "#00FFFF", num, "#00FFFF", num + 1));
					stringBuilder.Append("\n<color=yellow>재료</color> : " + component.GetUpgradeRequirementText());
					if (nextLevelRadius.HasValue)
					{
						stringBuilder.Append(string.Format("\n<color={0}>범위</color> : {1:0}m", "yellow", nextLevelRadius.Value));
					}
					stringBuilder.Append("\n<color=yellow>연료</color> : " + component.GetNextLevelFuelInfoText());
					string nextLevelFullFuelText = component.GetNextLevelFullFuelText();
					if (!string.IsNullOrEmpty(nextLevelFullFuelText))
					{
						stringBuilder.Append(string.Format("\n<color={0}>Lv1/Lv{1} 연료</color> :", "yellow", num + 1));
						stringBuilder.Append("\n" + nextLevelFullFuelText);
					}
				}
				else
				{
					stringBuilder.Append(" $territoryward_max_level");
				}
			}
			if (num >= 5 && (Object)(object)component != (Object)null)
			{
				if (component.IsShielded())
				{
					int num2 = Mathf.CeilToInt(component.GetShieldRemainingMinutes());
					string text3 = Localization.instance.Localize("$territoryward_shield_active", new string[1] { num2.ToString() });
					stringBuilder.Append("\n<color=#00FFFF>[" + text3 + "]</color>");
					if (flag)
					{
						stringBuilder.Append(string.Format("\n[<color={0}><b>{1}</b></color>] $territoryward_shield_deactivate_hint_key", "yellow", TerritoryConfig.ShieldKey.Value));
					}
				}
				else if (flag)
				{
					float shieldBankedRemainingMinutes = component.GetShieldBankedRemainingMinutes();
					if (shieldBankedRemainingMinutes > 0f)
					{
						int num3 = Mathf.CeilToInt(shieldBankedRemainingMinutes);
						string arg2 = Localization.instance.Localize("$territoryward_shield_resume_hint", new string[1] { num3.ToString() });
						stringBuilder.Append(string.Format("\n[<color={0}><b>{1}</b></color>] {2}", "yellow", TerritoryConfig.ShieldKey.Value, arg2));
					}
					else
					{
						string arg3 = Localization.instance.Localize(TerritoryWardController.Resolve(TerritoryConfig.ShieldItemName.Value) ?? TerritoryConfig.ShieldItemName.Value);
						stringBuilder.Append(string.Format("\n[<color={0}><b>{1}</b></color>] $territoryward_shield_hint_key ({2} x1)", "yellow", TerritoryConfig.ShieldKey.Value, arg3));
					}
				}
			}
			__result = Localization.instance.Localize(stringBuilder.ToString());
		}

		private static string GetPermittedNamesString(PrivateArea instance, ZNetView nview)
		{
			try
			{
				if ((Object)(object)nview != (Object)null && nview.IsValid())
				{
					ZDO zDO = nview.GetZDO();
					int num = zDO.GetInt("permitted", 0);
					if (num > 0)
					{
						List<string> list = new List<string>(num);
						for (int i = 0; i < num; i++)
						{
							string text = zDO.GetString("pu_name" + i, "");
							if (!string.IsNullOrEmpty(text))
							{
								list.Add(text);
							}
						}
						if (list.Count > 0)
						{
							return string.Join(", ", list);
						}
					}
				}
			}
			catch
			{
			}
			try
			{
				FieldInfo[] fields = typeof(PrivateArea).GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (!fieldInfo.Name.ToLower().Contains("permitted") || !(fieldInfo.GetValue(instance) is IEnumerable enumerable))
					{
						continue;
					}
					List<string> list2 = new List<string>();
					foreach (object item in enumerable)
					{
						if (item != null)
						{
							string text2 = item.GetType().GetProperty("Value")?.GetValue(item) as string;
							if (!string.IsNullOrEmpty(text2))
							{
								list2.Add(text2);
							}
						}
					}
					if (list2.Count > 0)
					{
						return string.Join(", ", list2);
					}
				}
			}
			catch
			{
			}
			return "없음";
		}
	}
	[HarmonyPatch(typeof(Hud), "UpdateCrosshair")]
	public static class Patch_Hud_WardHoverTextPosition
	{
		private static Vector2? s_basePos;

		private static Vector2? s_baseSizeDelta;

		private static TextMeshProUGUI s_rightColumn;

		private static RectTransform s_dividerRect;

		private const float OffsetY = 340f;

		private const float WidthMultiplier = 1.3225f;

		private const float DividerWidth = 4f;

		private const float ColumnGap = 12f;

		private const float MinDividerHeight = 200f;

		private const float DividerHeightPad = 20f;

		private static void Postfix(Hud __instance)
		{
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: 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_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: 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_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_028b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_031a: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				object? obj = typeof(Hud).GetField("m_hoverName", BindingFlags.Instance | BindingFlags.Public)?.GetValue(__instance);
				Component val = (Component)((obj is Component) ? obj : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				RectTransform component = val.GetComponent<RectTransform>();
				if ((Object)(object)component == (Object)null)
				{
					return;
				}
				PropertyInfo property = ((object)val).GetType().GetProperty("text", BindingFlags.Instance | BindingFlags.Public);
				if (property == null)
				{
					return;
				}
				string text = (property.GetValue(val) as string) ?? "";
				bool flag = text.Contains("영토 와드") || text.Contains("Territory Ward");
				if (!s_basePos.HasValue)
				{
					s_basePos = component.anchoredPosition;
				}
				if (!s_baseSizeDelta.HasValue)
				{
					s_baseSizeDelta = component.sizeDelta;
				}
				component.anchoredPosition = s_basePos.Value + (Vector2)(flag ? new Vector2(0f, 340f) : Vector2.zero);
				if (!flag)
				{
					component.sizeDelta = s_baseSizeDelta.Value;
					if ((Object)(object)s_rightColumn != (Object)null)
					{
						((Component)s_rightColumn).gameObject.SetActive(false);
					}
					if ((Object)(object)s_dividerRect != (Object)null)
					{
						((Component)s_dividerRect).gameObject.SetActive(false);
					}
					return;
				}
				EnsureColumnObjects(val, component);
				float num = s_baseSizeDelta.Value.x * 1.3225f;
				component.sizeDelta = new Vector2(num, s_baseSizeDelta.Value.y);
				string[] array = text.Split(new char[1] { '\n' });
				int num2 = Mathf.CeilToInt((float)array.Length / 2f);
				string value = string.Join("\n", array, 0, num2);
				string text2 = string.Join("\n", array, num2, array.Length - num2);
				property.SetValue(val, value);
				((TMP_Text)s_rightColumn).text = text2;
				Vector2 anchoredPosition = component.anchoredPosition;
				float num3 = num + 12f;
				float num4 = num + 24f + 4f;
				RectTransform component2 = ((Component)s_rightColumn).GetComponent<RectTransform>();
				component2.sizeDelta = new Vector2(num, s_baseSizeDelta.Value.y);
				component2.anchoredPosition = anchoredPosition + new Vector2(num4, 0f);
				((Component)s_rightColumn).gameObject.SetActive(true);
				TextMeshProUGUI val2 = (TextMeshProUGUI)(object)((val is TextMeshProUGUI) ? val : null);
				float num5 = (((Object)(object)val2 != (Object)null) ? ((TMP_Text)val2).preferredHeight : 200f);
				float preferredHeight = ((TMP_Text)s_rightColumn).preferredHeight;
				float num6 = Mathf.Max(Mathf.Max(num5, preferredHeight), 200f) + 20f;
				s_dividerRect.sizeDelta = new Vector2(4f, num6);
				s_dividerRect.anchoredPosition = anchoredPosition + new Vector2(num3, 0f);
				((Component)s_dividerRect).gameObject.SetActive(true);
			}
			catch
			{
			}
		}

		private static void EnsureColumnObjects(Component originalComp, RectTransform originalRt)
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)s_rightColumn == (Object)null)
			{
				GameObject val = Object.Instantiate<GameObject>(originalComp.gameObject, ((Transform)originalRt).parent);
				((Object)val).name = "TerritoryWard_HoverTextRightColumn";
				s_rightColumn = val.GetComponent<TextMeshProUGUI>();
			}
			if ((Object)(object)s_dividerRect == (Object)null)
			{
				GameObject val2 = new GameObject("TerritoryWard_HoverTextDivider", new Type[2]
				{
					typeof(RectTransform),
					typeof(Image)
				});
				val2.transform.SetParent(((Transform)originalRt).parent, false);
				((Graphic)val2.GetComponent<Image>()).color = new Color(1f, 1f, 1f, 0.4f);
				s_dividerRect = val2.GetComponent<RectTransform>();
				s_dividerRect.pivot = new Vector2(0.5f, 1f);
			}
		}
	}
	internal static class WardInventoryHelper
	{
		internal static bool IsWardStorage(Inventory inv)
		{
			return inv.m_name == "$territoryward_storage";
		}

		internal static bool IsWardFuel(string name)
		{
			return name == "$item_wood" || name == "$item_resin";
		}
	}
	[HarmonyPatch(typeof(InventoryGrid), "UpdateInventory")]
	public static class Patch_InventoryGrid_UpdateInventory_ForceRebuild
	{
		private static void Prefix(InventoryGrid __instance, Inventory inventory)
		{
			if (inventory != null)
			{
				int num = inventory.GetWidth() * inventory.GetHeight();
				if (__instance.m_elements.Count != num)
				{
					__instance.m_width = -1;
				}
			}
		}
	}
	[HarmonyPatch(typeof(InventoryGrid), "GetElement")]
	public static class Patch_InventoryGrid_GetElement_Safety
	{
		private static bool Prefix(InventoryGrid __instance, int x, int y, int width, ref Element __result)
		{
			int num = y * width + x;
			if (num >= 0 && num < __instance.m_elements.Count)
			{
				return true;
			}
			if (__instance.m_elements.Count == 0)
			{
				return true;
			}
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogWarning((object)$"[Territory] InventoryGrid.GetElement 범위 밖 접근 방어: x={x}, y={y}, width={width}, elements={__instance.m_elements.Count}");
			}
			__result = __instance.m_elements[Mathf.Clamp(num, 0, __instance.m_elements.Count - 1)];
			return false;
		}
	}
	[HarmonyPatch(typeof(Container), "Interact")]
	public static class Patch_Container_Interact_IntrusionAlert
	{
		private static void Prefix(Container __instance, Humanoid character)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			IntrusionAlert.CheckAndAlert(((Component)__instance).transform.position, character);
		}
	}
	[HarmonyPatch(typeof(CraftingStation), "Interact")]
	public static class Patch_CraftingStation_Interact_IntrusionAlert
	{
		private static void Prefix(CraftingStation __instance, Humanoid user)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			IntrusionAlert.CheckAndAlert(((Component)__instance).transform.position, user);
		}
	}
	internal static class IntrusionAlert
	{
		public static void CheckAndAlert(Vector3 position, Humanoid character)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)character != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			foreach (PrivateArea allArea in PrivateArea.m_allAreas)
			{
				if (allArea.IsEnabled() && ((Object)((Component)allArea).gameObject).name.Contains("territoryward") && allArea.IsInside(position, 0f) && !allArea.HaveLocalAccess())
				{
					((Component)allArea).GetComponent<TerritoryWardController>()?.ReportIntrusion(Player.m_localPlayer.GetPlayerName());
				}
			}
		}
	}
	public static class TerritoryLocalization
	{
		public static void Register()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text = "Korean";
			localization.AddTranslation(ref text, new Dictionary<string, string>
			{
				["territoryward_name"] = "영토 와드",
				["territoryward_storage"] = "영토 와드 창고",
				["territoryward_no_fuel"] = "연료 부족으로 영토 와드가 비활성화되었습니다!",
				["territoryward_off_blocked"] = "비활성화된 영토 와드 구역에서는 사용할 수 없습니다!",
				["territoryward_no_build"] = "영토 와드 구역 안에서만 건설할 수 있습니다!",
				["territoryward_must_activate"] = "영토와드를 활성화 해야합니다!",
				["territoryward_no_overlap"] = "다른 영토 와드 구역 안에서는 설치할 수 없습니다!",
				["territoryward_fuel_hint"] = "연료 창고 열기",
				["territoryward_disabled"] = "영토 와드 시스템이 비활성화되어 있습니다!",
				["territoryward_limit_reached"] = "영토 와드 설치 한도를 초과했습니다!",
				["territoryward_upgrade_hint_key"] = "영토 와드 업그레이드",
				["territoryward_range_label"] = "범위",
				["territoryward_fuel_label"] = "연료",
				["territoryward_fuel_per_minutes"] = "$1분마다",
				["territoryward_fuel_or"] = "또는",
				["territoryward_upgrade_too_far"] = "영토 와드와 너무 멀리 떨어져 있습니다!",
				["territoryward_upgrade_not_creator"] = "영토 와드를 설치한 사람만 업그레이드할 수 있습니다!",
				["territoryward_intrusion_alert"] = "$1가 승인없이 영토에 침입했습니다.",
				["territoryward_upgrade_success"] = "영토 와드가 업그레이드되었습니다!",
				["territoryward_max_level"] = "이미 최대 레벨입니다!",
				["territoryward_missing_fuel_suffix"] = " 부족!",
				["territoryward_shield_hint_key"] = "영토 보호 활성화",
				["territoryward_shield_deactivate_hint_key"] = "영토 보호 비활성화",
				["territoryward_shield_active"] = "보호 중 — 남은 $1분",
				["territoryward_shield_started"] = "영토 보호가 활성화되었습니다! (1시간)",
				["territoryward_shield_stopped"] = "영토 보호가 비활성화되었습니다.",
				["territoryward_shield_resumed"] = "남은 시간으로 영토 보호가 재개되었습니다! (아이템 소모 없음)",
				["territoryward_shield_resume_hint"] = "재개 (아이템 소모 없음, 남은 $1분)",
				["territoryward_shield_no_item"] = "슈트링 코어가 부족합니다!",
				["territoryward_shield_low_level"] = "Lv5 이상에서만 사용 가능합니다!",
				["territoryward_rangering_hint_key"] = "범위 링 토글",
				["territoryward_shield_hud"] = "[ 영토 보호 중 — $1분 남음 ]",
				["territoryward_intrusion_chat"] = "[영토 침입 경고] $1가 승인 없이 영토에 진입했습니다!"
			});
			text = "English";
			localization.AddTranslation(ref text, new Dictionary<string, string>
			{
				["territoryward_name"] = "Territory Ward",
				["territoryward_storage"] = "Territory Ward Storage",
				["territoryward_no_fuel"] = "Territory Ward deactivated: out of fuel!",
				["territoryward_off_blocked"] = "Cannot use items inside a deactivated Territory Ward!",
				["territoryward_no_build"] = "You can only build inside a Territory Ward!",
				["territoryward_must_activate"] = "You must activate the Territory Ward!",
				["territoryward_no_overlap"] = "Cannot place a Territory Ward inside another Territory Ward!",
				["territoryward_fuel_hint"] = "Open Fuel Storage",
				["territoryward_disabled"] = "Territory Ward system is disabled!",
				["territoryward_limit_reached"] = "Territory Ward placement limit reached!",
				["territoryward_upgrade_hint_key"] = "Upgrade Territory Ward",
				["territoryward_range_label"] = "Range",
				["territoryward_fuel_label"] = "Fuel",
				["territoryward_fuel_per_minutes"] = "every $1 min",
				["territoryward_fuel_or"] = "or",
				["territoryward_upgrade_too_far"] = "You are too far from the Territory Ward!",
				["territoryward_upgrade_not_creator"] = "Only the creator of this Territory Ward can upgrade it!",
				["territoryward_intrusion_alert"] = "$1 has invaded the territory without permission!",
				["territoryward_upgrade_success"] = "Territory Ward upgraded!",
				["territoryward_max_level"] = "Already at max level!",
				["territoryward_missing_fuel_suffix"] = " is missing!",
				["territoryward_shield_hint_key"] = "Activate Territory Shield",
				["territoryward_shield_deactivate_hint_key"] = "Deactivate Territory Shield",
				["territoryward_shield_active"] = "Shield Active — $1 min remaining",
				["territoryward_shield_started"] = "Territory Shield activated! (1 hour)",
				["territoryward_shield_stopped"] = "Territory Shield deactivated.",
				["territoryward_shield_resumed"] = "Territory Shield resumed with remaining time! (no item consumed)",
				["territoryward_shield_resume_hint"] = "Resume (no item needed, $1 min left)",
				["territoryward_shield_no_item"] = "Not enough Surtling Core!",
				["territoryward_shield_low_level"] = "Requires Lv5 or higher!",
				["territoryward_rangering_hint_key"] = "Toggle Range Ring",
				["territoryward_shield_hud"] = "[ Shield Active — $1 min remaining ]",
				["territoryward_intrusion_chat"] = "[Intrusion Alert] $1 has entered the territory without permission!"
			});
		}

		public static void RefreshWardDescription()
		{
			CustomLocalization localization = LocalizationManager.Instance.GetLocalization();
			string text = Localization.instance.Localize(TerritoryWardController.Resolve(TerritoryConfig.Lv1FuelA.Value, warnIfMissing: false) ?? "$item_wood");
			string text2 = Localization.instance.Localize(TerritoryWardController.Resolve(TerritoryConfig.Lv1FuelB.Value, warnIfMissing: false) ?? "$item_resin");
			float value = TerritoryConfig.Lv1Radius.Value;
			int value2 = TerritoryConfig.Lv1FuelAAmount.Value;
			int value3 = TerritoryConfig.Lv1FuelBAmount.Value;
			float value4 = TerritoryConfig.Lv1IntervalMinutes.Value;
			string text3 = "Korean";
			localization.AddTranslation(ref text3, new Dictionary<string, string> { ["territoryward_desc"] = $"반경 {value:0}미터의 영토를 설정합니다.\n" + "ON 상태에서만 구역 안에서 건설하고 상호작용할 수 있습니다.\n" + $"연료: {text} {value2}개 + {text2} {value3}개 / {value4:0}분마다" });
			text3 = "English";
			localization.AddTranslation(ref text3, new Dictionary<string, string> { ["territoryward_desc"] = $"Sets a territory with {value:0}m radius.\n" + "Building and interaction only allowed when ON.\n" + $"Fuel: {text} x{value2} + {text2} x{value3} every {value4:0} min" });
		}
	}
	[BepInPlugin("KorCaptain_territorial_ward", "Captain Territorial", "1.0.21")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal const string UpgradeButtonName = "TerritorialWardUpgrade";

		internal static ButtonConfig UpgradeButton;

		internal static ButtonConfig ShieldButton;

		internal static ButtonConfig RangeRingButton;

		internal static ManualLogSource Log;

		private readonly Harmony _harmony = new Harmony("KorCaptain.Captain_territorial");

		private void Awake()
		{
			//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_0077: 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_0094: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			TerritoryConfig.Init(((BaseUnityPlugin)this).Config);
			TerritoryLocalization.Register();
			VFXManager.Initialize();
			PrefabManager.OnVanillaPrefabsAvailable += TerritoryWard.Create;
			PrefabManager.OnVanillaPrefabsAvailable += TerritoryLocalization.RefreshWardDescription;
			UpgradeButton = new ButtonConfig
			{
				Name = "TerritorialWardUpgrade",
				Config = TerritoryConfig.UpgradeKey,
				HintToken = "$territoryward_upgrade_hint_key"
			};
			InputManager.Instance.AddButton(((BaseUnityPlugin)this).Info.Metadata.GUID, UpgradeButton);
			ShieldButton = new ButtonConfig
			{
				Name = "TerritorialWardShield",
				Config = TerritoryConfig.ShieldKey,
				HintToken = "$territoryward_shield_hint_key"
			};
			InputManager.Instance.AddButton(((BaseUnityPlugin)this).Info.Metadata.GUID, ShieldButton);
			RangeRingButton = new ButtonConfig
			{
				Name = "TerritorialWardRangeRing",
				Config = TerritoryConfig.RangeRingKey,
				HintToken = "$territoryward_rangering_hint_key"
			};
			InputManager.Instance.AddButton(((BaseUnityPlugin)this).Info.Metadata.GUID, RangeRingButton);
			SynchronizationManager.OnConfigurationSynchronized += delegate(object _, ConfigurationSynchronizationEventArgs e)
			{
				if (e.InitialSynchronization)
				{
					TerritoryLocalization.RefreshWardDescription();
				}
			};
			_harmony.PatchAll();
			PrintLoadedMessage();
		}

		private void PrintLoadedMessage()
		{
			string text = $"[Captain_territorial] Captain Territorial {((BaseUnityPlugin)this).Info.Metadata.Version} Loaded!";
			try
			{
				Type type = typeof(BaseUnityPlugin).Assembly.GetType("BepInEx.ConsoleManager");
				MethodInfo methodInfo = type?.GetMethod("SetConsoleColor", BindingFlags.Static | BindingFlags.Public);
				TextWriter textWriter = type?.GetProperty("StandardOutStream", BindingFlags.Static | BindingFlags.Public)?.GetValue(null) as TextWriter;
				if (methodInfo != null && textWriter != null)
				{
					methodInfo.Invoke(null, new object[1] { ConsoleColor.Cyan });
					textWriter.WriteLine(text);
					methodInfo.Invoke(null, new object[1] { ConsoleColor.Gray });
				}
				else
				{
					Log.LogMessage((object)text);
				}
			}
			catch
			{
				Log.LogMessage((object)text);
			}
		}

		private void OnDestroy()
		{
			_harmony.UnpatchSelf();
		}
	}
	[HarmonyPatch(typeof(WearNTear), "Damage")]
	public static class Patch_WearNTear_Damage_ShieldZone
	{
		private static bool Prefix(WearNTear __instance)
		{
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			foreach (PrivateArea allArea in PrivateArea.m_allAreas)
			{
				if (allArea.IsEnabled() && ((Object)((Component)allArea).gameObject).name.Contains("territoryward"))
				{
					TerritoryWardController component = ((Component)allArea).GetComponent<TerritoryWardController>();
					if ((Object)(object)component != (Object)null && component.IsShielded() && allArea.IsInside(((Component)__instance).transform.position, 0f))
					{
						return false;
					}
				}
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(Character), "Damage")]
	public static class Patch_Character_Damage_ShieldZone
	{
		private static bool Prefix(Character __instance)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			if (!(__instance is Player))
			{
				return true;
			}
			foreach (PrivateArea allArea in PrivateArea.m_allAreas)
			{
				if (allArea.IsEnabled() && ((Object)((Component)allArea).gameObject).name.Contains("territoryward"))
				{
					TerritoryWardController component = ((Component)allArea).GetComponent<TerritoryWardController>();
					if ((Object)(object)component != (Object)null && component.IsShielded() && allArea.IsInside(((Component)__instance).transform.position, 0f))
					{
						return false;
					}
				}
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(BaseAI), "FindEnemy")]
	public static class Patch_BaseAI_FindEnemy_ShieldZone
	{
		private static bool Prefix(BaseAI __instance, ref Character __result)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			foreach (PrivateArea allArea in PrivateArea.m_allAreas)
			{
				if (allArea.IsEnabled() && ((Object)((Component)allArea).gameObject).name.Contains("territoryward"))
				{
					TerritoryWardController component = ((Component)allArea).GetComponent<TerritoryWardController>();
					if (!((Object)(object)component == (Object)null) && component.IsShielded() && allArea.IsInside(((Component)__instance).transform.position, 0f))
					{
						__result = null;
						return false;
					}
				}
			}
			return true;
		}
	}
	public static class TerritoryWard
	{
		public const string PrefabName = "territoryward";

		public const string StorageName = "$territoryward_storage";

		internal static readonly List<PrivateArea> s_wards = new List<PrivateArea>(16);

		private static Piece s_piece;

		private static Requirement[] s_normalRequirements;

		private static readonly Requirement[] s_freeRequirements = (Requirement[])(object)new Requirement[0];

		public static void Create()
		{
			//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_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)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Expected O, but got Unknown
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Expected O, but got Unknown
			PieceConfig val = new PieceConfig
			{
				Name = "$territoryward_name",
				Description = "$territoryward_desc",
				PieceTable = "Hammer",
				Category = "Misc"
			};
			val.AddRequirement(new RequirementConfig("Wood", 10, 0, true));
			val.AddRequirement(new RequirementConfig("Stone", 10, 0, true));
			CustomPiece val2 = new CustomPiece("territoryward", "guard_stone", val);
			if ((Object)(object)val2.PiecePrefab == (Object)null)
			{
				Plugin.Log.LogError((object)"[Captain_territorial] guard_stone 클론 실패 — 바닐라 프리팹 없음");
				PrefabManager.OnVanillaPrefabsAvailable -= Create;
				return;
			}
			PrivateArea component = val2.PiecePrefab.GetComponent<PrivateArea>();
			if ((Object)(object)component != (Object)null)
			{
				component.m_name = "$territoryward_name";
			}
			Container val3 = val2.PiecePrefab.AddComponent<Container>();
			val3.m_name = "$territoryward_storage";
			val3.m_width = 2;
			val3.m_height = 2;
			val3.m_defaultItems = new DropTable();
			val3.m_checkGuardStone = false;
			val2.PiecePrefab.AddComponent<TerritoryWardController>();
			PieceManager.Instance.AddPiece(val2);
			PrefabManager.OnVanillaPrefabsAvailable -= Create;
			s_piece = val2.PiecePrefab.GetComponent<Piece>();
			s_normalRequirements = s_piece.m_resources;
			ApplyAdminBypass(TerritoryConfig.AdminBypass.Value);
			TerritoryConfig.AdminBypass.SettingChanged += delegate
			{
				ApplyAdminBypass(TerritoryConfig.AdminBypass.Value);
			};
			Plugin.Log.LogInfo((object)"[Captain_territorial] territoryward 등록 완료");
		}

		private static void ApplyAdminBypass(bool enabled)
		{
			if (!((Object)(object)s_piece == (Object)null))
			{
				s_piece.m_resources = (enabled ? s_freeRequirements : s_normalRequirements);
			}
		}

		public static bool IsInsideActiveWard(Vector3 point)
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			foreach (PrivateArea s_ward in s_wards)
			{
				if ((Object)(object)s_ward == (Object)null || !s_ward.IsEnabled() || !(Vector3.Distance(((Component)s_ward).transform.position, point) <= s_ward.m_radius))
				{
					continue;
				}
				return true;
			}
			return false;
		}

		public static bool IsInsideDeactivatedWard(Vector3 point)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			foreach (PrivateArea s_ward in s_wards)
			{
				if ((Object)(object)s_ward == (Object)null || s_ward.IsEnabled() || !(Vector3.Distance(((Component)s_ward).transform.position, point) <= s_ward.m_radius))
				{
					continue;
				}
				return true;
			}
			return false;
		}
	}
	public class TerritoryWardController : MonoBehaviour
	{
		private struct ResolvedTier
		{
			public int Level;

			public string NameA;

			public int AmountA;

			public string NameB;

			public int AmountB;

			public string NameC;

			public int AmountC;

			public float IntervalSeconds;
		}

		internal ZNetView m_nview;

		private Container m_container;

		private PrivateArea m_privateArea;

		private Piece m_piece;

		private static readonly FieldInfo s_hoveringField = typeof(Player).GetField("m_hovering", BindingFlags.Instance | BindingFlags.NonPublic);

		private readonly List<ResolvedTier> m_tiers = new List<ResolvedTier>();

		private bool m_fuelDepleted = false;

		private bool m_missingFuelWarned = false;

		private bool m_wasEnabled = false;

		private int m_level = 1;

		private float m_lastIntrusionAlertTime = -999f;

		private PinData m_minimapPin;

		private readonly Dictionary<string, float> m_intruders = new Dictionary<string, float>();

		private GameObject m_shieldGenObject;

		private bool m_showRangeRing = false;

		private const string ZDO_LAST_CONSUME = "tw_lastConsume";

		private const string ZDO_SHIELD_END = "tw_shield_end";

		private const string ZDO_SHIELD_REMAINING = "tw_shield_remaining";

		private const string ZDO_LEVEL = "tw_level";

		private const float CHECK_INTERVAL = 5f;

		private const float INTRUSION_ALERT_COOLDOWN = 10f;

		private static readonly (int Width, int Height)[] s_storageSizes = new(int, int)[8]
		{
			(2, 2),
			(2, 3),
			(3, 3),
			(3, 4),
			(4, 4),
			(4, 5),
			(5, 5),
			(5, 6)
		};

		private static bool s_shieldTemplateUnavailableLogged = false;

		private bool m_showWhitelistUI = false;

		private List<KeyValuePair<long, string>> m_uiPermitted = new List<KeyValuePair<long, string>>();

		private Vector2 m_uiScrollPos;

		private static GUIStyle s_intruderStyle;

		private static GUIStyle s_titleStyle;

		private static GUIStyle s_sectionStyle;

		private static GUIStyle s_shieldHUDStyle;

		private void Awake()
		{
			m_nview = ((Component)this).GetComponent<ZNetView>();
			m_container = ((Component)this).GetComponent<Container>();
			m_privateArea = ((Component)this).GetComponent<PrivateArea>();
			m_piece = ((Component)this).GetComponent<Piece>();
			if ((Object)(object)m_nview != (Object)null)
			{
				m_nview.Register<int>("RPC_ApplyLevel", (Action<long, int>)RPC_ApplyLevel);
				m_nview.Register<string>("RPC_ReportIntrusion", (Action<long, string>)RPC_ReportIntrusion);
				m_nview.Register<float>("RPC_ActivateShield", (Action<long, float>)RPC_ActivateShield);
				m_nview.Register("RPC_DeactivateShield", (Action<long>)RPC_DeactivateShield);
			}
		}

		private void Start()
		{
			int level = 1;
			if ((Object)(object)m_nview != (Object)null && m_nview.IsValid())
			{
				level = m_nview.GetZDO().GetInt("tw_level", 1);
			}
			ApplyLevel(level);
			AddMinimapPin();
			if ((Object)(object)m_privateArea != (Object)null)
			{
				TerritoryWard.s_wards.Add(m_privateArea);
			}
			if ((Object)(object)m_nview != (Object)null && m_nview.IsOwner())
			{
				((MonoBehaviour)this).InvokeRepeating("CheckConsumption", 5f, 5f);
			}
		}

		private void OnDestroy()
		{
			((MonoBehaviour)this).CancelInvoke();
			if ((Object)(object)m_privateArea != (Object)null)
			{
				TerritoryWard.s_wards.Remove(m_privateArea);
			}
			RemoveMinimapPin();
			StopShieldVFX();
		}

		private void AddMinimapPin()
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: 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)
			if (!((Object)(object)Minimap.instance == (Object)null))
			{
				RemoveMinimapPin();
				string arg = (((Object)(object)m_nview != (Object)null && m_nview.IsValid()) ? m_nview.GetZDO().GetString("creatorName", "???") : "???");
				string text = $"영토 와드 Lv{m_level} <color=green>[{arg}]</color>";
				m_minimapPin = Minimap.instance.AddPin(((Component)this).transform.position, (PinType)3, text, false, false, 0L, default(PlatformUserID));
			}
		}

		private void RemoveMinimapPin()
		{
			if (m_minimapPin != null && !((Object)(object)Minimap.instance == (Object)null))
			{
				Minimap.instance.RemovePin(m_minimapPin);
				m_minimapPin = null;
			}
		}

		private void ApplyLevel(int level)
		{
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0330: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0359: Unknown result type (might be due to invalid IL or missing references)
			//IL_035b: Unknown result type (might be due to invalid IL or missing references)
			m_level = level;
			float radius = TerritoryConfig.GetRadius(level);
			if ((Object)(object)m_privateArea != (Object)null)
			{
				m_privateArea.m_radius = radius;
				if ((Object)(object)m_privateArea.m_areaMarker != (Object)null)
				{
					m_privateArea.m_areaMarker.m_radius = radius;
				}
			}
			if ((Object)(object)m_shieldGenObject != (Object)null)
			{
				ShieldGenerator component = m_shieldGenObject.GetComponent<ShieldGenerator>();
				if ((Object)(object)component != (Object)null)
				{
					component.m_minShieldRadius = radius;
					component.m_maxShieldRadius = radius;
					component.m_radiusTarget = radius;
					component.m_radius = radius;
				}
			}
			if ((Object)(object)m_container == (Object)null)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)$"[Territory] ApplyLevel Lv{level}: m_container가 null — 창고 리사이즈 스킵");
				}
			}
			else
			{
				Inventory inventory = m_container.GetInventory();
				if (inventory == null)
				{
					ManualLogSource log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogWarning((object)$"[Territory] ApplyLevel Lv{level}: GetInventory()가 null — 창고 리사이즈 스킵");
					}
				}
				else
				{
					(int, int) tuple = s_storageSizes[Mathf.Clamp(level, 1, s_storageSizes.Length) - 1];
					inventory.m_width = Mathf.Max(inventory.m_width, tuple.Item1);
					inventory.m_height = Mathf.Max(inventory.m_height, tuple.Item2);
					ManualLogSource log3 = Plugin.Log;
					if (log3 != null)
					{
						log3.LogInfo((object)$"[Territory] ApplyLevel Lv{level}: 창고 크기 목표 {tuple.Item1}x{tuple.Item2}, 실제 적용 {inventory.GetWidth()}x{inventory.GetHeight()}");
					}
					bool flag = false;
					foreach (ItemData allItem in inventory.GetAllItems())
					{
						if (allItem.m_gridPos.x >= 0 && allItem.m_gridPos.x < inventory.m_width && allItem.m_gridPos.y >= 0 && allItem.m_gridPos.y < inventory.m_height)
						{
							continue;
						}
						Vector2i val = inventory.FindEmptySlot(false);
						if (val.x < 0)
						{
							ManualLogSource log4 = Plugin.Log;
							if (log4 != null)
							{
								log4.LogWarning((object)$"[Territory] 창고 아이템 '{allItem.m_shared.m_name}'가 범위 밖({allItem.m_gridPos.x},{allItem.m_gridPos.y})인데 빈 칸을 못 찾음 (창고 {inventory.m_width}x{inventory.m_height})");
							}
							continue;
						}
						ManualLogSource log5 = Plugin.Log;
						if (log5 != null)
						{
							log5.LogWarning((object)$"[Territory] 창고 아이템 '{allItem.m_shared.m_name}' gridPos({allItem.m_gridPos.x},{allItem.m_gridPos.y})가 범위 밖 — ({val.x},{val.y})로 재배치");
						}
						allItem.m_gridPos = val;
						flag = true;
					}
					if (flag && (Object)(object)m_nview != (Object)null && m_nview.IsOwner())
					{
						m_container.Save();
					}
				}
			}
			m_tiers.Clear();
			foreach (TerritoryConfig.FuelTier fuelTier in TerritoryConfig.GetFuelTiers(level))
			{
				bool flag2 = !string.IsNullOrEmpty(fuelTier.ItemC);
				m_tiers.Add(new ResolvedTier
				{
					Level = fuelTier.Level,
					NameA = (Resolve(fuelTier.ItemA) ?? fuelTier.ItemA),
					AmountA = fuelTier.AmountA,
					NameB = (Resolve(fuelTier.ItemB) ?? fuelTier.ItemB),
					AmountB = fuelTier.AmountB,
					NameC = (flag2 ? (Resolve(fuelTier.ItemC) ?? fuelTier.ItemC) : null),
					AmountC = (flag2 ? fuelTier.AmountC : 0),
					IntervalSeconds = fuelTier.IntervalSeconds
				});
			}
		}

		private void RPC_ApplyLevel(long sender, int level)
		{
			if ((Object)(object)m_nview != (Object)null && m_nview.IsOwner())
			{
				m_nview.GetZDO().Set("tw_level", level);
			}
			ApplyLevel(level);
			AddMinimapPin();
		}

		public void ReportIntrusion(string intruderName)
		{
			if (!((Object)(object)m_nview == (Object)null) && m_nview.IsValid() && !(Time.time - m_lastIntrusionAlertTime < 10f))
			{
				m_lastIntrusionAlertTime = Time.time;
				m_nview.InvokeRPC(ZNetView.Everybody, "RPC_ReportIntrusion", new object[1] { intruderName });
			}
		}

		private void RPC_ReportIntrusion(long sender, string intruderName)
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)m_privateArea == (Object)null)
			{
				return;
			}
			long playerID = Game.instance.GetPlayerProfile().GetPlayerID();
			bool flag = (Object)(object)m_piece != (Object)null && m_piece.GetCreator() == playerID;
			bool flag2 = m_privateArea.IsPermitted(playerID);
			if (flag || flag2)
			{
				m_intruders[intruderName] = Time.time;
				string text = Localization.instance.Localize("$territoryward_intrusion_alert", new string[1] { intruderName });
				((Character)Player.m_localPlayer).Message((MessageType)2, text, 0, (Sprite)null);
				VFXManager.PlayIntrusionAlert(((Component)Player.m_localPlayer).transform.position);
				if ((Object)(object)Chat.instance != (Object)null)
				{
					string text2 = Localization.instance.Localize("$territoryward_intrusion_chat", new string[1] { intruderName });
					((Terminal)Chat.instance).AddString("", text2, (Type)1, false);
				}
			}
		}

		private void Update()
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			UpdateAreaMarkerForBuilding();
			bool flag = IsShielded();
			if (flag && (Object)(object)m_shieldGenObject == (Object)null)
			{
				StartShieldVFX();
			}
			if (!flag && (Object)(object)m_shieldGenObject != (Object)null)
			{
				StopShieldVFX();
			}
			if ((Object)(object)Player.m_localPlayer == (Object)null || (Object)(object)m_privateArea == (Object)null)
			{
				return;
			}
			float num = Vector3.Distance(((Component)Player.m_localPlayer).transform.position, ((Component)this).transform.position);
			if ((Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303)) && Input.GetKeyDown((KeyCode)101) && num <= 5f && IsHoveredByLocalPlayer(((Component)this).gameObject))
			{
				if (m_privateArea.m_piece.IsCreator())
				{
					m_showWhitelistUI = !m_showWhitelistUI;
					if (m_showWhitelistUI)
					{
						RefreshWhitelistUI();
					}
				}
				else
				{
					m_nview.InvokeRPC("TogglePermitted", new object[2]
					{
						Player.m_localPlayer.GetPlayerID(),
						Player.m_localPlayer.GetPlayerName()
					});
				}
			}
			else if (Input.GetKeyDown(TerritoryConfig.FuelStorageKey.Value) && num <= 5f && IsHoveredByLocalPlayer(((Component)this).gameObject))
			{
				if ((Object)(object)m_container != (Object)null)
				{
					ApplyLevel(m_level);
					m_container.Interact((Humanoid)(object)Player.m_localPlayer, false, false);
				}
			}
			else if (Plugin.RangeRingButton != null && ZInput.GetButtonDown(Plugin.RangeRingButton.Name) && num <= 5f && IsHoveredByLocalPlayer(((Component)this).gameObject))
			{
				m_showRangeRing = !m_showRangeRing;
			}
			else if (Plugin.ShieldButton != null && ZInput.GetButtonDown(Plugin.ShieldButton.Name))
			{
				HandleShieldActivation(num);
			}
			else if (ZInput.GetButtonDown(Plugin.UpgradeButton.Name))
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"[Territory] U key pressed near ward");
				}
				if (num > 3f)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_upgrade_too_far", 0, (Sprite)null);
				}
				else if ((Object)(object)m_piece == (Object)null || !m_piece.IsCreator())
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_upgrade_not_creator", 0, (Sprite)null);
				}
				else if (m_level >= 8)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_max_level", 0, (Sprite)null);
				}
				else
				{
					TryUpgrade();
				}
			}
		}

		private static bool IsHoveredByLocalPlayer(GameObject obj)
		{
			try
			{
				object? obj2 = s_hoveringField?.GetValue(Player.m_localPlayer);
				GameObject val = (GameObject)((obj2 is GameObject) ? obj2 : null);
				return (Object)(object)val != (Object)null && (Object)(object)((Component)val.transform.root).gameObject == (Object)(object)obj;
			}
			catch
			{
				return false;
			}
		}

		private void UpdateAreaMarkerForBuilding()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)m_privateArea == (Object)null))
			{
				Player localPlayer = Player.m_localPlayer;
				if ((Object)(object)localPlayer != (Object)null && ((Object)(object)localPlayer.m_placementGhost != (Object)null || m_showRangeRing) && Vector3.Distance(((Component)localPlayer).transform.position, ((Component)this).transform.position) <= m_privateArea.m_radius + 20f)
				{
					m_privateArea.ShowAreaMarker();
				}
			}
		}

		public string GetUpgradeRequirementText()
		{
			if (m_level >= 8)
			{
				return Localization.instance.Localize("$territoryward_max_level");
			}
			TerritoryConfig.UpgradeCostInfo upgradeCost = TerritoryConfig.GetUpgradeCost(m_level + 1);
			string text = Localization.instance.Localize(Resolve(upgradeCost.ItemA) ?? upgradeCost.ItemA);
			string text2 = Localization.instance.Localize(Resolve(upgradeCost.ItemB) ?? upgradeCost.ItemB);
			string text3 = $"{text} x{upgradeCost.ItemAAmount} + {text2} x{upgradeCost.ItemBAmount}";
			if (upgradeCost.Coins > 0)
			{
				string arg = Localization.instance.Localize(Resolve("Coins") ?? "$item_coins");
				text3 += $" + {arg} x{upgradeCost.Coins}";
			}
			return text3;
		}

		public int GetLevel()
		{
			return m_level;
		}

		private static string FormatTierItems(string nameA, int amountA, string nameB, int amountB, string nameC, int amountC)
		{
			string text = $"{Localization.instance.Localize(nameA)} {amountA}, {Localization.instance.Localize(nameB)} {amountB}";
			if (!string.IsNullOrEmpty(nameC))
			{
				text += $", {Localization.instance.Localize(nameC)} {amountC}";
			}
			return text;
		}

		public string GetFuelInfoText()
		{
			string text = Localization.instance.Localize("$territoryward_fuel_or");
			List<string> list = new List<string>();
			foreach (ResolvedTier tier in m_tiers)
			{
				string text2 = (tier.IntervalSeconds / 60f).ToString("0");
				string text3 = Localization.instance.Localize("$territoryward_fuel_per_minutes", new string[1] { text2 });
				list.Add(text3 + " " + FormatTierItems(tier.NameA, tier.AmountA, tier.NameB, tier.AmountB, tier.NameC, tier.AmountC));
			}
			return string.Join("\n" + text + "\n", list);
		}

		public string GetNextLevelFuelInfoText()
		{
			if (m_level >= 8)
			{
				return "";
			}
			List<TerritoryConfig.FuelTier> fuelTiers = TerritoryConfig.GetFuelTiers(m_level + 1);
			TerritoryConfig.FuelTier fuelTier = fuelTiers[fuelTiers.Count - 1];
			string nameA = Resolve(fuelTier.ItemA) ?? fuelTier.ItemA;
			string nameB = Resolve(fuelTier.ItemB) ?? fuelTier.ItemB;
			string nameC = (string.IsNullOrEmpty(fuelTier.ItemC) ? null : (Resolve(fuelTier.ItemC) ?? fuelTier.ItemC));
			string text = (fuelTier.IntervalSeconds / 60f).ToString("0");
			string text2 = Localization.instance.Localize("$territoryward_fuel_per_minutes", new string[1] { text });
			return text2 + " " + FormatTierItems(nameA, fuelTier.AmountA, nameB, fuelTier.AmountB, nameC, fuelTier.AmountC);
		}

		public string GetNextLevelFullFuelText()
		{
			if (m_level >= 8)
			{
				return "";
			}
			int uptoLevel = m_level + 1;
			List<TerritoryConfig.FuelTier> fuelTiers = TerritoryConfig.GetFuelTiers(uptoLevel);
			if (fuelTiers.Count == 0)
			{
				return "";
			}
			string text = Localization.instance.Localize("$territoryward_fuel_or");
			List<string> list = new List<string>();
			foreach (TerritoryConfig.FuelTier item in fuelTiers)
			{
				string nameA = Resolve(item.ItemA) ?? item.ItemA;
				string nameB = Resolve(item.ItemB) ?? item.ItemB;
				string nameC = (string.IsNullOrEmpty(item.ItemC) ? null : (Resolve(item.ItemC) ?? item.ItemC));
				string text2 = (item.IntervalSeconds / 60f).ToString("0");
				string text3 = Localization.instance.Localize("$territoryward_fuel_per_minutes", new string[1] { text2 });
				list.Add(text3 + " " + FormatTierItems(nameA, item.AmountA, nameB, item.AmountB, nameC, item.AmountC));
			}
			return string.Join("\n" + text + "\n", list);
		}

		public float? GetNextLevelRadius()
		{
			if (m_level >= 8)
			{
				return null;
			}
			return TerritoryConfig.GetRadius(m_level + 1);
		}

		private void TryUpgrade()
		{
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			int num = m_level + 1;
			TerritoryConfig.UpgradeCostInfo upgradeCost = TerritoryConfig.GetUpgradeCost(num);
			if (!TerritoryConfig.AdminBypass.Value)
			{
				Inventory inventory = ((Humanoid)Player.m_localPlayer).GetInventory();
				string text = Resolve(upgradeCost.ItemA) ?? upgradeCost.ItemA;
				string text2 = Resolve(upgradeCost.ItemB) ?? upgradeCost.ItemB;
				string text3 = Resolve("Coins") ?? "$item_coins";
				int num2 = inventory.CountItems(text, -1, false);
				int num3 = inventory.CountItems(text2, -1, false);
				int num4 = inventory.CountItems(text3, -1, false);
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"[Territory] TryUpgrade Lv{num}: A:{num2}/{upgradeCost.ItemAAmount}, B:{num3}/{upgradeCost.ItemBAmount}, Coin:{num4}/{upgradeCost.Coins}");
				}
				List<string> list = new List<string>();
				string text4 = Localization.instance.Localize("$territoryward_missing_fuel_suffix");
				if (num2 < upgradeCost.ItemAAmount)
				{
					list.Add(Localization.instance.Localize(text) + text4);
				}
				if (num3 < upgradeCost.ItemBAmount)
				{
					list.Add(Localization.instance.Localize(text2) + text4);
				}
				if (num4 < upgradeCost.Coins)
				{
					list.Add(Localization.instance.Localize(text3) + text4);
				}
				if (list.Count > 0)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, string.Join("\n", list), 0, (Sprite)null);
					return;
				}
				inventory.RemoveItem(text, upgradeCost.ItemAAmount, -1, true);
				inventory.RemoveItem(text2, upgradeCost.ItemBAmount, -1, true);
				if (upgradeCost.Coins > 0)
				{
					inventory.RemoveItem(text3, upgradeCost.Coins, -1, true);
				}
			}
			m_nview.InvokeRPC(ZNetView.Everybody, "RPC_ApplyLevel", new object[1] { num });
			VFXManager.PlayUpgradeEffect(((Component)this).transform.position);
			((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_upgrade_success", 0, (Sprite)null);
		}

		public bool IsShielded()
		{
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
			{
				return false;
			}
			float num = m_nview.GetZDO().GetFloat("tw_shield_end", 0f);
			return (Object)(object)ZNet.instance != (Object)null && ZNet.instance.GetTimeSeconds() < (double)num;
		}

		public float GetShieldRemainingMinutes()
		{
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
			{
				return 0f;
			}
			float num = m_nview.GetZDO().GetFloat("tw_shield_end", 0f);
			float num2 = num - (float)ZNet.instance.GetTimeSeconds();
			return Mathf.Max(0f, num2 / 60f);
		}

		public float GetShieldBankedRemainingMinutes()
		{
			if ((Object)(object)m_nview == (Object)null || !m_nview.IsValid())
			{
				return 0f;
			}
			return m_nview.GetZDO().GetFloat("tw_shield_remaining", 0f) / 60f;
		}

		private void StartShieldVFX()
		{
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Expected O, but got Unknown
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)m_shieldGenObject != (Object)null)
			{
				return;
			}
			ZNetScene instance = ZNetScene.instance;
			GameObject val = ((instance != null) ? instance.GetPrefab("charred_shieldgenerator") : null);
			ShieldGenerator val2 = ((val != null) ? val.GetComponent<ShieldGenerator>() : null);
			if ((Object)(object)val2?.m_shieldDome == (Object)null)
			{
				if (!s_shieldTemplateUnavailableLogged)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)"[Territory] charred_shieldgenerator ShieldGenerator not found — shield VFX skipped");
					}
					s_shieldTemplateUnavailableLogged = true;
				}
				return;
			}
			if ((Object)(object)ShieldGenerator.m_shieldDomeEffect == (Object)null)
			{
				ShieldGenerator.m_shieldDomeEffect = Object.FindObjectOfType<ShieldDomeImageEffect>();
			}
			if (!((Object)(object)ShieldGenerator.m_shieldDomeEffect == (Object)null))
			{
				m_shieldGenObject = new GameObject("TW_ShieldVFX");
				m_shieldGenObject.transform.position = ((Component)this).transform.position;
				GameObject val3 = Object.Instantiate<GameObject>(val2.m_shieldDome);
				val3.transform.SetParent(m_shieldGenObject.transform);
				val3.transform.localPosition = Vector3.zero;
				val3.SetActive(true);
				ShieldGenerator val4 = m_shieldGenObject.AddComponent<ShieldGenerator>();
				val4.m_shieldDome = val3;
				val4.m_minShieldRadius = m_privateArea.m_radius;
				val4.m_maxShieldRadius = m_privateArea.m_radius;
				val4.m_radiusTarget = m_privateArea.m_radius;
				val4.m_radius = m_privateArea.m_radius;
				val4.m_lastFuel = 1f;
				val4.m_maxFuel = 1;
				val4.m_fuelPerDamage = 0f;
				val4.m_enableAttack = false;
				val4.m_energyParticles = (ParticleSystem[])(object)new ParticleSystem[0];
				val4.m_coloredLights = (Light[])(object)new Light[0];
			}
		}

		private void StopShieldVFX()
		{
			if (!((Object)(object)m_shieldGenObject == (Object)null))
			{
				Object.Destroy((Object)(object)m_shieldGenObject);
				m_shieldGenObject = null;
			}
		}

		private void HandleShieldActivation(float dist)
		{
			if (!m_privateArea.m_piece.IsCreator() || dist > 5f || !IsHoveredByLocalPlayer(((Component)this).gameObject))
			{
				return;
			}
			if (m_level < 5)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_shield_low_level", 0, (Sprite)null);
				return;
			}
			if (IsShielded())
			{
				m_nview.InvokeRPC(ZNetView.Everybody, "RPC_DeactivateShield", Array.Empty<object>());
				((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_shield_stopped", 0, (Sprite)null);
				return;
			}
			float num = (((Object)(object)m_nview != (Object)null && m_nview.IsValid()) ? m_nview.GetZDO().GetFloat("tw_shield_remaining", 0f) : 0f);
			if (num > 0f)
			{
				m_nview.InvokeRPC(ZNetView.Everybody, "RPC_ActivateShield", new object[1] { num });
				((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_shield_resumed", 0, (Sprite)null);
				return;
			}
			string text = Resolve(TerritoryConfig.ShieldItemName.Value) ?? TerritoryConfig.ShieldItemName.Value;
			Inventory inventory = m_container.GetInventory();
			if (inventory.CountItems(text, -1, false) < 1)
			{
				((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_shield_no_item", 0, (Sprite)null);
				return;
			}
			inventory.RemoveItem(text, 1, -1, true);
			m_nview.InvokeRPC(ZNetView.Everybody, "RPC_ActivateShield", new object[1] { 3600f });
			((Character)Player.m_localPlayer).Message((MessageType)2, "$territoryward_shield_started", 0, (Sprite)null);
		}

		private void RPC_ActivateShield(long sender, float duration)
		{
			if (!((Object)(object)m_nview == (Object)null) && m_nview.IsOwner())
			{
				m_nview.GetZDO().Set("tw_shield_end", (float)ZNet.instance.GetTimeSeconds() + duration);
				m_nview.GetZDO().Set("tw_shield_remaining", 0f);
			}
		}

		private void RPC_DeactivateShield(long sender)
		{
			if (!((Object)(object)m_nview == (Object)null) && m_nview.IsOwner())
			{
				float num = (float)ZNet.instance.GetTimeSeconds();
				float num2 = m_nview.GetZDO().GetFloat("tw_shield_end", 0f);
				m_nview.GetZDO().Set("tw_shield_remaining", Mathf.Max(0f, num2 - num));
				m_nview.GetZDO().Set("tw_shield_end", num);
			}
		}

		internal static string Resolve(string prefabName, bool warnIfMissing = true)
		{
			if ((Object)(object)ObjectDB.instance == (Object)null)
			{
				return null;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName);
			string text = ((itemPrefab == null) ? null : itemPrefab.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_name);
			if (text == null && warnIfMissing)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[Territory] Resolve: '" + prefabName + "' not found in ObjectDB — CountItems will return 0"));
				}
			}
			return text;
		}

		private void CheckConsumption()
		{
			if ((Object)(object)m_nview == (Object)null || !m_nvi