Decompiled source of RandomTerrainEnhance v1.0.20

RandomTerrainEnhance.dll

Decompiled a week ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using ExitGames.Client.Photon;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PeakCompatibility;
using PeakGameMeters;
using Photon.Pun;
using Photon.Realtime;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UIElements;
using Zorro.Core;

[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("AiAe")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.20.0")]
[assembly: AssemblyInformationalVersion("1.0.20+beb91238582d60e31105455f250d7a12bd6a2262")]
[assembly: AssemblyProduct("RandomTerrainEnhance")]
[assembly: AssemblyTitle("RandomTerrainEnhance")]
[assembly: AssemblyVersion("1.0.20.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 PeakGameMeters
{
	internal static class GameMeterMigration
	{
		internal const string Marker = "# PEAK game-metre migration v1 completed";

		internal static string UpgradeText(string text, float scale, Func<string, string, bool> matches)
		{
			if (text.Contains("# PEAK game-metre migration v1 completed"))
			{
				return text;
			}
			if (float.IsNaN(scale) || float.IsInfinity(scale) || scale <= 0f)
			{
				throw new InvalidOperationException("Invalid PEAK unitsToMeters.");
			}
			string text2 = string.Empty;
			string text3 = Regex.Match(text, "\\r\\n|\\n|\\r").Value;
			if (text3.Length == 0)
			{
				text3 = Environment.NewLine;
			}
			StringBuilder stringBuilder = new StringBuilder("# PEAK game-metre migration v1 completed" + text3);
			foreach (Match item in Regex.Matches(text, "[^\\r\\n]*(?:\\r\\n|\\n|\\r|$)"))
			{
				if (item.Length == 0)
				{
					continue;
				}
				string text4 = item.Value;
				string text5 = text4.Trim();
				if (text5.StartsWith("[", StringComparison.Ordinal) && text5.EndsWith("]", StringComparison.Ordinal))
				{
					text2 = text5.Substring(1, text5.Length - 2).Trim();
				}
				int num = text4.IndexOf('=');
				if (num >= 0 && !text5.StartsWith("#", StringComparison.Ordinal) && !text5.StartsWith(";", StringComparison.Ordinal) && matches(text2, text4.Substring(0, num).Trim()))
				{
					if (!float.TryParse(text4.Substring(num + 1).Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out var result) || float.IsNaN(result) || float.IsInfinity(result))
					{
						throw new FormatException("Invalid legacy distance in section " + text2 + "; migration aborted.");
					}
					float f = result * scale;
					if (float.IsNaN(f) || float.IsInfinity(f))
					{
						throw new FormatException("Legacy distance overflow; migration aborted.");
					}
					string value = Regex.Match(text4, "(?:\\r\\n|\\n|\\r)$").Value;
					text4 = text4.Substring(0, num + 1) + " " + f.ToString("R", CultureInfo.InvariantCulture) + value;
				}
				stringBuilder.Append(text4);
			}
			return stringBuilder.ToString();
		}

		internal static void Upgrade(ConfigFile config, float scale, Func<string, string, bool> matches)
		{
			string configFilePath = config.ConfigFilePath;
			string text = configFilePath + ".game-meters-v1";
			if (File.Exists(text))
			{
				if (File.ReadAllText(text).Trim() != "# PEAK game-metre migration v1 completed")
				{
					throw new IOException("Invalid game-metre migration record: " + text);
				}
				return;
			}
			bool saveOnConfigSet = config.SaveOnConfigSet;
			config.SaveOnConfigSet = false;
			try
			{
				if (File.Exists(configFilePath))
				{
					string text2 = File.ReadAllText(configFilePath);
					string text3 = UpgradeText(text2, scale, matches);
					if (text3 != text2)
					{
						string text4 = configFilePath + "." + Guid.NewGuid().ToString("N") + ".tmp";
						string destinationBackupFileName = configFilePath + ".unity-units-" + DateTime.UtcNow.ToString("yyyyMMddHHmmssfffffff", CultureInfo.InvariantCulture) + ".bak";
						try
						{
							File.WriteAllText(text4, text3, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
							File.Replace(text4, configFilePath, destinationBackupFileName);
						}
						finally
						{
							if (File.Exists(text4))
							{
								File.Delete(text4);
							}
						}
					}
				}
				Directory.CreateDirectory(Path.GetDirectoryName(configFilePath));
				string text5 = text + "." + Guid.NewGuid().ToString("N") + ".tmp";
				try
				{
					File.WriteAllText(text5, "# PEAK game-metre migration v1 completed", new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
					File.Move(text5, text);
				}
				finally
				{
					if (File.Exists(text5))
					{
						File.Delete(text5);
					}
				}
				if (File.Exists(configFilePath))
				{
					config.Reload();
				}
			}
			finally
			{
				config.SaveOnConfigSet = saveOnConfigSet;
			}
		}
	}
}
namespace PeakCompatibility
{
	internal static class CampfireCleanupGuard
	{
		private const string IteratorName = "ShowNextSegmentCoroutine";

		private const string CleanupListFieldName = "viewsToDestoryIfNotAlreadyWhenSwitchingSegments";

		private static FieldInfo? _cleanupListField;

		private static Func<bool>? _enabled;

		private static Action<string>? _log;

		private static Action<PhotonView> _nextDestroy = PhotonNetwork.Destroy;

		private static bool _installed;

		private static bool _errorLogged;

		private static readonly HashSet<int> LoggedViews = new HashSet<int>();

		internal static string State { get; private set; } = "Not installed";

		internal static void Install(Harmony harmony, Func<bool> enabled, Action<string> log)
		{
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Expected O, but got Unknown
			if (_installed)
			{
				return;
			}
			_enabled = enabled;
			_log = log;
			try
			{
				_cleanupListField = AccessTools.Field(typeof(MapHandler), "viewsToDestoryIfNotAlreadyWhenSwitchingSegments");
				List<MethodInfo> list = new List<MethodInfo>();
				FindIteratorMoveNext(typeof(MapHandler), list);
				if (_cleanupListField == null || list.Count != 1)
				{
					State = "Skipped: segment cleanup target not uniquely identified";
					log("[CampfireCleanup] " + State);
					return;
				}
				MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(PhotonNetwork), "Destroy", new Type[1] { typeof(PhotonView) }, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.DeclaredMethod(typeof(CampfireCleanupGuard), "DestroyUnlessProtected", (Type[])null, (Type[])null);
				MethodInfo methodInfo3 = AccessTools.DeclaredMethod(typeof(CampfireCleanupGuard), "Transpile", (Type[])null, (Type[])null);
				if (methodInfo == null || methodInfo2 == null || methodInfo3 == null)
				{
					State = "Skipped: Photon destroy signature changed";
					log("[CampfireCleanup] " + State);
					return;
				}
				harmony.Patch((MethodBase)list[0], (HarmonyMethod)null, (HarmonyMethod)null, new HarmonyMethod(methodInfo3), (HarmonyMethod)null, (HarmonyMethod)null);
				_installed = true;
				if (State == "Installed")
				{
					log("[CampfireCleanup] Installed component/root guard for segment item cleanup (not ViewID 55).");
				}
			}
			catch (Exception ex)
			{
				State = "Install failed";
				log("[CampfireCleanup] " + State + ": " + ex.Message);
			}
		}

		private static void FindIteratorMoveNext(Type parent, List<MethodInfo> candidates)
		{
			Type[] nestedTypes = parent.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic);
			foreach (Type type in nestedTypes)
			{
				if (type.Name.IndexOf("ShowNextSegmentCoroutine", StringComparison.Ordinal) >= 0)
				{
					MethodInfo methodInfo = AccessTools.DeclaredMethod(type, "MoveNext", (Type[])null, (Type[])null);
					if (methodInfo != null && methodInfo.ReturnType == typeof(bool))
					{
						candidates.Add(methodInfo);
					}
				}
				FindIteratorMoveNext(type, candidates);
			}
		}

		private static IEnumerable<CodeInstruction> Transpile(IEnumerable<CodeInstruction> instructions)
		{
			AccessTools.DeclaredMethod(typeof(PhotonNetwork), "Destroy", new Type[1] { typeof(PhotonView) }, (Type[])null);
			MethodInfo operand = AccessTools.DeclaredMethod(typeof(CampfireCleanupGuard), "DestroyUnlessProtected", (Type[])null, (Type[])null);
			List<CodeInstruction> list = instructions.ToList();
			List<CodeInstruction> list2 = list.Where(IsDestroyChainCall).ToList();
			if (list2.Count != 1 || list.All((CodeInstruction i) => !(i.operand is FieldInfo fieldInfo) || !(fieldInfo.Name == "viewsToDestoryIfNotAlreadyWhenSwitchingSegments")))
			{
				State = "Skipped: unexpected segment-cleanup IL";
				_log?.Invoke("[CampfireCleanup] " + State);
				return list;
			}
			if (!(list2[0].operand is MethodInfo methodInfo))
			{
				return list;
			}
			_nextDestroy = (Action<PhotonView>)methodInfo.CreateDelegate(typeof(Action<PhotonView>));
			list2[0].operand = operand;
			State = "Installed";
			return list;
		}

		private static bool IsDestroyChainCall(CodeInstruction instruction)
		{
			MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(PhotonNetwork), "Destroy", new Type[1] { typeof(PhotonView) }, (Type[])null);
			if (CodeInstructionExtensions.Calls(instruction, methodInfo))
			{
				return true;
			}
			if (!(instruction.operand is MethodInfo methodInfo2) || methodInfo2.Name != "DestroyUnlessProtected")
			{
				return false;
			}
			string text = methodInfo2.DeclaringType?.FullName;
			if (methodInfo2 != AccessTools.DeclaredMethod(typeof(CampfireCleanupGuard), "DestroyUnlessProtected", (Type[])null, (Type[])null) && methodInfo2.IsStatic && methodInfo2.ReturnType == typeof(void) && methodInfo2.GetParameters().Length == 1 && methodInfo2.GetParameters()[0].ParameterType == typeof(PhotonView) && text == typeof(CampfireCleanupGuard).FullName)
			{
				if (!(methodInfo2.Module.Assembly.GetName().Name == "RandomTerrainEnhance"))
				{
					return methodInfo2.Module.Assembly.GetName().Name == "TerrainCustomiser";
				}
				return true;
			}
			return false;
		}

		private static void DestroyUnlessProtected(PhotonView view)
		{
			if (!TryProtectRegisteredKilnCampfire(view))
			{
				_nextDestroy(view);
			}
		}

		private static bool TryProtectRegisteredKilnCampfire(PhotonView view)
		{
			try
			{
				if (_enabled == null || !_enabled() || (Object)(object)view == (Object)null)
				{
					return false;
				}
				MapHandler instance = Singleton<MapHandler>.Instance;
				if ((Object)(object)instance == (Object)null || !IsRegisteredKilnCampfire(instance.segments, view))
				{
					return false;
				}
				if (LoggedViews.Add(((Object)view).GetInstanceID()))
				{
					_log?.Invoke("[CampfireCleanup] Preserved registered Kiln campfire in segment cleanup; ViewID=" + view.ViewID + ".");
				}
				return true;
			}
			catch (Exception ex)
			{
				if (!_errorLogged)
				{
					_errorLogged = true;
					_log?.Invoke("[CampfireCleanup] Check failed; keeping vanilla destroy: " + ex.Message);
				}
				return false;
			}
		}

		private static bool IsRegisteredKilnCampfire(MapSegment[]? segments, PhotonView view)
		{
			if (segments == null || (Object)(object)view == (Object)null)
			{
				return false;
			}
			Campfire component = ((Component)view).GetComponent<Campfire>();
			if ((Object)(object)component == (Object)null || ((Object)component).name.IndexOf("Kiln", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return false;
			}
			Transform transform = ((Component)view).transform;
			Transform transform2 = ((Component)component).transform;
			foreach (MapSegment val in segments)
			{
				if (val != null && !((Object)(object)val.segmentCampfire == (Object)null))
				{
					Transform transform3 = val.segmentCampfire.transform;
					if (((Object)(object)transform == (Object)(object)transform3 || transform.IsChildOf(transform3)) && ((Object)(object)transform2 == (Object)(object)transform3 || transform2.IsChildOf(transform3)))
					{
						return true;
					}
				}
			}
			return false;
		}

		internal static void ResetScene()
		{
			LoggedViews.Clear();
		}
	}
	internal static class GeneratedMapScope
	{
		private static WeakReference _map = new WeakReference(null);

		internal static void Mark(object handler)
		{
			_map = new WeakReference(handler);
		}

		internal static bool IsCurrent(object handler)
		{
			object target = _map.Target;
			if (handler != null && target != null)
			{
				return target == handler;
			}
			return false;
		}

		internal static void Clear()
		{
			_map = new WeakReference(null);
		}
	}
}
namespace RandomTerrainEnhance
{
	public static class Arbiter
	{
		public const string TFA_GUID = "com.CptPICHU.peak.truefinalascent";

		private static Type _tFinalAscent;

		private static Type _tRoom;

		private static Type _tTrStepAside;

		private static PropertyInfo _pActive;

		private static FieldInfo _fActiveBacking;

		private static FieldInfo _fWeTurnedItOff;

		private static MethodInfo _mComeBack;

		private static bool _restoreToasted;

		public static string TfaVersion { get; private set; }

		public static bool TfaLoaded => TfaVersion != null;

		private static bool FixEnabled
		{
			get
			{
				if (Plugin.EnableTfaFix != null)
				{
					return Plugin.EnableTfaFix.Value;
				}
				return true;
			}
		}

		public static void Detect()
		{
			if (!Chainloader.PluginInfos.TryGetValue("com.CptPICHU.peak.truefinalascent", out var value))
			{
				TfaVersion = null;
				return;
			}
			TfaVersion = value.Metadata.Version.ToString();
			_tFinalAscent = AccessTools.TypeByName("TrueFinalAscent.FinalAscent");
			_tRoom = AccessTools.TypeByName("TrueFinalAscent.FinalAscentRoom");
			_tTrStepAside = AccessTools.TypeByName("TrueFinalAscent.FinalAscentTerrainRandomiser");
			if (_tFinalAscent != null)
			{
				_pActive = AccessTools.Property(_tFinalAscent, "Active");
				_fActiveBacking = AccessTools.Field(_tFinalAscent, "<Active>k__BackingField");
			}
			if (_tTrStepAside != null)
			{
				_fWeTurnedItOff = AccessTools.Field(_tTrStepAside, "_weTurnedItOff");
				_mComeBack = AccessTools.Method(_tTrStepAside, "ComeBack", (Type[])null, (Type[])null);
			}
			Plugin.Log.LogInfo((object)("[地形增强] 检测到 TrueFinalAscent v" + TfaVersion + ",仲裁层已启用" + $"(Active={_pActive != null || _fActiveBacking != null} ComeBack={_mComeBack != null})"));
		}

		public static bool FaActive()
		{
			try
			{
				if (_pActive != null)
				{
					return (bool)_pActive.GetValue(null);
				}
				if (_fActiveBacking != null)
				{
					return (bool)_fActiveBacking.GetValue(null);
				}
			}
			catch
			{
			}
			return false;
		}

		public static bool FaRoomFlag()
		{
			if (!PhotonNetwork.InRoom)
			{
				return false;
			}
			Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties;
			bool flag = default(bool);
			int num;
			if (customProperties != null && ((Dictionary<object, object>)(object)customProperties).TryGetValue((object)"FA", out object value))
			{
				if (value is bool)
				{
					flag = (bool)value;
					num = 1;
				}
				else
				{
					num = 0;
				}
			}
			else
			{
				num = 0;
			}
			return (byte)((uint)num & (flag ? 1u : 0u)) != 0;
		}

		public static bool FaRun()
		{
			if (!FaActive())
			{
				return FaRoomFlag();
			}
			return true;
		}

		public static bool Allows(ITerrainTarget t, Cap cap)
		{
			if (cap == Cap.Sync || cap == Cap.Bake)
			{
				return true;
			}
			if (!FaRun())
			{
				return true;
			}
			if (t != null && t.State.OffReason == null)
			{
				t.State.OffReason = Loc.T("Final Ascent run (TrueFinalAscent)", "Final Ascent 局(TrueFinalAscent 接管地形)");
			}
			return false;
		}

		public static void OnGenerationBegin(ITerrainTarget t)
		{
			try
			{
				if (FixEnabled && PhotonNetwork.InRoom && FaRoomFlag() && t != null && t.IsRunActive())
				{
					if (PhotonNetwork.IsMasterClient)
					{
						ClearStaleFaKeys(t.NameZh + " 正在生成本局地形");
						return;
					}
					t.State.OffReason = Loc.T("stale Final Ascent room flag detected", "检测到上一局 Final Ascent 的残留房间标记");
					Gui.AddToast(Loc.T("[RandomTerrainEnhance] Stale Final Ascent room flag detected while " + t.NameEn + " is generating. Terrain may differ and TrueFinalAscent may pull you to the ground; ask the host to restart the lobby.", "[随机地形增强] 检测到上一局 Final Ascent 的残留房间标记,而本局地形由" + t.NameZh + "生成。地形可能不一致、TrueFinalAscent 可能把你往地面拖拽;建议让主机重建房间。"));
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[地形增强] FA 残留检查异常: " + ex.Message));
			}
		}

		public static void ClearStaleFaKeys(string why)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			if (!FixEnabled || !PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient)
			{
				return;
			}
			try
			{
				Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties;
				if (customProperties == null)
				{
					return;
				}
				Hashtable val = new Hashtable();
				foreach (object key in ((Dictionary<object, object>)(object)customProperties).Keys)
				{
					if (key is string text && text.StartsWith("FA", StringComparison.Ordinal))
					{
						val[(object)text] = null;
					}
				}
				if (((Dictionary<object, object>)(object)val).Count != 0)
				{
					PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
					Plugin.Log.LogWarning((object)string.Format("{0} 已清理 {1} 个残留的 Final Ascent 房间属性({2})", "[地形增强]", ((Dictionary<object, object>)(object)val).Count, why));
					Gui.AddToast(Loc.T(string.Format("[{0}] Cleared {1} stale Final Ascent room flag(s)", "RandomTerrainEnhance", ((Dictionary<object, object>)(object)val).Count), string.Format("[{0}] 已清理 {1} 个残留的 Final Ascent 房间标记", "随机地形增强", ((Dictionary<object, object>)(object)val).Count)));
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[地形增强] 清理残留 FA 键失败: " + ex.Message));
			}
		}

		public static void AirportTick()
		{
			if (!TfaLoaded || _mComeBack == null || _fWeTurnedItOff == null)
			{
				return;
			}
			if (!Plugin.InAirport())
			{
				_restoreToasted = false;
			}
			else
			{
				if (FaRun())
				{
					return;
				}
				try
				{
					object value = _fWeTurnedItOff.GetValue(null);
					if (value is bool && (bool)value)
					{
						_mComeBack.Invoke(null, null);
						Plugin.Log.LogWarning((object)"[地形增强] 已替 TrueFinalAscent 还原地形随机器开关(它在局末不会自己还原)");
						if (!_restoreToasted)
						{
							_restoreToasted = true;
							Gui.AddToast(Loc.T("[RandomTerrainEnhance] Restored TerrainRandomiser's switch that TrueFinalAscent left turned off", "[随机地形增强] 已还原被 TrueFinalAscent 关掉且未复原的地形随机器开关"));
						}
					}
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("[地形增强] 还原地形随机器开关失败: " + ex.Message));
				}
			}
		}
	}
	public static class GenFixes
	{
		[HarmonyPatch(typeof(MapHandler), "InitializeMap")]
		internal static class MapInitPatch
		{
			private static object _cachedSettings;

			private static int _cachedSeed;

			private static bool DropLobbyStaleSettings(TrTarget tr)
			{
				try
				{
					if (!PhotonNetwork.InRoom)
					{
						return false;
					}
					if (PhotonNetwork.IsMasterClient)
					{
						return false;
					}
					if (!tr.LocalWantsRandom())
					{
						return false;
					}
					string text = tr.RoomMapSettingsJson();
					if (!string.IsNullOrEmpty(text) && EnableRandomiserInJson(text))
					{
						return false;
					}
					Player masterClient = PhotonNetwork.MasterClient;
					if (masterClient != null && RoomWatch.WithinGrace(masterClient) && string.IsNullOrEmpty(text))
					{
						return false;
					}
					tr.ClearRoomMapSettings();
					Plugin.Log.LogWarning((object)"[地形增强] 房主本局未启用随机地形,本机检测到来自 Steam 大厅的残留随机配置,已清除并跟随房主走原版地形(房主权威)");
					return true;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("[地形增强] 大厅脏数据检查异常: " + ex.Message));
					return false;
				}
			}

			private static bool EnableRandomiserInJson(string json)
			{
				try
				{
					Match match = Regex.Match(json, "\"enableRandomiser\"\\s*:\\s*(true|false)");
					return match.Success && match.Groups[1].Value == "true";
				}
				catch
				{
					return false;
				}
			}

			private static bool GuardUnsupportedScene(TrTarget tr)
			{
				try
				{
					if (!tr.LocalWantsRandom())
					{
						return false;
					}
					if (tr.CurrentSceneSupportsTr())
					{
						return false;
					}
					tr.ClearRoomMapSettings();
					Plugin.Log.LogWarning((object)"[地形增强] 当前场景缺少地形随机器所需结构(非 WilIsland 类,如 Level_x),已屏蔽随机配置改走原版,避免 TR 空引用导致地图不生成/掉虚空");
					return true;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("[地形增强] 非常规场景守卫异常: " + ex.Message));
					return false;
				}
			}

			private static void EnsureRoomSettings(TrTarget tr)
			{
				try
				{
					object roomMapSettingsRaw = tr.GetRoomMapSettingsRaw();
					if (roomMapSettingsRaw != null)
					{
						_cachedSettings = roomMapSettingsRaw;
						_cachedSeed = tr.SeedOf(roomMapSettingsRaw);
						SameRunReload = false;
					}
					else
					{
						if (_cachedSettings == null)
						{
							return;
						}
						string text = tr.RoomMapSettingsJson();
						if (!string.IsNullOrEmpty(text))
						{
							int num = SeedOfJson(text);
							if (num != 0 && num == _cachedSeed)
							{
								tr.SetRoomMapSettingsRaw(_cachedSettings);
								SameRunReload = true;
								Plugin.Log.LogInfo((object)string.Format("{0} 二次加载检测到地形随机器配置已被清空,已回补本局配置(seed={1}),使本次生成仍走随机地形而非原版", "[地形增强]", num));
							}
						}
					}
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("[地形增强] 回补地形随机器配置失败: " + ex.Message));
				}
			}

			private static bool DropForCustomMap(TrTarget tr)
			{
				if (!TcSession.OwnsMap())
				{
					return false;
				}
				_cachedSettings = null;
				_cachedSeed = 0;
				SameRunReload = false;
				GeneratedMapScope.Clear();
				tr.State.HasLocked = false;
				tr.State.InGeneration = false;
				tr.State.FixActive = false;
				tr.State.ViewFixActive = false;
				tr.State.OffReason = null;
				ViewFix.Reset();
				SyncCheck.OnForeignMap();
				if (tr.GetRoomMapSettingsRaw() != null)
				{
					tr.ClearRoomMapSettings();
					Plugin.Log.LogInfo((object)"[地形增强] 本局是地形定制器自定义图:已清掉本机地形随机器的残留配置,不生成随机图");
				}
				return true;
			}

			private static int SeedOfJson(string json)
			{
				try
				{
					Match match = Regex.Match(json, "\"seed\"\\s*:\\s*(-?\\d+)");
					int result;
					return (match.Success && int.TryParse(match.Groups[1].Value, out result)) ? result : 0;
				}
				catch
				{
					return 0;
				}
			}

			[HarmonyPrefix]
			[HarmonyPriority(700)]
			private static void Pre(out bool __state)
			{
				__state = false;
				try
				{
					Plugin.ApplyHostBake(force: true);
					TrTarget tR = Targets.TR;
					if (tR.Version == null || DropForCustomMap(tR) || DropLobbyStaleSettings(tR) || GuardUnsupportedScene(tR))
					{
						return;
					}
					EnsureRoomSettings(tR);
					if (!tR.IsRunActive() || InitDone())
					{
						return;
					}
					SyncCheck.OnGenerationBegin(tR);
					ViewFix.Reset();
					Targets.BeginRunFor(tR);
					tR.State.Seed = tR.GetSeed();
					Arbiter.OnGenerationBegin(tR);
					bool flag = Negotiate.Decide(tR, Cap.Rng);
					bool flag2 = Negotiate.Decide(tR, Cap.ViewId);
					if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient)
					{
						Plugin.GenLock? genLock = Negotiate.GetGenLock(tR);
						if (genLock.HasValue && genLock.Value.Seed == tR.State.Seed && Negotiate.HostPatch() != Tri.No && Arbiter.Allows(tR, Cap.Rng))
						{
							flag = genLock.Value.Fix;
							flag2 = genLock.Value.Vf;
						}
					}
					tR.State.FixActive = flag;
					tR.State.ViewFixActive = flag2;
					tR.State.HasLocked = true;
					GeneratedMapScope.Mark(Singleton<MapHandler>.Instance);
					__state = true;
					if (PhotonNetwork.IsMasterClient || !PhotonNetwork.InRoom)
					{
						BroadcastGenLock(tR);
					}
					Plugin.Log.LogInfo((object)("[地形增强] 地形随机器生成开始: 随机流隔离=" + (flag ? "启用" : "关闭") + " " + string.Format("ViewID对齐={0} seed={1}", flag2 ? "启用" : "关闭", tR.State.Seed) + ((tR.State.OffReason == null) ? "" : ("(" + tR.State.OffReason + ")"))));
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("[地形增强] 生成开始处理异常: " + ex.Message));
				}
			}

			[HarmonyPostfix]
			[HarmonyPriority(0)]
			private static void Post(bool __state)
			{
				TrTarget tR = Targets.TR;
				if (__state && InitDone())
				{
					tR.State.InGeneration = false;
					SyncCheck.OnGenerationEnd(tR);
				}
			}
		}

		[HarmonyPatch(typeof(PropSpawner), "ExecuteImmediately")]
		private static class PropSpawnerIsolate
		{
			[HarmonyPrefix]
			[HarmonyPriority(700)]
			private static void Pre(PropSpawner __instance, out State? __state)
			{
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				__state = null;
				ITerrainTarget terrainTarget = IsolatingTarget();
				if (terrainTarget != null && !((Object)(object)__instance == (Object)null))
				{
					__state = Random.state;
					Random.InitState(PathSeed(((Component)__instance).transform, terrainTarget.State.Seed));
				}
			}

			[HarmonyPostfix]
			[HarmonyPriority(0)]
			private static void Post(State? __state)
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				if (__state.HasValue)
				{
					Random.state = __state.Value;
				}
			}
		}

		private static string _pendingLock;

		private static ITerrainTarget _pendingLockTarget;

		private static readonly FieldRef<MapHandler, bool> _initDone = AccessTools.FieldRefAccess<MapHandler, bool>("hasFinishedStartRoutine");

		public static bool SameRunReload { get; private set; }

		public static bool FixActive => Targets.TR.State.FixActive;

		public static bool HasLocked => Targets.TR.State.HasLocked;

		public static bool? GetRoomFix()
		{
			return Negotiate.GetRoomBool(Targets.TR.Keys.Fix);
		}

		public static int TryGetSeed()
		{
			return Targets.TR.GetSeed();
		}

		private static bool InitDone()
		{
			try
			{
				MapHandler instance = Singleton<MapHandler>.Instance;
				return (Object)(object)instance != (Object)null && _initDone.Invoke(instance);
			}
			catch
			{
				return false;
			}
		}

		private static void BroadcastGenLock(ITerrainTarget t)
		{
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Expected O, but got Unknown
			//IL_00b8: Expected O, but got Unknown
			_pendingLock = null;
			_pendingLockTarget = null;
			bool? localBake = Plugin.GetLocalBake();
			string text = string.Format("{0}|{1}|", t.State.Seed, (!localBake.HasValue) ? "?" : (localBake.Value ? "1" : "0")) + (t.State.FixActive ? "1" : "0") + "|" + (t.State.ViewFixActive ? "1" : "0");
			if (PhotonNetwork.InRoom)
			{
				Room currentRoom = PhotonNetwork.CurrentRoom;
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)t.Keys.GenLock, (object)text);
				currentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
			}
			else
			{
				_pendingLock = text;
				_pendingLockTarget = t;
			}
		}

		public static void FlushPendingLock()
		{
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			//IL_0049: Expected O, but got Unknown
			if (_pendingLock != null && _pendingLockTarget != null && PhotonNetwork.InRoom && PhotonNetwork.IsMasterClient)
			{
				Room currentRoom = PhotonNetwork.CurrentRoom;
				Hashtable val = new Hashtable();
				((Dictionary<object, object>)val).Add((object)_pendingLockTarget.Keys.GenLock, (object)_pendingLock);
				currentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
				Plugin.Log.LogInfo((object)("[地形增强] 已补发生成锁定 (QuickLoad): " + _pendingLock));
				_pendingLock = null;
				_pendingLockTarget = null;
			}
		}

		private static ITerrainTarget IsolatingTarget()
		{
			ITerrainTarget[] all = Targets.All;
			foreach (ITerrainTarget terrainTarget in all)
			{
				if (terrainTarget.Version != null)
				{
					TargetState state = terrainTarget.State;
					if (state.FixActive && state.InGeneration)
					{
						return terrainTarget;
					}
				}
			}
			return null;
		}

		private static int PathSeed(Transform t, int runSeed)
		{
			int num = -2128831035;
			while ((Object)(object)t != (Object)null)
			{
				string name = ((Object)t).name;
				foreach (char c in name)
				{
					num = (num ^ c) * 16777619;
				}
				num = (num ^ t.GetSiblingIndex()) * 16777619;
				t = t.parent;
			}
			return num ^ (runSeed * 486187739);
		}
	}
	public class GuiHost : MonoBehaviour
	{
		private void OnGUI()
		{
			Gui.Draw();
		}
	}
	public static class Gui
	{
		private class Toast
		{
			public string Msg;

			public float Until;
		}

		private struct Cell
		{
			public string Text;

			public Color Color;

			public Cell(string t, Color c)
			{
				//IL_0008: Unknown result type (might be due to invalid IL or missing references)
				//IL_0009: Unknown result type (might be due to invalid IL or missing references)
				Text = t;
				Color = c;
			}
		}

		[CompilerGenerated]
		private static class <>O
		{
			public static WindowFunction <0>__DrawDetailWindow;

			public static WindowFunction <1>__DrawMainWindow;
		}

		public static bool ShowPanel;

		public static bool ShowDetail;

		private static readonly Color ColGreen = new Color(0.56f, 0.75f, 0.56f);

		private static readonly Color ColRed = new Color(0.79f, 0.51f, 0.51f);

		private static readonly Color ColGray = new Color(0.68f, 0.7f, 0.73f);

		private static readonly Color ColText = new Color(0.84f, 0.84f, 0.84f);

		private static readonly Color ColHead = new Color(0.88f, 0.84f, 0.72f);

		private static readonly Color ColGold = new Color(0.95f, 0.87f, 0.55f);

		private static GUIStyle _panel;

		private static GUIStyle _title;

		private static GUIStyle _cell;

		private static GUIStyle _head;

		private static GUIStyle _foot;

		private static GUIStyle _toastStyle;

		private static GUIStyle _tab;

		private static GUIStyle _tabActive;

		private static GUIStyle _wrapCell;

		private static GUIStyle _titleText;

		private static Texture2D _bg;

		private static Texture2D _bgTitle;

		private static Texture2D _bgToast;

		private static Texture2D _bgTab;

		private static Texture2D _bgTabActive;

		private static bool _stylesReady;

		private static Vector2 _scroll;

		private static int _tabIndex;

		private static Rect _mainRect = new Rect(20f, 70f, 760f, 0f);

		private static Rect _detailRect = new Rect(20f, 40f, 660f, 0f);

		private static readonly GUILayoutOption[] W60 = (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) };

		private static readonly GUILayoutOption[] W80 = (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) };

		private static readonly GUILayoutOption[] W90 = (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) };

		private static readonly GUILayoutOption[] W100 = (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) };

		private static readonly GUILayoutOption[] W110 = (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(110f) };

		private static readonly GUILayoutOption[] W120 = (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) };

		private static readonly GUILayoutOption[] W130 = (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(130f) };

		private static readonly GUILayoutOption[] W150 = (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(150f) };

		private static readonly GUILayoutOption[] W170 = (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(170f) };

		private static readonly GUILayoutOption[] W200 = (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) };

		private static readonly GUILayoutOption[] W230 = (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(230f) };

		private static readonly GUILayoutOption[] H280 = (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(280f) };

		private static readonly GUILayoutOption[] NoOpts = (GUILayoutOption[])(object)new GUILayoutOption[0];

		private static readonly List<Toast> _toasts = new List<Toast>();

		private const float RebuildInterval = 0.5f;

		private static float _nextRebuild;

		private static bool _forceRebuild;

		private static string _mTitle = "";

		private static readonly List<Cell[]> _mRows = new List<Cell[]>();

		private static readonly List<Cell[]> _mSettings = new List<Cell[]>();

		private static readonly List<Cell> _mNotes = new List<Cell>();

		private static string[] _mHeaders = Array.Empty<string>();

		private static GUILayoutOption[][] _mRowWidths = Array.Empty<GUILayoutOption[]>();

		private static string _dSummary = "";

		private static string _dBiome;

		private static string _dNoData;

		private static Cell[] _dSyncLine = Array.Empty<Cell>();

		private static string[] _dTabs = Array.Empty<string>();

		private static readonly List<Cell[]> _dRows = new List<Cell[]>();

		private static readonly GUILayoutOption[][] _dRowWidths = new GUILayoutOption[6][] { W230, W120, W60, W60, W60, W60 };

		private static string _dFirstDiv = "无";

		private const int DetailRowCap = 60;

		private static string _dOverflow;

		public static bool WantsDraw
		{
			get
			{
				if (!ShowPanel && !ShowDetail)
				{
					return _toasts.Count > 0;
				}
				return true;
			}
		}

		public static void AddToast(string msg)
		{
			_toasts.Add(new Toast
			{
				Msg = msg,
				Until = Time.unscaledTime + 10f
			});
			Plugin.Log.LogWarning((object)msg);
		}

		public static void Invalidate()
		{
			_forceRebuild = true;
		}

		private static Texture2D Tex(Color c)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1);
			val.SetPixel(0, 0, c);
			val.Apply();
			return val;
		}

		private static void EnsureStyles()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_00e2: Expected O, but got Unknown
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: 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)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Expected O, but got Unknown
			//IL_0134: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Expected O, but got Unknown
			//IL_0165: Expected O, but got Unknown
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0175: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Expected O, but got Unknown
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: 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_01c1: Expected O, but got Unknown
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Expected O, but got Unknown
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_021a: Expected O, but got Unknown
			//IL_021a: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: 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_023f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Expected O, but got Unknown
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Expected O, but got Unknown
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_027e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Expected O, but got Unknown
			//IL_02a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Expected O, but got Unknown
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Expected O, but got Unknown
			if (!_stylesReady)
			{
				_bg = Tex(new Color(0.08f, 0.086f, 0.098f, 0.92f));
				_bgTitle = Tex(new Color(0.2f, 0.215f, 0.235f, 1f));
				_bgToast = Tex(new Color(0.12f, 0.09f, 0.09f, 0.92f));
				_bgTab = Tex(new Color(0.15f, 0.16f, 0.176f, 1f));
				_bgTabActive = Tex(new Color(0.23f, 0.2f, 0.145f, 1f));
				GUIStyle val = new GUIStyle();
				val.normal.background = _bg;
				val.padding = new RectOffset(10, 10, 6, 8);
				_panel = val;
				GUIStyle val2 = new GUIStyle();
				val2.normal.background = _bgTitle;
				val2.normal.textColor = new Color(0.91f, 0.91f, 0.91f);
				val2.fontSize = 14;
				val2.padding = new RectOffset(10, 10, 6, 6);
				_title = val2;
				GUIStyle val3 = new GUIStyle();
				val3.normal.textColor = ColText;
				val3.fontSize = 13;
				val3.padding = new RectOffset(4, 4, 3, 3);
				_cell = val3;
				GUIStyle val4 = new GUIStyle(_cell);
				val4.normal.textColor = ColGray;
				val4.fontSize = 12;
				_head = val4;
				GUIStyle val5 = new GUIStyle(_cell);
				val5.normal.textColor = ColGray;
				val5.fontSize = 11;
				val5.wordWrap = true;
				val5.richText = true;
				_foot = val5;
				GUIStyle val6 = new GUIStyle();
				val6.normal.background = _bgToast;
				val6.normal.textColor = new Color(0.89f, 0.78f, 0.78f);
				val6.fontSize = 13;
				val6.padding = new RectOffset(10, 10, 6, 6);
				val6.wordWrap = true;
				_toastStyle = val6;
				GUIStyle val7 = new GUIStyle();
				val7.normal.background = _bgTab;
				val7.normal.textColor = ColGray;
				val7.fontSize = 12;
				val7.padding = new RectOffset(12, 12, 3, 3);
				val7.alignment = (TextAnchor)4;
				_tab = val7;
				GUIStyle val8 = new GUIStyle(_tab);
				val8.normal.background = _bgTabActive;
				val8.normal.textColor = new Color(0.82f, 0.56f, 0.56f);
				_tabActive = val8;
				_wrapCell = new GUIStyle(_cell)
				{
					wordWrap = true
				};
				GUIStyle val9 = new GUIStyle();
				val9.normal.textColor = new Color(0.91f, 0.91f, 0.91f);
				val9.fontSize = 14;
				_titleText = val9;
				_stylesReady = true;
			}
		}

		private static void Label(string text, Color c, GUIStyle style, GUILayoutOption[] opts)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: 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_0026: Unknown result type (might be due to invalid IL or missing references)
			Color textColor = style.normal.textColor;
			style.normal.textColor = c;
			GUILayout.Label(text, style, opts);
			style.normal.textColor = textColor;
		}

		public static void Draw()
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Invalid comparison between Unknown and I4
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Expected O, but got Unknown
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			if (!WantsDraw)
			{
				return;
			}
			EnsureStyles();
			DrawToasts();
			if ((!ShowPanel && !ShowDetail) || InPauseMenu())
			{
				return;
			}
			if ((int)Event.current.type == 8 && (_forceRebuild || Time.unscaledTime >= _nextRebuild))
			{
				_forceRebuild = false;
				_nextRebuild = Time.unscaledTime + 0.5f;
				if (ShowDetail)
				{
					RebuildDetail();
				}
				else
				{
					RebuildMain();
				}
			}
			if (ShowDetail)
			{
				Rect detailRect = _detailRect;
				object obj = <>O.<0>__DrawDetailWindow;
				if (obj == null)
				{
					WindowFunction val = DrawDetailWindow;
					<>O.<0>__DrawDetailWindow = val;
					obj = (object)val;
				}
				_detailRect = GUILayout.Window(93442, detailRect, (WindowFunction)obj, GUIContent.none, _panel, Array.Empty<GUILayoutOption>());
			}
			else
			{
				Rect mainRect = _mainRect;
				object obj2 = <>O.<1>__DrawMainWindow;
				if (obj2 == null)
				{
					WindowFunction val2 = DrawMainWindow;
					<>O.<1>__DrawMainWindow = val2;
					obj2 = (object)val2;
				}
				_mainRect = GUILayout.Window(93441, mainRect, (WindowFunction)obj2, GUIContent.none, _panel, Array.Empty<GUILayoutOption>());
			}
		}

		private static bool InPauseMenu()
		{
			try
			{
				return GUIManager.InPauseMenu;
			}
			catch
			{
				return false;
			}
		}

		private static void DrawToasts()
		{
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			_toasts.RemoveAll((Toast t) => Time.unscaledTime > t.Until);
			float num = 10f;
			foreach (Toast toast in _toasts)
			{
				GUI.Label(new Rect(10f, num, 470f, 44f), toast.Msg, _toastStyle);
				num += 50f;
			}
		}

		private static Version SafeVer(string s)
		{
			try
			{
				return string.IsNullOrEmpty(s) ? null : new Version(s);
			}
			catch
			{
				return null;
			}
		}

		private static Color VerColor(string ver, Version latest)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			Version version = SafeVer(ver);
			if (version == null)
			{
				return ColGray;
			}
			if (latest != null && version < latest)
			{
				return ColRed;
			}
			return ColGreen;
		}

		private static Cell VerCell(string ver, string prefix, Version latest)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			if (ver != null)
			{
				return new Cell(prefix + "_" + ver, VerColor(ver, latest));
			}
			return new Cell(Loc.T("Unknown", "未知"), ColGray);
		}

		private static Cell BakeCell(string flag, bool forced)
		{
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			string text = ((flag == "1") ? Loc.T("On", "启用") : ((flag == "0") ? Loc.T("Off", "关闭") : Loc.T("Unknown", "未知")));
			if (forced)
			{
				text += Loc.T(" (forced)", " (已强制跟随)");
			}
			return new Cell(text, (flag == "?") ? ColGray : ColGold);
		}

		private static Cell UnknownCell()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			return new Cell(Loc.T("Unknown", "未知"), ColGray);
		}

		private static void RebuildMain()
		{
			//IL_033b: Unknown result type (might be due to invalid IL or missing references)
			//IL_038d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0386: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0518: Unknown result type (might be due to invalid IL or missing references)
			//IL_051d: Unknown result type (might be due to invalid IL or missing references)
			//IL_052a: Unknown result type (might be due to invalid IL or missing references)
			//IL_050a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0511: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b9: Unknown result type (might be due to invalid IL or missing references)
			_mRows.Clear();
			_mSettings.Clear();
			_mNotes.Clear();
			LocalMods.EnsureDetected();
			Player[] array = (PhotonNetwork.InRoom ? PhotonNetwork.PlayerList : Array.Empty<Player>());
			Dictionary<int, Plugin.PlayerInfo> dictionary = new Dictionary<int, Plugin.PlayerInfo>(array.Length);
			Player[] array2 = array;
			foreach (Player val in array2)
			{
				dictionary[val.ActorNumber] = Plugin.ParsePlayer(val);
			}
			Version version = null;
			Version version2 = null;
			Version version3 = SafeVer("1.0.20");
			foreach (Plugin.PlayerInfo value2 in dictionary.Values)
			{
				Version version4 = SafeVer(value2.TrVer);
				if (version4 != null && (version == null || version4 > version))
				{
					version = version4;
				}
				Version version5 = SafeVer(value2.WindVer);
				if (version5 != null && (version2 == null || version5 > version2))
				{
					version2 = version5;
				}
				Version version6 = SafeVer(value2.RteVer);
				if (version6 != null && (version3 == null || version6 > version3))
				{
					version3 = version6;
				}
			}
			if (!PhotonNetwork.InRoom)
			{
				Version version7 = SafeVer(Plugin.TrVersion);
				if (version7 != null)
				{
					version = version7;
				}
				Version version8 = SafeVer(Plugin.WindVersion);
				if (version8 != null)
				{
					version2 = version8;
				}
			}
			Player val2 = (PhotonNetwork.InRoom ? PhotonNetwork.MasterClient : null);
			if (val2 != null)
			{
				dictionary.TryGetValue(val2.ActorNumber, out var _);
			}
			bool flag = Plugin.TfaVersion != null || dictionary.Values.Any((Plugin.PlayerInfo playerInfo2) => playerInfo2.TfaVer != null);
			bool flag2 = Plugin.WindVersion != null || dictionary.Values.Any((Plugin.PlayerInfo playerInfo2) => playerInfo2.WindVer != null);
			List<string> list = new List<string> { Loc.T("Player (·mod ver)", "玩家 (·本模组版本)") };
			List<GUILayoutOption[]> list2 = new List<GUILayoutOption[]> { W200 };
			list.Add(Loc.T("Randomiser", "随机地形"));
			list2.Add(W90);
			if (flag)
			{
				list.Add("TFA");
				list2.Add(W60);
			}
			if (flag2)
			{
				list.Add(Loc.T("Wind", "挡风"));
				list2.Add(W80);
			}
			list.Add(Loc.T("Baking", "光照烘焙"));
			list2.Add(W110);
			list.Add(Loc.T("Sync", "同步状态"));
			list2.Add(W120);
			_mHeaders = list.ToArray();
			_mRowWidths = list2.ToArray();
			_mTitle = Loc.T("RandomTerrainEnhance v1.0.20 — Room Sync Status", "随机地形增强 v1.0.20 — 房间同步状态");
			List<Cell> list3 = new List<Cell>(_mHeaders.Length);
			if (!PhotonNetwork.InRoom)
			{
				bool? localBake = Plugin.GetLocalBake();
				list3.Add(new Cell(Loc.T("Local (offline) ·RTE1.0.20", "本机 (未联机) ·RTE1.0.20"), ColText));
				list3.Add(VerCell(Plugin.TrVersion, Loc.T("TR", "随机"), version));
				if (flag)
				{
					list3.Add(new Cell(Plugin.TfaVersion ?? "—", (Plugin.TfaVersion == null) ? ColGray : ColGreen));
				}
				if (flag2)
				{
					list3.Add(VerCell(Plugin.WindVersion, Loc.T("Wind", "挡风"), version2));
				}
				list3.Add(BakeCell((!localBake.HasValue) ? "?" : (localBake.Value ? "1" : "0"), forced: false));
				list3.Add(new Cell("—", ColGray));
				_mRows.Add(list3.ToArray());
			}
			else
			{
				foreach (Player item in array.OrderByDescending((Player p) => p.IsMasterClient))
				{
					Plugin.PlayerInfo playerInfo = dictionary[item.ActorNumber];
					string text = (playerInfo.HasPatch ? (" ·RTE" + (playerInfo.RteVer ?? "?")) : Loc.T(" ·no-mod", " ·无本模组"));
					string t = Names.Truncate(item.NickName, 10) + (item.IsMasterClient ? Loc.T(" (Host)", " (主机)") : "") + text;
					Version version9 = SafeVer(playerInfo.RteVer);
					Color c = ((!playerInfo.HasPatch) ? ColGray : ((version9 != null && version3 != null && version9 < version3) ? ColRed : ColText));
					list3.Clear();
					list3.Add(new Cell(t, c));
					if (!playerInfo.HasPatch)
					{
						for (int num = 1; num < _mHeaders.Length; num++)
						{
							list3.Add(UnknownCell());
						}
						_mRows.Add(list3.ToArray());
						continue;
					}
					list3.Add(VerCell(playerInfo.TrVer, Loc.T("TR", "随机"), version));
					if (flag)
					{
						list3.Add(new Cell(playerInfo.TfaVer ?? "—", (playerInfo.TfaVer == null) ? ColGray : ColGreen));
					}
					if (flag2)
					{
						list3.Add(VerCell(playerInfo.WindVer, Loc.T("Wind", "挡风"), version2));
					}
					list3.Add(BakeCell(playerInfo.Bake, playerInfo.Forced && !item.IsMasterClient));
					list3.Add(SyncCell(item));
					_mRows.Add(list3.ToArray());
				}
			}
			BuildSettings(flag, flag2);
			BuildNotes(dictionary, array, version, version2, version3);
		}

		private static Cell SyncCell(Player p)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			if (p.IsMasterClient)
			{
				return new Cell(Loc.T("Baseline", "基准"), ColGreen);
			}
			if (!SyncCheck.Results.TryGetValue(p.ActorNumber, out var value))
			{
				return new Cell("", ColText);
			}
			string curB = SyncCheck.CurrentBiomeZh;
			float num2;
			string arg;
			if (!string.IsNullOrEmpty(curB))
			{
				int num = value.Mismatches.Count((SyncCheck.Mismatch m) => m.Biome == curB);
				num2 = ((SyncCheck.BiomeTotals.TryGetValue(curB, out var value2) && value2 > 0) ? ((float)num / (float)value2 * 100f) : ((num > 0) ? 100f : 0f));
				arg = Loc.Biome(curB);
			}
			else
			{
				num2 = value.Rate;
				arg = Loc.T("Whole Map", "全图");
			}
			bool flag = num2 < Plugin.AlertThreshold.Value;
			return new Cell($"[{arg}][{num2:F1}%]", flag ? ColGreen : ColRed);
		}

		private static Cell OnOff(bool? v)
		{
			//IL_000e: 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)
			if (!v.HasValue)
			{
				return new Cell("?", ColGray);
			}
			return new Cell(v.Value ? Loc.T("On", "开") : Loc.T("Off", "关"), ColGold);
		}

		private static void AddSetting(string name, Cell host, Cell eff, string note, Color noteCol)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			_mSettings.Add(new Cell[4]
			{
				new Cell(name, ColText),
				host,
				eff,
				new Cell(note, noteCol)
			});
		}

		private static void BuildSettings(bool anyTfa, bool anyWind)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0444: Unknown result type (might be due to invalid IL or missing references)
			//IL_0449: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04da: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0625: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0302: Unknown result type (might be due to invalid IL or missing references)
			//IL_056c: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_059e: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_039f: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d3: Unknown result type (might be due to invalid IL or missing references)
			bool flag = !PhotonNetwork.InRoom || PhotonNetwork.IsMasterClient;
			bool flag2 = anyTfa && Arbiter.TfaLoaded && Arbiter.FaRun();
			if (!flag2 && TcSession.OwnsMap())
			{
				AddSetting(Loc.T("Terrain source", "本局地形"), new Cell(Loc.T("Custom", "定制器"), ColText), new Cell("—", ColGray), Loc.T("TerrainCustomiser custom map; this mod stands aside this round. Sync info: TerrainCustomiser panel (F11)", "地形定制器自定义图,本模组本局不介入;同步信息见地形定制器面板(F11)"), ColGray);
				return;
			}
			string text = ((SyncCheck.LocalSeed != 0) ? SyncCheck.LocalSeed.ToString() : "—");
			ITerrainTarget genTarget = SyncCheck.GenTarget;
			string t = (flag2 ? "TFA" : ((genTarget == null) ? Loc.T("vanilla", "原版") : Loc.T("Random", "随机")));
			string text2 = (flag2 ? Loc.T("TFA Final Ascent", "TFA 最终天阶") : ((genTarget == null) ? Loc.T("vanilla", "原版") : (Loc.Zh ? genTarget.NameZh : genTarget.NameEn)));
			string note = Loc.T("seed " + text + " · " + text2 + " · ", "种子 " + text + " · " + text2 + " · ") + (flag2 ? Loc.T("Final Ascent builds its own mountain; the settings below don't apply this round", "最终天阶自己拼山,下面的设置本局不生效") : Loc.T("everyone must generate the same map", "全员必须生成同一张图"));
			AddSetting(Loc.T("Terrain source", "本局地形"), new Cell(t, ColText), new Cell("—", ColGray), note, ColGray);
			ITerrainTarget[] all = Targets.All;
			foreach (ITerrainTarget terrainTarget in all)
			{
				if (terrainTarget.Version != null)
				{
					TargetState state = terrainTarget.State;
					bool flag3 = (state.HasLocked ? state.FixActive : Negotiate.Decide(terrainTarget, Cap.Rng));
					bool flag4 = (state.HasLocked ? state.ViewFixActive : Negotiate.Decide(terrainTarget, Cap.ViewId));
					bool? v = (flag ? new bool?(Negotiate.LocalSwitch(Cap.Rng)) : Negotiate.GetRoomBool(terrainTarget.Keys.Fix));
					bool? v2 = (flag ? new bool?(Negotiate.LocalSwitch(Cap.ViewId)) : Negotiate.GetRoomBool(terrainTarget.Keys.ViewFix));
					string text3 = (state.HasLocked ? Loc.T("this round", "本局") : Loc.T("next round", "下一局"));
					string text4 = Negotiate.ForcedOffReason(terrainTarget);
					string text5 = state.OffReason ?? ((text4 != null) ? Loc.T("disabled room-wide: " + text4 + " lack this mod", "已全房关闭:" + text4 + " 未装本模组") : null);
					Cell eff = OnOff(flag3);
					if (v == true && !flag3)
					{
						eff.Color = ColRed;
					}
					AddSetting(Loc.T("RNG isolation", "随机流隔离"), OnOff(v), eff, (text5 != null && v == true && !flag3) ? text5 : Loc.T("Host decides; everyone needs this mod (" + text3 + ")", "主机决定,需全员装本模组(" + text3 + ")"), (text5 != null && v == true && !flag3) ? ColRed : ColGray);
					Cell eff2 = OnOff(flag4);
					if (v2 == true && !flag4)
					{
						eff2.Color = ColRed;
					}
					AddSetting(Loc.T("ViewID alignment", "ViewID 对齐"), OnOff(v2), eff2, Loc.T("Statues, berries, chests become interactable on clients", "决定客机的雕像/果子/箱子能否交互"), ColGray);
				}
			}
			bool? v3 = Plugin.GetRoomBake() ?? (flag ? Plugin.GetLocalBake() : ((bool?)null));
			bool? localBake = Plugin.GetLocalBake();
			Cell eff3 = OnOff(localBake);
			if (v3.HasValue && localBake.HasValue && v3.Value != localBake.Value)
			{
				eff3.Color = ColRed;
			}
			string text6 = Loc.T("Clients follow the host", "客机跟随主机");
			if (anyWind)
			{
				text6 += Loc.T((v3 == true) ? "; wind mod off" : "; wind mod on", (v3 == true) ? ",挡风模组关" : ",挡风模组开");
			}
			if (Plugin.BakePending)
			{
				text6 += Loc.T(" — applies next round", "(下一局生效)");
			}
			AddSetting(Loc.T("Lightmap baking", "光照烘焙"), OnOff(v3), eff3, text6, Plugin.BakePending ? ColRed : ColGray);
			if (WindShelter.Enable != null && WindShelter.Enable.Value && Plugin.WindVersion == null)
			{
				bool flag5 = (Plugin.GetRoomBake() ?? Plugin.GetLocalBake()) == false && (!Arbiter.TfaLoaded || !Arbiter.FaRun());
				AddSetting(Loc.T("Storm shelter", "风暴遮蔽"), new Cell("—", ColGray), new Cell(flag5 ? Loc.T("raycast", "射线") : Loc.T("lightmap", "光照"), flag5 ? ColGold : ColGray), flag5 ? Loc.T("baking off → upwind raycast (built-in); per-PC, local only", "烘焙关→上风射线判定(内置);各机本地、不影响同步") : Loc.T("baking on → uses the baked lightmap", "烘焙开→用烘焙好的光照体积"), ColGray);
			}
			if (Plugin.EnableSceneGuard != null)
			{
				AddSetting(Loc.T("Client scene guard", "客机场景守卫"), new Cell("—", ColGray), OnOff(Plugin.EnableSceneGuard.Value), Loc.T("Stops slow clients reloading the island (host invisible, items gone)", "防慢客机开局重载岛(看不见主机、物品消失)"), ColGray);
			}
		}

		private static void BuildNotes(Dictionary<int, Plugin.PlayerInfo> infos, Player[] players, Version latestTr, Version latestWind, Version latestRte)
		{
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			List<string> list2 = new List<string>();
			foreach (Player val in players)
			{
				if (!infos.TryGetValue(val.ActorNumber, out var value))
				{
					continue;
				}
				if (!value.HasPatch)
				{
					list.Add(Names.Truncate(val.NickName, 10));
					continue;
				}
				Version version = SafeVer(value.RteVer);
				if (version != null && latestRte != null && version < latestRte)
				{
					list2.Add(Names.Truncate(val.NickName, 10) + " " + value.RteVer);
				}
			}
			if (list.Count > 0)
			{
				_mNotes.Add(new Cell(Loc.T("Without this mod: " + string.Join(", ", list.ToArray()) + " — room-wide fixes are off", "未装本模组:" + string.Join("、", list.ToArray()) + " —— 全房的改流修复因此关闭"), ColRed));
			}
			if (list2.Count > 0)
			{
				_mNotes.Add(new Cell(Loc.T(string.Format("Older version: {0} (newest {1})", string.Join(", ", list2.ToArray()), latestRte), string.Format("版本落后:{0}(房内最新 {1})", string.Join("、", list2.ToArray()), latestRte)), ColRed));
			}
			if (!string.IsNullOrEmpty(SyncCheck.BiomeSummaryShort))
			{
				_mNotes.Add(new Cell(Loc.T("Biomes: " + SyncCheck.BiomeSummaryShort, "生态:" + SyncCheck.BiomeSummaryShort), ColGray));
			}
			_mNotes.Add(new Cell(Loc.T("Version baseline: randomiser " + (latestTr?.ToString() ?? "?") + ((latestWind != null) ? $" / wind {latestWind}" : "") + " · Sync column = current biome only, hold F8 for detail", "版本基准:随机地形 " + (latestTr?.ToString() ?? "?") + ((latestWind != null) ? $" / 挡风 {latestWind}" : "") + " · 同步状态列只算当前生态,长按 F8 看明细"), ColGray));
		}

		private static void DrawMainWindow(int _)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_0325: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginHorizontal(_title, Array.Empty<GUILayoutOption>());
			GUILayout.Label(_mTitle, _titleText, NoOpts);
			GUILayout.FlexibleSpace();
			Label(Loc.T("F8 close · hold F8 details", "F8 关闭 · 长按F8 详情"), ColGray, _head, NoOpts);
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			for (int i = 0; i < _mHeaders.Length && i < _mRowWidths.Length; i++)
			{
				GUILayout.Label(_mHeaders[i], _head, _mRowWidths[i]);
			}
			GUILayout.EndHorizontal();
			foreach (Cell[] mRow in _mRows)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				for (int j = 0; j < mRow.Length && j < _mRowWidths.Length; j++)
				{
					Label(mRow[j].Text, mRow[j].Color, _cell, _mRowWidths[j]);
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.Space(8f);
			Label(Loc.T("Multiplayer sync settings", "联机同步设置"), ColHead, _cell, NoOpts);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(Loc.T("Setting", "设置项"), _head, W170);
			GUILayout.Label(Loc.T("Host", "主机"), _head, W60);
			GUILayout.Label(Loc.T("This PC", "本机生效"), _head, W80);
			GUILayout.Label(Loc.T("Note", "说明"), _head, NoOpts);
			GUILayout.EndHorizontal();
			foreach (Cell[] mSetting in _mSettings)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				Label(mSetting[0].Text, mSetting[0].Color, _cell, W170);
				Label(mSetting[1].Text, mSetting[1].Color, _cell, W60);
				Label(mSetting[2].Text, mSetting[2].Color, _cell, W80);
				Label(mSetting[3].Text, mSetting[3].Color, _foot, NoOpts);
				GUILayout.EndHorizontal();
			}
			if (_mNotes.Count > 0)
			{
				GUILayout.Space(6f);
				foreach (Cell mNote in _mNotes)
				{
					Label(mNote.Text, mNote.Color, _foot, NoOpts);
				}
			}
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 30f));
		}

		private static void RebuildDetail()
		{
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_043a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0457: Unknown result type (might be due to invalid IL or missing references)
			//IL_048b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0484: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ce: Unknown result type (might be due to invalid IL or missing references)
			_dRows.Clear();
			_dNoData = null;
			_dBiome = null;
			string arg = ((SyncCheck.LocalSeed != 0) ? SyncCheck.LocalSeed.ToString() : Loc.T("Unknown", "未知"));
			string arg2 = ((SyncCheck.LastCheckTime == default(DateTime)) ? "—" : SyncCheck.LastCheckTime.ToString("HH:mm:ss"));
			_dSummary = Loc.T($"Seed {arg} · {SyncCheck.LocalTotal} spawners · checked at {arg2}", $"本图种子 {arg} · spawner 总数 {SyncCheck.LocalTotal} · 校验时间 {arg2}");
			if (!string.IsNullOrEmpty(SyncCheck.BiomeSummary))
			{
				_dBiome = Loc.T("Biomes: " + SyncCheck.BiomeSummary, "当前生态:" + SyncCheck.BiomeSummary);
			}
			List<SyncCheck.Result> list = SyncCheck.Results.Values.OrderByDescending((SyncCheck.Result r) => r.Mismatches.Count).ToList();
			float th = Plugin.AlertThreshold.Value;
			List<SyncCheck.Result> list2 = list.Where((SyncCheck.Result r) => r.Mismatches.Count > 0).ToList();
			List<SyncCheck.Result> list3 = list2.Where((SyncCheck.Result r) => r.Rate >= th).ToList();
			List<SyncCheck.Result> list4 = list.Where((SyncCheck.Result r) => r.Mismatches.Count == 0 || r.Rate < th).ToList();
			if (list.Count == 0)
			{
				_dNoData = Loc.T("No sync data yet (collected ~10s after generation; the other player needs this patch installed)", "尚未收到校验数据(生成完成约 10 秒后自动统计;对方需安装本补丁)");
				_dSyncLine = Array.Empty<Cell>();
				_dTabs = Array.Empty<string>();
				return;
			}
			List<Cell> list5 = new List<Cell>
			{
				new Cell(Loc.T($"Sync: {list4.Count}/{list.Count}", $"同步情况:{list4.Count}/{list.Count}"), (list4.Count == list.Count) ? ColGreen : ColText)
			};
			if (list3.Count > 0)
			{
				list5.Add(new Cell(Loc.T(", desynced: ", ",不同步玩家:"), ColText));
				list5.Add(new Cell(string.Join(" | ", list3.Select((SyncCheck.Result r) => Loc.T($"{Names.Truncate(r.Nick, 12)} {r.MatchCount}/{r.Total} match, {r.Mismatches.Count} desynced {r.Rate:F1}%", $"{Names.Truncate(r.Nick, 12)} {r.MatchCount}/{r.Total} 一致,{r.Mismatches.Count} 项不同步 {r.Rate:F1}%"))), ColRed));
			}
			if (list4.Count > 0)
			{
				list5.Add(new Cell(Loc.T("  in sync: ", "  同步:"), ColGray));
				list5.Add(new Cell(string.Join(" | ", list4.Select((SyncCheck.Result r) => Names.Truncate(r.Nick, 12) + ((r.Mismatches.Count > 0) ? $"({r.Rate:F1}%)" : ""))), ColGray));
			}
			_dSyncLine = list5.ToArray();
			if (list2.Count == 0)
			{
				_dTabs = Array.Empty<string>();
				return;
			}
			if (_tabIndex >= list2.Count)
			{
				_tabIndex = 0;
			}
			_dTabs = list2.Select(delegate(SyncCheck.Result r)
			{
				List<string> list6 = (from m in r.Mismatches
					select Loc.Biome(SyncCheck.BiomeOfSegmentName(m.Biome ?? "")) into b
					where !string.IsNullOrEmpty(b) && b != "?"
					select b).Distinct().Take(3).ToList();
				string text = ((list6.Count == 0) ? "" : (" [" + string.Join("·", list6) + "]"));
				return Loc.T($"{Names.Truncate(r.Nick, 10)}{text}[{r.Mismatches.Count}][{r.Rate:F1}%]", $"{Names.Truncate(r.Nick, 10)}{text}[{r.Mismatches.Count}项][{r.Rate:F1}%]");
			}).ToArray();
			SyncCheck.Result result = list2[_tabIndex];
			int num = Math.Min(result.Mismatches.Count, 60);
			for (int num2 = 0; num2 < num; num2++)
			{
				SyncCheck.Mismatch mismatch = result.Mismatches[num2];
				_dRows.Add(new Cell[6]
				{
					new Cell(Names.Truncate($"{mismatch.Name} (#{(uint)mismatch.Id % 10000u})", 30), ColText),
					new Cell(Names.Truncate(Loc.Zh ? Names.Translate(mismatch.Name) : mismatch.Name, 10), ColText),
					new Cell(Names.Truncate(Loc.Biome(SyncCheck.BiomeOfSegmentName(mismatch.Biome ?? "")), Loc.Zh ? 6 : 10), ColText),
					new Cell(mismatch.HostCount.ToString(), ColText),
					new Cell(mismatch.TheirCount.ToString(), (mismatch.TheirCount == mismatch.HostCount) ? ColText : ColRed),
					new Cell(mismatch.PosDiff ? Loc.T("Diff", "不一致") : Loc.T("Same", "一致"), mismatch.PosDiff ? ColRed : ColGreen)
				});
			}
			_dOverflow = ((result.Mismatches.Count > 60) ? Loc.T($"… {result.Mismatches.Count - 60} more rows omitted (full list in sync_report_*.log)", $"… 另有 {result.Mismatches.Count - 60} 条已省略(完整清单见 sync_report_*.log)") : null);
			_dFirstDiv = result.FirstDivergence ?? Loc.T("None", "无");
		}

		private static void DrawDetailWindow(int _)
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_024f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_025e: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0317: 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_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginHorizontal(_title, Array.Empty<GUILayoutOption>());
			GUILayout.Label(Loc.T("Sync Details (hold F8 to open)", "同步数据详情(长按 F8 展开)"), _titleText, NoOpts);
			GUILayout.FlexibleSpace();
			Label(Loc.T("short press F8 to return", "短按F8返回"), ColGray, _head, NoOpts);
			GUILayout.EndHorizontal();
			Label(Loc.T("Check Summary", "校验概况"), ColHead, _cell, NoOpts);
			Label(_dSummary, ColText, _cell, NoOpts);
			if (_dBiome != null)
			{
				Label(_dBiome, ColText, _wrapCell, NoOpts);
			}
			if (_dNoData != null)
			{
				Label(_dNoData, ColGray, _cell, NoOpts);
			}
			else if (_dSyncLine.Length != 0)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				Cell[] dSyncLine = _dSyncLine;
				for (int i = 0; i < dSyncLine.Length; i++)
				{
					Cell cell = dSyncLine[i];
					Label(cell.Text, cell.Color, _cell, NoOpts);
				}
				GUILayout.FlexibleSpace();
				GUILayout.EndHorizontal();
			}
			if (_dTabs.Length != 0)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				for (int j = 0; j < _dTabs.Length; j++)
				{
					if (GUILayout.Button(_dTabs[j], (j == _tabIndex) ? _tabActive : _tab, NoOpts) && _tabIndex != j)
					{
						_tabIndex = j;
						Invalidate();
					}
				}
				GUILayout.FlexibleSpace();
				GUILayout.EndHorizontal();
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label("Spawner (ID)", _head, W230);
				GUILayout.Label(Loc.T("Name", "译名"), _head, W120);
				GUILayout.Label(Loc.T("Biome", "生态"), _head, W60);
				GUILayout.Label(Loc.T("Host", "主机"), _head, W60);
				GUILayout.Label(Loc.T("Theirs", "对方"), _head, W60);
				GUILayout.Label(Loc.T("Pos", "位置"), _head, W60);
				GUILayout.EndHorizontal();
				_scroll = GUILayout.BeginScrollView(_scroll, H280);
				foreach (Cell[] dRow in _dRows)
				{
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					for (int k = 0; k < dRow.Length; k++)
					{
						Label(dRow[k].Text, dRow[k].Color, _cell, _dRowWidths[k]);
					}
					GUILayout.EndHorizontal();
				}
				GUILayout.EndScrollView();
				if (_dOverflow != null)
				{
					Label(_dOverflow, ColGray, _foot, NoOpts);
				}
				Label(Loc.T("First Divergence", "首个分叉点"), ColHead, _cell, NoOpts);
				Label(_dFirstDiv, ColText, _cell, NoOpts);
				Label(Loc.T("Details broadcast to everyone's log: BepInEx\\config\\随机地形增强\\sync_report_*.log", "明细已广播至全员日志:BepInEx\\config\\随机地形增强\\sync_report_*.log"), ColGray, _foot, NoOpts);
			}
			GUI.DragWindow(new Rect(0f, 0f, 10000f, 30f));
		}
	}
	internal static class LanguageConfig
	{
		private static string _existing;

		internal static void Capture(ConfigFile config)
		{
			_existing = (File.Exists(config.ConfigFilePath) ? File.ReadAllText(config.ConfigFilePath) : "");
		}

		internal static ConfigEntry<T> Bind<T>(ConfigFile config, string enSection, string zhSection, string enKey, string zhKey, T value, string description)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			return Bind(config, enSection, zhSection, enKey, zhKey, value, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()));
		}

		internal static ConfigEntry<T> Bind<T>(ConfigFile config, string enSection, string zhSection, string enKey, string zhKey, T value, ConfigDescription description)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Invalid comparison between Unknown and I4
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			SystemLanguage systemLanguage = Application.systemLanguage;
			int num;
			string text;
			if ((int)systemLanguage != 6 && (int)systemLanguage != 40)
			{
				num = (((int)systemLanguage == 41) ? 1 : 0);
				if (num == 0)
				{
					text = enSection;
					goto IL_001e;
				}
			}
			else
			{
				num = 1;
			}
			text = zhSection;
			goto IL_001e;
			IL_001e:
			string text2 = text;
			string text3 = ((num != 0) ? zhKey : enKey);
			string[][] array = new string[3][]
			{
				new string[2] { text2, text3 },
				new string[2] { enSection, enKey },
				new string[2] { zhSection, zhKey }
			};
			foreach (string[] array2 in array)
			{
				if (Regex.IsMatch(Regex.Match(_existing, "(?ms)^\\[" + Regex.Escape(array2[0]) + "\\]\\s*\\r?\\n(.*?)(?=^\\[|\\z)").Groups[1].Value, "(?m)^\\s*" + Regex.Escape(array2[1]) + "\\s*="))
				{
					return config.Bind<T>(array2[0], array2[1], value, description);
				}
			}
			return config.Bind<T>(enSection, enKey, value, description);
		}
	}
	public static class Loc
	{
		private static string _setting = "Auto";

		private static readonly Dictionary<string, string> BiomeEn = new Dictionary<string, string>
		{
			{ "海滩", "Shore" },
			{ "雨林", "Tropics" },
			{ "森蕈", "Roots" },
			{ "雪山", "Alpine" },
			{ "方山", "Mesa" },
			{ "火山", "Caldera" },
			{ "沼泽", "Swamp" },
			{ "原版", "Vanilla" },
			{ "熔炉", "The Kiln" },
			{ "顶峰", "The Peak" }
		};

		public static bool Zh => Resolve(_setting, LocalizedText.CURRENT_LANGUAGE);

		public static event Action Changed;

		public static void Init(string setting)
		{
			_setting = setting ?? "Auto";
		}

		public static void SetLanguage(string setting)
		{
			Init(setting);
			Loc.Changed?.Invoke();
		}

		public static void OnGameLanguageChanged()
		{
			Loc.Changed?.Invoke();
		}

		public static bool Resolve(string setting, Language language)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Invalid comparison between Unknown and I4
			if (setting == "中文")
			{
				return true;
			}
			if (setting == "English")
			{
				return false;
			}
			if ((int)language != 9)
			{
				return (int)language == 10;
			}
			return true;
		}

		public static string T(string en, string zh)
		{
			if (!Zh)
			{
				return en;
			}
			return zh;
		}

		public static string Biome(string zhKey)
		{
			if (Zh || string.IsNullOrEmpty(zhKey))
			{
				return zhKey;
			}
			if (!BiomeEn.TryGetValue(zhKey, out var value))
			{
				return zhKey;
			}
			return value;
		}
	}
	public static class LocalMods
	{
		private static ConfigEntryBase _tfaLighting;

		private static bool _detected;

		public static void EnsureDetected()
		{
			if (_detected)
			{
				return;
			}
			_detected = true;
			try
			{
				Type type = AccessTools.TypeByName("TrueFinalAscent.Plugin");
				if (type != null)
				{
					object? obj = AccessTools.Field(type, "Lighting")?.GetValue(null);
					_tfaLighting = (ConfigEntryBase)((obj is ConfigEntryBase) ? obj : null);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[地形增强] 探测 TFA 配置失败: " + ex.Message));
			}
		}

		public static string TfaLightingToken()
		{
			EnsureDetected();
			ConfigEntryBase tfaLighting = _tfaLighting;
			return (((tfaLighting != null) ? tfaLighting.BoxedValue : null) as string) ?? "-";
		}
	}
	public static class TcSession
	{
		private const string MAP_DATA_KEY = "TC_mapData";

		private static readonly HashSet<string> OwnStates = new HashSet<string> { "WaitingForMapData", "WaitingToStartCustomMap", "LoadingCustomMap", "CustomMapReady", "InCustomMap", "LoadingEditor", "InEditor" };

		private static bool _resolved;

		private static PropertyInfo _stateProp;

		public static bool OwnsMap()
		{
			try
			{
				if (PhotonNetwork.InRoom)
				{
					Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties;
					if (customProperties != null && ((Dictionary<object, object>)(object)customProperties).TryGetValue((object)"TC_mapData", out object value) && value is byte[] array && array.Length != 0)
					{
						return true;
					}
				}
				if (!_resolved)
				{
					_resolved = true;
					Type type = AccessTools.TypeByName("TerrainCustomiser.Session.SessionState");
					if (type != null)
					{
						_stateProp = AccessTools.Property(type, "Current");
					}
				}
				object obj = _stateProp?.GetValue(null);
				return obj != null && OwnStates.Contains(obj.ToString());
			}
			catch
			{
				return false;
			}
		}
	}
	public static class Names
	{
		private static readonly Dictionary<string, string> Map = new Dictionary<string, string>
		{
			{ "Bounce Shrooms", "大型踏板菇" },
			{ "Shroom Spawners", "蘑菇刷新点" },
			{ "Glow Mushrooms", "发光蘑菇" },
			{ "Exploding Shrooms", "爆炸蘑菇" },
			{ "ExploShrooms", "爆炸蘑菇" },
			{ "PoisonShrooms", "毒蘑菇" },
			{ "Evil Shroom", "邪恶蘑菇" },
			{ "Scorpion", "蝎子" },
			{ "Scorpions", "蝎子" },
			{ "Spiders", "蜘蛛" },
			{ "Zombie Spawner", "僵尸刷新点" },
			{ "Vines", "藤蔓" },
			{ "Ivy", "常春藤" },
			{ "Luggage", "行李箱" },
			{ "LuggageSpawner", "行李箱" },
			{ "Root Spawner", "根须" },
			{ "Geysers", "间歇泉" },
			{ "Weed", "杂草" },
			{ "BeachGrass", "滩草" },
			{ "Driftwood", "浮木" },
			{ "Behive", "蜂巢" },
			{ "ShittyPiton", "岩钉" },
			{ "Monsteras", "龟背竹" },
			{ "FlashPlant", "闪光植物" },
			{ "Shrub", "灌木" },
			{ "Bushes", "灌木丛" },
			{ "Pine", "松树" },
			{ "Trees", "树" },
			{ "DeadTree", "枯树" },
			{ "Ice_DeadTree", "冰封枯树" },
			{ "Palms", "棕榈" },
			{ "Cacti", "仙人掌" },
			{ "Dynamite", "炸药" },
			{ "Ferns", "蕨类" }
		};

		private static readonly Dictionary<string, string> BiomeMap = new Dictionary<string, string>
		{
			{ "Shore", "海滩" },
			{ "Tropics", "雨林" },
			{ "Roots", "森蕈" },
			{ "Alpine", "雪山" },
			{ "Mesa", "方山" },
			{ "Volcano", "火山" },
			{ "Swamp", "沼泽" },
			{ "Vanilla", "原版" }
		};

		private static readonly Dictionary<string, string> VariantMap = new Dictionary<string, string>
		{
			{ "Default", "默认变体(Default)" },
			{ "NoVariant", "无变体(No Variant)" },
			{ "SnakeBeach", "蛇骨海滩(Snake Beach)" },
			{ "RedBeach", "红沙海岸(Red Beach)" },
			{ "BlueBeach", "深蓝海岸(Blue Beach)" },
			{ "JellyHell", "水母地狱(Jelly Hell)" },
			{ "BlackSand", "黑沙洲(Black Sand)" },
			{ "Lava", "熔岩区(Lava)" },
			{ "Pillars", "石柱群(Pillars)" },
			{ "Thorny", "荆棘(Thorny)" },
			{ "Bombs", "雷区(Bombs)" },
			{ "Ivy", "藤蔓谷(Ivy)" },
			{ "SkyJungle", "天空丛林(Sky Jungle)" },
			{ "Cave Mania", "狂热洞穴(Cave Mania)" },
			{ "Deep Water", "深水区(Deep Water)" },
			{ "Bomb Beetle", "伐木场(Bomb Beetle)" },
			{ "Deep Woods", "深林(Deep Woods)" },
			{ "Clearcut", "伐木林地(Clearcut)" },
			{ "Spiky", "尖刺重重(Spiky)" },
			{ "GeyserHell", "喷泉地狱(Geyser Hell)" },
			{ "ScorpionsHell", "毒蝎地狱(Scorpions Hell)" },
			{ "CacusHell", "巨仙人掌地狱(Cacus Hell)" },
			{ "CactusForest", "仙人掌森林(Cactus Forest)" },
			{ "DynamiteHell", "炸药地狱(Dynamite Hell)" },
			{ "TornadoHell", "龙卷风地狱(Tornado Hell)" },
			{ "TumblerHell", "风滚草地狱(Tumbler Hell)" },
			{ "Tomb", "古墓(Tomb)" }
		};

		private static bool _templateLoaded;

		private static readonly KeyValuePair<string, string>[] SegmentAlias = new KeyValuePair<string, string>[14]
		{
			new KeyValuePair<string, string>("shore", "海滩"),
			new KeyValuePair<string, string>("beach", "海滩"),
			new KeyValuePair<string, string>("tropic", "雨林"),
			new KeyValuePair<string, string>("jungle", "雨林"),
			new KeyValuePair<string, string>("roots", "森蕈"),
			new KeyValuePair<string, string>("alpine", "雪山"),
			new KeyValuePair<string, string>("snow", "雪山"),
			new KeyValuePair<string, string>("mesa", "方山"),
			new KeyValuePair<string, string>("desert", "方山"),
			new KeyValuePair<string, string>("caldera", "火山"),
			new KeyValuePair<string, string>("volcano", "火山"),
			new KeyValuePair<string, string>("swamp", "沼泽"),
			new KeyValuePair<string, string>("kiln", "熔炉"),
			new KeyValuePair<string, string>("peak", "顶峰")
		};

		public static string Translate(string raw)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return raw;
			}
			if (Map.TryGetValue(raw, out var value))
			{
				return value;
			}
			foreach (KeyValuePair<string, string> item in Map)
			{
				if (raw.StartsWith(item.Key))
				{
					return item.Value;
				}
			}
			return raw;
		}

		public static void LoadZhTemplate()
		{
			if (_templateLoaded)
			{
				return;
			}
			_templateLoaded = true;
			try
			{
				string[] files = Directory.GetFiles(Paths.PluginPath, "TerrainRandomiser_ZH*.txt", SearchOption.AllDirectories);
				if (files.Length == 0)
				{
					return;
				}
				string text = null;
				string[] array = File.ReadAllLines(files[0]);
				for (int i = 0; i < array.Length; i++)
				{
					string text2 = array[i].Trim();
					if (text2.StartsWith("=="))
					{
						text = text2;
						continue;
					}
					int num = text2.IndexOf('=');
					if (num <= 0 || text == null)
					{
						continue;
					}
					string text3 = text2.Substring(0, num).Trim();
					string text4 = text2.Substring(num + 1).Trim();
					if (text3.Length != 0 && text4.Length != 0)
					{
						if (text.Contains("生态") || text.Contains("Biomes"))
						{
							BiomeMap[text3] = text4;
						}
						else if (text.Contains("变体") || text.Contains("Variants"))
						{
							VariantMap[text3] = text4;
						}
					}
				}
				Plugin.Log.LogInfo((object)("[地形增强] 已加载汉化模板: " + files[0]));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[地形增强] 汉化模板加载失败: " + ex.Message));
			}
		}

		private static string StripParen(string s)
		{
			return Regex.Replace(s, "\\s*\\([^)]*\\)\\s*$", "");
		}

		public static string Biome(string raw)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return raw;
			}
			if (!BiomeMap.TryGetValue(raw, out var value))
			{
				return raw;
			}
			if (!value.Contains("("))
			{
				return value + "(" + raw + ")";
			}
			return value;
		}

		public static string Variant(string raw)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return raw;
			}
			if (!VariantMap.TryGetValue(raw, out var value))
			{
				return raw;
			}
			if (!value.Contains("("))
			{
				return value + "(" + raw + ")";
			}
			return value;
		}

		public static string BiomeShort(string raw)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return raw;
			}
			if (!BiomeMap.TryGetValue(raw, out var value))
			{
				return raw;
			}
			return StripParen(value);
		}

		public static string VariantShort(string raw)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return raw;
			}
			if (!VariantMap.TryGetValue(raw, out var value))
			{
				return raw;
			}
			return StripParen(value);
		}

		public static string SegmentZh(string raw)
		{
			if (string.IsNullOrEmpty(raw))
			{
				return "";
			}
			string text = raw.ToLowerInvariant();
			KeyValuePair<string, string>[] segmentAlias = SegmentAlias;
			for (int i = 0; i < segmentAlias.Length; i++)
			{
				KeyValuePair<string, string> keyValuePair = segmentAlias[i];
				if (text.Contains(keyValuePair.Key))
				{
					return keyValuePair.Value;
				}
			}
			return raw;
		}

		public static string Truncate(string s, int max)
		{
			if (string.IsNullOrEmpty(s) || s.Length <= max)
			{
				return s;
			}
			return s.Substring(0, max - 1) + "…";
		}
	}
	public enum Tri
	{
		Unknown,
		No,
		Yes
	}
	public static class Negotiate
	{
		private static readonly Dictionary<string, string> _forcedOff = new Dictionary<string, string>();

		private static readonly Dictionary<string, string> _toasted = new Dictionary<string, string>();

		public static string ForcedOffReason(ITerrainTarget t)
		{
			if (!_forcedOff.TryGetValue(t.Id, out var value))
			{
				return null;
			}
			return value;
		}

		public static Tri HostPatch()
		{
			if (!PhotonNetwork.InRoom)
			{
				return Tri.Unknown;
			}
			Player masterClient = PhotonNetwork.MasterClient;
			if (masterClient == null)
			{
				return Tri.Unknown;
			}
			if (masterClient.IsLocal)
			{
				return Tri.Yes;
			}
			if (Plugin.ParsePlayer(masterClient).HasPatch)
			{
				return Tri.Yes;
			}
			if (!RoomWatch.WithinGrace(masterClient))
			{
				return Tri.No;
			}
			return Tri.Unknown;
		}

		public static Tri HostSupports(ITerrainTarget t)
		{
			Tri tri = HostPatch();
			if (tri != Tri.Yes)
			{
				return tri;
			}
			Player masterClient = PhotonNetwork.MasterClient;
			if (masterClient == null)
			{
				return Tri.Unknown;
			}
			if (masterClient.IsLocal)
			{
				return Tri.Yes;
			}
			if (!Plugin.ParsePlayer(masterClient).Supports(t.Id))
			{
				return Tri.No;
			}
			return Tri.Yes;
		}

		public static bool? GetRoomBool(string key)
		{
			if (!PhotonNetwork.InRoom)
			{
				return null;
			}
			Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties;
			if (customProperties != null && ((Dictionary<object, object>)(object)customProperties).TryGetValue((object)key, out object value) && value is bool)
			{
				return (bool)value;
			}
			return null;
		}

		public static Plugin.GenLock? GetGenLock(ITerrainTarget t)
		{
			if (!PhotonNetwork.InRoom)
			{
				return null;
			}
			Hashtable customProperties = ((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties;
			if (customProperties == null || !((Dictionary<object, object>)(object)customProperties).TryGetValue((object)t.Keys.GenLock, out object value) || !(value is string text))
			{
				return null;
			}
			string[] array = text.Split(new char[1] { '|' });
			if (array.Length < 4 || !int.TryParse(array[0], out var result))
			{
				return null;
			}
			return new Plugin.GenLock
			{
				Seed = result,
				Bake = ((array[1] == "?") ? ((bool?)null) : new bool?(array[1] == "1")),
				Fix = (array[2] == "1"),
				Vf = (array[3] == "1")
			};
		}

		public static bool LocalSwitch(Cap cap)
		{
			return cap switch
			{
				Cap.Rng => Plugin.EnableGenFixes.Value, 
				Cap.ViewId => Plugin.EnableViewFix.Value, 
				Cap.Sync => true, 
				_ => false, 
			};
		}

		public static bool Decide(ITerrainTarget t, Cap cap)
		{
			if (t == null || t.Version == null)
			{
				return false;
			}
			if ((t.Caps & cap) == 0)
			{
				return false;
			}
			if (!Arbiter.Allows(t, cap))
			{
				return false;
			}
			bool flag = LocalSwitch(cap);
			if (!PhotonNetwork.InRoom)
			{
				return flag;
			}
			if (PhotonNetwork.IsMasterClient)
			{
				if ((cap == Cap.Rng || cap == Cap.ViewId) && ForcedOffReason(t) != null)
				{
					return false;
				}
				return flag;
			}
			Tri tri = HostPatch();
			if (tri == Tri.No)
			{
				return false;
			}
			if (HostSupports(t) == Tri.No)
			{
				return false;
			}
			Plugin.GenLock? genLock = GetGenLock(t);
			if (genLock.HasValue && genLock.Value.Seed == t.GetSeed())
			{
				if (cap != Cap.Rng)
				{
					return genLock.Value.Vf;
				}
				return genLock.Value.Fix;
			}
			bool? roomBool = GetRoomBool((cap == Cap.Rng) ? t.Keys.Fix : t.Keys.ViewFix);
			if (roomBool.HasValue)
			{
				return roomBool.Value;
			}
			return tri == Tri.Yes && flag;
		}

		public static List<string> ScanMissing(ITerrainTarget t)
		{
			List<string> list = new List<string>();
			if (!PhotonNetwork.InRoom)
			{
				return list;
			}
			Player[] playerList = PhotonNetwork.PlayerList;
			foreach (Player val in playerList)
			{
				if (val == null || val.IsLocal)
				{
					continue;
				}
				Plugin.PlayerInfo playerInfo = Plugin.ParsePlayer(val);
				string text = Names.Truncate(val.NickName, 12);
				if (!playerInfo.HasPatch)
				{
					if (!RoomWatch.WithinGrace(val))
					{
						list.Add(text);
					}
				}
				else if (!playerInfo.Supports(t.Id))
				{
					list.Add(text + "(旧版)");
				}
			}
			return list;
		}

		public static void HostTick()
		{
			if (!PhotonNetwork.InRoom || !PhotonNetwork.IsMasterClient)
			{
				return;
			}
			ITerrainTarget[] all = Targets.All;
			foreach (ITerrainTarget terrainTarget in all)
			{
				if (terrainTarget.Version == null)
				{
					_forcedOff.Remove(terrainTarget.Id);
					continue;
				}
				if (!LocalSwitch(Cap.Rng) && !LocalSwitch(Cap.ViewId))
				{
					_forcedOff.Remove(terrainTarget.Id);
					_toasted.Remove(terrainTarget.Id);
					continue;
				}
				List<string> list = ScanMissing(terrainTarget);
				if (list.Count == 0)
				{
					if (_forcedOff.Remove(terrainTarget.Id))
					{
						_toasted.Remove(terrainTarget.Id);
						Gui.Invalidate();
					}
					continue;
				}
				string text = string.Join("、", list.ToArray());
				_forcedOff.TryGetValue(terrainTarget.Id, out var value);
				_forcedOff[terrainTarget.Id] = text;
				if (value != text)
				{
					Gui.Invalidate();
					if (!_toasted.TryGetValue(terrainTarget.Id, out var value2) || value2 != text)
					{
						_toasted[terrainTarget.Id] = text;
						Gui.AddToast(Loc.T("[RandomTerrainEnhance] " + terrainTarget.NameEn + " enhancements disabled room-wide: " + text + " lack this mod", "[随机地形增强] 已为全房关闭" + terrainTarget.NameZh + "增强:" + text + " 未安装本模组"));
					}
				}
			}
		}

		public static string BuildPayload()
		{
			bool? localBake = Plugin.GetLocalBake();
			string text = ((!localBake.HasValue) ? "?" : (localBake.Value ? "1" : "0"));
			string text2 = Arbiter.TfaVersion ?? "-";
			return string.Join("|", Targets.TR.Version ?? "-", Plugin.WindVersion ?? "-", text, "1.0.20", Plugin.BakeForced ? "1" : "0", text2, "-", "-", LocalMods.TfaLightingToken().Replace('|', '/'), (Plugin.EnableSceneGuard != null && Plugin.EnableSceneGuard.Value) ? "1" : "0");
		}

		public static void OnMasterSwitched(Player newMaster)
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			_forcedOff.Clear();
			_toasted.Clear();
			ITerrainTarget[] all = Targets.All;
			foreach (ITerrainTarget obj in all)
			{
				obj.State.HasLocked = false;
				obj.State.OffReason = null;
			}
			ViewFix.Reset();
			Gui.Invalidate();
			if (!PhotonNetwork.InRoom)
			{
				return;
			}
			if (newMaster == null || !newMaster.IsLocal)
			{
				Plugin.Log.LogInfo((object)("[地形增强] 房主已换人(" + (((newMaster != null) ? newMaster.NickName : null) ?? "?") + "),残留房间属性将不再被采信,等待新主机重建"));
				return;
			}
			try
			{
				Hashtable val = new Hashtable();
				all = Targets.All;
				for (int i = 0; i < all.Length; i++)
				{
					foreach (string item in all[i].Keys.All())
					{
						if (((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties != null && ((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).ContainsKey((object)item))
						{
							val[(object)item] = null;
						}
					}
				}
				if (((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties != null && ((Dictionary<object, object>)(object)((RoomInfo)PhotonNetwork.CurrentRoom).CustomProperties).ContainsKey((object)"RTE_bake"))
				{
					val[(object)"RTE_bake"] = null;
				}
				if (((Dictionary<object, object>)(object)val).Count > 0)
				{
					PhotonNetwork.CurrentRoom.SetCustomProperties(val, (Hashtable)null, (WebFlags)null);
					Plugin.Log.LogInfo((object)string.Format("{0} 已接任房主并清理 {1} 个残留房间属性,下一次 tick 按本机配置重建", "[地形增强]", ((Dictionary<object, object>)(object)val).Count));
				}
				Arbiter.ClearStaleFaKeys("接任房主");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[地形增强] 清理残留房间属性失败: " + ex.Message));
			}
		}

		public static void OnLeftRoom()
		{
			GeneratedMapScope.Clear();
			_forcedOff.Clear();
			_toasted.Clear();
			ITerrainTarget[] all = Targets.All;
			foreach (ITerrainTarget obj in all)
			{
				obj.State.HasLocked = false;
				obj.State.InGeneration = false;
				obj.State.OffReason = null;
				obj.State.Missing.Clear();
			}
			ViewFix.Reset();
		}
	}
	public class RoomWatch : IInRoomCallbacks, IMatchmakingCallbacks
	{
		public const float GraceSeconds = 5f;

		private static readonly Dictionary<int, float> _seenAt = new Dictionary<int, float>();

		private static float _masterSwitchAt = -999f;

		public static void Note(Player p)
		{
			if (p != null && !_seenAt.ContainsKey(p.ActorNumber))
			{
				_seenAt[p.ActorNumber] = Time.unscaledTime;
			}
		}

		public static bool WithinGrace(Player p)
		{
			if (p == null)
			{
				return true;
			}
			if (Time.unscaledTime - _masterSwitchAt < 5f)
			{
				return true;
			}
			if (!_seenAt.TryGetValue(p.ActorNumber, out var value))
			{
				Note(p);
				return true;
			}
			return Time.unscaledTime - value < 5f;
		}

		public void OnPlayerEnteredRoom(Player newPlayer)
		{
			Note(newPlayer);
			Gui.Invalidate();
		}

		public void OnPlayerLeftRoom(Player otherPlayer)
		{
			if (otherPlayer != null)
			{
				_seenAt.Remove(otherPlayer.ActorNumber);
			}
			Gui.Invalidate();
		}

		public void OnRoomPropertiesUpdate(Hashtable propertiesThatChanged)
		{
			Gui.Invalidate();
		}

		public void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps)
		{
			Gui.Invalidate();
		}

		public void OnMasterClientSwitched(Player newMasterClient)
		{
			_masterSwitchAt = Time.unscaledTime;
			Negotiate.OnMasterSwitched(newMasterClient);
		}

		public void OnJoinedRoom()
		{
			_seenAt.Clear();
			_masterSwitchAt = Time.unscaledTime;
			Player[] playerList = PhotonNetwork.PlayerList;
			for (int i = 0; i < playerList.Length; i++)
			{
				Note(playerList[i]);
			}
		}

		public void OnLeftRoom()
		{
			_seenAt.Clear();
			Negotiate.OnLeftRoom();
		}

		public void OnFriendListUpdate(List<FriendInfo> friendList)
		{
		}

		public void OnCreatedRoom()
		{
		}

		public void OnC