Decompiled source of BetterMapFix v1.1.12

plugins/BetterMapFix/BetterMapFix.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("BetterMapFix")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.11.0")]
[assembly: AssemblyInformationalVersion("1.1.11")]
[assembly: AssemblyProduct("BetterMapFix")]
[assembly: AssemblyTitle("BetterMapFix")]
[assembly: AssemblyVersion("1.1.11.0")]
[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 BetterMapFix
{
	internal static class BetterMapApi
	{
		internal const string PluginGuid = "xtav1m.BetterMap";

		internal static Type PluginType;

		internal static Type PinRulesType;

		internal static Type RuleType;

		internal static Type AutoPinsType;

		internal static Type PinRecordType;

		internal static Type PinNamesType;

		internal static MethodInfo MMinimapAddPin;

		internal static MethodInfo MMinimapUpdate;

		internal static FieldInfo FAutoPin;

		internal static FieldInfo FMergeDistance;

		internal static FieldInfo FExplorationRadius;

		internal static MethodInfo MBindPinRules;

		internal static ConfigFile BetterMapConfig;

		internal static FieldInfo FRulesAll;

		internal static FieldInfo FName;

		internal static FieldInfo FDescription;

		internal static FieldInfo FNameToken;

		internal static FieldInfo FPrefabs;

		internal static FieldInfo FBiome;

		internal static FieldInfo FCategory;

		internal static FieldInfo FDefaultOn;

		internal static FieldInfo FIsLocation;

		internal static FieldInfo FEnabled;

		internal static FieldInfo FComponent;

		internal static MethodInfo MSweep;

		internal static MethodInfo MBuild;

		internal static MethodInfo MPlace;

		internal static MethodInfo MPinRecordHas;

		internal static MethodInfo MPinNamesFor;

		internal static bool Ready { get; private set; }

		internal static string FailReason { get; private set; }

		internal static bool SupportsComponent => FComponent != null;

		internal static bool Init(Assembly betterMap, ConfigFile betterMapConfig)
		{
			List<string> list = new List<string>();
			try
			{
				BetterMapConfig = betterMapConfig;
				PluginType = betterMap.GetType("BetterMap.Plugin", throwOnError: false);
				PinRulesType = betterMap.GetType("BetterMap.Scripts.Pins.PinRules", throwOnError: false);
				RuleType = betterMap.GetType("BetterMap.Scripts.Pins.PinRules+Rule", throwOnError: false);
				AutoPinsType = betterMap.GetType("BetterMap.Scripts.Pins.AutoPins", throwOnError: false);
				PinRecordType = betterMap.GetType("BetterMap.Scripts.Pins.PinRecord", throwOnError: false);
				PinNamesType = betterMap.GetType("BetterMap.Scripts.Pins.PinNames", throwOnError: false);
				if (PluginType == null)
				{
					list.Add("BetterMap.Plugin");
				}
				if (PinRulesType == null)
				{
					list.Add("PinRules");
				}
				if (RuleType == null)
				{
					list.Add("PinRules+Rule");
				}
				if (AutoPinsType == null)
				{
					list.Add("AutoPins");
				}
				if (PinRecordType == null)
				{
					list.Add("PinRecord");
				}
				if (PinNamesType == null)
				{
					list.Add("PinNames");
				}
				if (list.Count > 0)
				{
					FailReason = "缺少类型:" + string.Join(", ", list);
					return false;
				}
				MBindPinRules = Find(PluginType, "BindPinRules", list, "Plugin.BindPinRules");
				MSweep = Find(AutoPinsType, "Sweep", list, "AutoPins.Sweep");
				MBuild = Find(AutoPinsType, "Build", list, "AutoPins.Build");
				MPlace = Find(AutoPinsType, "Place", list, "AutoPins.Place");
				MPinRecordHas = Find(PinRecordType, "Has", list, "PinRecord.Has");
				MPinNamesFor = AccessTools.Method(PinNamesType, "For", new Type[2]
				{
					RuleType,
					typeof(GameObject)
				}, (Type[])null);
				if (MPinNamesFor == null)
				{
					list.Add("PinNames.For(Rule, GameObject)");
				}
				MMinimapAddPin = AccessTools.Method(typeof(Minimap), "AddPin", (Type[])null, (Type[])null);
				MMinimapUpdate = AccessTools.Method(typeof(Minimap), "Update", (Type[])null, (Type[])null);
				FAutoPin = Field(PluginType, "autoPin", list);
				FMergeDistance = Field(PluginType, "autoPinMergeDistance", list);
				FExplorationRadius = Field(PluginType, "explorationRadius", list);
				FRulesAll = Field(PinRulesType, "All", list);
				FName = Field(RuleType, "Name", list);
				FDescription = Field(RuleType, "Description", list);
				FNameToken = Field(RuleType, "NameToken", list);
				FPrefabs = Field(RuleType, "Prefabs", list);
				FBiome = Field(RuleType, "Biome", list);
				FCategory = Field(RuleType, "Category", list);
				FDefaultOn = Field(RuleType, "DefaultOn", list);
				FIsLocation = Field(RuleType, "IsLocation", list);
				FEnabled = Field(RuleType, "Enabled", list);
				if (list.Count > 0)
				{
					FailReason = "缺少成员:" + string.Join(", ", list);
					return false;
				}
				FComponent = AccessTools.Field(RuleType, "Component");
				Ready = true;
				return true;
			}
			catch (Exception ex)
			{
				FailReason = ex.ToString();
				return false;
			}
		}

		private static MethodInfo Find(Type t, string name, List<string> missing, string label)
		{
			MethodInfo methodInfo = AccessTools.Method(t, name, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				missing.Add(label);
			}
			return methodInfo;
		}

		private static FieldInfo Field(Type t, string name, List<string> missing)
		{
			FieldInfo fieldInfo = AccessTools.Field(t, name);
			if (fieldInfo == null)
			{
				missing.Add(t.Name + "." + name);
			}
			return fieldInfo;
		}

		internal static IList Rules()
		{
			return FRulesAll.GetValue(null) as IList;
		}

		internal static bool AutoPinEnabled()
		{
			return Value<bool>(FAutoPin);
		}

		internal static float ExplorationRadius()
		{
			return Value<float>(FExplorationRadius);
		}

		internal static float MergeDistance()
		{
			return Value<float>(FMergeDistance);
		}

		private static T Value<T>(FieldInfo configEntryField)
		{
			if (!(configEntryField.GetValue(null) is ConfigEntry<T> val))
			{
				return default(T);
			}
			return val.Value;
		}

		internal static string Name(object rule)
		{
			return (string)FName.GetValue(rule);
		}

		internal static Biome BiomeOf(object rule)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return (Biome)FBiome.GetValue(rule);
		}

		internal static object Category(object rule)
		{
			return FCategory.GetValue(rule);
		}

		internal static string[] PrefabsOf(object rule)
		{
			try
			{
				return FPrefabs.GetValue(rule) as string[];
			}
			catch
			{
				return null;
			}
		}

		internal static bool IsLocation(object rule)
		{
			return (bool)FIsLocation.GetValue(rule);
		}

		internal static bool HasComponent(object rule)
		{
			if (FComponent != null)
			{
				return FComponent.GetValue(rule) != null;
			}
			return false;
		}

		internal static bool? RuleEnabled(object rule)
		{
			if (!(FEnabled.GetValue(rule) is ConfigEntry<bool> val))
			{
				return null;
			}
			return val.Value;
		}

		internal static object NewRule(string name, string description, string nameToken, string[] prefabs, Biome biome, object category, bool defaultOn, bool isLocation, Type component = null)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			object obj = Activator.CreateInstance(RuleType);
			FName.SetValue(obj, name);
			FDescription.SetValue(obj, description);
			FNameToken.SetValue(obj, nameToken);
			FPrefabs.SetValue(obj, (component != null) ? null : prefabs);
			FBiome.SetValue(obj, biome);
			FCategory.SetValue(obj, category);
			FDefaultOn.SetValue(obj, defaultOn);
			FIsLocation.SetValue(obj, isLocation);
			FEnabled.SetValue(obj, null);
			if (component != null && FComponent != null)
			{
				FComponent.SetValue(obj, component);
			}
			return obj;
		}

		internal static void Place(object rule, Vector3 pos)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			MPlace.Invoke(null, new object[3] { rule, null, pos });
		}

		internal static void BindRule(object rule)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			if (BetterMapConfig != null && FEnabled.GetValue(rule) == null)
			{
				ConfigEntry<bool> value = BetterMapConfig.Bind<bool>("Auto Pins - " + FBiome.GetValue(rule), (string)FName.GetValue(rule), (bool)FDefaultOn.GetValue(rule), new ConfigDescription((string)FDescription.GetValue(rule), (AcceptableValueBase)null, Array.Empty<object>()));
				FEnabled.SetValue(rule, value);
			}
		}

		internal static bool AlreadyRecorded(object category, Vector3 pos, float mergeDistance)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			return (bool)MPinRecordHas.Invoke(null, new object[3] { category, pos, mergeDistance });
		}
	}
	[BepInPlugin("bettermapfix.client.only", "BetterMapFix", "1.1.11")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class BetterMapFixPlugin : BaseUnityPlugin
	{
		public const string Guid = "bettermapfix.client.only";

		public const string PluginName = "BetterMapFix";

		public const string PluginVersion = "1.1.11";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> Enabled;

		internal static ConfigEntry<bool> ScanVegvisirs;

		internal static ConfigEntry<bool> InjectCaveRules;

		internal static ConfigEntry<bool> LogUnknownPinNames;

		internal static ConfigEntry<bool> ChineseLabelEnabled;

		internal static ConfigEntry<string> NameMap;

		internal static ConfigEntry<bool> MergeDefaultMap;

		internal static ConfigEntry<bool> RenameExistingPins;

		internal static ConfigEntry<bool> DumpLocations;

		internal static ConfigEntry<string> DumpZNetNames;

		internal static ConfigEntry<bool> VerbosePinLog;

		private void Awake()
		{
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: Expected O, but got Unknown
			//IL_0223: Unknown result type (might be due to invalid IL or missing references)
			//IL_0231: Expected O, but got Unknown
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Expected O, but got Unknown
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Expected O, but got Unknown
			//IL_02d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dd: Expected O, but got Unknown
			//IL_0308: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Expected O, but got Unknown
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_036a: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "Enabled", true, "总开关。关掉后本补丁完全不介入 BetterMap(重新加载生效)。\nMaster switch. Off = this patch does nothing at all.");
			ScanVegvisirs = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Vegvisirs", "Scan Vegvisirs", true, "修复「Boss 指引石被找到后不落图钉」。\n做法:沿用原模组自己的扫描节奏(Sweep Interval)与探索半径(Exploration Radius),\n补扫玩家附近真实存在的指引石,再调用原模组自己的落钉函数。\n开关仍然听 BetterMap 各群系里的 Vegvisirs 选项(本补丁不改它)。\n【BetterMap 1.0.4 起】上游自己已经会用「Location 生成事件 + 扫内部组件」标记指引石,\n本补丁也把迷雾之地那条规则交给它(填 Rule.Component)。此时这一项相当于**兜底**:\n上游落过钉的位置会被去重记录挡住,所以不会出现重复图钉,只是多扫一遍。\nFix: pin boss vegvisir stones, using BetterMap's own sweep cadence / radius / pin code.");
			InjectCaveRules = ((BaseUnityPlugin)this).Config.Bind<bool>("3 - Caves", "Inject Cave Rules", true, "向 BetterMap 补几条它漏掉的地牢入口规则(腐疫矿区、腐朽之穴等)。\n注入后这些开关出现在 BetterMap 自己的 cfg 里,按群系排在其它洞穴选项旁边:\n  [Auto Pins - Mistlands]  Infested Mines(腐疫矿区)\n  [Auto Pins - AshLands]   Morgen Holes(腐朽之穴)\n  [Auto Pins - Mountain]   Frost Caves / Hildir Cave\n  [Auto Pins - BlackForest] Half Burried Crypt / Hildir Crypt\n  [Auto Pins - Plains]     Hildir Fortress\n原模组自己已经有的条目(如 1.0.4 的 Frost Caves)会被自动跳过,不会重复。\nAdds the dungeon-entrance rules BetterMap is missing (infested mines, morgen holes etc.).\nTheir switches show up in BetterMap's own config file, next to the other caves.");
			LogUnknownPinNames = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Labels", "Log Unknown Pin Names", true, "**诊断开关**:把「映射表没命中」的图钉名打进日志(去重,最多 60 个,满就停)。\n用途:有些图钉名不是规则名(比如生物走 Character.m_name),静态分析看不出来,\n只能靠真机日志。看到不认识的英文名,加进 `Name Map` 就能翻。\nDiagnostic: log pin names the name map did not match (deduped, max 60).");
			ChineseLabelEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Labels", "Chinese Labels", true, "把地图图钉上的英文名换成中文(洞穴、要塞、祭坛那类地点图钉)。\n只改图钉标签这一层:不动 BetterMap 的 cfg 键名、规则表、图标与去重记录。\n做法是给原模组算图钉名的函数做一个精确整串替换。\nRename map pin labels to Chinese. Only the label string changes - config keys, rules,\nicons and the de-dup record are untouched.");
			NameMap = ((BaseUnityPlugin)this).Config.Bind<string>("4 - Labels", "Name Map", "Burial Chambers=陪葬墓室,Troll Caves=巨魔洞穴,Bear Caves=巨熊洞穴,Sunken Crypts=沉没墓穴,Frost Caves=冰霜洞穴,Half Burried Crypt=半埋墓穴,Hildir Cave=希尔迪洞穴,Hildir Crypt=希尔迪墓穴,Hildir Fortress=希尔迪平原要塞,Entrance to the Queen=女王巢穴入口,Charred Fortresses=焦黑要塞,Dvergr Town=矮人村落,Infested Mines=腐疫矿区,Putrid Holes=腐朽之穴,Morkhalla=黑暗大厅,The Hole=冰窟营地,Memorial Places=纪念之地,Places of Mystery=谜团之地,Tar Pits=焦油坑,Sulfur Arches=硫磺拱,Frozen Trolls=冰冻巨魔遗骸,Boar Runestones=鬓猪符文石,Draugr Runestones=尸鬼符文石,Greydwarf Runestones=灰矮人符文石,Altar of Eikthyr=埃克提尔祭坛,Altar of the Elder=上古者祭坛,Altar of Bonemass=骨魔祭坛,Altar of Moder=龙母祭坛,Altar of Yagluth=亚格鲁斯祭坛,Altar of Fader=法德祭坛,Copper Deposits=铜矿源,Tin Deposits=锡矿源,Silver Deposits=银矿源,Obsidian Deposits=黑曜石矿源,Flametal=焰金属,Muddy Scrap Piles=泥泞废料堆,Giant Remains=巨人遗骸,Yggdrasil Roots=世界之树根,Flint=燧石,Thistle=蓟草,Mushrooms=蘑菇,Dandelions=蒲公英,Blueberry Bushes=蓝莓丛,Raspberry Bushes=覆盆子丛,Cloudberry Bushes=云莓丛,Lingonberry Bushes=越橘丛,Carrot Seeds=胡萝卜种子,Turnip Seeds=芜菁种子,Kale Seeds=羽衣甘蓝种子,Vineberries=酒莓,Smoke Puffs=余烬泡泡,Jotun Puffs=巨人泡泡,Magecap=法师帽菇,Snowballs=雪球,Beehives=蜂房,Greydwarf Nests=灰矮人巢穴,Greydwarf Nest=灰矮人巢穴,Drake Nests=幼龙巢,Surtling Fire Holes=苏尔特尔火洞,Volture Nests=兀鹰巢,Fuling Totems=丑地精图腾,Dvergr Needle Crates=矮人针箱,Dvergr Excavations=矮人挖掘场,Charred Skulls=焦黑头骨,Charred Tower Ruins=焦黑塔遗迹,Charred Spawner Towers=焦黑刷怪塔,Ash Pots=灰烬陶罐,Ash Pot=灰烬陶罐,Unstable Lava Rock=不稳定熔岩,Leviathans=甲壳素,Leviathan=甲壳素,Vegvisirs=导向符文石,Soft Tissue=软组织", "英文名=中文名,用逗号分隔。只做**整串精确匹配**,不在这张表里的名字原样保留。\n规则名可以照抄 BetterMap cfg 里的键名。\n※ 本表会与内置默认表**合并**(见下面 Merge Default Map)。\n※ 内置表已覆盖 BetterMap **全部规则名**(69 条),所以正常情况下你不用动这里。\n※ `英文名=`(值留空)表示**删掉这一条**,用来去掉不想要的内置译名。\n想改某条内置译名,直接写 `英文名=你的译名`(你的优先),例如:\n   Thistle=蓟,Leviathans=大海龟,Silver Deposits=银矿脉\n(在游戏里改这项会立即生效;直接改 cfg 文件要重启游戏。)\nComma-separated English=Chinese pairs, matched as a whole string only.\nMerged with the built-in table (which already covers all 69 rule names);\n`Name=` with an empty value removes that entry.");
			MergeDefaultMap = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Labels", "Merge Default Map", true, "把**内置默认译名表**合并进你上面那张 `Name Map`(你的条目优先、可覆盖内置译名)。\n为什么需要它:BepInEx 的配置有个特性 —— 当 cfg 文件里**已经存在**某个键时,\n它**不会**用新的默认值去覆盖你文件里的旧值。于是本补丁每次升级新增的内置译名,\n对老用户(cfg 里已写过旧表)**永远不会生效**,表现为\n「新补的地牢图钉标出来了,但名字还是英文」。\n开着这项就会自动补齐,你不必手动去改 cfg。(补丁 1.1.0 起有这个开关。)\n· 想完全自己掌控映射表(只认你写的那张):关掉本项;\n· 想删掉某条内置译名:在 Name Map 里写「英文名=」(值留空),或直接关掉本项。\nMerge the built-in default map into your Name Map (yours wins). Needed because\nBepInEx keeps the value already written in your config file, so newly added\nbuilt-in entries would otherwise never take effect after a mod update.");
			RenameExistingPins = ((BaseUnityPlugin)this).Config.Bind<bool>("4 - Labels", "Rename Existing Pins", true, "连**已经放上去的旧图钉**也一并改名(名字是落钉那一刻写进地图数据的,所以要单独跑一趟)。\n只重命名名字精确命中映射表的图钉,其余一概不碰;关掉它就只影响新落的钉。\nAlso rename pins that are already on the map. Only exact matches are touched.");
			DumpLocations = ((BaseUnityPlugin)this).Config.Bind<bool>("9 - Debug", "Dump Location Names", false, "打开后,世界加载完把游戏的地点表整表打进日志(名字 / 预制体名 / 群系 / 是否启用)。\n用来核对洞穴位置名对不对(例如确认 MountainCave02 就是冰霜洞穴)。\nLog the whole location table once per world load — to verify the injected prefab names.");
			DumpZNetNames = ((BaseUnityPlugin)this).Config.Bind<string>("9 - Debug", "Dump ZNet Names", "giant", "**诊断**:把 `ZNetScene` 里名字含该关键词的预制体 / 世界里活着的实例打进日志\n(一个世界只打一次)。多个关键词用逗号分隔;留空即关闭。\n回答两个问题:① 规则里写的预制体名**到底注册没有**(没注册 ⇒ 永远匹配不到);\n② 世界里那个东西的**实际名字**是什么。\nDump ZNetScene prefab/instance names matching these substrings. Empty = off.");
			VerbosePinLog = ((BaseUnityPlugin)this).Config.Bind<bool>("9 - Debug", "Verbose Pin Log", true, "每落一个指引石图钉就打一行日志(群系 + 坐标 + 距离)。\nLog every vegvisir pin this patch places.");
			if (!Enabled.Value)
			{
				Log.LogInfo((object)"BetterMapFix: 配置里已关闭,不介入。");
				return;
			}
			if (!Chainloader.PluginInfos.TryGetValue("xtav1m.BetterMap", out var value) || (Object)(object)value.Instance == (Object)null)
			{
				Log.LogWarning((object)"BetterMapFix: 没检测到 BetterMap(xtav1m.BetterMap),补丁不生效。装上 BetterMap 后重启游戏即可。");
				return;
			}
			if (!BetterMapApi.Init(((object)value.Instance).GetType().Assembly, value.Instance.Config))
			{
				Log.LogError((object)("BetterMapFix: BetterMap 内部接口自检不通过(多半是它换了版本),补丁不生效。\n  原因:" + BetterMapApi.FailReason));
				return;
			}
			Harmony val = new Harmony("bettermapfix.client.only");
			try
			{
				val.Patch((MethodBase)BetterMapApi.MBuild, new HarmonyMethod(AccessTools.Method(typeof(RuleInjection), "BuildPrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				val.Patch((MethodBase)BetterMapApi.MBindPinRules, new HarmonyMethod(AccessTools.Method(typeof(RuleInjection), "BindPinRulesPrefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				if (ScanVegvisirs.Value)
				{
					val.Patch((MethodBase)BetterMapApi.MSweep, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(VegvisirScanner), "Postfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
				if (ChineseLabelEnabled.Value && BetterMapApi.MPinNamesFor != null)
				{
					val.Patch((MethodBase)BetterMapApi.MPinNamesFor, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(ChineseLabels), "PinNamesForPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					if (BetterMapApi.MMinimapAddPin != null)
					{
						val.Patch((MethodBase)BetterMapApi.MMinimapAddPin, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(ChineseLabels), "AddPinPostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					}
					else
					{
						Log.LogWarning((object)"BetterMapFix: 找不到 Minimap.AddPin,非规则路径落钉的图钉名不会中文。");
					}
					if (RenameExistingPins.Value)
					{
						if (BetterMapApi.MMinimapUpdate != null)
						{
							val.Patch((MethodBase)BetterMapApi.MMinimapUpdate, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(ChineseLabels), "MinimapUpdatePostfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						}
						else
						{
							Log.LogWarning((object)"BetterMapFix: 找不到 Minimap.Update,已有图钉不会改名(新落钉仍为中文)。");
						}
					}
					ChineseLabels.ReloadMap();
					NameMap.SettingChanged += delegate
					{
						ChineseLabels.ReloadMap();
					};
					MergeDefaultMap.SettingChanged += delegate
					{
						ChineseLabels.ReloadMap();
					};
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("BetterMapFix: 挂 Harmony 补丁失败:" + ex));
				return;
			}
			Log.LogInfo((object)string.Format("BetterMapFix {0} 已加载:洞穴规则注入={1},指引石扫描={2},中文图钉名={3}(接口自检通过)。", "1.1.11", InjectCaveRules.Value, ScanVegvisirs.Value, ChineseLabelEnabled.Value));
			Log.LogInfo((object)("BetterMapFix: 检测到 BetterMap 支持 Rule.Component(1.0.4+):" + (BetterMapApi.SupportsComponent ? "是 —— 迷雾之地 Vegvisirs 交给它自己的「Location 内部组件」通道,本补丁扫描仅兜底。" : "否(1.0.2/1.0.3)—— 迷雾之地 Vegvisirs 只能靠本补丁自己扫描落钉。")));
		}

		private void Update()
		{
			DebugDump.Tick();
		}
	}
	internal static class ChineseLabels
	{
		private static Dictionary<string, string> _map = new Dictionary<string, string>(StringComparer.Ordinal);

		private static FieldInfo _mPins;

		private static PropertyInfo _pinNameTextProp;

		private static PropertyInfo _tmpTextProp;

		private static bool _reflectBroken;

		private static bool _loggedTextFail;

		private static float _nextRenamePass;

		private static int _renamedTotal;

		internal const float RenameInterval = 2f;

		internal const string DefaultMap = "Burial Chambers=陪葬墓室,Troll Caves=巨魔洞穴,Bear Caves=巨熊洞穴,Sunken Crypts=沉没墓穴,Frost Caves=冰霜洞穴,Half Burried Crypt=半埋墓穴,Hildir Cave=希尔迪洞穴,Hildir Crypt=希尔迪墓穴,Hildir Fortress=希尔迪平原要塞,Entrance to the Queen=女王巢穴入口,Charred Fortresses=焦黑要塞,Dvergr Town=矮人村落,Infested Mines=腐疫矿区,Putrid Holes=腐朽之穴,Morkhalla=黑暗大厅,The Hole=冰窟营地,Memorial Places=纪念之地,Places of Mystery=谜团之地,Tar Pits=焦油坑,Sulfur Arches=硫磺拱,Frozen Trolls=冰冻巨魔遗骸,Boar Runestones=鬓猪符文石,Draugr Runestones=尸鬼符文石,Greydwarf Runestones=灰矮人符文石,Altar of Eikthyr=埃克提尔祭坛,Altar of the Elder=上古者祭坛,Altar of Bonemass=骨魔祭坛,Altar of Moder=龙母祭坛,Altar of Yagluth=亚格鲁斯祭坛,Altar of Fader=法德祭坛,Copper Deposits=铜矿源,Tin Deposits=锡矿源,Silver Deposits=银矿源,Obsidian Deposits=黑曜石矿源,Flametal=焰金属,Muddy Scrap Piles=泥泞废料堆,Giant Remains=巨人遗骸,Yggdrasil Roots=世界之树根,Flint=燧石,Thistle=蓟草,Mushrooms=蘑菇,Dandelions=蒲公英,Blueberry Bushes=蓝莓丛,Raspberry Bushes=覆盆子丛,Cloudberry Bushes=云莓丛,Lingonberry Bushes=越橘丛,Carrot Seeds=胡萝卜种子,Turnip Seeds=芜菁种子,Kale Seeds=羽衣甘蓝种子,Vineberries=酒莓,Smoke Puffs=余烬泡泡,Jotun Puffs=巨人泡泡,Magecap=法师帽菇,Snowballs=雪球,Beehives=蜂房,Greydwarf Nests=灰矮人巢穴,Greydwarf Nest=灰矮人巢穴,Drake Nests=幼龙巢,Surtling Fire Holes=苏尔特尔火洞,Volture Nests=兀鹰巢,Fuling Totems=丑地精图腾,Dvergr Needle Crates=矮人针箱,Dvergr Excavations=矮人挖掘场,Charred Skulls=焦黑头骨,Charred Tower Ruins=焦黑塔遗迹,Charred Spawner Towers=焦黑刷怪塔,Ash Pots=灰烬陶罐,Ash Pot=灰烬陶罐,Unstable Lava Rock=不稳定熔岩,Leviathans=甲壳素,Leviathan=甲壳素,Vegvisirs=导向符文石,Soft Tissue=软组织";

		private const int UnknownNameLimit = 60;

		private static HashSet<string> _unknownNames;

		private static List<KeyValuePair<string, string>> ParsePairs(string raw)
		{
			List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>();
			if (string.IsNullOrEmpty(raw))
			{
				return list;
			}
			string[] array = raw.Split(',', '\n');
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length == 0)
				{
					continue;
				}
				int num = text.IndexOf('=');
				if (num > 0)
				{
					string text2 = text.Substring(0, num).Trim();
					string value = text.Substring(num + 1).Trim();
					if (text2.Length > 0)
					{
						list.Add(new KeyValuePair<string, string>(text2, value));
					}
				}
			}
			return list;
		}

		internal static void ReloadMap()
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal);
			int num = 0;
			if (BetterMapFixPlugin.MergeDefaultMap.Value)
			{
				foreach (KeyValuePair<string, string> item in ParsePairs("Burial Chambers=陪葬墓室,Troll Caves=巨魔洞穴,Bear Caves=巨熊洞穴,Sunken Crypts=沉没墓穴,Frost Caves=冰霜洞穴,Half Burried Crypt=半埋墓穴,Hildir Cave=希尔迪洞穴,Hildir Crypt=希尔迪墓穴,Hildir Fortress=希尔迪平原要塞,Entrance to the Queen=女王巢穴入口,Charred Fortresses=焦黑要塞,Dvergr Town=矮人村落,Infested Mines=腐疫矿区,Putrid Holes=腐朽之穴,Morkhalla=黑暗大厅,The Hole=冰窟营地,Memorial Places=纪念之地,Places of Mystery=谜团之地,Tar Pits=焦油坑,Sulfur Arches=硫磺拱,Frozen Trolls=冰冻巨魔遗骸,Boar Runestones=鬓猪符文石,Draugr Runestones=尸鬼符文石,Greydwarf Runestones=灰矮人符文石,Altar of Eikthyr=埃克提尔祭坛,Altar of the Elder=上古者祭坛,Altar of Bonemass=骨魔祭坛,Altar of Moder=龙母祭坛,Altar of Yagluth=亚格鲁斯祭坛,Altar of Fader=法德祭坛,Copper Deposits=铜矿源,Tin Deposits=锡矿源,Silver Deposits=银矿源,Obsidian Deposits=黑曜石矿源,Flametal=焰金属,Muddy Scrap Piles=泥泞废料堆,Giant Remains=巨人遗骸,Yggdrasil Roots=世界之树根,Flint=燧石,Thistle=蓟草,Mushrooms=蘑菇,Dandelions=蒲公英,Blueberry Bushes=蓝莓丛,Raspberry Bushes=覆盆子丛,Cloudberry Bushes=云莓丛,Lingonberry Bushes=越橘丛,Carrot Seeds=胡萝卜种子,Turnip Seeds=芜菁种子,Kale Seeds=羽衣甘蓝种子,Vineberries=酒莓,Smoke Puffs=余烬泡泡,Jotun Puffs=巨人泡泡,Magecap=法师帽菇,Snowballs=雪球,Beehives=蜂房,Greydwarf Nests=灰矮人巢穴,Greydwarf Nest=灰矮人巢穴,Drake Nests=幼龙巢,Surtling Fire Holes=苏尔特尔火洞,Volture Nests=兀鹰巢,Fuling Totems=丑地精图腾,Dvergr Needle Crates=矮人针箱,Dvergr Excavations=矮人挖掘场,Charred Skulls=焦黑头骨,Charred Tower Ruins=焦黑塔遗迹,Charred Spawner Towers=焦黑刷怪塔,Ash Pots=灰烬陶罐,Ash Pot=灰烬陶罐,Unstable Lava Rock=不稳定熔岩,Leviathans=甲壳素,Leviathan=甲壳素,Vegvisirs=导向符文石,Soft Tissue=软组织"))
				{
					dictionary[item.Key] = item.Value;
					num++;
				}
			}
			int num2 = 0;
			int num3 = 0;
			int num4 = 0;
			foreach (KeyValuePair<string, string> item2 in ParsePairs(BetterMapFixPlugin.NameMap.Value))
			{
				if (item2.Value.Length == 0)
				{
					if (dictionary.Remove(item2.Key))
					{
						num4++;
					}
					continue;
				}
				if (dictionary.ContainsKey(item2.Key))
				{
					num3++;
				}
				else
				{
					num2++;
				}
				dictionary[item2.Key] = item2.Value;
			}
			_map = dictionary;
			string text = (BetterMapFixPlugin.MergeDefaultMap.Value ? $"内置 {num} 条 ∪ 用户表" : "只用用户表(不合并内置)");
			BetterMapFixPlugin.Log.LogInfo((object)string.Format("BetterMapFix: 中文名映射 = {0}(覆盖 {1} / 用户新增 {2} / 显式删除 {3})→ 生效 {4} 条{5}", text, num3, num2, num4, dictionary.Count, (dictionary.Count == 0) ? "(映射为空 ⇒ 图钉名保持原样)" : ""));
		}

		internal static void PinNamesForPostfix(ref string __result)
		{
			try
			{
				if (BetterMapFixPlugin.ChineseLabelEnabled.Value && !string.IsNullOrEmpty(__result) && _map.TryGetValue(__result, out var value))
				{
					__result = value;
				}
			}
			catch (Exception ex)
			{
				BetterMapFixPlugin.Log.LogError((object)("BetterMapFix: 图钉名替换出错(已忽略):" + ex.Message));
			}
		}

		internal static void AddPinPostfix(PinData __result)
		{
			try
			{
				if (__result == null || !BetterMapFixPlugin.ChineseLabelEnabled.Value)
				{
					return;
				}
				string name = __result.m_name;
				if (!string.IsNullOrEmpty(name))
				{
					if (_map.TryGetValue(name, out var value))
					{
						RenamePin(__result, value);
					}
					else
					{
						LogUnknownName(name);
					}
				}
			}
			catch (Exception ex)
			{
				BetterMapFixPlugin.Log.LogError((object)("BetterMapFix: AddPin 改名出错(已忽略):" + ex.Message));
			}
		}

		internal static void MinimapUpdatePostfix()
		{
			try
			{
				if (BetterMapFixPlugin.ChineseLabelEnabled.Value && !(Time.time < _nextRenamePass))
				{
					_nextRenamePass = Time.time + 2f;
					if (BetterMapFixPlugin.RenameExistingPins.Value && _map.Count > 0)
					{
						RenameExisting();
					}
				}
			}
			catch (Exception ex)
			{
				BetterMapFixPlugin.Log.LogError((object)("BetterMapFix: 图钉重命名出错(已忽略):" + ex.Message));
			}
		}

		private static void RenameExisting()
		{
			Minimap instance = Minimap.instance;
			if ((Object)(object)instance == (Object)null || _map.Count == 0)
			{
				return;
			}
			if (_mPins == null)
			{
				_mPins = AccessTools.Field(typeof(Minimap), "m_pins");
			}
			if (_mPins == null)
			{
				if (!_reflectBroken)
				{
					_reflectBroken = true;
					BetterMapFixPlugin.Log.LogWarning((object)"BetterMapFix: 找不到 Minimap.m_pins,已有图钉无法改名(新落钉仍是中文)。");
				}
			}
			else
			{
				if (!(_mPins.GetValue(instance) is IList list))
				{
					return;
				}
				int num = 0;
				for (int i = 0; i < list.Count; i++)
				{
					object? obj = list[i];
					PinData val = (PinData)((obj is PinData) ? obj : null);
					if (val != null)
					{
						string name = val.m_name;
						if (!string.IsNullOrEmpty(name) && _map.TryGetValue(name, out var value))
						{
							RenamePin(val, value);
							num++;
						}
					}
				}
				if (num > 0)
				{
					_renamedTotal += num;
					BetterMapFixPlugin.Log.LogInfo((object)$"BetterMapFix: 已有图钉改中文名 {num} 个(累计 {_renamedTotal} 个)。");
				}
			}
		}

		private static void LogUnknownName(string name)
		{
			if (!BetterMapFixPlugin.LogUnknownPinNames.Value || name.StartsWith("$"))
			{
				return;
			}
			for (int i = 0; i < name.Length; i++)
			{
				if (name[i] > '~')
				{
					return;
				}
			}
			if (_unknownNames == null)
			{
				_unknownNames = new HashSet<string>(StringComparer.Ordinal);
			}
			if (_unknownNames.Count < 60 && _unknownNames.Add(name))
			{
				BetterMapFixPlugin.Log.LogInfo((object)$"BetterMapFix: [诊断] 未翻译的图钉名 #{_unknownNames.Count}: \"{name}\"(满 {60} 个后停止记录)");
			}
		}

		private static void RenamePin(PinData pin, string zh)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			pin.m_name = zh;
			PinNameData namePinData = pin.m_NamePinData;
			if (namePinData == null)
			{
				pin.m_NamePinData = new PinNameData(pin);
				return;
			}
			try
			{
				if (_pinNameTextProp == null)
				{
					_pinNameTextProp = ((object)namePinData).GetType().GetProperty("PinNameText");
				}
				object obj = ((_pinNameTextProp != null) ? _pinNameTextProp.GetValue(namePinData) : null);
				if (obj == null)
				{
					pin.m_NamePinData = new PinNameData(pin);
					return;
				}
				if (_tmpTextProp == null)
				{
					_tmpTextProp = obj.GetType().GetProperty("text");
				}
				if (_tmpTextProp != null)
				{
					_tmpTextProp.SetValue(obj, zh);
				}
			}
			catch (Exception ex)
			{
				if (!_loggedTextFail)
				{
					_loggedTextFail = true;
					BetterMapFixPlugin.Log.LogWarning((object)("BetterMapFix: 改图钉显示文本失败(数据里的名字已是中文,下次加载世界会正确显示):" + ex.Message));
				}
			}
		}
	}
	internal static class DebugDump
	{
		private static ZoneSystem _lastZoneSystem;

		private static int _lastCount = -1;

		private static ZNetScene _lastScene;

		private static bool _znetLogged;

		private static FieldInfo _mInstances;

		internal static void TickZNet()
		{
			try
			{
				string value = BetterMapFixPlugin.DumpZNetNames.Value;
				if (string.IsNullOrEmpty(value))
				{
					return;
				}
				ZNetScene instance = ZNetScene.instance;
				if ((Object)(object)instance == (Object)null || (_znetLogged && _lastScene == instance))
				{
					return;
				}
				_lastScene = instance;
				_znetLogged = true;
				List<string> list = new List<string>();
				string[] array = value.Split(',', '\n');
				for (int i = 0; i < array.Length; i++)
				{
					string text = array[i].Trim();
					if (text.Length > 0)
					{
						list.Add(text);
					}
				}
				if (list.Count == 0)
				{
					return;
				}
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append("BetterMapFix: [诊断] ZNetScene 名字核查(关键词:").Append(value).Append(")");
				foreach (string item in list)
				{
					GameObject val = null;
					try
					{
						val = instance.GetPrefab(item);
					}
					catch
					{
					}
					if ((Object)(object)val == (Object)null)
					{
						stringBuilder.Append("\n    [注册检查] «").Append(item).Append("» → **未注册**:规则写这个名字永远匹配不到!");
						continue;
					}
					int value2 = 0;
					try
					{
						value2 = instance.GetPrefabHash(val);
					}
					catch
					{
					}
					stringBuilder.Append("\n    [注册检查] «").Append(item).Append("» → 已注册,hash=")
						.Append(value2);
				}
				List<string> list2 = new List<string>();
				try
				{
					if (instance.m_prefabs != null)
					{
						foreach (GameObject prefab in instance.m_prefabs)
						{
							if ((Object)(object)prefab != (Object)null && Contains(((Object)prefab).name, list))
							{
								list2.Add(((Object)prefab).name);
							}
						}
					}
				}
				catch (Exception ex)
				{
					stringBuilder.Append("\n    <读 m_prefabs 失败:").Append(ex.Message).Append(">");
				}
				list2.Sort(StringComparer.OrdinalIgnoreCase);
				stringBuilder.Append("\n    [已注册预制体] 命中 ").Append(list2.Count).Append(" 个:");
				for (int j = 0; j < list2.Count && j < 80; j++)
				{
					stringBuilder.Append("\n        ").Append(list2[j]);
				}
				HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
				try
				{
					if (_mInstances == null)
					{
						_mInstances = AccessTools.Field(typeof(ZNetScene), "m_instances");
					}
					IDictionary dictionary = ((_mInstances == null) ? null : (_mInstances.GetValue(instance) as IDictionary));
					if (dictionary != null)
					{
						foreach (DictionaryEntry item2 in dictionary)
						{
							object? value3 = item2.Value;
							ZNetView val2 = (ZNetView)((value3 is ZNetView) ? value3 : null);
							if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).gameObject == (Object)null))
							{
								string name = ((Object)((Component)val2).gameObject).name;
								if (name != null && Contains(name, list))
								{
									hashSet.Add(name);
								}
							}
						}
					}
					else
					{
						stringBuilder.Append("\n    <m_instances 取不到(字段没找到)>");
					}
				}
				catch (Exception ex2)
				{
					stringBuilder.Append("\n    <读 m_instances 失败:").Append(ex2.Message).Append(">");
				}
				List<string> list3 = new List<string>(hashSet);
				list3.Sort(StringComparer.OrdinalIgnoreCase);
				stringBuilder.Append("\n    [世界里活着] 命中 ").Append(list3.Count).Append(" 个:");
				for (int k = 0; k < list3.Count && k < 80; k++)
				{
					stringBuilder.Append("\n        ").Append(list3[k]);
				}
				BetterMapFixPlugin.Log.LogInfo((object)stringBuilder.ToString());
			}
			catch (Exception ex3)
			{
				BetterMapFixPlugin.Log.LogError((object)("BetterMapFix: ZNetScene 名字核查出错:" + ex3));
				BetterMapFixPlugin.DumpZNetNames.Value = string.Empty;
			}
		}

		private static bool Contains(string name, List<string> keys)
		{
			for (int i = 0; i < keys.Count; i++)
			{
				if (name.IndexOf(keys[i], StringComparison.OrdinalIgnoreCase) >= 0)
				{
					return true;
				}
			}
			return false;
		}

		internal static void Tick()
		{
			TickLocations();
			TickZNet();
		}

		private static void TickLocations()
		{
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!BetterMapFixPlugin.DumpLocations.Value)
				{
					return;
				}
				ZoneSystem instance = ZoneSystem.instance;
				if ((Object)(object)instance == (Object)null || instance.m_locations == null || instance.m_locations.Count == 0 || (_lastZoneSystem == instance && _lastCount == instance.m_locations.Count))
				{
					return;
				}
				_lastZoneSystem = instance;
				_lastCount = instance.m_locations.Count;
				List<string> list = new List<string>();
				foreach (ZoneLocation location in instance.m_locations)
				{
					if (location != null)
					{
						list.Add($"{location.m_name,-34} | prefab={location.m_prefabName,-34} | biome={location.m_biome,-12} | enable={location.m_enable}");
					}
				}
				list.Sort(StringComparer.OrdinalIgnoreCase);
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append("BetterMapFix: 世界地点表共 ").Append(list.Count).Append(" 条(找洞穴就看 prefab 这一列):");
				for (int i = 0; i < list.Count; i++)
				{
					stringBuilder.Append("\n    ").Append(list[i]);
				}
				BetterMapFixPlugin.Log.LogInfo((object)stringBuilder.ToString());
			}
			catch (Exception ex)
			{
				BetterMapFixPlugin.Log.LogError((object)("BetterMapFix: 打印地点表出错:" + ex));
				BetterMapFixPlugin.DumpLocations.Value = false;
			}
		}
	}
	internal static class RuleInjection
	{
		private static bool _injected;

		private static readonly List<object> _injectedRules = new List<object>();

		private static readonly char[] ForbiddenKeyChars = new char[8] { '=', '\n', '\t', '\\', '"', '\'', '[', ']' };

		private static bool KeySafe(string name, out string bad)
		{
			bad = null;
			if (string.IsNullOrEmpty(name))
			{
				bad = "(空)";
				return false;
			}
			char[] forbiddenKeyChars = ForbiddenKeyChars;
			for (int i = 0; i < forbiddenKeyChars.Length; i++)
			{
				char c = forbiddenKeyChars[i];
				if (name.IndexOf(c) >= 0)
				{
					bad = c switch
					{
						'\t' => "\\t", 
						'\n' => "\\n", 
						_ => c.ToString(), 
					};
					return false;
				}
			}
			return true;
		}

		private static bool SamePrefabSet(string[] a, string[] b)
		{
			if (a == null || b == null)
			{
				return false;
			}
			if (a.Length != b.Length)
			{
				return false;
			}
			HashSet<string> hashSet = new HashSet<string>(a, StringComparer.Ordinal);
			for (int i = 0; i < b.Length; i++)
			{
				if (!hashSet.Contains(b[i]))
				{
					return false;
				}
			}
			return true;
		}

		internal static void BindPinRulesPrefix()
		{
			Guarded(selfBind: false);
		}

		internal static void BuildPrefix()
		{
			Guarded(selfBind: true);
		}

		private static void Guarded(bool selfBind)
		{
			try
			{
				EnsureInjected(selfBind);
			}
			catch (Exception ex)
			{
				BetterMapFixPlugin.Log.LogError((object)("BetterMapFix: 规则注入/绑定出错,已吞掉以免影响 BetterMap:" + ex));
			}
		}

		private static void EnsureInjected(bool selfBind)
		{
			if (!_injected)
			{
				try
				{
					Inject();
				}
				catch (Exception ex)
				{
					BetterMapFixPlugin.Log.LogError((object)("BetterMapFix: 注入洞穴规则失败:" + ex));
					return;
				}
			}
			if (!selfBind)
			{
				return;
			}
			for (int i = 0; i < _injectedRules.Count; i++)
			{
				object rule = _injectedRules[i];
				try
				{
					BetterMapApi.BindRule(rule);
				}
				catch (Exception ex2)
				{
					BetterMapFixPlugin.Log.LogError((object)$"BetterMapFix: 给规则 {BetterMapApi.Name(rule)} 建开关失败(这条不会生效,其余照常):{ex2.Message}");
				}
			}
		}

		private static void Inject()
		{
			if (_injected)
			{
				return;
			}
			IList list = BetterMapApi.Rules();
			if (list == null)
			{
				BetterMapFixPlugin.Log.LogWarning((object)"BetterMapFix: PinRules.All 取不到,这次不注入规则。");
				return;
			}
			object category = CategoryOf(list, "Troll Caves");
			object category2 = CategoryOf(list, "Vegvisirs");
			object category3 = CategoryOf(list, "Giant Remains");
			if (BetterMapFixPlugin.InjectCaveRules.Value)
			{
				AddRule(list, "Frost Caves", "冰霜洞穴的入口(Mountains / MountainCave02)。原版 BetterMap 只在黑森林补了墓穴、巨魔洞、熊洞,山脉这一整段没有洞穴条目。", new string[1] { "MountainCave02" }, (Biome)4, category, defaultOn: true, null, isLocation: true);
				AddRule(list, "Half Burried Crypt", "半埋的森林墓穴入口(BlackForest / HalfBurried_ForestCrypt)。默认关:实测游戏地点表里它的 m_enable=False,原版不会放置它,所以正常情况下不会落钉。", new string[1] { "HalfBurried_ForestCrypt" }, (Biome)8, category, defaultOn: false, null, isLocation: true);
				AddRule(list, "Hildir Cave", "希尔迪的洞穴入口(Mountains / Hildir_cave)。默认关:随希尔迪内容出现。", new string[1] { "Hildir_cave" }, (Biome)4, category, defaultOn: false, null, isLocation: true);
				AddRule(list, "Hildir Crypt", "希尔迪的墓穴入口(BlackForest / Hildir_crypt)。默认关:随希尔迪内容出现。", new string[1] { "Hildir_crypt" }, (Biome)8, category, defaultOn: false, null, isLocation: true);
				AddRule(list, "Hildir Fortress", "希尔迪的平原要塞入口(Plains / Hildir_plainsfortress)。默认关:随希尔迪内容出现。", new string[1] { "Hildir_plainsfortress" }, (Biome)16, category, defaultOn: false, null, isLocation: true);
				AddRule(list, "Soft Tissue", "软组织(Mistlands / giant_brain)。上游的 Giant Remains 只钉骨与盔甲武器,不认软组织。", new string[1] { "giant_brain" }, (Biome)512, category3, defaultOn: true, null, isLocation: false);
			}
			if (BetterMapApi.SupportsComponent)
			{
				AddRule(list, "Vegvisirs", "指引石:迷雾之地的女王(SeekerQueen)。原模组每段都有 Vegvisirs,唯独迷雾之地缺这一条。", null, (Biome)512, category2, defaultOn: true, "$piece_vegvisir", isLocation: false, typeof(Vegvisir));
			}
			else
			{
				AddRule(list, "Vegvisirs", "指引石:迷雾之地的女王(SeekerQueen)。原模组每段都有 Vegvisirs,唯独迷雾之地缺这一条。", new string[1] { "Vegvisir_SeekerQueen" }, (Biome)512, category2, defaultOn: true, "$piece_vegvisir", isLocation: false);
			}
			_injected = true;
			BetterMapFixPlugin.Log.LogInfo((object)("BetterMapFix: 规则注入完成(洞穴 " + (BetterMapFixPlugin.InjectCaveRules.Value ? "已开" : "已关") + ",含迷雾之地 Vegvisirs" + (BetterMapApi.SupportsComponent ? "(走上游 Component 通道)" : "(走预制体通道)") + "),共 " + _injectedRules.Count + " 条。"));
		}

		private static object CategoryOf(IList all, string ruleName)
		{
			for (int i = 0; i < all.Count; i++)
			{
				object obj = all[i];
				if (obj != null && BetterMapApi.Name(obj) == ruleName)
				{
					return BetterMapApi.Category(obj);
				}
			}
			BetterMapFixPlugin.Log.LogWarning((object)("BetterMapFix: 没找到规则 «" + ruleName + "»,类别留空。"));
			return null;
		}

		private unsafe static void AddRule(IList all, string name, string description, string[] prefabs, Biome biome, object category, bool defaultOn, string nameToken, bool isLocation, Type component = null)
		{
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			if (!KeySafe(name, out var bad))
			{
				BetterMapFixPlugin.Log.LogError((object)("BetterMapFix: 规则名 «" + name + "» 含 BepInEx 禁用字符 «" + bad + "»,跳过注入 —— 这个名字会被原模组当成 cfg 键,带非法字符会让它 Bind 时抛异常。"));
				return;
			}
			for (int i = 0; i < all.Count; i++)
			{
				object obj = all[i];
				if (obj != null && BetterMapApi.Name(obj) == name && BetterMapApi.BiomeOf(obj) == biome)
				{
					BetterMapFixPlugin.Log.LogInfo((object)("BetterMapFix: 规则 [" + ((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString() + "] " + name + " 已存在(原模组自己提供,或本补丁已注入过),跳过。"));
					return;
				}
			}
			if (prefabs != null && prefabs.Length != 0)
			{
				for (int j = 0; j < all.Count; j++)
				{
					object obj2 = all[j];
					if (obj2 != null)
					{
						string[] array = BetterMapApi.PrefabsOf(obj2);
						if (array != null && array.Length != 0 && SamePrefabSet(array, prefabs))
						{
							BetterMapFixPlugin.Log.LogInfo((object)("BetterMapFix: 规则 «" + name + "» 盯的 prefab 已被上游规则 «" + BetterMapApi.Name(obj2) + "» 覆盖 ⇒ 跳过注入(上游已提供,不需要补)。"));
							return;
						}
					}
				}
			}
			object obj3 = BetterMapApi.NewRule(name, description, nameToken, prefabs, biome, category, defaultOn, isLocation, component);
			all.Add(obj3);
			_injectedRules.Add(obj3);
			string text = ((component != null) ? ("组件 " + component.Name) : ((prefabs != null) ? string.Join(", ", prefabs) : "(无)"));
			BetterMapFixPlugin.Log.LogInfo((object)string.Format("BetterMapFix: +规则 [{0}] {1} → {2}(默认 {3},{4})", biome, name, text, defaultOn ? "开" : "关", isLocation ? "地点类" : ((component != null) ? "组件类" : "预制体类")));
		}
	}
	internal static class VegvisirScanner
	{
		private static readonly Dictionary<Biome, object> _ruleCache = new Dictionary<Biome, object>();

		private static bool _placeBroken;

		internal static void Postfix()
		{
			try
			{
				Scan();
			}
			catch (Exception ex)
			{
				BetterMapFixPlugin.Log.LogError((object)("BetterMapFix: 指引石扫描出错:" + ex));
			}
		}

		private static void Scan()
		{
			//IL_0044: 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)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			if (!BetterMapFixPlugin.ScanVegvisirs.Value || !BetterMapApi.AutoPinEnabled())
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			float num = BetterMapApi.ExplorationRadius();
			if (num <= 0f)
			{
				return;
			}
			float num2 = num * num;
			float mergeDistance = BetterMapApi.MergeDistance();
			Vector3 position = ((Component)localPlayer).transform.position;
			Vegvisir[] array = Object.FindObjectsByType<Vegvisir>((FindObjectsSortMode)0);
			if (array == null || array.Length == 0)
			{
				return;
			}
			int num3 = 0;
			int num4 = 0;
			int num5 = 0;
			foreach (Vegvisir val in array)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Vector3 position2 = ((Component)val).transform.position;
				Vector3 val2 = position2 - position;
				if (((Vector3)(ref val2)).sqrMagnitude > num2)
				{
					continue;
				}
				num3++;
				Biome val3 = Heightmap.FindBiome(position2);
				object obj = RuleFor(val3);
				if (obj == null)
				{
					num5++;
					continue;
				}
				bool? flag = BetterMapApi.RuleEnabled(obj);
				if (flag.HasValue && !flag.Value)
				{
					num5++;
				}
				else if (BetterMapApi.AlreadyRecorded(BetterMapApi.Category(obj), position2, mergeDistance))
				{
					num5++;
				}
				else if (Place(obj, position2))
				{
					num4++;
					if (BetterMapFixPlugin.VerbosePinLog.Value)
					{
						BetterMapFixPlugin.Log.LogInfo((object)$"BetterMapFix: 指引石已标记 [{val3}] 位置 {position2.x:0.0},{position2.z:0.0}(距玩家 {Vector3.Distance(position2, position):0.0} m)");
					}
				}
			}
			if (num4 > 0 || (num3 > 0 && BetterMapFixPlugin.VerbosePinLog.Value))
			{
				BetterMapFixPlugin.Log.LogInfo((object)$"BetterMapFix: 本轮扫到附近指引石 {num3} 块 → 新落钉 {num4},跳过 {num5}(已记过账 / 该段开关关着)。");
			}
		}

		private static object RuleFor(Biome biome)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			if (_ruleCache.TryGetValue(biome, out var value))
			{
				return value;
			}
			object obj = null;
			IList list = BetterMapApi.Rules();
			if (list != null)
			{
				for (int i = 0; i < list.Count; i++)
				{
					object obj2 = list[i];
					if (obj2 != null && !(BetterMapApi.Name(obj2) != "Vegvisirs") && !BetterMapApi.IsLocation(obj2) && BetterMapApi.BiomeOf(obj2) == biome)
					{
						obj = obj2;
						break;
					}
				}
			}
			_ruleCache[biome] = obj;
			return obj;
		}

		private static bool Place(object rule, Vector3 pos)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (_placeBroken)
			{
				return false;
			}
			try
			{
				BetterMapApi.Place(rule, pos);
				return true;
			}
			catch (Exception ex)
			{
				_placeBroken = true;
				BetterMapFixPlugin.Log.LogError((object)("BetterMapFix: 调用 AutoPins.Place 失败,指引石补标记停用(其余功能不受影响):" + ex));
				return false;
			}
		}
	}
}