Decompiled source of ForestCreator v1.0.7

ForestCreator.dll

Decompiled 13 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using ATS_API.Buildings;
using ATS_API.Effects;
using ATS_API.Helpers;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Cysharp.Threading.Tasks;
using Eremite;
using Eremite.Buildings;
using Eremite.Buildings.UI;
using Eremite.Buildings.UI.Rainpunk;
using Eremite.Characters;
using Eremite.Characters.Automatons;
using Eremite.Characters.Behaviours;
using Eremite.Characters.Villagers;
using Eremite.Controller;
using Eremite.Model;
using Eremite.Model.Effects;
using Eremite.Model.Sound;
using Eremite.Model.State;
using Eremite.Services;
using Eremite.View;
using Eremite.View.HUD;
using Eremite.View.HUD.Construction;
using Eremite.View.Menu.Pick;
using Eremite.View.UI;
using Eremite.WorldMap;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("ForestCreator")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.7.0")]
[assembly: AssemblyInformationalVersion("1.0.7+068852371e0e48e0e5714faded8aa51c616de3ab")]
[assembly: AssemblyProduct("ForestCreator")]
[assembly: AssemblyTitle("ForestCreator")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.7.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}
namespace ForestCreator
{
	[BepInPlugin("ForestCreator", "ForestCreator", "1.0.7")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		internal sealed class SpawnerGroupRequest : GroupRequest
		{
			private readonly SpawnerModel _model;

			public override BuildingModel Model => (BuildingModel)(object)_model;

			public SpawnerGroupRequest(SpawnerModel model, IConstructionPlanner planner, Action onFinished)
				: base(planner, onFinished)
			{
				_model = model;
			}

			public override void Spawn(List<Vector2Int> positions)
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Unknown result type (might be due to invalid IL or missing references)
				//IL_0082: Unknown result type (might be due to invalid IL or missing references)
				//IL_008c: Expected O, but got Unknown
				//IL_008d: Unknown result type (might be due to invalid IL or missing references)
				//IL_008e: Unknown result type (might be due to invalid IL or missing references)
				int num = 0;
				if (positions != null)
				{
					foreach (Vector2Int position in positions)
					{
						if (num >= 400)
						{
							break;
						}
						Spawner val = null;
						try
						{
							if (GameMB.MapService.IsFieldEmpty(position))
							{
								val = ((Serviceable)this).Instantiate<Spawner>(_model.prefab);
								if (!((Object)(object)val == (Object)null))
								{
									val.SetUp(_model, new SpawnerState(_model, GameMB.StateService.GetUniqueId(), 0, GameMB.ConstructionService.GetConstructionCostFor((BuildingModel)(object)_model)));
									((Building)val).SetPosition(VectorExtensions.ToWorld(position));
									((Building)val).ManualPlacingFinished();
									num++;
								}
							}
						}
						catch (Exception)
						{
							try
							{
								if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null)
								{
									Object.Destroy((Object)(object)((Component)val).gameObject);
								}
							}
							catch
							{
							}
						}
					}
				}
				if (num > 0)
				{
					try
					{
						Serviceable.SoundsManager.PlaySoundEffect(Serviceable.Sounds.BuildingPlaced);
					}
					catch
					{
					}
				}
			}
		}

		private const string LayoutLogPath = "C:\\Users\\WenQuan\\Doubao\\chats\\2026-11-07\\new-chat\\fc_diag.txt";

		private static bool _fcNativePanelDumped;

		private static FieldInfo _brainStackField;

		internal const string FC_WorshipBuilderName = "Forest Creator Fervent Worship";

		internal const string FC_ProtectionBuilderName = "Forest Creator Divine Protection";

		private static string _fcWorshipEffectName;

		private static string _fcProtectionEffectName;

		private static HookedEffectModel _fcWorshipModel;

		private static HookedEffectModel _fcProtectionModel;

		private static bool _fcCornerstonesRegistered;

		private static bool _fcCornerstonesFailed;

		private static bool _fcWorshipActive;

		private static bool _fcProtectionActive;

		private const string PathGameContentServiceIsUnlocked = "IsUnlocked";

		private static readonly string[] PlantingDisplayKeywords = new string[5] { "温室", "护林", "greenhouse", "forester", "grove" };

		private static readonly string[] NonShopBuildingNames = new string[1] { "Homestead" };

		private static readonly string[] QueryOnlyUnlockNames = new string[1] { "Homestead" };

		private static int _hearthProductionLogBudget = 24;

		private static readonly string[] LowTierCampNames = new string[4] { "Primitive Forager's Camp", "Primitive Herbalist's Camp", "Primitive Trapper's Camp", "Primitive Fishing Hut" };

		private static bool _metaCampsCleaned;

		private const float SlotRadius = 125f;

		private static bool _suppressCycleYears;

		private static readonly string[] DragPlacingSpawnerNames = new string[1] { "Biome Grass Spawner" };

		private static readonly string[] DragPlacingSpawnerDisplayKeywords = new string[5] { "沃土", "肥沃", "Fertile Soil", "FertileSoil", "Fertile" };

		private static SpawnerModel ActiveDragSpawner;

		private const int DragPlacingMaxTilesPerDrag = 400;

		private const bool VerboseSpawnerDragDiagnostics = true;

		private static readonly string[] FC_StartingCornerstoneNames = new string[7] { "Hauling Cart in All Warehouses", "2 Hauling Carts in Main Warehouse", "Accidental Barrels", "Amber for Wood", "Woodcutting speed for water", "Lumber Speed +50", "[Altar] Villager for glade" };

		private static bool _steamDlcVerifyFailed;

		internal const string FC_TownHallBuilderName = "Forest Creator Town Hall";

		internal const string FC_TownHallCurrency = "[Valuable] Amber";

		internal const string FC_TownHallCostGood = "[Mat Raw] Wood";

		internal const int FC_TownHallPrice = 2;

		private const string FC_LookTemplateName = "Holy Temple";

		internal static InstitutionBuildingBuilder _fcTownHallBuilder;

		internal static string _fcTownHallName;

		private static bool _fcTownHallRegistered;

		private static bool _fcTownHallFailed;

		private static bool _fcTownHallPoolDone;

		private static GameContentService _fcContentSvc;

		private static bool _fcLookApplied;

		public static Plugin Instance;

		private Harmony harmony;

		internal static void LogInfo(string msg)
		{
			try
			{
				Plugin instance = Instance;
				if (instance != null)
				{
					ManualLogSource logger = ((BaseUnityPlugin)instance).Logger;
					if (logger != null)
					{
						logger.LogInfo((object)msg);
					}
				}
			}
			catch
			{
			}
		}

		internal static void LogError(string msg)
		{
			try
			{
				Plugin instance = Instance;
				if (instance != null)
				{
					ManualLogSource logger = ((BaseUnityPlugin)instance).Logger;
					if (logger != null)
					{
						logger.LogError((object)msg);
					}
				}
			}
			catch
			{
			}
		}

		[Conditional("DEBUG")]
		internal static void FileLog(string msg)
		{
			try
			{
				string directoryName = Path.GetDirectoryName("C:\\Users\\WenQuan\\Doubao\\chats\\2026-11-07\\new-chat\\fc_diag.txt");
				if (!Directory.Exists(directoryName))
				{
					Directory.CreateDirectory(directoryName);
				}
				File.AppendAllText("C:\\Users\\WenQuan\\Doubao\\chats\\2026-11-07\\new-chat\\fc_diag.txt", msg + "\n");
			}
			catch
			{
			}
			try
			{
				Plugin instance = Instance;
				if (instance != null)
				{
					ManualLogSource logger = ((BaseUnityPlugin)instance).Logger;
					if (logger != null)
					{
						logger.LogInfo((object)("[DIAG] " + msg));
					}
				}
			}
			catch
			{
			}
		}

		internal static void DumpNativePanelOnce(Transform root)
		{
			if (_fcNativePanelDumped || (Object)(object)root == (Object)null)
			{
				return;
			}
			_fcNativePanelDumped = true;
			try
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.AppendLine("==== NATIVE PANEL DUMP (TownHall reference) ====");
				WalkUI(root, 0, stringBuilder);
			}
			catch (Exception)
			{
			}
		}

		private static void WalkUI(Transform t, int depth, StringBuilder sb)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)t == (Object)null || depth > 5 || sb.Length > 150000)
			{
				return;
			}
			try
			{
				sb.Append(' ', depth * 2).Append('[').Append(((Object)((Component)t).gameObject).name)
					.Append(']');
				if (!((Component)t).gameObject.activeSelf)
				{
					sb.Append(" inactive");
				}
				Image component = ((Component)t).GetComponent<Image>();
				if ((Object)(object)component != (Object)null)
				{
					sb.Append(" img(spr=").Append(((Object)(object)component.sprite != (Object)null) ? ((Object)component.sprite).name : "null").Append(", type=")
						.Append(component.type)
						.Append(", c=")
						.Append(((Graphic)component).color)
						.Append(')');
				}
				TMP_Text component2 = ((Component)t).GetComponent<TMP_Text>();
				if ((Object)(object)component2 != (Object)null)
				{
					sb.Append(" tmp(\"").Append((component2.text ?? "").Replace("\n", "\\n")).Append("\" font=")
						.Append(((Object)(object)component2.font != (Object)null) ? ((Object)component2.font).name : "null")
						.Append(" size=")
						.Append(component2.fontSize)
						.Append(" c=")
						.Append(((Graphic)component2).color)
						.Append(')');
				}
				if ((Object)(object)((Component)t).GetComponent<Button>() != (Object)null)
				{
					sb.Append(" <BUTTON>");
				}
				if ((Object)(object)((Component)t).GetComponent<ScrollRect>() != (Object)null)
				{
					sb.Append(" <SCROLL>");
				}
				sb.AppendLine();
				for (int i = 0; i < t.childCount; i++)
				{
					WalkUI(t.GetChild(i), depth + 1, sb);
				}
			}
			catch
			{
			}
		}

		private static void DumpImages(GameObject go, string tag)
		{
			try
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append("IMAGES[" + tag + "] go=" + ((Object)go).name);
				Image[] componentsInChildren = go.GetComponentsInChildren<Image>(true);
				foreach (Image val in componentsInChildren)
				{
					object[] obj = new object[4]
					{
						((Object)((Component)val).gameObject).name,
						null,
						null,
						null
					};
					Sprite sprite = val.sprite;
					obj[1] = ((sprite != null) ? ((Object)sprite).name : null);
					obj[2] = ((Component)val).gameObject.activeSelf;
					obj[3] = (Object)(object)((Graphic)val).material != (Object)null;
					stringBuilder.Append(string.Format(" |[{0} spr={1} act={2} mat={3}]", obj));
				}
			}
			catch (Exception)
			{
			}
		}

		private static void DumpTree(BuildingsPickScreen __instance, string tag)
		{
			try
			{
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append("TREE[" + tag + "] root=" + ((Object)__instance).name);
				Transform transform = ((Component)__instance).transform;
				DumpNode(stringBuilder, (RectTransform)(object)((transform is RectTransform) ? transform : null), 0, 3);
			}
			catch (Exception)
			{
			}
		}

		private static void DumpNode(StringBuilder sb, RectTransform rt, int depth, int maxDepth)
		{
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: 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_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			if ((Object)(object)rt == (Object)null || depth > maxDepth)
			{
				return;
			}
			object[] obj = new object[5]
			{
				new string('.', depth),
				((Object)rt).name,
				rt.anchoredPosition.y,
				null,
				null
			};
			Rect rect = rt.rect;
			obj[3] = ((Rect)(ref rect)).height;
			obj[4] = ((Transform)rt).position.y;
			sb.Append(string.Format(" |{0}[{1} apY={2:F0} h={3:F0} worldY={4:F0}]", obj));
			foreach (Transform item in (Transform)rt)
			{
				Transform val = item;
				DumpNode(sb, (RectTransform)(object)((val is RectTransform) ? val : null), depth + 1, maxDepth);
			}
		}

		[HarmonyPatch(typeof(BuildingsPanel), "Start")]
		[HarmonyPostfix]
		private static void MakeRainCatchersRepeatable()
		{
			try
			{
				Settings val = ((MainController.Instance != null) ? MainController.Instance.Settings : null);
				if ((Object)(object)val == (Object)null || val.Buildings == null)
				{
					return;
				}
				int num = 0;
				BuildingModel[] buildings = val.Buildings;
				foreach (BuildingModel val2 in buildings)
				{
					if (!((Object)(object)val2 == (Object)null) && val2 is RainCatcherModel && !val2.repeatable)
					{
						val2.repeatable = true;
						num++;
					}
				}
				_ = 0;
			}
			catch (Exception)
			{
			}
		}

		[HarmonyPatch(typeof(BuildingsPanel), "Start")]
		[HarmonyPostfix]
		private static void MakeTradingPostMovable()
		{
			try
			{
				Settings val = ((MainController.Instance != null) ? MainController.Instance.Settings : null);
				if ((Object)(object)val == (Object)null || val.Buildings == null)
				{
					return;
				}
				int num = 0;
				BuildingModel[] buildings = val.Buildings;
				foreach (BuildingModel val2 in buildings)
				{
					if (!((Object)(object)val2 == (Object)null) && val2 is TradingPostModel && !val2.movable)
					{
						val2.movable = true;
						num++;
					}
				}
				_ = 0;
			}
			catch (Exception)
			{
			}
		}

		[HarmonyPatch(typeof(GameController), "StartGame")]
		[HarmonyPostfix]
		private static void ApplyCheatsAtStart()
		{
			try
			{
				if (!GameController.IsGameActive)
				{
					return;
				}
				try
				{
					SO.HostilityService.AddEffectHostility(FCConfig.StartHostility.Value);
				}
				catch
				{
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR ApplyCheatsAtStart: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(ReputationService), "GetReputationPenaltySpeed")]
		[HarmonyPostfix]
		private static void PatchImpatienceRate(ref float __result)
		{
			__result *= FCConfig.ImpatienceMultiplier.Value;
		}

		[HarmonyPatch(typeof(EffectsService), "GetProfessionBonusSpeed")]
		[HarmonyPostfix]
		private static void PatchWoodcutterWalk(string profession, ref float __result)
		{
			if (profession != null && profession.IndexOf("wood", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				__result += FCConfig.WoodcutterWalkBonus.Value;
			}
		}

		[HarmonyPatch(typeof(EffectsService), "GetInternalProductionRate")]
		[HarmonyPostfix]
		private static void PatchWoodcutterWork(Building building, ref float __result)
		{
			try
			{
				if (!((Object)(object)building == (Object)null))
				{
					BuildingModel buildingModel = building.BuildingModel;
					ProfessionModel val = (((Object)(object)buildingModel != (Object)null) ? buildingModel.Profession : null);
					string text = (((Object)(object)val != (Object)null) ? ((Object)val).name : null);
					if (text != null && text.IndexOf("wood", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						__result *= FCConfig.WoodcutterWorkMultiplier.Value;
					}
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(DailyService), "GetRewardsFor")]
		[HarmonyPostfix]
		private static void PatchDailyRewards(ref List<MetaCurrency> __result)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (__result != null)
				{
					float value = FCConfig.DailyRewardMultiplier.Value;
					for (int i = 0; i < __result.Count; i++)
					{
						__result[i] *= value;
					}
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(MetaEconomyService), "GetCurrenciesFor")]
		[HarmonyPostfix]
		private static void PatchRegularRewards(ref List<MetaCurrency> __result)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (__result != null)
				{
					float value = FCConfig.RegularRewardMultiplier.Value;
					for (int i = 0; i < __result.Count; i++)
					{
						__result[i] *= value;
					}
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(PerksService), "Sort")]
		[HarmonyPrefix]
		private static void CleanBrokenPerks(PerksService __instance)
		{
			try
			{
				FieldInfo field = ((object)__instance).GetType().GetField("<SortedPerks>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field == null || !(field.GetValue(__instance) is IList list))
				{
					return;
				}
				List<object> list2 = new List<object>();
				foreach (object item in list)
				{
					FieldInfo fieldInfo = item.GetType().GetField("name") ?? item.GetType().GetField("perkName");
					if (string.IsNullOrEmpty((fieldInfo != null) ? (fieldInfo.GetValue(item) as string) : null))
					{
						list2.Add(item);
					}
				}
				foreach (object item2 in list2)
				{
					list.Remove(item2);
					((BaseUnityPlugin)Instance).Logger.LogInfo((object)"FC: removed broken empty-name PerkState from SortedPerks");
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC CLEAN perks: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(MainController), "OnServicesReady")]
		[HarmonyPostfix]
		private static void DoubleCoverageRange()
		{
			try
			{
				Settings settings = MainController.Instance.Settings;
				if ((Object)(object)settings == (Object)null || settings.Buildings == null)
				{
					return;
				}
				int num = 0;
				int num2 = 0;
				BuildingModel[] buildings = settings.Buildings;
				foreach (BuildingModel val in buildings)
				{
					HearthModel val2 = (HearthModel)(object)((val is HearthModel) ? val : null);
					if (val2 != null)
					{
						val2.hubRange *= FCConfig.HearthRangeMultiplier.Value;
						num++;
						continue;
					}
					CampModel val3 = (CampModel)(object)((val is CampModel) ? val : null);
					if (val3 != null)
					{
						val3.maxDistance *= FCConfig.CampRangeMultiplier.Value;
						num2++;
					}
				}
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)$"FC: doubled coverage for {num} hearths and {num2} camps");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC COVERAGE: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(ProductionCalculator), "GetProductionMultiplier")]
		[HarmonyPostfix]
		private static void Robot_ProductionMultiplier(Building __0, RecipeModel __1, Actor __2, float __3, ref int __result)
		{
			try
			{
				if (__2 is Automaton)
				{
					__result *= FCConfig.RobotProductionMultiplier.Value;
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(EffectsService), "GetProductionRate")]
		[HarmonyPostfix]
		private static void Robot_ProductionRate(Building __0, Actor __1, RecipeModel __2, ref float __result)
		{
			try
			{
				if (__1 is Automaton)
				{
					__result *= FCConfig.RobotProductionRateMultiplier.Value;
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(MB), "GetText", new Type[] { typeof(string) })]
		[HarmonyPostfix]
		private static void MB_GetText(string key, ref string __result)
		{
			try
			{
				if (key == "GameUI_WorkerSlot_AutomatonTooltip_Desc")
				{
					__result = "使用先进的机器人技术代替工人工作,生产时间大幅缩短,产出倍率大幅提升。";
				}
			}
			catch
			{
			}
		}

		private static bool ActorBrain_StackEmpty(ActorBrain brain)
		{
			try
			{
				if (_brainStackField == null)
				{
					_brainStackField = AccessTools.Field(typeof(ActorBrain), "stack");
				}
				if (_brainStackField == null)
				{
					return false;
				}
				return !(_brainStackField.GetValue(brain) is Stack<ActorTask> stack) || stack.Count == 0;
			}
			catch
			{
				return false;
			}
		}

		[HarmonyPatch(typeof(ActorBrain), "GetCurrentIcon")]
		[HarmonyPrefix]
		private static bool ActorBrain_GetCurrentIcon_Prefix(ActorBrain __instance, ref Sprite __result)
		{
			if (ActorBrain_StackEmpty(__instance))
			{
				__result = null;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(ActorBrain), "GetCurrentDescription")]
		[HarmonyPrefix]
		private static bool ActorBrain_GetCurrentDescription_Prefix(ActorBrain __instance, ref string __result)
		{
			if (ActorBrain_StackEmpty(__instance))
			{
				__result = "";
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(ActorBrain), "GetCurrentProgress")]
		[HarmonyPrefix]
		private static bool ActorBrain_GetCurrentProgress_Prefix(ActorBrain __instance, ref float __result)
		{
			if (ActorBrain_StackEmpty(__instance))
			{
				__result = 0f;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(ActorBrain), "GetCurrentGood")]
		[HarmonyPrefix]
		private static bool ActorBrain_GetCurrentGood_Prefix(ActorBrain __instance, ref Good __result)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			if (ActorBrain_StackEmpty(__instance))
			{
				__result = Good.None;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(ActorTasksList), "OnStart")]
		[HarmonyPostfix]
		private static void ActorTasksList_OnStart_Postfix(ActorTasksList __instance)
		{
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Expected O, but got Unknown
			try
			{
				object? obj = AccessTools.Field(typeof(ActorTask), "brain")?.GetValue(__instance);
				ActorBrain val = (ActorBrain)((obj is ActorBrain) ? obj : null);
				object? obj2 = AccessTools.Field(typeof(ActorTask), "actor")?.GetValue(__instance);
				Actor val2 = (Actor)((obj2 is Actor) ? obj2 : null);
				if (val != null && !((Object)(object)val2 == (Object)null))
				{
					FieldInfo fieldInfo = AccessTools.Field(typeof(ActorBrain), "stack");
					if (!(fieldInfo == null) && (!(fieldInfo.GetValue(val) is Stack<ActorTask> { Count: >0 } stack) || (object)stack.Peek() == __instance))
					{
						IdleWait val3 = new IdleWait();
						((ActorTask)val3).SetUp(val2, val, new ActorTaskState((ActorTaskType)204));
						val.PushTask((ActorTask)(object)val3);
					}
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(FulfillNeeds), "CanStart")]
		[HarmonyPrefix]
		private static bool FulfillNeeds_CanStart_Prefix(FulfillNeeds __instance, ref bool __result)
		{
			if (AccessTools.Field(typeof(FulfillNeeds), "villager")?.GetValue(__instance) == null)
			{
				__result = false;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(BaseInstantTask), "GetIcon")]
		[HarmonyPrefix]
		private static bool BaseInstantTask_GetIcon_Prefix(ref Sprite __result)
		{
			__result = null;
			return false;
		}

		[HarmonyPatch(typeof(BaseInstantTask), "GetDescription")]
		[HarmonyPrefix]
		private static bool BaseInstantTask_GetDescription_Prefix(ref string __result)
		{
			__result = "";
			return false;
		}

		internal static void CreateCustomCornerstones()
		{
			if (_fcCornerstonesRegistered || _fcCornerstonesFailed)
			{
				return;
			}
			try
			{
				HookedEffectBuilder obj = CreateFerventWorship();
				HookedEffectBuilder val = CreateDivineProtection();
				_fcWorshipModel = ((EffectBuilder<HookedEffectModel>)(object)obj).EffectModel;
				_fcProtectionModel = ((EffectBuilder<HookedEffectModel>)(object)val).EffectModel;
				_fcWorshipEffectName = (((Object)(object)_fcWorshipModel != (Object)null) ? ((Object)_fcWorshipModel).name : null);
				_fcProtectionEffectName = (((Object)(object)_fcProtectionModel != (Object)null) ? ((Object)_fcProtectionModel).name : null);
				_fcCornerstonesRegistered = true;
				((BaseUnityPlugin)Instance).Logger.LogInfo((object)("FC CORNERSTONE registered: " + _fcWorshipEffectName + " / " + _fcProtectionEffectName));
			}
			catch (Exception ex)
			{
				_fcCornerstonesFailed = true;
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR CreateCustomCornerstones: " + ex));
			}
		}

		private static HookedEffectBuilder CreateFerventWorship()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_008b: Expected O, but got Unknown
			HookedEffectBuilder val = new HookedEffectBuilder("ForestCreator", "Forest Creator Fervent Worship", FC_IconPath("fc_blue_dragon.png"));
			((EffectBuilder<HookedEffectModel>)val).SetPositive(true);
			((EffectBuilder<HookedEffectModel>)val).SetRarity((EffectRarity)5);
			((EffectBuilder<HookedEffectModel>)val).SetObtainedAsCornerstone(100);
			((EffectBuilder<HookedEffectModel>)val).SetAvailableInAllBiomesAndSeasons();
			((EffectBuilder<HookedEffectModel>)val).SetDrawLimit(1);
			((EffectBuilder<HookedEffectModel>)val).SetLabel("ForestCreator", (SystemLanguage)10);
			((EffectBuilder<HookedEffectModel>)val).SetLabel("森林造物主", (SystemLanguage)40);
			((EffectBuilder<HookedEffectModel>)val).SetDisplayName("Forest Creator's Fervent Worship", (SystemLanguage)10);
			((EffectBuilder<HookedEffectModel>)val).SetDescription("The settlers of this town worship the Forest Creator with such fervor that they no longer wish to leave. Villagers never leave the settlement.", (SystemLanguage)10);
			((EffectBuilder<HookedEffectModel>)val).SetDisplayName("森林造物主的狂热崇拜", (SystemLanguage)40);
			((EffectBuilder<HookedEffectModel>)val).SetDescription("定居点的居民对森林造物主狂热崇拜,因此不会想要离开。", (SystemLanguage)40);
			return val;
		}

		private static HookedEffectBuilder CreateDivineProtection()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			//IL_008b: Expected O, but got Unknown
			HookedEffectBuilder val = new HookedEffectBuilder("ForestCreator", "Forest Creator Divine Protection", FC_IconPath("fc_gold_dragon.png"));
			((EffectBuilder<HookedEffectModel>)val).SetPositive(true);
			((EffectBuilder<HookedEffectModel>)val).SetRarity((EffectRarity)5);
			((EffectBuilder<HookedEffectModel>)val).SetObtainedAsCornerstone(100);
			((EffectBuilder<HookedEffectModel>)val).SetAvailableInAllBiomesAndSeasons();
			((EffectBuilder<HookedEffectModel>)val).SetDrawLimit(1);
			((EffectBuilder<HookedEffectModel>)val).SetLabel("ForestCreator", (SystemLanguage)10);
			((EffectBuilder<HookedEffectModel>)val).SetLabel("森林造物主", (SystemLanguage)40);
			((EffectBuilder<HookedEffectModel>)val).SetDisplayName("Forest Creator's Divine Protection", (SystemLanguage)10);
			((EffectBuilder<HookedEffectModel>)val).SetDescription("The Forest Creator watches over this town, so its settlers cannot die abnormally. Villagers never die from starvation, disease, events or assaults.", (SystemLanguage)10);
			((EffectBuilder<HookedEffectModel>)val).SetDisplayName("森林造物主的神圣庇佑", (SystemLanguage)40);
			((EffectBuilder<HookedEffectModel>)val).SetDescription("森林造物主庇护着定居点的居民,因此定居点的居民不会异常死去。", (SystemLanguage)40);
			return val;
		}

		private static string FC_IconPath(string fileName)
		{
			try
			{
				string directoryName = Path.GetDirectoryName(typeof(Plugin).Assembly.Location);
				if (!string.IsNullOrEmpty(directoryName))
				{
					string text = Path.Combine(Path.Combine(directoryName, "Assets"), fileName);
					if (File.Exists(text))
					{
						return text;
					}
				}
			}
			catch
			{
			}
			((BaseUnityPlugin)Instance).Logger.LogWarning((object)("FC CORNERSTONE icon not found next to plugin, falling back to plugins-wide search: " + fileName));
			return fileName;
		}

		internal static void FC_InjectCustomCornerstones()
		{
			InjectCustomCornerstone(_fcWorshipModel, "worship");
			InjectCustomCornerstone(_fcProtectionModel, "protection");
		}

		private static void InjectCustomCornerstone(HookedEffectModel model, string tag)
		{
			if ((Object)(object)model == (Object)null || FC_IsAlreadyApplied(((Object)model).name))
			{
				return;
			}
			try
			{
				((EffectModel)model).Apply((EffectContextType)0, (string)null, 0);
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)$"FC ERR inject cornerstone '{((Object)model).name}': {arg}");
			}
		}

		internal static void SyncCustomCornerstoneFlags()
		{
			_fcWorshipActive = (Object)(object)_fcWorshipModel != (Object)null && FC_IsAlreadyApplied(((Object)_fcWorshipModel).name);
			_fcProtectionActive = (Object)(object)_fcProtectionModel != (Object)null && FC_IsAlreadyApplied(((Object)_fcProtectionModel).name);
		}

		internal static bool FC_IsAlreadyApplied(string effectName)
		{
			if (string.IsNullOrEmpty(effectName))
			{
				return false;
			}
			try
			{
				IStateService stateService = Serviceable.StateService;
				if (stateService == null)
				{
					return false;
				}
				Dictionary<string, PerkState> dictionary = ((stateService.Effects != null) ? stateService.Effects.perks : null);
				if (dictionary != null && dictionary.ContainsKey(effectName))
				{
					return true;
				}
				GameHookedEffectsState hookedEffects = stateService.HookedEffects;
				if (hookedEffects != null)
				{
					if (ContainsHooked(hookedEffects.activeEffects, effectName))
					{
						return true;
					}
					if (ContainsHooked(hookedEffects.toAdd, effectName))
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool ContainsHooked(List<HookedEffectState> states, string effectName)
		{
			if (states == null)
			{
				return false;
			}
			for (int i = 0; i < states.Count; i++)
			{
				HookedEffectState val = states[i];
				if (val != null && val.model == effectName)
				{
					return true;
				}
			}
			return false;
		}

		[HarmonyPatch(typeof(Villager), "Die", new Type[]
		{
			typeof(VillagerLossType),
			typeof(string),
			typeof(bool),
			typeof(float),
			typeof(SoundModel)
		})]
		[HarmonyPrefix]
		private static bool FC_BlockVillagerLoss(VillagerLossType __0)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return FC_ShouldAllowLoss(__0);
		}

		[HarmonyPatch(typeof(Villager), "DieAsync", new Type[]
		{
			typeof(VillagerLossType),
			typeof(string),
			typeof(bool),
			typeof(float),
			typeof(SoundModel)
		})]
		[HarmonyPrefix]
		private static bool FC_BlockVillagerLossAsync(VillagerLossType __0)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return FC_ShouldAllowLoss(__0);
		}

		private static bool FC_ShouldAllowLoss(VillagerLossType lossType)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			try
			{
				if ((int)lossType == 1 && _fcProtectionActive)
				{
					return false;
				}
				if ((int)lossType == 2 && _fcWorshipActive)
				{
					return false;
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR FC_ShouldAllowLoss: " + ex.Message));
			}
			return true;
		}

		[HarmonyPatch(typeof(MainController), "OnServicesReady")]
		[HarmonyPostfix]
		private static void SetStartingPreparationPoints()
		{
			try
			{
				Settings settings = MainController.Instance.Settings;
				if ((Object)(object)settings != (Object)null && (Object)(object)settings.embarkConfig != (Object)null)
				{
					_ = settings.embarkConfig.preparationPoints;
					int value = FCConfig.EmbarkPreparationPoints.Value;
					settings.embarkConfig.preparationPoints = value;
				}
				else
				{
					((BaseUnityPlugin)Instance).Logger.LogError((object)"Could not find embarkConfig to change starting preparation points!");
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("Failed to change starting preparation points: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(BuildingsPickScreen), "Show")]
		[HarmonyPrefix]
		private static void ExpandStartingPicks(BuildingsPickScreen __instance)
		{
			__instance.maxInOffer = FCConfig.EmbarkMaxPicks.Value;
		}

		[HarmonyPatch(typeof(BuildingsPickScreen), "Show")]
		[HarmonyPostfix]
		private static void AddExtraEmbarkOffers(BuildingsPickScreen __instance)
		{
			//IL_059a: Unknown result type (might be due to invalid IL or missing references)
			//IL_059f: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b8: Expected O, but got Unknown
			//IL_04ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04be: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d2: Expected O, but got Unknown
			try
			{
				EmbarkBonusesState val = null;
				PropertyInfo property = typeof(BuildingsPickScreen).GetProperty("State", BindingFlags.Instance | BindingFlags.NonPublic);
				if (property != null)
				{
					object? value = property.GetValue(__instance);
					val = (EmbarkBonusesState)((value is EmbarkBonusesState) ? value : null);
				}
				if (val == null)
				{
					return;
				}
				try
				{
					Settings ss = MainController.Instance.Settings;
					List<string> list = new List<string>();
					foreach (ConditionPickState buildingsOption in val.buildingsOptions)
					{
						if (buildingsOption == null)
						{
							list.Add("(null)");
							continue;
						}
						string text = KindOf(buildingsOption.name);
						list.Add(buildingsOption.name + ((text != "") ? ("[" + text + "]") : ""));
					}
					List<string> list2 = new List<string>();
					foreach (ConditionPickState effectsOption in val.effectsOptions)
					{
						if (effectsOption == null)
						{
							list2.Add("(null)");
							continue;
						}
						string text2 = KindOf(effectsOption.name);
						list2.Add(effectsOption.name + ((text2 != "") ? ("[" + text2 + "]") : "") + "<" + EffTypeOf(effectsOption.name) + ">");
					}
					List<string> list3 = new List<string>();
					foreach (GoodPickState goodsOption in val.goodsOptions)
					{
						if (goodsOption == null)
						{
							list3.Add("(null)");
							continue;
						}
						string text3 = KindOf(goodsOption.name);
						list3.Add(goodsOption.name + ((text3 != "") ? ("[" + text3 + "]") : ""));
					}
					string EffTypeOf(string n)
					{
						if ((Object)(object)ss == (Object)null)
						{
							return "";
						}
						try
						{
							return ((object)ss.GetEffect(n))?.GetType().Name ?? "(no-effect)";
						}
						catch
						{
							return "(eff-key?)";
						}
					}
					string KindOf(string n)
					{
						if ((Object)(object)ss == (Object)null)
						{
							return "";
						}
						try
						{
							BuildingModel building = ss.GetBuilding(n);
							if (building is CampModel)
							{
								return "Camp";
							}
							if (building is GathererHutModel)
							{
								return "GathererHut";
							}
							if (building is FishingHutModel)
							{
								return "FishingHut";
							}
							if (building is FarmModel)
							{
								return "Farm";
							}
						}
						catch
						{
							return "(bld-key?)";
						}
						return "";
					}
				}
				catch (Exception ex)
				{
					((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR EMBARK-STATE dump: " + ex.Message));
				}
				Settings settings = MainController.Instance.Settings;
				if ((Object)(object)settings == (Object)null)
				{
					return;
				}
				if (true)
				{
					try
					{
						val.effectsOptions.RemoveAll((ConditionPickState o) => o != null && IsGatherOrFarmEffect(o.name));
						_ = 0;
					}
					catch (Exception ex2)
					{
						((BaseUnityPlugin)Instance).Logger.LogError((object)("removing gather/farm effects: " + ex2.Message));
					}
				}
				GoodModel[] goods = settings.Goods;
				foreach (GoodModel val2 in goods)
				{
					if (!((Object)(object)val2 == (Object)null))
					{
						string text4 = null;
						try
						{
							text4 = ((val2.displayName != null) ? val2.displayName.Text : null);
						}
						catch
						{
						}
						string text5 = (text4 ?? "").ToLowerInvariant();
						bool num2 = text5.Contains("晶露") || text5.Contains("露水") || text5.Contains("dew");
						bool flag = text5.Contains("铜矿") || text5.Contains("copper ore") || text5.Contains("copper");
						bool flag2 = text5.Contains("铜条") || text5.Contains("copper bar");
						bool flag3 = text5.Contains("植物纤维") || text5.Contains("纤维") || text5.Contains("fiber") || text5.Contains("fibre");
						bool flag4 = text5.Contains("香草") || text5.Contains("herb") || text5.Contains("vanilla");
						bool flag5 = text5.Contains("海洋精华") || text5.Contains("ocean essence");
						bool flag6 = text5.Contains("染料") || text5.Contains("dye");
						bool flag7 = text5.Contains("管道") || text5.Contains("pipe");
						bool flag8 = text5.Contains("肥料") || text5.Contains("fertilizer");
						if ((num2 || flag || flag2 || flag3 || flag4 || flag5 || flag6 || flag7 || flag8) && !HasGoodOption(val, ((SO)val2).Name))
						{
							val.goodsOptions.Add(new GoodPickState
							{
								name = ((SO)val2).Name,
								amount = 10,
								cost = 1
							});
							_ = flag7 || flag8;
						}
					}
				}
				EffectModel[] effects = settings.effects;
				foreach (EffectModel val3 in effects)
				{
					if (!((Object)(object)val3 == (Object)null))
					{
						string text6 = null;
						try
						{
							text6 = ((val3.displayName != null) ? val3.displayName.Text : null);
						}
						catch
						{
						}
						string text7 = (text6 ?? "").ToLowerInvariant();
						if ((text7.Contains("昆虫输送线") || text7.Contains("昆虫输送") || text7.Contains("insect supply") || text7.Contains("insect line")) && val3 is CompositeEffectModel && !HasEffectOption(val, ((SO)val3).Name))
						{
							val.effectsOptions.Add(new ConditionPickState
							{
								name = ((SO)val3).Name,
								cost = 1
							});
						}
						if (!text7.Contains("染料"))
						{
							text7.Contains("dye");
						}
						if (!text7.Contains("昆虫"))
						{
							text7.Contains("insect");
						}
					}
				}
				Type type = ((object)__instance).GetType();
				MethodInfo method = type.GetMethod("UpdateGoodsOfferSlots", BindingFlags.Instance | BindingFlags.NonPublic);
				MethodInfo method2 = type.GetMethod("UpdateRewardsOfferSlots", BindingFlags.Instance | BindingFlags.NonPublic);
				if (method != null)
				{
					method.Invoke(__instance, null);
				}
				if (method2 != null)
				{
					method2.Invoke(__instance, null);
				}
			}
			catch (Exception ex3)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("AddExtraEmbarkOffers failed: " + ex3.Message));
			}
		}

		private static bool HasGoodOption(EmbarkBonusesState state, string name)
		{
			foreach (GoodPickState goodsOption in state.goodsOptions)
			{
				if (goodsOption != null && goodsOption.name == name)
				{
					return true;
				}
			}
			return false;
		}

		private static bool HasEffectOption(EmbarkBonusesState state, string name)
		{
			foreach (ConditionPickState effectsOption in state.effectsOptions)
			{
				if (effectsOption != null && effectsOption.name == name)
				{
					return true;
				}
			}
			return false;
		}

		private static bool HasRewardPicked(EmbarkBonusesState state, string name)
		{
			foreach (ConditionPickState item in state.rewardsPicked)
			{
				if (item != null && item.name == name)
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsGatherOrFarmEffect(string effectName)
		{
			if (string.IsNullOrEmpty(effectName))
			{
				return false;
			}
			Settings settings = MainController.Instance.Settings;
			if ((Object)(object)settings == (Object)null)
			{
				return false;
			}
			try
			{
				EffectModel effect = settings.GetEffect(effectName);
				BaseBuildingEffectModel val = (BaseBuildingEffectModel)(object)((effect is BaseBuildingEffectModel) ? effect : null);
				if (val != null && (Object)(object)val.building != (Object)null)
				{
					return IsGatherOrFarm(val.building);
				}
			}
			catch
			{
			}
			string[] array = new string[4] { " Blueprint", "Blueprint", " blueprint", " blueprint " };
			foreach (string text in array)
			{
				if (!effectName.EndsWith(text, StringComparison.OrdinalIgnoreCase))
				{
					continue;
				}
				string text2 = effectName.Substring(0, effectName.Length - text.Length).Trim();
				if (text2.Length == 0)
				{
					continue;
				}
				try
				{
					BuildingModel building = settings.GetBuilding(text2);
					if ((Object)(object)building != (Object)null && IsGatherOrFarm(building))
					{
						return true;
					}
				}
				catch
				{
				}
			}
			return false;
		}

		[HarmonyPatch(typeof(MetaStateService), "CreateEmbarkBonuses")]
		[HarmonyPostfix]
		private static void FilterEmbarkBuildingOptions(ref EmbarkBonusesState __result)
		{
			try
			{
				if (__result == null || __result.buildingsOptions == null)
				{
					return;
				}
				Settings settings = MainController.Instance.Settings;
				if ((Object)(object)settings == (Object)null)
				{
					return;
				}
				_ = __result.buildingsOptions.Count;
				List<string> removed = new List<string>();
				__result.buildingsOptions.RemoveAll(delegate(ConditionPickState opt)
				{
					if (opt == null || string.IsNullOrEmpty(opt.name))
					{
						return false;
					}
					BuildingModel building = settings.GetBuilding(opt.name);
					if ((Object)(object)building != (Object)null && IsAutoUnlockCandidate(building))
					{
						removed.Add(opt.name);
						return true;
					}
					return false;
				});
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR FilterEmbarkBuildingOptions: " + ex.Message));
			}
		}

		private static bool IsGatherOrFarm(BuildingModel b)
		{
			if (!(b is CampModel) && !(b is GathererHutModel) && !(b is FishingHutModel))
			{
				return b is FarmModel;
			}
			return true;
		}

		private static bool IsPlantingByDisplayName(BuildingModel b)
		{
			try
			{
				string text = ((b.displayName != null) ? b.displayName.Text : null);
				if (string.IsNullOrEmpty(text))
				{
					return false;
				}
				string text2 = text.ToLowerInvariant();
				string[] plantingDisplayKeywords = PlantingDisplayKeywords;
				foreach (string value in plantingDisplayKeywords)
				{
					if (text2.Contains(value))
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		private static bool IsQueryOnlyUnlock(BuildingModel b)
		{
			if ((Object)(object)b == (Object)null)
			{
				return false;
			}
			string a = ((SO)b).Name ?? "";
			string[] queryOnlyUnlockNames = QueryOnlyUnlockNames;
			foreach (string b2 in queryOnlyUnlockNames)
			{
				if (string.Equals(a, b2, StringComparison.Ordinal))
				{
					return true;
				}
			}
			return false;
		}

		private static bool IsDeniedBuilding(BuildingModel b)
		{
			if ((Object)(object)b == (Object)null)
			{
				return true;
			}
			string text = ((SO)b).Name ?? "";
			string[] nonShopBuildingNames = NonShopBuildingNames;
			foreach (string b2 in nonShopBuildingNames)
			{
				if (string.Equals(text, b2, StringComparison.Ordinal))
				{
					return true;
				}
			}
			if (text.StartsWith("Ruined", StringComparison.Ordinal))
			{
				return true;
			}
			if (text.EndsWith("(no reward)", StringComparison.Ordinal))
			{
				return true;
			}
			return false;
		}

		private static bool IsAutoUnlockCandidate(BuildingModel b)
		{
			if ((Object)(object)b == (Object)null)
			{
				return false;
			}
			if (IsDeniedBuilding(b))
			{
				return false;
			}
			if (((SO)b).Name == "Biome Grass Spawner")
			{
				return true;
			}
			if (!IsGatherOrFarm(b))
			{
				return IsPlantingByDisplayName(b);
			}
			return true;
		}

		[HarmonyPatch(typeof(ConstructionService), "ShouldShowInShop")]
		[HarmonyPrefix]
		private static bool HideNonShopBuildings(BuildingModel __0, ref bool __result)
		{
			try
			{
				if ((Object)(object)__0 == (Object)null)
				{
					return true;
				}
				if (IsQueryOnlyUnlock(__0))
				{
					return true;
				}
				if (IsDeniedBuilding(__0))
				{
					__result = false;
					return false;
				}
			}
			catch
			{
			}
			return true;
		}

		[HarmonyPatch(typeof(GameContentService), "OnLoading")]
		[HarmonyPostfix]
		private static void InjectQueryOnlyBuildings(GameContentService __instance)
		{
			try
			{
				_fcContentSvc = __instance;
				if (!_fcTownHallRegistered && !_fcTownHallFailed)
				{
					CreateTownHall();
				}
				Settings val = ((MainController.Instance != null) ? MainController.Instance.Settings : null);
				ContentState val2 = ((__instance != null) ? __instance.State : null);
				if ((Object)(object)val == (Object)null || val2 == null || val2.buildings == null)
				{
					return;
				}
				bool flag = false;
				List<string> list = new List<string>();
				string[] queryOnlyUnlockNames = QueryOnlyUnlockNames;
				foreach (string text in queryOnlyUnlockNames)
				{
					if (!((Object)(object)val.GetBuilding(text) == (Object)null) && !val2.buildings.Contains(text))
					{
						val2.buildings.Add(text);
						list.Add(text);
						flag = true;
					}
				}
				if (flag)
				{
					__instance.CacheProperties();
				}
				InjectTownHallIntoPool(__instance);
			}
			catch (Exception)
			{
			}
		}

		private static void DedupeNames(List<string> list)
		{
			if (list == null)
			{
				return;
			}
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			int num = 0;
			for (int i = 0; i < list.Count; i++)
			{
				string text = list[i];
				if (text != null && hashSet.Add(text))
				{
					list[num++] = text;
				}
			}
			if (num < list.Count)
			{
				list.RemoveRange(num, list.Count - num);
			}
		}

		[HarmonyPatch(typeof(MetaPerksService), "GetBasePreparationPoints")]
		[HarmonyPrefix]
		private static void AddAutoUnlockedBuildings()
		{
			try
			{
				ContentState content = MB.MetaStateService.Content;
				if (content == null)
				{
					((BaseUnityPlugin)Instance).Logger.LogError((object)"FC AUTOUNLOCK: Content is null, skip.");
					return;
				}
				Settings settings = MainController.Instance.Settings;
				List<string> list = new List<string>();
				int num = 0;
				if (content.buildings != null)
				{
					int count = content.buildings.Count;
					DedupeNames(content.buildings);
					num += count - content.buildings.Count;
				}
				if (content.essentialBuildings != null)
				{
					int count2 = content.essentialBuildings.Count;
					DedupeNames(content.essentialBuildings);
					num += count2 - content.essentialBuildings.Count;
				}
				List<string> list2 = new List<string>();
				if ((Object)(object)settings != (Object)null && settings.Buildings != null)
				{
					BuildingModel[] buildings = settings.Buildings;
					foreach (BuildingModel val in buildings)
					{
						if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(((SO)val).Name) && IsAutoUnlockCandidate(val))
						{
							list2.Add(((SO)val).Name);
						}
					}
				}
				foreach (string item in list2)
				{
					if (!content.buildings.Contains(item))
					{
						content.buildings.Add(item);
					}
					if (!content.essentialBuildings.Contains(item))
					{
						content.essentialBuildings.Add(item);
						list.Add(item);
					}
				}
				_ = list.Count;
				_ = 0;
				_ = 0;
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR AddAutoUnlockedBuildings: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(GameContentService), "IsUnlocked")]
		[HarmonyPostfix]
		private static void AutoUnlockBuildings(GameContentService __instance, BuildingModel building, ref bool __result)
		{
			try
			{
				if (!__result && !((Object)(object)building == (Object)null) && IsAutoUnlocked(building))
				{
					__result = true;
				}
			}
			catch (Exception)
			{
			}
		}

		private static bool IsAutoUnlocked(BuildingModel b)
		{
			if ((Object)(object)b == (Object)null)
			{
				return false;
			}
			if (FC_IsTownHall(b))
			{
				return true;
			}
			if (IsQueryOnlyUnlock(b))
			{
				return true;
			}
			if (IsDeniedBuilding(b))
			{
				return false;
			}
			if (((SO)b).Name == "Biome Grass Spawner")
			{
				return true;
			}
			if (IsGatherOrFarm(b) || IsPlantingByDisplayName(b))
			{
				return true;
			}
			string text = null;
			try
			{
				text = ((b.displayName != null) ? b.displayName.Text : null);
			}
			catch
			{
			}
			string text2 = (text ?? "").ToLowerInvariant();
			if (text2.Contains("高级") || text2.Contains("advanced"))
			{
				return true;
			}
			return false;
		}

		[HarmonyPatch(typeof(UpgradableBuilding), "AllGoodsAvailableFor")]
		[HarmonyPrefix]
		private static bool FreeUpgrade_AllGoodsAvailableFor(UpgradableBuilding __instance, ref bool __result)
		{
			if (IsFreeUpgradeBuilding(__instance))
			{
				__result = true;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(UpgradableBuilding), "RemoveGoods")]
		[HarmonyPrefix]
		private static bool FreeUpgrade_RemoveGoods(UpgradableBuilding __instance, int __0, Func<int, bool> __1)
		{
			if (IsFreeUpgradeBuilding(__instance))
			{
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(BuildingUpgradesPanel), "SetUpGoods")]
		[HarmonyPostfix]
		private static void FreeUpgrade_SetUpGoods(BuildingUpgradesPanel __instance)
		{
			try
			{
				object? obj = AccessTools.Field(typeof(BuildingUpgradesPanel), "building")?.GetValue(__instance);
				UpgradableBuilding val = (UpgradableBuilding)((obj is UpgradableBuilding) ? obj : null);
				if (!((Object)(object)val == (Object)null) && IsFreeUpgradeBuilding(val))
				{
					HideGoodsArea(__instance);
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC UPGRADE-PANEL: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(UpgradableBuilding), "CanUpgrade")]
		[HarmonyPrefix]
		private static bool FreeUpgrade_CanUpgrade(UpgradableBuilding __instance, ref bool __result)
		{
			if (IsFreeUpgradeBuilding(__instance))
			{
				__result = true;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(BuildingUpgradesPanel), "UpdateContent")]
		[HarmonyPostfix]
		private static void FreeUpgrade_UpdateContent(BuildingUpgradesPanel __instance)
		{
			try
			{
				object? obj = AccessTools.Field(typeof(BuildingUpgradesPanel), "building")?.GetValue(__instance);
				if (IsFreeUpgradeBuilding((UpgradableBuilding)((obj is UpgradableBuilding) ? obj : null)))
				{
					HideGoodsArea(__instance);
				}
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(BuildingRainpunkPanel), "SetUpUnlockPrice")]
		[HarmonyPostfix]
		private static void StripRainpunkUnlockPrice(BuildingRainpunkPanel __instance)
		{
			try
			{
				TMP_Text unlockCounter = __instance.unlockCounter;
				if (!((Object)(object)unlockCounter == (Object)null))
				{
					string text = unlockCounter.text ?? "";
					int num = text.IndexOf('(');
					if (num < 0)
					{
						num = text.IndexOf('(');
					}
					if (num >= 0)
					{
						unlockCounter.text = text.Substring(0, num).TrimEnd(Array.Empty<char>());
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC STRIP-RAINPUNK-PRICE: " + ex.Message));
			}
		}

		private static void HideGoodsArea(BuildingUpgradesPanel panel)
		{
			object? obj = AccessTools.Field(typeof(BuildingUpgradesPanel), "goodsLayout")?.GetValue(panel);
			Component val = (Component)((obj is Component) ? obj : null);
			object? obj2 = AccessTools.Field(typeof(BuildingUpgradesPanel), "noGoodsText")?.GetValue(panel);
			GameObject val2 = (GameObject)((obj2 is GameObject) ? obj2 : null);
			if ((Object)(object)val != (Object)null && val.gameObject.activeSelf)
			{
				val.gameObject.SetActive(false);
			}
			if ((Object)(object)val2 != (Object)null && val2.activeSelf)
			{
				val2.SetActive(false);
			}
		}

		[HarmonyPatch(typeof(Workshop), "UnlockRainpunk")]
		[HarmonyPrefix]
		private static bool FreeRainpunkUnlock(Workshop __instance)
		{
			try
			{
				__instance.state.rainpunkUnlocked = true;
				IGameBlackboardService gameBlackboardService = GameMB.GameBlackboardService;
				if (gameBlackboardService != null)
				{
					object obj = AccessTools.Property(((object)gameBlackboardService).GetType(), "OnRainpunkUnlocked")?.GetValue(gameBlackboardService);
					if (obj != null)
					{
						AccessTools.Method(obj.GetType(), "OnNext", new Type[1] { typeof(Workshop) }, (Type[])null)?.Invoke(obj, new object[1] { __instance });
					}
				}
				return false;
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC FREE-RAINPUNK: " + ex.Message));
				return true;
			}
		}

		[HarmonyPatch(typeof(BuildingUpgradesPanel), "UpgradeClicked")]
		[HarmonyPrefix]
		private static void Diag_PipesBeforeUpgrade()
		{
			try
			{
			}
			catch
			{
			}
		}

		[HarmonyPatch(typeof(BuildingUpgradesPanel), "UpgradeClicked")]
		[HarmonyPostfix]
		private static void Diag_PipesAfterUpgrade()
		{
			try
			{
			}
			catch
			{
			}
		}

		private static string PipeAmount()
		{
			try
			{
				IStorageService storageService = GameMB.StorageService;
				if (storageService == null)
				{
					return "?";
				}
				return storageService.GetAmount("Pipes").ToString();
			}
			catch
			{
				return "?";
			}
		}

		private static bool IsFreeUpgradeBuilding(UpgradableBuilding b)
		{
			return (Object)(object)b != (Object)null;
		}

		[HarmonyPatch(typeof(UpgradableBuilding), "Upgrade")]
		[HarmonyPostfix]
		private static void FreeUpgrade_SyncUpgrade(UpgradableBuilding __instance, int __0, int __1)
		{
			try
			{
				House val = (House)(object)((__instance is House) ? __instance : null);
				if (val == null)
				{
					return;
				}
				BuildingModel buildingModel = ((Building)val).BuildingModel;
				if ((Object)(object)buildingModel == (Object)null)
				{
					return;
				}
				Dictionary<int, House> houses = GameMB.BuildingsService.Houses;
				if (houses == null)
				{
					return;
				}
				MethodInfo methodInfo = AccessTools.Method(typeof(UpgradableBuilding), "GrantUpgrade", (Type[])null, (Type[])null);
				MethodInfo methodInfo2 = AccessTools.Method(typeof(UpgradableBuilding), "RiseLevel", (Type[])null, (Type[])null);
				int num = 0;
				foreach (KeyValuePair<int, House> item in houses)
				{
					House value = item.Value;
					if (!((Object)(object)value == (Object)null) && !((Object)(object)value == (Object)(object)val) && !((Object)(object)((Building)value).BuildingModel != (Object)(object)buildingModel) && !((UpgradableBuilding)value).IsMaxLevelReached())
					{
						methodInfo?.Invoke(value, new object[2] { __0, __1 });
						methodInfo2?.Invoke(value, null);
						num++;
					}
				}
				_ = 0;
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC SYNC-UPGRADE: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(EffectsService), "GetHearthMaxHP")]
		[HarmonyPostfix]
		private static void ForestCreator_HearthMaxHP_X10(EffectsService __instance, ref int __result)
		{
			try
			{
				Settings settings = MainController.Instance.Settings;
				if ((Object)(object)settings == (Object)null)
				{
					return;
				}
				int hearthBaseHP = settings.blightConfig.hearthBaseHP;
				EffectsState effects = __instance.Effects;
				if (effects == null)
				{
					return;
				}
				int hearthBonusHP = effects.hearthBonusHP;
				int num = 0;
				if (FCConfig.EnableDecorationResistance.Value)
				{
					try
					{
						IBuildingsService buildingsService = GameMB.BuildingsService;
						if (buildingsService != null && buildingsService.Decorations != null)
						{
							foreach (KeyValuePair<int, Decoration> decoration in buildingsService.Decorations)
							{
								Decoration value = decoration.Value;
								if ((Object)(object)value == (Object)null)
								{
									continue;
								}
								BuildingModel buildingModel = ((Building)value).BuildingModel;
								DecorationModel val = (DecorationModel)(object)((buildingModel is DecorationModel) ? buildingModel : null);
								if (!((Object)(object)val == (Object)null))
								{
									int num2 = Mathf.Max(1, ((Vector2Int)(ref ((BuildingModel)val).size)).x * ((Vector2Int)(ref ((BuildingModel)val).size)).y);
									int num3 = FCConfig.DecorationGreenPerTile.Value;
									if ((Object)(object)val.tier != (Object)null)
									{
										num3 = val.tier.order switch
										{
											0 => FCConfig.DecorationGreenPerTile.Value, 
											1 => FCConfig.DecorationBluePerTile.Value, 
											2 => FCConfig.DecorationGoldPerTile.Value, 
											_ => FCConfig.DecorationGreenPerTile.Value, 
										};
									}
									num += num2 * num3;
								}
							}
						}
					}
					catch (Exception)
					{
					}
				}
				__result = Mathf.Max(1, hearthBaseHP + hearthBonusHP * FCConfig.HearthUpgradeBonusMultiplier.Value + num);
			}
			catch (Exception)
			{
			}
		}

		[HarmonyPatch(typeof(ProductionCalculator), "GetProductionFactor")]
		[HarmonyPostfix]
		private static void HearthBoostPrimaryProduction(Building __0, ref float __result)
		{
			try
			{
				if (!(__result <= 0f) && IsPrimaryGoodProducer(__0))
				{
					int hearthProductionMultiplier = GetHearthProductionMultiplier();
					if (hearthProductionMultiplier > 1)
					{
						__result *= hearthProductionMultiplier;
					}
				}
			}
			catch (Exception)
			{
			}
		}

		[Conditional("DEBUG")]
		private static void DebugLogProduction(Building building, int multiplier)
		{
			if (_hearthProductionLogBudget > 0)
			{
				_hearthProductionLogBudget--;
			}
		}

		private static bool IsPrimaryGoodProducer(Building building)
		{
			if ((Object)(object)building == (Object)null)
			{
				return false;
			}
			if (!(building is Camp) && !(building is GathererHut) && !(building is FishingHut) && !(building is Farm))
			{
				return building is RainCatcher;
			}
			return true;
		}

		private static int GetHearthProductionMultiplier()
		{
			int ancientHearthLevel = GetAncientHearthLevel();
			if (ancientHearthLevel >= 3)
			{
				return FCConfig.HearthLevel3ProductionMultiplier.Value;
			}
			if (ancientHearthLevel == 2)
			{
				return FCConfig.HearthLevel2ProductionMultiplier.Value;
			}
			return FCConfig.HearthLevel1ProductionMultiplier.Value;
		}

		private static int GetAncientHearthLevel()
		{
			try
			{
				IBuildingsService buildingsService = GameMB.BuildingsService;
				if (buildingsService == null)
				{
					return 1;
				}
				Hearth mainHearth = buildingsService.GetMainHearth();
				if ((Object)(object)mainHearth != (Object)null)
				{
					return Mathf.Max(1, ((UpgradableBuilding)mainHearth).GetCurrentLevel());
				}
				int num = 0;
				if (buildingsService.Hearths != null)
				{
					foreach (KeyValuePair<int, Hearth> hearth in buildingsService.Hearths)
					{
						Hearth value = hearth.Value;
						if (!((Object)(object)value == (Object)null))
						{
							num = Mathf.Max(num, ((UpgradableBuilding)value).GetCurrentLevel());
						}
					}
				}
				return Mathf.Max(1, num);
			}
			catch
			{
				return 1;
			}
		}

		[HarmonyPatch(typeof(ResolveService), "GetResolveFor")]
		[HarmonyPostfix]
		private static void DecorationResolveBonus(ref float __result)
		{
			try
			{
				int decorationResolveBonus = GetDecorationResolveBonus();
				if (decorationResolveBonus > 0)
				{
					__result += decorationResolveBonus;
				}
			}
			catch (Exception)
			{
			}
		}

		private static int GetDecorationResolveBonus()
		{
			try
			{
				IBuildingsService buildingsService = GameMB.BuildingsService;
				if (buildingsService == null || buildingsService.Decorations == null)
				{
					return 0;
				}
				int num = 0;
				foreach (KeyValuePair<int, Decoration> decoration in buildingsService.Decorations)
				{
					Decoration value = decoration.Value;
					if ((Object)(object)value == (Object)null)
					{
						continue;
					}
					BuildingModel buildingModel = ((Building)value).BuildingModel;
					DecorationModel val = (DecorationModel)(object)((buildingModel is DecorationModel) ? buildingModel : null);
					if (!((Object)(object)val == (Object)null))
					{
						int num2 = Mathf.Max(1, ((Vector2Int)(ref ((BuildingModel)val).size)).x * ((Vector2Int)(ref ((BuildingModel)val).size)).y);
						int num3 = FCConfig.DecorationGreenResolvePerTile.Value;
						if ((Object)(object)val.tier != (Object)null)
						{
							num3 = val.tier.order switch
							{
								1 => FCConfig.DecorationBlueResolvePerTile.Value, 
								2 => FCConfig.DecorationGoldResolvePerTile.Value, 
								_ => FCConfig.DecorationGreenResolvePerTile.Value, 
							};
						}
						num += num2 * num3;
					}
				}
				return num;
			}
			catch
			{
				return 0;
			}
		}

		[HarmonyPatch(typeof(EffectsService), "GetHouseCapacity", new Type[] { typeof(House) })]
		[HarmonyPostfix]
		private static void GetHouseCapacity_House_Postfix(ref int __result)
		{
			__result *= FCConfig.HouseCapacityMultiplier.Value;
		}

		[HarmonyPatch(typeof(EffectsService), "GetHouseCapacity", new Type[] { typeof(HouseModel) })]
		[HarmonyPostfix]
		private static void GetHouseCapacity_HouseModel_Postfix(ref int __result)
		{
			__result *= FCConfig.HouseCapacityMultiplier.Value;
		}

		[HarmonyPatch(typeof(MetaPerksService), "GetBasePreparationPoints")]
		[HarmonyPrefix]
		private static void RemoveLowTierCampsFromMetaContent()
		{
			try
			{
				ContentState content = MB.MetaStateService.Content;
				if (content == null || content.buildings == null)
				{
					return;
				}
				int num = 0;
				string[] lowTierCampNames = LowTierCampNames;
				foreach (string item in lowTierCampNames)
				{
					if (content.essentialBuildings != null)
					{
						while (content.essentialBuildings.Contains(item))
						{
							content.essentialBuildings.Remove(item);
							num++;
						}
					}
				}
				if (num > 0 || !_metaCampsCleaned)
				{
					_metaCampsCleaned = true;
				}
			}
			catch (Exception)
			{
			}
		}

		[HarmonyPatch(typeof(ConstructionService), "ShouldShowInShop")]
		[HarmonyPrefix]
		private static bool HideLowTierCampsFromShop(BuildingModel __0, ref bool __result)
		{
			try
			{
				if ((Object)(object)__0 != (Object)null && IsLowTierCamp(((SO)__0).Name))
				{
					__result = false;
					return false;
				}
			}
			catch
			{
			}
			return true;
		}

		private static bool IsLowTierCamp(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return false;
			}
			string[] lowTierCampNames = LowTierCampNames;
			foreach (string text in lowTierCampNames)
			{
				if (name == text)
				{
					return true;
				}
			}
			return false;
		}

		[HarmonyPatch(typeof(BuildingsPickScreen), "Show")]
		[HarmonyPostfix]
		private static void ReservePickedRows(BuildingsPickScreen __instance)
		{
			try
			{
				if (!((Object)(object)__instance == (Object)null))
				{
					((MonoBehaviour)Instance).StartCoroutine(ReservePickedRowsDeferred(__instance));
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("ReservePickedRows failed: " + ex.Message));
			}
		}

		private static IEnumerator ReservePickedRowsDeferred(BuildingsPickScreen __instance)
		{
			while ((Object)(object)__instance == (Object)null || !((Component)__instance).gameObject.activeInHierarchy)
			{
				yield return null;
			}
			yield return null;
			yield return null;
			try
			{
				Transform transform = ((Component)__instance).transform;
				RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
				Transform val2 = (((Object)(object)val != (Object)null) ? ((Transform)val).Find("Content") : null);
				Transform val3 = (((Object)(object)val2 != (Object)null) ? val2.Find("Picked") : null);
				RectTransform val4 = (RectTransform)(object)((val3 is RectTransform) ? val3 : null);
				if ((Object)(object)val4 == (Object)null)
				{
					DumpTree(__instance, "NOPICKED");
					yield break;
				}
				Transform obj = ((Transform)val4).Find("Content");
				RectTransform val5 = (RectTransform)(object)((obj is RectTransform) ? obj : null);
				GridLayoutGroup val6 = (((Object)(object)val5 != (Object)null) ? ((Component)val5).GetComponent<GridLayoutGroup>() : null);
				int num = 9;
				float num2 = 0f;
				if ((Object)(object)val6 != (Object)null)
				{
					if ((int)val6.constraint == 1)
					{
						num = val6.constraintCount;
					}
					num2 = val6.cellSize.y + val6.spacing.y;
				}
				if (num2 <= 0f)
				{
					val6 = ((Component)val3).GetComponent<GridLayoutGroup>();
					if ((Object)(object)val6 != (Object)null)
					{
						if ((int)val6.constraint == 1)
						{
							num = val6.constraintCount;
						}
						num2 = val6.cellSize.y + val6.spacing.y;
					}
				}
				Rect rect;
				if (num2 <= 0f)
				{
					foreach (Transform item in (Transform)val4)
					{
						Transform val7 = item;
						if (((Component)val7).gameObject.activeSelf)
						{
							rect = ((RectTransform)val7).rect;
							num2 = ((Rect)(ref rect)).height;
							break;
						}
					}
				}
				Transform val8 = ((Transform)val4).Find("ConfirmButton");
				if (num2 > 0f && (Object)(object)val8 != (Object)null)
				{
					RectTransform val9 = (RectTransform)(object)((val8 is RectTransform) ? val8 : null);
					int num3 = Mathf.Max(1, (FCConfig.EmbarkMaxPicks.Value + num - 1) / num);
					float num4 = (((Object)(object)val5 != (Object)null) ? (0f - ((Transform)val5).localPosition.y) : 0f) + (float)num3 * num2;
					float y = val9.anchoredPosition.y;
					rect = val9.rect;
					float height = ((Rect)(ref rect)).height;
					float num5 = 70f;
					rect = val4.rect;
					float num6 = ((Rect)(ref rect)).height - y - height / 2f;
					float num7 = num4 + num5 - num6;
					if (num7 > 0f)
					{
						float y2 = val4.pivot.y;
						float x = val4.sizeDelta.x;
						rect = val4.rect;
						val4.sizeDelta = new Vector2(x, ((Rect)(ref rect)).height + num7);
						val4.anchoredPosition = new Vector2(val4.anchoredPosition.x, val4.anchoredPosition.y - num7 * (1f - y2));
					}
				}
				DumpTree(__instance, "LAYOUT");
				DumpSlots(__instance, val4, val5);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("ReservePickedRowsDeferred failed: " + ex.Message));
			}
		}

		private static void DumpSlots(BuildingsPickScreen __instance, RectTransform picked, RectTransform gridContent)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: 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_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c3: 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_02e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Expected O, but got Unknown
			//IL_014c: 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_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				StringBuilder stringBuilder = new StringBuilder();
				object[] array = new object[4];
				Rect rect = picked.rect;
				array[0] = ((Rect)(ref rect)).height;
				array[1] = picked.anchorMin;
				array[2] = picked.anchorMax;
				array[3] = picked.pivot;
				stringBuilder.Append(string.Format("SLOTS pickedH={0:F0} anchorMin={1} anchorMax={2} pivot={3}", array));
				if ((Object)(object)gridContent != (Object)null)
				{
					object[] obj = new object[6]
					{
						((Object)gridContent).name,
						null,
						null,
						null,
						null,
						null
					};
					rect = gridContent.rect;
					obj[1] = ((Rect)(ref rect)).height;
					obj[2] = ((Transform)gridContent).localPosition.y;
					obj[3] = gridContent.anchorMin;
					obj[4] = gridContent.anchorMax;
					obj[5] = gridContent.pivot;
					stringBuilder.Append(string.Format(" | grid(name={0},h={1:F0},lp={2:F0},anchorMin={3},anchorMax={4},pivot={5})", obj));
					int num = 0;
					foreach (Transform item in (Transform)gridContent)
					{
						Transform val = item;
						RectTransform val2 = (RectTransform)(object)((val is RectTransform) ? val : null);
						object[] obj2 = new object[8]
						{
							num++,
							((Object)val).name,
							((Component)val).gameObject.activeSelf,
							null,
							null,
							null,
							null,
							null
						};
						float num2;
						if (!((Object)(object)val2 != (Object)null))
						{
							num2 = 0f;
						}
						else
						{
							rect = val2.rect;
							num2 = ((Rect)(ref rect)).height;
						}
						obj2[3] = num2;
						obj2[4] = (((Object)(object)val2 != (Object)null) ? ((Transform)val2).localPosition.y : 0f);
						obj2[5] = (((Object)(object)val2 != (Object)null) ? val2.anchorMin : Vector2.zero);
						obj2[6] = (((Object)(object)val2 != (Object)null) ? val2.anchorMax : Vector2.zero);
						obj2[7] = (((Object)(object)val2 != (Object)null) ? val2.pivot : Vector2.zero);
						stringBuilder.Append(string.Format(" |slot{0}(name={1},active={2},h={3:F0},lp={4:F0},anchorMin={5},anchorMax={6},pivot={7})", obj2));
					}
				}
				string[] array2 = new string[5] { "PointsLeft", "Plus", "BonusPointsLeft", "ConfirmButton", "EarlyEndMarker" };
				foreach (string text in array2)
				{
					Transform val3 = ((Transform)picked).Find(text);
					if (!((Object)(object)val3 == (Object)null))
					{
						RectTransform val4 = (RectTransform)(object)((val3 is RectTransform) ? val3 : null);
						object[] obj3 = new object[7]
						{
							text,
							val4.anchoredPosition.y,
							((Transform)val4).localPosition.y,
							null,
							null,
							null,
							null
						};
						rect = val4.rect;
						obj3[3] = ((Rect)(ref rect)).height;
						obj3[4] = val4.anchorMin;
						obj3[5] = val4.anchorMax;
						obj3[6] = val4.pivot;
						stringBuilder.Append(string.Format(" |{0}(apY={1:F0},lp={2:F0},h={3:F0},anchorMin={4},anchorMax={5},pivot={6})", obj3));
					}
				}
			}
			catch (Exception)
			{
			}
		}

		[HarmonyPatch(typeof(ProductionCalculator), "GetProductionMultiplier")]
		[HarmonyPostfix]
		private static void RobotGetsEngineBonus(ProductionCalculator __instance, Building building, Actor actor, ref int __result)
		{
			try
			{
				if (!((Object)(object)actor == (Object)null) && !actor.CanCritProduction && __result == 1)
				{
					float num = 0f;
					UpgradableBuildingState val = (((Object)(object)building != (Object)null) ? building.UpgradableState : null);
					if (val != null)
					{
						num = val.chanceForExtraProductionBonus;
					}
					__result = 1 + (int)num;
					float num2 = num - (float)(int)num;
					if (num2 > 0f && Random.value < num2)
					{
						__result++;
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR RobotGetsEngineBonus: " + ex.Message));
			}
		}

		private static Vector2 GetRadialPosition(int index, int maxSlots)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			float num = (float)index * MathF.PI * 2f / (float)maxSlots;
			return new Vector2(Mathf.Sin(num) * 125f, Mathf.Cos(num) * 125f);
		}

		private static bool BuildingSupportsRobot(RacesMenu menu)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				FieldInfo field = typeof(RacesMenu).GetField("building", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				object obj = (object)((field != null) ? /*isinst with value type is only supported in some contexts*/: null);
				ProductionBuilding val = (ProductionBuilding)((obj is ProductionBuilding) ? obj : null);
				if (val == null)
				{
					return false;
				}
				if (val is ICollector)
				{
					return true;
				}
				if (val is IWorkshop || val is Institution)
				{
					BuildingModel buildingModel = ((Building)val).BuildingModel;
					ProfessionModel val2 = (((Object)(object)buildingModel != (Object)null) ? buildingModel.Profession : null);
					return (Object)(object)val2 != (Object)null && (int)val2.behaviour != 0;
				}
				return false;
			}
			catch
			{
				return false;
			}
		}

		[HarmonyPatch(typeof(RacesMenu), "SetUp")]
		[HarmonyPostfix]
		private static void AddRobotSlotToRacesMenu(RacesMenu __instance)
		{
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0305: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if ((Object)(object)__instance == (Object)null)
				{
					return;
				}
				FieldInfo field = typeof(RacesMenu).GetField("slots", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field == null || !(field.GetValue(__instance) is List<RacesMenuSlot> { Count: not 0 } list))
				{
					return;
				}
				_ = (Building)(typeof(RacesMenu).GetField("building", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(__instance));
				Transform[] componentsInChildren = ((Component)((Component)__instance).transform).GetComponentsInChildren<Transform>(true);
				foreach (Transform val in componentsInChildren)
				{
					if ((Object)(object)val != (Object)null && ((Object)val).name == "RobotSlot")
					{
						Object.DestroyImmediate((Object)(object)((Component)val).gameObject);
					}
				}
				try
				{
					FieldInfo field2 = typeof(RadialMenu).GetField("slotsRadius", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field2 != null)
					{
						field2.SetValue(__instance, 125f);
					}
				}
				catch (Exception)
				{
				}
				int count = list.Count;
				if (!BuildingSupportsRobot(__instance))
				{
					int maxSlots = count;
					for (int j = 0; j < count; j++)
					{
						RectTransform component = ((Component)list[j]).GetComponent<RectTransform>();
						if ((Object)(object)component != (Object)null)
						{
							component.anchoredPosition = GetRadialPosition(j, maxSlots);
						}
					}
					return;
				}
				int maxSlots2 = count + 1;
				for (int k = 0; k < count; k++)
				{
					RectTransform component2 = ((Component)list[k]).GetComponent<RectTransform>();
					if ((Object)(object)component2 != (Object)null)
					{
						component2.anchoredPosition = GetRadialPosition(k, maxSlots2);
					}
				}
				RacesMenuSlot val2 = null;
				foreach (RacesMenuSlot item in list)
				{
					if (!((Object)(object)item == (Object)null))
					{
						Transform val3 = ((Component)item).transform.Find("Content");
						if ((Object)(object)val3 != (Object)null && ((Component)val3).gameObject.activeSelf)
						{
							val2 = item;
							break;
						}
					}
				}
				if ((Object)(object)val2 == (Object)null)
				{
					val2 = list[count - 1];
				}
				GameObject val4 = Object.Instantiate<GameObject>(((Component)val2).gameObject, ((Component)val2).transform.parent);
				((Object)val4).name = "RobotSlot";
				Transform val5 = val4.transform.Find("Content");
				if ((Object)(object)val5 != (Object)null)
				{
					((Component)val5).gameObject.SetActive(true);
				}
				Transform val6 = val4.transform.Find("EmptyMarker");
				if ((Object)(object)val6 != (Object)null)
				{
					((Component)val6).gameObject.SetActive(false);
				}
				val4.SetActive(true);
				RacesMenuSlot component3 = val4.GetComponent<RacesMenuSlot>();
				if ((Object)(object)component3 != (Object)null)
				{
					((Behaviour)component3).enabled = false;
					Object.DestroyImmediate((Object)(object)component3);
				}
				Button componentInChildren = val4.GetComponentInChildren<Button>();
				if ((Object)(object)componentInChildren != (Object)null)
				{
					((UnityEventBase)componentInChildren.onClick).RemoveAllListeners();
				}
				HideClonedTagIcon(val2, val4, "leftTagIcon");
				HideClonedTagIcon(val2, val4, "rightTagIcon");
				RectTransform component4 = val4.GetComponent<RectTransform>();
				if ((Object)(object)component4 != (Object)null)
				{
					component4.anchoredPosition = GetRadialPosition(count, maxSlots2);
				}
				val4.AddComponent<RobotMenuSlot>().SetUp(__instance);
				DumpImages(val4, "after-robot-SetUp");
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("AddRobotSlotToRacesMenu failed: " + ex2.Message));
			}
		}

		private static void HideClonedTagIcon(RacesMenuSlot template, GameObject robotGo, string fieldName)
		{
			try
			{
				FieldInfo field = typeof(RacesMenuSlot).GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
				if (field == null)
				{
					return;
				}
				object? value = field.GetValue(template);
				Image val = (Image)((value is Image) ? value : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				Transform transform = ((Component)val).transform;
				Transform transform2 = ((Component)template).transform;
				string text = ((Object)transform).name;
				Transform parent = transform.parent;
				while ((Object)(object)parent != (Object)null && (Object)(object)parent != (Object)(object)transform2)
				{
					text = ((Object)parent).name + "/" + text;
					parent = parent.parent;
				}
				Transform val2 = robotGo.transform.Find(text);
				if ((Object)(object)val2 != (Object)null)
				{
					((Component)val2).gameObject.SetActive(false);
					Image component = ((Component)val2).GetComponent<Image>();
					if ((Object)(object)component != (Object)null)
					{
						component.sprite = null;
					}
				}
			}
			catch (Exception)
			{
			}
		}

		[HarmonyPatch(typeof(GameHistoryCreator), "SaveHistory")]
		[HarmonyPrefix]
		private static bool SkipDefeatHistory(bool __0)
		{
			try
			{
				if (!__0)
				{
					return false;
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR SkipDefeatHistory: " + ex.Message));
			}
			return true;
		}

		[HarmonyPatch(typeof(StatsService), "GameFinished")]
		[HarmonyPrefix]
		private static bool SkipDefeatStats(bool __0)
		{
			try
			{
				if (!__0)
				{
					return false;
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR SkipDefeatStats: " + ex.Message));
			}
			return true;
		}

		[HarmonyPatch(typeof(CycleStateGameUpdater), "AddFailedCity")]
		[HarmonyPrefix]
		private static bool SkipFailedCity(bool __0)
		{
			try
			{
				if (!__0)
				{
					return false;
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR SkipFailedCity: " + ex.Message));
			}
			return true;
		}

		[HarmonyPatch(typeof(WorldStateService), "FixState")]
		[HarmonyPostfix]
		private static void ClearFailedCities(WorldState __result)
		{
			try
			{
				if (__result != null && __result.failedCities != null && __result.failedCities.Count > 0)
				{
					_ = __result.failedCities.Count;
					__result.failedCities.Clear();
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR ClearFailedCities: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(CycleStateGameUpdater), "GameFinished")]
		[HarmonyPrefix]
		private static bool SkipDefeatCycleProgress(bool __0)
		{
			try
			{
				if (!__0)
				{
					return false;
				}
				_suppressCycleYears = false;
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR SkipDefeatCycleProgress: " + ex.Message));
			}
			return true;
		}

		[HarmonyPatch(typeof(CycleStateGameUpdater), "AddYears")]
		[HarmonyPrefix]
		private static bool GuardAddYears()
		{
			try
			{
				if (_suppressCycleYears)
				{
					return false;
				}
				return true;
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR GuardAddYears: " + ex.Message));
			}
			return true;
		}

		private static void LogSpawnerCandidate(BuildingModel model)
		{
			if ((Object)(object)model == (Object)null)
			{
				return;
			}
			string text = ((SO)model).Name ?? string.Empty;
			_ = ((object)model).GetType().Name;
			if (!(model is SpawnerModel) && text.IndexOf("Spawner", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("Biome", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("Grass", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("Soil", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("Fertile", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return;
			}
			_ = string.Empty;
			try
			{
				if (model.displayName == null)
				{
					_ = string.Empty;
				}
				else
				{
					_ = model.displayName.Text;
				}
			}
			catch
			{
			}
		}

		private static bool IsDragPlacingSpawner(BuildingModel model)
		{
			if ((Object)(object)model == (Object)null || !(model is SpawnerModel))
			{
				return false;
			}
			string a = ((SO)model).Name ?? string.Empty;
			string[] dragPlacingSpawnerNames = DragPlacingSpawnerNames;
			foreach (string b in dragPlacingSpawnerNames)
			{
				if (string.Equals(a, b, StringComparison.OrdinalIgnoreCase))
				{
					return true;
				}
			}
			try
			{
				string text = ((model.displayName != null) ? model.displayName.Text : null);
				if (!string.IsNullOrEmpty(text))
				{
					dragPlacingSpawnerNames = DragPlacingSpawnerDisplayKeywords;
					foreach (string value in dragPlacingSpawnerNames)
					{
						if (text.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0)
						{
							return true;
						}
					}
				}
			}
			catch
			{
			}
			return false;
		}

		[HarmonyPatch(typeof(BuildingsPanel), "CreateRequest")]
		[HarmonyPrefix]
		private static bool CreateRequest_DragPlacingSpawner(BuildingModel __0, BuildingsPanel __instance, ref IBuildingRequest __result)
		{
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Expected O, but got Unknown
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Expected O, but got Unknown
			try
			{
				ActiveDragSpawner = null;
				LogSpawnerCandidate(__0);
				if (!IsDragPlacingSpawner(__0))
				{
					return true;
				}
				IConstructionPlanner val = null;
				FieldInfo fieldInfo = AccessTools.Field(typeof(BuildingsPanel), "fieldsPlanner");
				if (fieldInfo != null)
				{
					object? value = fieldInfo.GetValue(__instance);
					val = (IConstructionPlanner)((value is IConstructionPlanner) ? value : null);
				}
				if (val == null)
				{
					return true;
				}
				MethodInfo methodInfo = AccessTools.Method(typeof(BuildingsPanel), "PlacingFinished", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					return true;
				}
				Action onFinished = (Action)Delegate.CreateDelegate(typeof(Action), __instance, methodInfo);
				__result = (IBuildingRequest)(object)new SpawnerGroupRequest((SpawnerModel)__0, val, onFinished);
				ActiveDragSpawner = (SpawnerModel)__0;
				return false;
			}
			catch (Exception)
			{
				return true;
			}
		}

		[HarmonyPatch(typeof(GroupRequest), "Dispose")]
		[HarmonyPostfix]
		private static void Dispose_ClearDragSpawner(object __instance)
		{
			if (__instance is SpawnerGroupRequest)
			{
				ActiveDragSpawner = null;
			}
		}

		[HarmonyPatch(typeof(FieldsPlanner), "IsAvaiable")]
		[HarmonyPrefix]
		private static bool IsAvaiable_AllowAnyFreeTile(int __0, int __1, ref bool __result)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)ActiveDragSpawner == (Object)null)
			{
				return true;
			}
			try
			{
				__result = GameMB.MapService.IsFieldEmpty(new Vector2Int(__0, __1));
			}
			catch (Exception)
			{
				__result = false;
			}
			return false;
		}

		[HarmonyPatch(typeof(GameController), "StartGame")]
		[HarmonyPostfix]
		private static void InjectStartingCornerstones()
		{
			try
			{
				Settings settings = MainController.Instance.Settings;
				if ((Object)(object)settings == (Object)null)
				{
					return;
				}
				IStateService stateService = Serviceable.StateService;
				if (stateService == null)
				{
					return;
				}
				if (stateService.Effects != null)
				{
					_ = stateService.Effects.perks;
				}
				TopUpWarehouseTo200();
				string[] fC_StartingCornerstoneNames = FC_StartingCornerstoneNames;
				foreach (string text in fC_StartingCornerstoneNames)
				{
					EffectModel val = null;
					try
					{
						val = settings.GetEffect(text);
					}
					catch
					{
					}
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					try
					{
						if (val.displayName != null)
						{
							_ = val.displayName.Text;
						}
					}
					catch
					{
					}
					if (!FC_IsAlreadyApplied(((Object)val).name))
					{
						try
						{
							val.Apply((EffectContextType)0, (string)null, 0);
						}
						catch (Exception ex)
						{
							((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR apply cornerstone '" + ((Object)val).name + "': " + ex.Message));
						}
					}
				}
				FC_InjectCustomCornerstones();
				SyncCustomCornerstoneFlags();
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR InjectStartingCornerstones: " + ex2.Message));
			}
		}

		private static void TopUpWarehouseTo200()
		{
			try
			{
				if (!GameController.IsGameActive)
				{
					return;
				}
				IStorageService storageService = Serviceable.StorageService;
				if (storageService == null)
				{
					return;
				}
				Storage main = storageService.Main;
				if ((Object)(object)main == (Object)null)
				{
					return;
				}
				LockedGoodsCollection goods = main.Goods;
				if (goods == null)
				{
					return;
				}
				List<string> list = new List<string>(((GoodsCollection)goods).goods.Keys);
				int value = FCConfig.WarehouseTopUpTarget.Value;
				int num = 0;
				foreach (string item in list)
				{
					int amount = ((GoodsCollection)goods).GetAmount(item);
					if (amount < value)
					{
						((GoodsCollection)goods).Add(item, value - amount);
						num++;
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR TopUpWarehouseTo200: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(SteamService), "VerifyDLC")]
		[HarmonyFinalizer]
		private static Exception GuardVerifyDLC(Exception __exception, ref UniTask<bool> __result)
		{
			//IL_000d: 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)
			if (__exception == null)
			{
				return null;
			}
			_steamDlcVerifyFailed = true;
			try
			{
				__result = UniTask.FromResult<bool>(true);
			}
			catch
			{
			}
			return null;
		}

		[HarmonyPatch(typeof(DLCsService), "IsDLCDowngrade")]
		[HarmonyPrefix]
		private static bool GuardIsDlcDowngrade(ref bool __result)
		{
			if (!_steamDlcVerifyFailed)
			{
				return true;
			}
			__result = false;
			return false;
		}

		[HarmonyPatch(typeof(DLCsService), "MarkSavesAsOld")]
		[HarmonyPrefix]
		private static bool GuardMarkSavesAsOld()
		{
			if (!_steamDlcVerifyFailed)
			{
				return true;
			}
			return false;
		}

		internal static void CreateTownHall()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Expected O, but got Unknown
			if (_fcTownHallRegistered || _fcTownHallFailed)
			{
				return;
			}
			InstitutionBuildingBuilder val;
			try
			{
				val = new InstitutionBuildingBuilder("ForestCreator", "Forest Creator Town Hall", FC_IconPath("fc_town_hall.png"));
			}
			catch (Exception ex)
			{
				_fcTownHallFailed = true;
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR CreateTownHall(ctor): " + ex));
				return;
			}
			try
			{
				InstitutionModel buildingModel = ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).BuildingModel;
				if ((Object)(object)buildingModel != (Object)null)
				{
					if (buildingModel.recipes == null)
					{
						buildingModel.recipes = (InstitutionRecipeModel[])(object)new InstitutionRecipeModel[0];
					}
					if (buildingModel.workplaces == null)
					{
						buildingModel.workplaces = (WorkplaceModel[])(object)new WorkplaceModel[0];
					}
					if (buildingModel.activeEffects == null)
					{
						buildingModel.activeEffects = (InstitutionEffectModel[])(object)new InstitutionEffectModel[0];
					}
					if (buildingModel.needsCache == null)
					{
						buildingModel.needsCache = new HashSet<NeedModel>();
					}
					if (buildingModel.goodsCache == null)
					{
						buildingModel.goodsCache = new HashSet<GoodModel>();
					}
				}
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR CreateTownHall(collections): " + ex2.Message));
			}
			try
			{
				InstitutionModel val2 = FC_FindLookTemplate();
				if ((Object)(object)val2 != (Object)null)
				{
					if ((Object)(object)val2.prefab != (Object)null && (Object)(object)((Component)val2.prefab).gameObject != (Object)null)
					{
						((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetCustomModel(((Component)val2.prefab).gameObject);
					}
					InstitutionModel buildingModel2 = ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).BuildingModel;
					if ((Object)(object)buildingModel2 != (Object)null && (Object)(object)((BuildingModel)val2).icon != (Object)null)
					{
						((BuildingModel)buildingModel2).icon = ((BuildingModel)val2).icon;
					}
				}
				else
				{
					FC_LogBuildingNames();
				}
			}
			catch (Exception ex3)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR CreateTownHall(look): " + ex3));
			}
			try
			{
				((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetDisplayName("Town Hall", (SystemLanguage)10);
				((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetDisplayName("城镇大厅", (SystemLanguage)40);
				string text = "Pay 2 Amber to recruit one villager of any race.";
				string text2 = "花费 2 琥珀,招募一名任意种族的居民。";
				((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetDescription(text, (SystemLanguage)10);
				((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetDescription(text2, (SystemLanguage)40);
				((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetLabel("Town Hall", (SystemLanguage)10);
				((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetLabel("城镇大厅", (SystemLanguage)40);
				((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetCategory((BuildingCategoriesTypes)1);
				((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetFootPrint(3, 3, (FieldType)40);
				((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetOrder(0);
				((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetRequiredGoods((NameToAmount[])(object)new NameToAmount[1] { NameToAmount.op_Implicit((15, "[Mat Raw] Wood")) });
			}
			catch (Exception ex4)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR CreateTownHall(texts): " + ex4.Message));
			}
			_fcTownHallBuilder = val;
			_fcTownHallName = (((Object)(object)((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).BuildingModel != (Object)null) ? ((Object)((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).BuildingModel).name : null);
			_fcTownHallRegistered = true;
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)("FC TOWNHALL registered: " + _fcTownHallName));
			try
			{
				InstitutionModel buildingModel3 = ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).BuildingModel;
				GoodRef[] array = (GoodRef[])(((Object)(object)buildingModel3 != (Object)null && ((BuildingModel)buildingModel3).requiredGoods != null) ? ((Array)((BuildingModel)buildingModel3).requiredGoods) : ((Array)new GoodRef[0]));
				for (int i = 0; i < array.Length; i++)
				{
					_ = array[i];
				}
			}
			catch (Exception)
			{
			}
			try
			{
				_ = ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).BuildingModel;
			}
			catch (Exception)
			{
			}
		}

		private static InstitutionModel FC_FindLookTemplate()
		{
			try
			{
				Settings val = ((MainController.Instance != null) ? MainController.Instance.Settings : null);
				if ((Object)(object)val == (Object)null || val.Buildings == null)
				{
					return null;
				}
				BuildingModel[] buildings = val.Buildings;
				foreach (BuildingModel obj in buildings)
				{
					InstitutionModel val2 = (InstitutionModel)(object)((obj is InstitutionModel) ? obj : null);
					if (!((Object)(object)val2 == (Object)null))
					{
						string text = (((Object)val2).name ?? "").Replace(" ", "").ToLowerInvariant();
						string text2 = "";
						try
						{
							text2 = ((((BuildingModel)val2).displayName != null) ? ((BuildingModel)val2).displayName.Text : "");
						}
						catch
						{
						}
						text2 = (text2 ?? "").ToLowerInvariant();
						if (text.Contains("holytemple") || text.Contains("Holy Temple".Replace(" ", "").ToLowerInvariant()) || text2.Contains("holy temple") || text2.Contains("圣殿") || text2.Contains("神庙"))
						{
							return val2;
						}
					}
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR FC_FindLookTemplate: " + ex.Message));
			}
			return null;
		}

		private static void FC_LogBuildingNames()
		{
			try
			{
				Settings val = ((MainController.Instance != null) ? MainController.Instance.Settings : null);
				if ((Object)(object)val == (Object)null || val.Buildings == null)
				{
					return;
				}
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append("FC BUILDINGS (institutions): ");
				BuildingModel[] buildings = val.Buildings;
				foreach (BuildingModel val2 in buildings)
				{
					if (val2 is InstitutionModel)
					{
						stringBuilder.Append('[').Append(((Object)val2).name).Append("] ");
					}
				}
			}
			catch
			{
			}
		}

		internal static void InjectTownHallIntoPool(GameContentService svc)
		{
			try
			{
				if (string.IsNullOrEmpty(_fcTownHallName) || svc == null)
				{
					return;
				}
				Settings val = ((MainController.Instance != null) ? MainController.Instance.Settings : null);
				if ((Object)(object)val == (Object)null || (Object)(object)val.GetBuilding(_fcTownHallName) == (Object)null)
				{
					return;
				}
				ContentState state = svc.State;
				if (state != null && state.buildings != null)
				{
					if (state.buildings.Contains(_fcTownHallName))
					{
						_fcTownHallPoolDone = true;
						return;
					}
					state.buildings.Add(_fcTownHallName);
					svc.CacheProperties();
					_fcTownHallPoolDone = true;
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR InjectTownHallIntoPool: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(BuildingManager), "Tick")]
		[HarmonyPostfix]
		private static void AfterBuildingManagerTick()
		{
			ApplyTownHallLookOnce();
			RetryTownHallPoolInjection();
		}

		private static void ApplyTownHallLookOnce()
		{
			if (!_fcTownHallRegistered || _fcL