Decompiled source of ForwindzCustomCornerstones v1.0.0

ForwindzCustomPerksMod.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ATS_API.Biomes;
using ATS_API.Effects;
using ATS_API.Helpers;
using ATS_API.Localization;
using BepInEx;
using BepInEx.Logging;
using Cysharp.Threading.Tasks;
using Cysharp.Threading.Tasks.CompilerServices;
using Eremite;
using Eremite.Buildings;
using Eremite.Controller;
using Eremite.Controller.Effects;
using Eremite.Model;
using Eremite.Model.Effects;
using Eremite.Model.Effects.Hooked;
using Eremite.Model.Orders;
using Eremite.Model.State;
using Eremite.Model.Trade;
using Eremite.Services;
using Eremite.Services.Orders;
using Eremite.Services.World;
using Eremite.WorldMap;
using Forwindz.Content;
using Forwindz.Framework.Effects;
using Forwindz.Framework.Hooks;
using Forwindz.Framework.Services;
using Forwindz.Framework.Utils;
using Forwindz.Framework.Utils.Extend;
using Forwindz.Scripts.Framework.Services;
using Forwindz.Scripts.Framework.Utils;
using ForwindzCustomPerks.Framework.Services;
using ForwindzCustomPerks.Scripts.Framework.Utils.Extend;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Sirenix.Utilities;
using UniRx;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("ForwindzCustomPerksMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("My First Mod for Against The Storm - by Forwindz")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+0dc3075784e55ef5f6b5c6ad2e8ecc863c024f9b")]
[assembly: AssemblyProduct("ForwindzCustomPerksMod")]
[assembly: AssemblyTitle("ForwindzCustomPerksMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace ForwindzCustomPerks
{
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "ForwindzCustomPerksMod";

		public const string PLUGIN_NAME = "ForwindzCustomPerksMod";

		public const string PLUGIN_VERSION = "1.0.0";
	}
}
namespace ForwindzCustomPerks.Scripts.Framework.Utils.Extend
{
	public static class TextArgExt
	{
		public static TextArg[] ToTextArgArray(this (TextArgType type, int sourceIndex)[] args)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			TextArg[] array = (TextArg[])(object)new TextArg[args.Length];
			for (int i = 0; i < args.Length; i++)
			{
				array[i] = new TextArg
				{
					sourceIndex = args[i].sourceIndex,
					type = args[i].type
				};
			}
			return array;
		}

		public static TextArg ToTextArg(this (TextArgType type, int sourceIndex) arg)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//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)
			//IL_001f: Expected O, but got Unknown
			TextArg val = new TextArg();
			(val.type, val.sourceIndex) = arg;
			return val;
		}
	}
}
namespace ForwindzCustomPerks.Framework.Services
{
	public class DynamicTraderExtraState
	{
		public float chanceToFreeEffect = 0f;
	}
	public class DynamicTraderInfoData
	{
		public List<string> forceTraderNameList = new List<string>();

		[JsonProperty]
		private Dictionary<string, DynamicTraderExtraState> traderGlobalStates = new Dictionary<string, DynamicTraderExtraState>();

		public Dictionary<string, float> effectsSellValue = new Dictionary<string, float>();

		public DynamicTraderExtraState GetTraderGlobalEffects(string traderName)
		{
			if (!traderGlobalStates.TryGetValue(traderName, out var value))
			{
				FLog.Info("[" + traderName + "] does not have extra states, create it");
				value = new DynamicTraderExtraState();
				traderGlobalStates[traderName] = value;
			}
			return value;
		}

		public bool GetEffectModifiedSellValue(string effectName, out float modifiedValue)
		{
			if (effectsSellValue.TryGetValue(effectName, out modifiedValue))
			{
				return true;
			}
			modifiedValue = 0f;
			return false;
		}
	}
	public class DynamicTraderInfoService : GameService, IDynamicTraderInfoService, IService
	{
		[ModSerializedField(SaveLoadType.Unknown, "")]
		internal DynamicTraderInfoData stateData = new DynamicTraderInfoData();

		private IDisposable traderArriveListener = null;

		private MethodInfo methodUpdateNextVisit = null;

		public DynamicTraderInfoData DynamicTraderState => stateData;

		static DynamicTraderInfoService()
		{
			CustomServiceManager.RegGameService<DynamicTraderInfoService>();
			PatchesManager.RegPatch<DynamicTraderInfoService>();
		}

		public override IService[] GetDependencies()
		{
			return (IService[])(object)new IService[2]
			{
				(IService)Serviceable.TradeService,
				CustomServiceManager.GetAsIService<IExtraStateService>()
			};
		}

		public void UpdateNextVisit()
		{
			if (methodUpdateNextVisit == null)
			{
				FLog.Error("Cannot invoke UpdateNextVisit()! The trader state cannot be update!");
			}
			else
			{
				methodUpdateNextVisit.Invoke(Serviceable.TradeService, null);
			}
		}

		public override void OnDestroy()
		{
			traderArriveListener.Dispose();
			((Service)this).OnDestroy();
		}

		public override UniTask OnLoading()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			methodUpdateNextVisit = AccessTools.Method(typeof(TradeService), "UpdateNextVisit", (Type[])null, (Type[])null);
			traderArriveListener = ObservableExtensions.Subscribe<TraderVisitState>(Serviceable.TradeService.OnTraderArrived, (Action<TraderVisitState>)OnTraderArrive);
			RestoreData();
			return UniTask.CompletedTask;
		}

		private void RestoreData()
		{
			FLog.Info("Restored DynamicTraderStateInfo > ");
			FLog.Info($"Sell Perks Count: {stateData.effectsSellValue.Count} | Force List: {stateData.forceTraderNameList.Count}");
		}

		private void OnTraderArrive(TraderVisitState visitState)
		{
			FLog.Info("Trader [" + visitState.trader + "] Arrived! Process its effect price!");
			ApplyEffectsToVisitState(visitState);
		}

		private void ApplyEffectsToVisitState(TraderVisitState newVisitState)
		{
			stateData.effectsSellValue.Clear();
			DynamicTraderExtraState traderGlobalEffects = stateData.GetTraderGlobalEffects(newVisitState.trader);
			if (!(traderGlobalEffects.chanceToFreeEffect > 0f))
			{
				return;
			}
			FLog.Info($"{newVisitState.trader} has {traderGlobalEffects.chanceToFreeEffect} free chance.");
			foreach (KeyValuePair<string, bool> effect in newVisitState.effects)
			{
				FLog.Info($"Check {effect}");
				string key = effect.Key;
				if (!effect.Value)
				{
					FLog.Info($"{traderGlobalEffects.chanceToFreeEffect} free chance for {effect}");
					if (RNG.Roll(traderGlobalEffects.chanceToFreeEffect))
					{
						stateData.effectsSellValue.Add(key, 0f);
						FLog.Info("Set " + key + " as free");
					}
				}
			}
		}

		public TraderModel GetForceTrader()
		{
			if (stateData.forceTraderNameList.Count == 0)
			{
				return null;
			}
			string text = stateData.forceTraderNameList.Where((string x) => !Serviceable.StateService.Trade.assaultedTraders.Contains(x)).FirstOrDefault();
			if (text == null || text.Length == 0)
			{
				return null;
			}
			return Serviceable.Settings.GetTrader(text);
		}

		public void AddForceTrader(string name)
		{
			FLog.Info("Add Force Trader: " + name);
			RemoveAssaultTrader(name);
			stateData.forceTraderNameList.Add(name);
			ResetNextTrader();
		}

		public void RemoveForceTrader(string name)
		{
			if (!stateData.forceTraderNameList.Remove(name))
			{
				FLog.Warning("Cannot remove forced trader [" + name + "]. It not exists in forced list!");
				return;
			}
			FLog.Info("Remove Force Trader: " + name);
			ResetNextTrader();
		}

		public void RemoveAssaultTrader(string name)
		{
			FLog.Info("Remove Assaulted Trader Record: " + name);
			Serviceable.StateService.Trade.assaultedTraders.Remove(name);
		}

		public void ResetNextTrader()
		{
			if (!Serviceable.TradeService.IsMainTraderInTheVillage())
			{
				FLog.Info("Reset Next Trader");
				float travelStartTime = -1f;
				bool flag = false;
				if (Serviceable.StateService.Trade.visit != null)
				{
					flag = true;
					travelStartTime = Serviceable.StateService.Trade.visit.travelStartTime;
				}
				Serviceable.StateService.Trade.visit = null;
				UpdateNextVisit();
				if (Serviceable.StateService.Trade.visit != null && flag)
				{
					Serviceable.StateService.Trade.visit.travelStartTime = travelStartTime;
				}
			}
		}

		public void SetEffectFreeChance(string traderName, float chance)
		{
			DynamicTraderExtraState traderGlobalEffects = stateData.GetTraderGlobalEffects(traderName);
			traderGlobalEffects.chanceToFreeEffect = chance;
			FLog.Info($"{traderName} set {chance} free effects chance.");
		}

		public void AddEffectFreeChance(string traderName, float chance)
		{
			DynamicTraderExtraState traderGlobalEffects = stateData.GetTraderGlobalEffects(traderName);
			traderGlobalEffects.chanceToFreeEffect += chance;
			FLog.Info($"{traderName} add {chance} free effects chance, now it is {traderGlobalEffects.chanceToFreeEffect}");
		}

		[HarmonyPatch(typeof(TradeService), "UpdateNextVisit")]
		[HarmonyPrefix]
		private static bool TradeService_UpdateNextVisit_PrePatch(TradeService __instance)
		{
			if (__instance.State.visit != null)
			{
				return true;
			}
			DynamicTraderInfoService service = CustomServiceManager.GetService<DynamicTraderInfoService>();
			TraderModel forceTrader = service.GetForceTrader();
			if ((Object)(object)forceTrader != (Object)null)
			{
				FLog.Info("Force to set trader as " + ((SO)forceTrader).Name);
				__instance.State.visit = __instance.CreateVisit(forceTrader, 0);
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(TradeService), "GetValueInCurrency", new Type[] { typeof(EffectModel) })]
		[HarmonyPostfix]
		private static void TradeService_GetValueInCurrency_Effect_PostPatch(TradeService __instance, ref float __result, EffectModel effect)
		{
			DynamicTraderInfoService service = CustomServiceManager.GetService<DynamicTraderInfoService>();
			if (service.stateData.GetEffectModifiedSellValue(((Object)effect).name, out var modifiedValue) && effect.tradingBuyValue != 0)
			{
				float num = __result * modifiedValue / (float)effect.tradingBuyValue;
				FLog.Info($"Change effect price from {__result} to {num}");
				__result = num;
			}
		}
	}
}
namespace Forwindz
{
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "Forwindz.CustomCornerstones";

		public const string PLUGIN_NAME = "f9's cornerstones";

		public const string PLUGIN_VERSION = "1.0.0";
	}
	[BepInPlugin("Forwindz.CustomCornerstones", "f9's cornerstones", "1.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin Instance;

		private void Awake()
		{
			Instance = this;
			ReflectUtils.InitializeAllStatics(typeof(Plugin).Assembly);
			PatchesManager.RegPatch<Plugin>();
			PatchesManager.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin Forwindz.CustomCornerstones is loaded!");
		}

		[HarmonyPatch(typeof(MainController), "InitReferences")]
		[HarmonyPostfix]
		private static void PostSetupMainController()
		{
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)"Initializing post Init References in MainController");
			LocalizationLoader.LoadLocalization("assets/lang");
			CustomCornerstones.CreateNewCornerstones();
		}
	}
}
namespace Forwindz.Scripts.Framework.Utils
{
	public static class BuildingHelper
	{
		public static int CountDecorationValue(DecorationTier tier)
		{
			int num = 0;
			foreach (Decoration value in GameMB.BuildingsService.Decorations.Values)
			{
				if (((Building)value).IsFinished() && value.model.hasDecorationTier && (Object)(object)value.model.tier == (Object)(object)tier)
				{
					num += value.model.decorationScore;
				}
			}
			return num;
		}

		public static int CountProductionBuildingArea()
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			foreach (ProductionBuilding productionBuilding in GameMB.BuildingsService.ProductionBuildings)
			{
				if (((Building)productionBuilding).IsFinished())
				{
					Vector2Int size = ((Building)productionBuilding).Size;
					num += ((Vector2Int)(ref size)).x * ((Vector2Int)(ref size)).y;
				}
			}
			return num;
		}

		public static bool IsDecorationBuilding(Building building)
		{
			string name = ((Object)building.BuildingModel.category).name;
			return name.Equals("Decorations");
		}

		public static bool IsRoad(Building building)
		{
			string name = ((Object)building.BuildingModel.category).name;
			return name.Equals("Roads");
		}
	}
	public static class Debug
	{
		static Debug()
		{
			PatchesManager.RegPatch(typeof(Debug));
		}
	}
}
namespace Forwindz.Scripts.Framework.Services
{
	public class BuildingMonitorState
	{
		public int buildingsCompleted = 0;

		public int decorationBuildingsCompleted = 0;

		public int roadsCompleted = 0;

		public int buildingsRemoved = 0;

		public int decorationBuildingsRemoved = 0;

		public int roadsRemoved = 0;
	}
	public class BuildingMonitorService : GameService, IService
	{
		[ModSerializedField(SaveLoadType.Unknown, "")]
		public BuildingMonitorState state = new BuildingMonitorState();

		public readonly Subject<Building> buildingConstructionFinishedSubject = new Subject<Building>();

		public readonly Subject<Building> buildingRemovedSubject = new Subject<Building>();

		public IObservable<Building> OnBuildingConstructionFinished => (IObservable<Building>)buildingConstructionFinishedSubject;

		public IObservable<Building> OnBuildingRemovedFinished => (IObservable<Building>)buildingRemovedSubject;

		static BuildingMonitorService()
		{
			CustomServiceManager.RegGameService<BuildingMonitorService>();
			PatchesManager.RegPatch<BuildingMonitorService>();
		}

		public override IService[] GetDependencies()
		{
			return (IService[])(object)new IService[4]
			{
				(IService)Serviceable.BuildingsService,
				CustomServiceManager.GetAsIService<IExtraStateService>(),
				CustomServiceManager.GetAsIService<IDynamicBuildingStateService>(),
				CustomServiceManager.GetAsIService<IDynamicHearthService>()
			};
		}

		public override void OnDestroy()
		{
			((Service)this).OnDestroy();
		}

		public override UniTask OnLoading()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			return UniTask.CompletedTask;
		}

		protected void OnBuildingCompleted(Building building)
		{
			state.buildingsCompleted++;
			if (BuildingHelper.IsDecorationBuilding(building))
			{
				state.decorationBuildingsCompleted++;
			}
			if (BuildingHelper.IsRoad(building))
			{
				state.roadsCompleted++;
			}
			buildingConstructionFinishedSubject.OnNext(building);
		}

		protected void OnBuildingRemoved(Building building)
		{
			state.buildingsRemoved++;
			if (BuildingHelper.IsDecorationBuilding(building))
			{
				state.decorationBuildingsRemoved++;
			}
			if (BuildingHelper.IsRoad(building))
			{
				state.roadsRemoved++;
			}
			buildingRemovedSubject.OnNext(building);
		}

		[HarmonyPatch(typeof(Building), "FinishConstruction")]
		[HarmonyPostfix]
		private static void Building_FinishConstruction_Postfix(Building __instance)
		{
			FLog.Info("Building finish: " + ((Object)__instance).name + " ||\t Category: " + ((Object)__instance.BuildingModel.category).name);
			CustomServiceManager.GetService<BuildingMonitorService>().OnBuildingCompleted(__instance);
		}

		[HarmonyPatch(typeof(Building), "Remove")]
		[HarmonyPostfix]
		private static void Building_Remove_Postfix(Building __instance)
		{
			FLog.Info("Building remove: " + ((Object)__instance).name + " ||\t Category: " + ((Object)__instance.BuildingModel.category).name);
			CustomServiceManager.GetService<BuildingMonitorService>().OnBuildingCompleted(__instance);
		}
	}
}
namespace Forwindz.Framework.Utils
{
	public static class AsyncUtils
	{
		public static async Task WaitForConditionAsync(Func<bool> condition, int checkInterval = 100, CancellationToken cancellationToken = default(CancellationToken))
		{
			while (!condition())
			{
				if (cancellationToken.IsCancellationRequested)
				{
					throw new TaskCanceledException();
				}
				await Task.Delay(checkInterval, cancellationToken);
			}
		}
	}
	public class CustomField<ObjectType, FieldType> where ObjectType : class where FieldType : class
	{
		private readonly ConditionalWeakTable<ObjectType, FieldType> customFields = new ConditionalWeakTable<ObjectType, FieldType>();

		private readonly Func<ObjectType, FieldType> initFieldFunc = (ObjectType inst) => null;

		public FieldType GetField(ObjectType instance)
		{
			if (customFields.TryGetValue(instance, out var value))
			{
				return value;
			}
			throw new Exception($"Try to get field {typeof(FieldType).FullName} from {typeof(ObjectType).FullName}, but instance {instance.GetHashCode()} haven't created field");
		}

		public void SetField(ObjectType instance, FieldType fieldContent)
		{
			customFields.Add(instance, fieldContent);
		}

		public void CreateField(ObjectType instance)
		{
			customFields.Add(instance, initFieldFunc(instance));
		}

		public void RemoveField(ObjectType instance)
		{
			customFields.Remove(instance);
		}

		public CustomField(Func<ObjectType, FieldType> initFieldFunc)
		{
			this.initFieldFunc = initFieldFunc;
			PatchUtils.InjectConstructorPostPatch<ObjectType>(CreateField);
		}
	}
	public struct CustomIntEnum<T> where T : Enum
	{
		public int value;

		public CustomIntEnum(int value)
		{
			this.value = value;
		}

		public static implicit operator T(CustomIntEnum<T> enumObj)
		{
			return (T)Enum.ToObject(typeof(T), enumObj.value);
		}

		public static implicit operator CustomIntEnum<T>(T enumObjOrg)
		{
			return new CustomIntEnum<T>((int)(object)enumObjOrg);
		}

		public static T GetMaxOriginalEnum()
		{
			return Enum.GetValues(typeof(T)).Cast<T>().Max();
		}

		public static int GetMaxOriginalEnumValue()
		{
			return (int)(object)Enum.GetValues(typeof(T)).Cast<T>().Max();
		}
	}
	[AttributeUsage(AttributeTargets.Field)]
	public class NewCustomEnumAttribute : Attribute
	{
		public string Name { get; }

		public object PredefinedValue { get; }

		public NewCustomEnumAttribute(string name = null, object predefinedValue = null)
		{
			Name = name;
			PredefinedValue = predefinedValue;
		}
	}
	public class CustomIntEnumManager<T> where T : Enum
	{
		private static Dictionary<string, CustomIntEnum<T>> nameEnumMapping = new Dictionary<string, CustomIntEnum<T>>();

		private static int curMaxIndex = CustomIntEnum<T>.GetMaxOriginalEnumValue();

		private static Dictionary<int, string> valueNameMapping = new Dictionary<int, string>();

		public static int CurrentMaxIndex => curMaxIndex;

		public static IReadOnlyDictionary<string, CustomIntEnum<T>> NameEnumMapping => nameEnumMapping;

		public static IReadOnlyDictionary<int, string> ValueNameMapping => valueNameMapping;

		public static CustomIntEnum<T> AddEnum(string name)
		{
			do
			{
				curMaxIndex++;
			}
			while (valueNameMapping.ContainsKey(curMaxIndex));
			CustomIntEnum<T> customIntEnum = new CustomIntEnum<T>(curMaxIndex);
			nameEnumMapping.Add(name, customIntEnum);
			valueNameMapping.Add(customIntEnum.value, name);
			FLog.Info($"Add enum {name}={customIntEnum.value} to {typeof(T).Name}");
			return customIntEnum;
		}

		public static CustomIntEnum<T> AddPredefinedEnum(string name, int value)
		{
			if (value < curMaxIndex)
			{
				FLog.Error($"Try to add enum {name}={value} to {typeof(T).Name}, but the predefined value is already used. This may overwrite the previous enum!");
			}
			else if (valueNameMapping.ContainsKey(value))
			{
				FLog.Error($"Try to add enum {name}={value} to {typeof(T).Name}, but the predefined value is already used by other predefinitions. This will overwrite the previous enum!");
			}
			CustomIntEnum<T> customIntEnum = new CustomIntEnum<T>(value);
			nameEnumMapping.Add(name, customIntEnum);
			valueNameMapping.Add(customIntEnum.value, name);
			FLog.Info($"Add predefined enum {name}={customIntEnum.value} to {typeof(T).Name}");
			return customIntEnum;
		}

		public static void ScanAndAssignEnumValues<C>()
		{
			Type typeFromHandle = typeof(C);
			FieldInfo[] fields = typeFromHandle.GetFields();
			FLog.Info($"{typeof(CustomIntEnum<T>).Name}: Scan enum values for {typeof(C).Name}, static fields count {fields.Length}");
			FieldInfo[] array = fields;
			foreach (FieldInfo fieldInfo in array)
			{
				NewCustomEnumAttribute customAttribute = fieldInfo.GetCustomAttribute<NewCustomEnumAttribute>();
				if (customAttribute == null)
				{
					continue;
				}
				string name = customAttribute.Name ?? fieldInfo.Name;
				if (!fieldInfo.IsInitOnly)
				{
					FLog.Warning("Enum field " + typeFromHandle.Name + "." + fieldInfo.Name + " is not readonly. New enum should be inmutable.");
				}
				FLog.Info("Find enum field: " + fieldInfo.FieldType.Name + " " + fieldInfo.Name);
				Type fieldType = fieldInfo.FieldType;
				if (fieldType == typeof(CustomIntEnum<T>))
				{
					if (customAttribute.PredefinedValue == null)
					{
						fieldInfo.SetValue(null, AddEnum(name));
					}
					else
					{
						fieldInfo.SetValue(null, AddPredefinedEnum(name, (int)customAttribute.PredefinedValue));
					}
					continue;
				}
				if (fieldType == typeof(T))
				{
					if (customAttribute.PredefinedValue == null)
					{
						fieldInfo.SetValue(null, (T)AddEnum(name));
					}
					else
					{
						fieldInfo.SetValue(null, (T)AddPredefinedEnum(name, (int)customAttribute.PredefinedValue));
					}
					continue;
				}
				FLog.Error(typeFromHandle.Name + "." + fieldInfo.Name + " has incorrect type, it should be CustomEnum<" + typeof(T).Name + "," + typeFromHandle.Name + ">");
			}
		}
	}
	public static class FLog
	{
		public static ManualLogSource logger = Logger.CreateLogSource("f9");

		public static void Debug(params object[] objs)
		{
			logger.LogDebug((object)objs);
		}

		public static void Debug(object obj)
		{
			logger.LogDebug(obj);
		}

		public static void Info(params object[] objs)
		{
			logger.LogInfo((object)objs);
		}

		public static void Info(object obj)
		{
			logger.LogInfo(obj);
		}

		public static void Warning(params object[] objs)
		{
			logger.LogWarning((object)objs);
		}

		public static void Warning(object obj)
		{
			logger.LogWarning(obj);
		}

		public static void Error(params object[] objs)
		{
			logger.LogError((object)objs);
		}

		public static void Error(object obj)
		{
			logger.LogError(obj);
		}

		public static void ErrorAndThrow(object obj)
		{
			logger.LogError(obj);
			throw new Exception("Throw Exception:" + obj.ToString());
		}

		public static void Fatal(params object[] objs)
		{
			logger.LogFatal((object)objs);
		}

		public static void Fatal(object obj)
		{
			logger.LogFatal(obj);
		}

		public static void FatalAndThrow(object obj)
		{
			logger.LogFatal(obj);
			throw new Exception("Throw Exception:" + obj.ToString());
		}

		public static void Message(params object[] objs)
		{
			logger.LogMessage((object)objs);
		}

		public static void Message(object obj)
		{
			logger.LogMessage(obj);
		}

		public static void Assert(bool result, object message)
		{
			if (!result)
			{
				logger.LogError((object)"Assert failed!");
				logger.LogError(message);
				throw new Exception("Assert Failed :" + message.ToString());
			}
		}

		public static void AssertNotNull<T>(T obj) where T : class
		{
			if (obj == null)
			{
				logger.LogError((object)("Not null Assert failed! " + typeof(T).FullName));
				throw new Exception("Not null Assert Failed for " + typeof(T).FullName);
			}
		}

		public static void AssertType<T>(object obj)
		{
			if (!obj.GetType().Equals(typeof(T)))
			{
				logger.LogError((object)("Type Assert failed! Get <" + obj.GetType().FullName + "> Expect <" + typeof(T).FullName + ">"));
				string text = obj?.ToString();
				if (text == null)
				{
					text = "null";
				}
				throw new Exception("Type Assert Failed :" + text);
			}
		}
	}
	public static class PatchesManager
	{
		private static Dictionary<Type, Harmony> patchTypes = new Dictionary<Type, Harmony>();

		public static Harmony harmony = new Harmony("Forwindz");

		private static bool dirty = true;

		public static void RegPatch<T>()
		{
			patchTypes[typeof(T)] = null;
			dirty = true;
		}

		public static void RegPatch(Type type)
		{
			patchTypes[type] = null;
			dirty = true;
		}

		public static void PatchAll()
		{
			if (!dirty)
			{
				return;
			}
			Dictionary<Type, Harmony> dictionary = new Dictionary<Type, Harmony>();
			foreach (KeyValuePair<Type, Harmony> patchType in patchTypes)
			{
				Type key = patchType.Key;
				Harmony value = patchType.Value;
				if (value == null)
				{
					FLog.Info("Try to Patch " + key.Namespace + " > " + key.Name);
					dictionary[key] = Harmony.CreateAndPatchAll(key, (string)null);
				}
				else
				{
					dictionary[key] = value;
				}
			}
			patchTypes = dictionary;
			dirty = false;
		}
	}
	public static class PatchUtils
	{
		public static void InjectConstructorPostPatch(Type injectClassType, MethodInfo methodInfo)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			ConstructorInfo[] constructors = injectClassType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			ConstructorInfo[] array = constructors;
			foreach (ConstructorInfo constructorInfo in array)
			{
				PatchesManager.harmony.Patch((MethodBase)constructorInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		public static void InjectConstructorPostPatch<T>(Action<T> action)
		{
			InjectConstructorPostPatch(typeof(T), ReflectUtils.GetMethodInfo(action));
		}
	}
	public static class ReflectUtils
	{
		public static MethodInfo GetMethodInfo(Action action)
		{
			return action.Method;
		}

		public static MethodInfo GetMethodInfo<T>(Action<T> action)
		{
			return action.Method;
		}

		public static MethodInfo GetMethodInfo<T, U>(Action<T, U> action)
		{
			return action.Method;
		}

		public static MethodInfo GetMethodInfo<TResult>(Func<TResult> fun)
		{
			return fun.Method;
		}

		public static MethodInfo GetMethodInfo<T, TResult>(Func<T, TResult> fun)
		{
			return fun.Method;
		}

		public static MethodInfo GetMethodInfo<T, U, TResult>(Func<T, U, TResult> fun)
		{
			return fun.Method;
		}

		public static MethodInfo GetMethodInfo(Delegate del)
		{
			return del.Method;
		}

		public static List<Type> GetAllBaseTypes(Type type)
		{
			List<Type> list = new List<Type>();
			Type baseType = type.BaseType;
			while (baseType != null)
			{
				list.Add(baseType);
				baseType = baseType.BaseType;
			}
			return list;
		}

		public static List<Type> GetAllBaseTypesAndInterfaces(Type type)
		{
			List<Type> list = new List<Type>();
			Type baseType = type.BaseType;
			while (baseType != null)
			{
				list.Add(baseType);
				baseType = baseType.BaseType;
			}
			list.AddRange(type.GetInterfaces());
			return list;
		}

		public static void InitializeAllStatics(Assembly assembly)
		{
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				if (type.TypeInitializer != null)
				{
					RuntimeHelpers.RunClassConstructor(type.TypeHandle);
				}
			}
		}

		public static ConstructorInfo GetNonParameterConstructor(Type type)
		{
			ConstructorInfo[] constructors = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			FLog.Info("Try to search non parameter constructor " + type.Name);
			ConstructorInfo[] array = constructors;
			foreach (ConstructorInfo constructorInfo in array)
			{
				ParameterInfo[] parameters = constructorInfo.GetParameters();
				Type declaringType = constructorInfo.DeclaringType;
				FLog.Info($"Detect {constructorInfo.Name} > {parameters} > {declaringType.Name} > Private {constructorInfo.IsPrivate}");
				if ((parameters == null || parameters.Length == 0) && !constructorInfo.IsStatic && declaringType.Equals(type))
				{
					return constructorInfo;
				}
			}
			return null;
		}

		public static FieldInfo GetDeclaredField<T>(string fieldName) where T : class
		{
			FieldInfo fieldInfo = AccessTools.DeclaredField(typeof(T), fieldName);
			if (fieldInfo == null)
			{
				FLog.Error("Cannot find declared field: " + typeof(T).Namespace + "." + typeof(T).Name + "." + fieldName);
			}
			return fieldInfo;
		}

		public static FieldInfo GetField<T>(string fieldName) where T : class
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(T), fieldName);
			if (fieldInfo == null)
			{
				FLog.Error("Cannot find declared field: " + typeof(T).Namespace + "." + typeof(T).Name + "." + fieldName);
			}
			return fieldInfo;
		}
	}
	public class CompositeEffectBuilder : EffectBuilder<CompositeEffectModel>
	{
		public EffectModel[] Effects
		{
			get
			{
				return base.m_effectModel.rewards;
			}
			set
			{
				SetEffects(value);
			}
		}

		public CompositeEffectBuilder(string guid, string name, string iconPath)
			: base(guid, name, iconPath)
		{
			base.m_effectModel.anyNestedToFit = false;
			base.m_effectModel.rewards = Array.Empty<EffectModel>();
		}

		public void AddEffect(EffectModel effect)
		{
			ArrayExtension.ForceAdd<EffectModel>(base.m_effectModel.rewards, effect);
		}

		public void AddEffects(IEnumerable<EffectModel> effects)
		{
			List<EffectModel> list = base.m_effectModel.rewards.ToList();
			list.AddRange(effects.ToList());
			base.m_effectModel.rewards = list.ToArray();
		}

		public void AddEffects(EffectModel[] effects)
		{
			List<EffectModel> list = base.m_effectModel.rewards.ToList();
			list.AddRange(effects.ToList());
			base.m_effectModel.rewards = list.ToArray();
		}

		public void SetEffect(EffectModel effect)
		{
			base.m_effectModel.rewards = (EffectModel[])(object)new EffectModel[1] { effect };
		}

		public void SetEffects(IEnumerable<EffectModel> effects)
		{
			base.m_effectModel.rewards = effects.ToArray();
		}

		public void SetEffects(EffectModel[] effects)
		{
			base.m_effectModel.rewards = effects;
		}

		public void ClearEffects()
		{
			base.m_effectModel.rewards = Array.Empty<EffectModel>();
		}

		public void SetDescriptionArgs(params (TextArgType type, int sourceIndex)[] args)
		{
			((EffectModel)base.m_effectModel).formatDescription = true;
			base.m_effectModel.dynamicDescriptionArgs = args.ToTextArgArray();
		}

		public void SetAnyNestedToFit(bool value)
		{
			base.m_effectModel.anyNestedToFit = value;
		}

		public void SetNestedPreviewIndex(int index)
		{
			if (index < 0)
			{
				base.m_effectModel.hasNestedPreview = false;
				return;
			}
			base.m_effectModel.hasNestedPreview = true;
			base.m_effectModel.nestedPreviewIndex = index;
		}

		public void SetNestedRetroactivePreviewIndex(int index)
		{
			if (index < 0)
			{
				base.m_effectModel.hasNestedRetroactivePreview = false;
				return;
			}
			base.m_effectModel.hasNestedRetroactivePreview = true;
			base.m_effectModel.nestedRetroactivePreviewEffectIndex = index;
		}

		public void SetNestedStatePreviewIndex(int index)
		{
			if (index < 0)
			{
				base.m_effectModel.hasNestedStatePreview = false;
				return;
			}
			base.m_effectModel.hasNestedStatePreview = true;
			base.m_effectModel.nestedStatePreviewEffectIndex = index;
		}

		public void SetNestedAmountIndex(int index)
		{
			if (index < 0)
			{
				base.m_effectModel.hasNestedAmount = false;
				return;
			}
			base.m_effectModel.hasNestedAmount = true;
			base.m_effectModel.nestedAmountEffectIndex = index;
		}

		public void SetNestedIntAmountIndex(int index)
		{
			if (index < 0)
			{
				base.m_effectModel.hasNestedIntAmount = false;
				return;
			}
			base.m_effectModel.hasNestedIntAmount = true;
			base.m_effectModel.nestedIntAmountEffectIndex = index;
		}

		public void SetNestedFloatAmountIndex(int index)
		{
			if (index < 0)
			{
				base.m_effectModel.hasNestedFloatAmount = false;
				return;
			}
			base.m_effectModel.hasNestedFloatAmount = true;
			base.m_effectModel.nestedFloatAmountEffectIndex = index;
		}

		public void SetShowEffectAsPerks(bool value)
		{
			base.m_effectModel.showEffectsAsPerks = value;
		}
	}
	public class EffectAvailability
	{
		public static List<IEffectBuilder> RegularCornerstones;

		static EffectAvailability()
		{
			RegularCornerstones = new List<IEffectBuilder>();
			PatchesManager.RegPatch<EffectAvailability>();
		}

		private static void SetAvailableBasedOnRarity(List<IEffectBuilder> effectModelBuilders)
		{
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Invalid comparison between Unknown and I4
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Expected O, but got Unknown
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Invalid comparison between Unknown and I4
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Expected O, but got Unknown
			Settings settings = SO.Settings;
			BiomeModel[] biomes = settings.biomes;
			HashSet<EffectsTable> hashSet = new HashSet<EffectsTable>();
			BiomeModel[] array = biomes;
			foreach (BiomeModel val in array)
			{
				int count = val.seasons.SeasonRewards.Count;
				for (int j = 0; j < count; j++)
				{
					SeasonRewardModel val2 = val.seasons.SeasonRewards[j];
					int year = val2.year;
					bool flag = year == 2 || year == 4 || year == 6;
					EffectsTable effectsTable = val2.effectsTable;
					if (hashSet.Contains(effectsTable))
					{
						continue;
					}
					hashSet.Add(effectsTable);
					EffectsTableEntity[] effects = val2.effectsTable.effects;
					List<EffectsTableEntity> list = new List<EffectsTableEntity>(effects);
					if (val2.effectsTable.effects.Length == 0)
					{
						continue;
					}
					foreach (IEffectBuilder effectModelBuilder in effectModelBuilders)
					{
						EffectModel model = effectModelBuilder.Model;
						EffectRarity rarity = model.rarity;
						EffectRarity val3 = rarity;
						if ((int)val3 != 4)
						{
							if ((int)val3 == 5 && flag)
							{
								EffectsTableEntity val4 = new EffectsTableEntity();
								val4.chance = 100;
								val4.effect = model;
								list.Add(val4);
								FLog.Info($"{((SO)val).Name} Legendary Availability: Add <{((SO)model).Name}> to Year <{year}>, Weight={val4.chance} | {list.Count}");
							}
						}
						else if (!flag)
						{
							EffectsTableEntity val5 = new EffectsTableEntity();
							val5.chance = 100;
							val5.effect = model;
							list.Add(val5);
							FLog.Info($"{((SO)val).Name} Epic Availability: Add <{((SO)model).Name}> to Year <{year}>, Weight={val5.chance} | {list.Count}");
						}
					}
					val2.effectsTable.effects = list.ToArray();
				}
			}
		}

		[HarmonyPatch(typeof(BiomeManager), "SyncBiomes")]
		[HarmonyPostfix]
		private static void API_BiomeManager_SyncBiomes_PostPatch()
		{
			SetAvailableBasedOnRarity(RegularCornerstones);
		}
	}
	public static class EffectFactoryExtend
	{
		public static T CreateEffect<T>() where T : EffectModel
		{
			T val = ScriptableObject.CreateInstance<T>();
			((EffectModel)val).blockedBy = Array.Empty<EffectModel>();
			((EffectModel)val).usabilityTags = Array.Empty<ModelTag>();
			return val;
		}

		public static ChanceForNoConsumptionEffectModel AddHookedEffect_ChanceForNoConsumptionEffectModel(IEffectBuilder effectBuilder, float amount)
		{
			ChanceForNoConsumptionEffectModel val = EffectFactory.NewHookedEffect<ChanceForNoConsumptionEffectModel>(effectBuilder);
			val.amount = amount;
			return val;
		}

		public static GoodEdibleEffectModel AddHookedEffect_GoodEdibleEffectModel(IEffectBuilder effectBuilder, GoodModel goodModel, bool ediable)
		{
			GoodEdibleEffectModel goodEdibleEffectModel = EffectFactory.NewHookedEffect<GoodEdibleEffectModel>(effectBuilder);
			goodEdibleEffectModel.good = goodModel;
			goodEdibleEffectModel.eatable = ediable;
			return goodEdibleEffectModel;
		}

		public static AddTraderFreeEffectChanceEffectModel AddHookedEffect_AddTraderFreeEffectChanceEffectModel(IEffectBuilder effectBuilder, TraderModel traderModel, float chance)
		{
			AddTraderFreeEffectChanceEffectModel addTraderFreeEffectChanceEffectModel = EffectFactory.NewHookedEffect<AddTraderFreeEffectChanceEffectModel>(effectBuilder);
			addTraderFreeEffectChanceEffectModel.trader = traderModel;
			addTraderFreeEffectChanceEffectModel.chance = chance;
			return addTraderFreeEffectChanceEffectModel;
		}

		public static OnlyTraderEffectModel AddHookedEffect_OnlyTraderEffectModel(IEffectBuilder effectBuilder, TraderModel traderModel)
		{
			OnlyTraderEffectModel onlyTraderEffectModel = EffectFactory.NewHookedEffect<OnlyTraderEffectModel>(effectBuilder);
			onlyTraderEffectModel.trader = traderModel;
			return onlyTraderEffectModel;
		}

		public static TraderIntervalEffectModel AddHookedEffect_TraderIntervalEffectModel(IEffectBuilder effectBuilder, float amount)
		{
			TraderIntervalEffectModel val = EffectFactory.NewHookedEffect<TraderIntervalEffectModel>(effectBuilder);
			val.amount = amount;
			return val;
		}

		public static HearthPopPercentEffectModel AddHookedEffect_HearthPopPercentEffectModel(IEffectBuilder effectBuilder, float percent)
		{
			HearthPopPercentEffectModel hearthPopPercentEffectModel = EffectFactory.NewHookedEffect<HearthPopPercentEffectModel>(effectBuilder);
			hearthPopPercentEffectModel.percent = percent;
			return hearthPopPercentEffectModel;
		}

		public static DecorationPercentEffectModel AddHookedEffect_DecorationPercentEffectModel(IEffectBuilder effectBuilder, float percent)
		{
			DecorationPercentEffectModel decorationPercentEffectModel = EffectFactory.NewHookedEffect<DecorationPercentEffectModel>(effectBuilder);
			decorationPercentEffectModel.percent = percent;
			return decorationPercentEffectModel;
		}

		public static VillagersBreakTimeRateEffectModel AddHookedEffect_VillagersBreakTimeRateEffectModel(IEffectBuilder effectBuilder, float percent)
		{
			VillagersBreakTimeRateEffectModel val = EffectFactory.NewHookedEffect<VillagersBreakTimeRateEffectModel>(effectBuilder);
			val.amount = percent;
			return val;
		}

		public static GlobalProductionRateEffectModel AddHookedEffect_GlobalProductionRateEffectModel(IEffectBuilder effectBuilder, float percent)
		{
			GlobalProductionRateEffectModel val = EffectFactory.NewHookedEffect<GlobalProductionRateEffectModel>(effectBuilder);
			val.amount = percent;
			return val;
		}

		public static HarvestingRateEffectModel AddHookedEffect_HarvestingRateEffectModel(IEffectBuilder effectBuilder, float percent)
		{
			HarvestingRateEffectModel val = EffectFactory.NewHookedEffect<HarvestingRateEffectModel>(effectBuilder);
			val.amount = percent;
			return val;
		}

		public static VillagersSpeedEffectModel AddHookedEffect_VillagersSpeedEffectModel(IEffectBuilder effectBuilder, VillagerSpeedRewardType type, float percent)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			VillagersSpeedEffectModel val = EffectFactory.NewHookedEffect<VillagersSpeedEffectModel>(effectBuilder);
			val.type = type;
			val.amount = percent;
			return val;
		}

		public static GlobalExtraProductionChanceEffectModel AddHookedEffect_GlobalExtraProductionChanceEffectModel(IEffectBuilder effectBuilder, float percent)
		{
			GlobalExtraProductionChanceEffectModel val = EffectFactory.NewHookedEffect<GlobalExtraProductionChanceEffectModel>(effectBuilder);
			((BaseRateAmountEffectModel)val).amount = percent;
			return val;
		}
	}
	public static class HookFactoryExtend
	{
		public static GoodProducedHook Create_GoodProducedHook(GoodRef goodRef, bool cycles)
		{
			return new GoodProducedHook
			{
				good = goodRef,
				cycles = cycles
			};
		}

		public static DecorationHook Create_DecorationHook(DecorationTier tier, int amount)
		{
			return new DecorationHook
			{
				decorationTier = tier,
				amount = amount
			};
		}
	}
	public class LocalizationLoader
	{
		public static void LoadLocalization(string folderPath = "lang")
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			FLog.Info("f9 cornerstone plugin patcher path " + directoryName);
			string path = Path.Combine(directoryName, folderPath);
			try
			{
				string[] files = Directory.GetFiles(path, "*.json", SearchOption.AllDirectories);
				string[] array = files;
				foreach (string text in array)
				{
					try
					{
						string text2 = File.ReadAllText(text);
						Dictionary<string, string> dictionary = JSON.FromJson<Dictionary<string, string>>(text2);
						string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text);
						SystemLanguage val = LocalizationManager.CodeToLanguage(fileNameWithoutExtension);
						foreach (KeyValuePair<string, string> item in dictionary)
						{
							LocalizationManager.AddString(item.Key, item.Value, val);
							Log.Info((object)$"{val} [{item.Key}]:{item.Value}", (Object)null);
						}
						Log.Info((object)$"Load {dictionary.Count} entries for {val} language, from {text}", (Object)null);
					}
					catch (Exception ex)
					{
						Log.Error((object)("Error while processing localization file: " + text), (Object)null);
						Log.Error((object)ex, (Object)null);
					}
				}
			}
			catch (Exception ex2)
			{
				Log.Error((object)ex2, (Object)null);
			}
		}
	}
	public static class Utils
	{
		public static string GetMd5Hash(string input)
		{
			using MD5 mD = MD5.Create();
			byte[] array = mD.ComputeHash(Encoding.UTF8.GetBytes(input));
			StringBuilder stringBuilder = new StringBuilder();
			byte[] array2 = array;
			foreach (byte b in array2)
			{
				stringBuilder.Append(b.ToString("x2"));
			}
			return stringBuilder.ToString();
		}

		public static T GetValue<T>(this WeakReference<T> instance) where T : class
		{
			if (instance.TryGetTarget(out var target))
			{
				return target;
			}
			return null;
		}

		public static void SetSeasonsTime(float drizzleTime, float clearanceTime, float stormTime, SeasonQuarter firstCornerstoneTime = 1)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			BiomeModel[] biomes = MB.Settings.biomes;
			foreach (BiomeModel val in biomes)
			{
				val.seasons.DrizzleTime = drizzleTime;
				val.seasons.ClearanceTime = clearanceTime;
				val.seasons.StormTime = stormTime;
				val.seasons.SeasonRewards[0].quarter = firstCornerstoneTime;
			}
		}

		public static string GetGoodIconAndName(GoodModel good)
		{
			string text = ((SO)good).Name;
			int num = text.LastIndexOf("]");
			if (num != -1)
			{
				text = text.Substring(num + 1);
			}
			else if (text.Contains("_Meta"))
			{
				text = text.Substring("_Meta".Length + 1);
			}
			text = text.Trim();
			return "<sprite name=\"" + ((SO)good).Name.ToLowerInvariant() + "\"> " + text;
		}
	}
}
namespace Forwindz.Framework.Utils.Extend
{
	public static class ArrayExt
	{
		public static T[] ForceAdd<T>(this T[] source, T item)
		{
			T[] array = new T[source.Length + 1];
			source.CopyTo(array, 0);
			array[^1] = item;
			return array;
		}

		public static void ForceAdd<T>(ref T[] source, T item)
		{
			source = source.ForceAdd(item);
		}

		public static T[] ForceRemove<T>(this T[] source, T item)
		{
			int num = Array.IndexOf(source, item);
			if (num < 0)
			{
				return source;
			}
			T[] array = new T[source.Length - 1];
			if (num > 0)
			{
				Array.Copy(source, 0, array, 0, num);
			}
			if (num < source.Length - 1)
			{
				Array.Copy(source, num + 1, array, num, source.Length - num - 1);
			}
			return array;
		}

		public static void ForceRemove<T>(ref T[] source, T item)
		{
			source = source.ForceRemove(item);
		}
	}
	public static class GoodModelExt
	{
		public static bool ContainTag(this GoodModel goodModel, string name)
		{
			ModelTag[] tags = goodModel.tags;
			foreach (ModelTag val in tags)
			{
				if (((SO)val).Name.Equals(name))
				{
					return true;
				}
			}
			return false;
		}
	}
	public static class SOExtend
	{
		public static List<T> DeepClone<T>(this List<T> objs) where T : SO
		{
			List<T> list = new List<T>();
			list.Capacity = objs.Count;
			for (int i = 0; i < objs.Count; i++)
			{
				list.Add(((SO)(object)objs[i]).DeepClone<T>());
			}
			return list;
		}

		public static T[] DeepClone<T>(this T[] objs) where T : SO
		{
			T[] array = new T[objs.Length];
			for (int i = 0; i < objs.Length; i++)
			{
				array[i] = ((SO)(object)objs[i]).DeepClone<T>();
			}
			return array;
		}

		public static T Clone<T>(this T original) where T : SO
		{
			if ((Object)(object)original == (Object)null)
			{
				return default(T);
			}
			return Object.Instantiate<T>(original);
		}

		public static SO DeepClone(this SO original)
		{
			if ((Object)(object)original == (Object)null)
			{
				return null;
			}
			SO val = Object.Instantiate<SO>(original);
			SODeepCopyFields(original, val);
			return val;
		}

		public static T DeepClone<T>(this SO original) where T : SO
		{
			return (T)(object)original.DeepClone();
		}

		private static void SODeepCopyFields(object source, object destination)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			FieldInfo[] fields = source.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			FieldInfo[] array = fields;
			foreach (FieldInfo fieldInfo in array)
			{
				if (!fieldInfo.IsNotSerialized && fieldInfo.FieldType.IsSubclassOf(typeof(SO)))
				{
					SO val = (SO)fieldInfo.GetValue(source);
					SO value = (((Object)(object)val != (Object)null) ? val.DeepClone() : null);
					fieldInfo.SetValue(destination, value);
				}
			}
		}
	}
}
namespace Forwindz.Framework.Services
{
	public static class CustomServiceManager
	{
		private static readonly List<Type> appExtraServiceTypes;

		private static readonly List<Type> gameExtraServiceTypes;

		private static readonly List<Type> metaExtraServiceTypes;

		private static readonly List<Type> worldExtraServiceTypes;

		private static Dictionary<Type, WeakReference<IService>> customServices;

		private static WeakReference<List<IService>> gameServices;

		private static WeakReference<List<IService>> metaServices;

		private static WeakReference<List<IService>> appServices;

		private static WeakReference<List<IService>> worldServices;

		public static IReadOnlyList<IService> GameServicesList => gameServices.GetValue();

		public static IReadOnlyList<IService> MetaServicesList => metaServices.GetValue();

		public static IReadOnlyList<IService> AppServicesList => appServices.GetValue();

		public static IReadOnlyList<IService> WorldServicesList => worldServices.GetValue();

		static CustomServiceManager()
		{
			appExtraServiceTypes = new List<Type>();
			gameExtraServiceTypes = new List<Type>();
			metaExtraServiceTypes = new List<Type>();
			worldExtraServiceTypes = new List<Type>();
			customServices = new Dictionary<Type, WeakReference<IService>>();
			gameServices = null;
			metaServices = null;
			appServices = null;
			worldServices = null;
			PatchesManager.RegPatch(typeof(CustomServiceManager));
		}

		public static void RegAppService<T>() where T : IService
		{
			appExtraServiceTypes.Add(typeof(T));
		}

		public static void RegGameService<T>() where T : IService
		{
			gameExtraServiceTypes.Add(typeof(T));
		}

		public static void RegMetaService<T>() where T : IService
		{
			metaExtraServiceTypes.Add(typeof(T));
		}

		public static void RegWorldService<T>() where T : IService
		{
			worldExtraServiceTypes.Add(typeof(T));
		}

		public static T GetService<T>()
		{
			if (customServices[typeof(T)].TryGetTarget(out var target))
			{
				return (T)(object)target;
			}
			return default(T);
		}

		public static IService GetAsIService<T>()
		{
			if (customServices[typeof(T)].TryGetTarget(out var target))
			{
				return target;
			}
			return null;
		}

		public static IService GetService(Type type)
		{
			if (customServices[type].TryGetTarget(out var target))
			{
				return target;
			}
			return null;
		}

		public static IService GetServiceSafe(Type type)
		{
			if (customServices.TryGetValue(type, out var value) && value.TryGetTarget(out var target))
			{
				return target;
			}
			return null;
		}

		public static T GetServiceSafe<T>() where T : IService
		{
			if (customServices.TryGetValue(typeof(T), out var value) && value.TryGetTarget(out var target) && target is T result)
			{
				return result;
			}
			return default(T);
		}

		[HarmonyPatch(typeof(WorldServices), "CreateServices")]
		[HarmonyPrefix]
		private static void WorldServicesCreate_PrePatch(WorldServices __instance)
		{
			foreach (Type worldExtraServiceType in worldExtraServiceTypes)
			{
				CreateServiceToList(__instance.allServices, worldExtraServiceType);
			}
			FLog.Info($"Try to create {worldExtraServiceTypes.Count} services in WorldServices");
			worldServices = new WeakReference<List<IService>>(__instance.allServices);
		}

		[HarmonyPatch(typeof(AppServices), "CreateServices")]
		[HarmonyPrefix]
		private static void AppServicesCreate_PrePatch(AppServices __instance)
		{
			foreach (Type appExtraServiceType in appExtraServiceTypes)
			{
				CreateServiceToList(__instance.allServices, appExtraServiceType);
			}
			FLog.Info($"Try to create {appExtraServiceTypes.Count} services in AppServices");
			appServices = new WeakReference<List<IService>>(__instance.allServices);
		}

		[HarmonyPatch(typeof(GameServices), "CreateServices")]
		[HarmonyPostfix]
		private static void GameServicesCreate_PostPatch(GameServices __instance)
		{
			foreach (Type gameExtraServiceType in gameExtraServiceTypes)
			{
				CreateServiceToList(__instance.allServices, gameExtraServiceType);
			}
			FLog.Info($"Try to create {gameExtraServiceTypes.Count} services in GameServices");
			gameServices = new WeakReference<List<IService>>(__instance.allServices);
		}

		[HarmonyPatch(typeof(MetaServices), "CreateServices")]
		[HarmonyPrefix]
		private static void MetaServicesCreate_PrePatch(MetaServices __instance)
		{
			foreach (Type metaExtraServiceType in metaExtraServiceTypes)
			{
				CreateServiceToList(__instance.allServices, metaExtraServiceType);
			}
			FLog.Info($"Try to create {metaExtraServiceTypes.Count} services in MetaServices");
			metaServices = new WeakReference<List<IService>>(__instance.allServices);
		}

		private static void CreateServiceToList(List<IService> allServices, Type serviceType)
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			FLog.Info("Try to create service " + serviceType.FullName);
			FLog.AssertNotNull(allServices);
			FLog.AssertNotNull(customServices);
			FLog.AssertNotNull(serviceType);
			ConstructorInfo nonParameterConstructor = ReflectUtils.GetNonParameterConstructor(serviceType);
			FLog.AssertNotNull(nonParameterConstructor);
			IService val = null;
			try
			{
				val = (IService)nonParameterConstructor.Invoke(null);
			}
			catch (Exception obj)
			{
				FLog.Error("Failed to create service!");
				FLog.Error(obj);
			}
			FLog.AssertNotNull<IService>(val);
			List<Type> list = new List<Type>();
			list.AddRange(serviceType.GetInterfaces());
			list.Add(serviceType);
			list.AddRange(TypeExtensions.GetBaseTypes(serviceType, false));
			List<Type> list2 = list;
			foreach (Type item in list2)
			{
				if (!(item == null) && GetServiceSafe(item) == null)
				{
					customServices[item] = new WeakReference<IService>(val);
					FLog.Info("Add Service " + serviceType.Name + " as " + item.Name);
				}
			}
			allServices.Add(val);
		}
	}
	internal class DecorationModelInfo
	{
		public DecorationTier tier;

		public int decorationScore;

		public DecorationModelInfo(DecorationModel decorationModel)
		{
			decorationScore = decorationModel.decorationScore;
			tier = decorationModel.tier;
		}

		public void Apply(DecorationModel decorationModel)
		{
			decorationModel.decorationScore = decorationScore;
			decorationModel.tier = tier;
		}
	}
	public class DynamicDecorationStateInfo
	{
		public float decorationPercent = 1f;
	}
	internal class DynamicBuildingState
	{
		[JsonIgnore]
		public Dictionary<string, DecorationModelInfo> originalDecorations = new Dictionary<string, DecorationModelInfo>();

		public Dictionary<string, DynamicDecorationStateInfo> decorationStates = new Dictionary<string, DynamicDecorationStateInfo>();

		public void InitGame()
		{
			List<DecorationModel> list = LinqExtensions.FilterCast<DecorationModel>((IEnumerable)MB.Settings.Buildings).ToList();
			foreach (DecorationModel item in list)
			{
				originalDecorations[((SO)item).Name] = new DecorationModelInfo(item);
			}
			ApplyStates();
		}

		public void AddDecorationPercent(string decoName, float percent)
		{
			if (decorationStates.TryGetValue(decoName, out var value))
			{
				value.decorationPercent += percent;
				return;
			}
			value = new DynamicDecorationStateInfo();
			value.decorationPercent += percent;
			decorationStates[decoName] = value;
		}

		public float GetDecorationPercent(string decoName)
		{
			if (decorationStates.TryGetValue(decoName, out var value))
			{
				return value.decorationPercent;
			}
			return 1f;
		}

		public void ApplyStates()
		{
			foreach (string key in decorationStates.Keys)
			{
				ApplyDecorationState(key);
			}
		}

		public void ApplyDecorationState(string decoName)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Expected O, but got Unknown
			DynamicDecorationStateInfo dynamicDecorationStateInfo = decorationStates[decoName];
			DecorationModelInfo decorationModelInfo = originalDecorations[decoName];
			DecorationModel val = (DecorationModel)MB.Settings.GetBuilding(decoName);
			val.decorationScore = (int)((float)decorationModelInfo.decorationScore * dynamicDecorationStateInfo.decorationPercent);
		}

		public void DestoryRestore()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Expected O, but got Unknown
			foreach (string key in decorationStates.Keys)
			{
				DecorationModelInfo decorationModelInfo = originalDecorations[key];
				DecorationModel val = (DecorationModel)MB.Settings.GetBuilding(key);
				val.decorationScore = decorationModelInfo.decorationScore;
			}
		}
	}
	public class DynamicBuildingStateService : GameService, IDynamicBuildingStateService, IService
	{
		[ModSerializedField(SaveLoadType.Unknown, "")]
		private DynamicBuildingState state = new DynamicBuildingState();

		private FieldInfo fieldInfo_decorationTypeOwning = null;

		private FieldInfo fieldInfo_monitor = null;

		public readonly Subject<Dictionary<string, DynamicDecorationStateInfo>> decorationValueChangeSubject = new Subject<Dictionary<string, DynamicDecorationStateInfo>>();

		public IObservable<Dictionary<string, DynamicDecorationStateInfo>> OnDecorationValueChange => (IObservable<Dictionary<string, DynamicDecorationStateInfo>>)decorationValueChangeSubject;

		public OrdersMonitor Reflect_OrderService_monitor => (OrdersMonitor)(fieldInfo_monitor?.GetValue(Serviceable.OrdersService));

		public Dictionary<ObjectiveState, DecorationTypeOwningLogic> Reflect_OrderMonitor_decorationTypeOwning
		{
			get
			{
				OrdersMonitor reflect_OrderService_monitor = Reflect_OrderService_monitor;
				if (reflect_OrderService_monitor == null)
				{
					return null;
				}
				return (Dictionary<ObjectiveState, DecorationTypeOwningLogic>)(fieldInfo_decorationTypeOwning?.GetValue(reflect_OrderService_monitor));
			}
		}

		static DynamicBuildingStateService()
		{
			CustomServiceManager.RegGameService<DynamicBuildingStateService>();
		}

		public override IService[] GetDependencies()
		{
			return (IService[])(object)new IService[4]
			{
				(IService)Serviceable.BuildingsService,
				(IService)Serviceable.RecipesService,
				(IService)Serviceable.OrdersService,
				CustomServiceManager.GetAsIService<IExtraStateService>()
			};
		}

		public override void OnDestroy()
		{
			state.DestoryRestore();
			((Service)this).OnDestroy();
		}

		public override UniTask OnLoading()
		{
			//IL_0034: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			fieldInfo_monitor = ReflectUtils.GetDeclaredField<OrdersService>("monitor");
			fieldInfo_decorationTypeOwning = ReflectUtils.GetDeclaredField<OrdersMonitor>("decorationTypeOwning");
			state.InitGame();
			UpdateDecorationOrder();
			return UniTask.CompletedTask;
		}

		private void UpdateDecorationOrder()
		{
			Dictionary<ObjectiveState, DecorationTypeOwningLogic> reflect_OrderMonitor_decorationTypeOwning = Reflect_OrderMonitor_decorationTypeOwning;
			if (reflect_OrderMonitor_decorationTypeOwning == null)
			{
				FLog.Error("Failed to get decoration orders, the decoration order info cannot be refreshed!");
				return;
			}
			foreach (KeyValuePair<ObjectiveState, DecorationTypeOwningLogic> item in reflect_OrderMonitor_decorationTypeOwning)
			{
				ObjectiveState key = item.Key;
				DecorationTypeOwningLogic value = item.Value;
				((OrderLogic)value).InitState(key);
			}
		}

		public void AddDecorationPercent(string decorationName, float percent)
		{
			AddDecorationPercentWithoutUpdate(decorationName, percent);
			decorationValueChangeSubject.OnNext(state.decorationStates);
			UpdateDecorationInfo();
		}

		private void AddDecorationPercentWithoutUpdate(string decorationName, float percent)
		{
			state.AddDecorationPercent(decorationName, percent);
			state.ApplyDecorationState(decorationName);
		}

		public void AddAllDecorationPercent(float percent)
		{
			foreach (string key in state.originalDecorations.Keys)
			{
				AddDecorationPercentWithoutUpdate(key, percent);
				state.ApplyDecorationState(key);
			}
			UpdateDecorationInfo();
		}

		private void UpdateDecorationInfo()
		{
			decorationValueChangeSubject.OnNext(state.decorationStates);
			UpdateDecorationOrder();
		}

		public float GetDecorationPercent(string decorationName)
		{
			return state.GetDecorationPercent(decorationName);
		}

		public int GetDecorationAmount(DecorationTier tier)
		{
			return Serviceable.BuildingsService.Decorations.Values.Sum((Decoration d) => (((Building)d).IsFinished() && d.model.hasDecorationTier && (Object)(object)d.model.tier == (Object)(object)tier) ? d.model.decorationScore : 0);
		}
	}
	public class ModifyGoodTypeState
	{
		public enum OperationType
		{
			SetEdiable,
			SetBurnable,
			SetTag
		}

		[JsonProperty]
		public readonly OperationType op;

		[JsonProperty]
		public readonly string content;

		[JsonProperty]
		public readonly bool boolState;

		private ModifyGoodTypeState()
		{
		}

		private ModifyGoodTypeState(OperationType op, string content, bool boolState)
		{
			this.op = op;
			this.content = content;
			this.boolState = boolState;
		}

		public static ModifyGoodTypeState GenAddTag(string tagName)
		{
			return new ModifyGoodTypeState(OperationType.SetTag, tagName, boolState: true);
		}

		public static ModifyGoodTypeState GenRemoveTag(string tagName)
		{
			return new ModifyGoodTypeState(OperationType.SetTag, tagName, boolState: false);
		}

		public static ModifyGoodTypeState GenSetEdiable(bool ediable)
		{
			return new ModifyGoodTypeState(OperationType.SetEdiable, null, ediable);
		}

		public static ModifyGoodTypeState GenSetBurnable(bool burnable)
		{
			return new ModifyGoodTypeState(OperationType.SetBurnable, null, burnable);
		}

		public bool IsAlreadyApplied(GoodModel goodModel)
		{
			switch (op)
			{
			case OperationType.SetEdiable:
				return goodModel.eatable == boolState;
			case OperationType.SetBurnable:
				return goodModel.canBeBurned = boolState;
			case OperationType.SetTag:
				if (boolState)
				{
					return goodModel.ContainTag(content);
				}
				return !goodModel.ContainTag(content);
			default:
				FLog.Warning($"Unknown enum values {op} in ModifyGoodTypeState");
				return false;
			}
		}

		public void ApplyState(GoodModel goodModel)
		{
			switch (op)
			{
			case OperationType.SetEdiable:
				goodModel.eatable = boolState;
				if (boolState)
				{
					Serviceable.StateService.Actors.rawFoodConsumptionPermits[((SO)goodModel).Name] = true;
				}
				else
				{
					Serviceable.StateService.Actors.rawFoodConsumptionPermits.Remove(((SO)goodModel).Name);
				}
				break;
			case OperationType.SetBurnable:
				goodModel.canBeBurned = boolState;
				Serviceable.HearthService.SetCanBeBurned(((SO)goodModel).Name, boolState);
				break;
			case OperationType.SetTag:
				if (boolState)
				{
					ArrayExt.ForceAdd(ref goodModel.tags, Serviceable.Settings.GetTag(content));
				}
				else
				{
					ArrayExt.ForceRemove(ref goodModel.tags, Serviceable.Settings.GetTag(content));
				}
				break;
			default:
				FLog.Warning($"Unknown enum values {op} in ModifyGoodTypeState");
				break;
			}
		}

		public void RemoveState(GoodModel goodModel)
		{
			switch (op)
			{
			case OperationType.SetEdiable:
				goodModel.eatable = !boolState;
				break;
			case OperationType.SetBurnable:
				goodModel.canBeBurned = !boolState;
				break;
			case OperationType.SetTag:
				if (!boolState)
				{
					ArrayExt.ForceAdd(ref goodModel.tags, Serviceable.Settings.GetTag(content));
				}
				else
				{
					ArrayExt.ForceRemove(ref goodModel.tags, Serviceable.Settings.GetTag(content));
				}
				break;
			default:
				FLog.Warning($"Unknown enum values {op} in ModifyGoodTypeState");
				break;
			}
		}

		public ModifyGoodTypeState GenerateInverseState()
		{
			return new ModifyGoodTypeState(op, content, !boolState);
		}

		public override bool Equals(object obj)
		{
			if (obj is ModifyGoodTypeState modifyGoodTypeState)
			{
				if (modifyGoodTypeState.op == op)
				{
					switch (op)
					{
					case OperationType.SetEdiable:
					case OperationType.SetBurnable:
						return modifyGoodTypeState.boolState == boolState;
					case OperationType.SetTag:
						return modifyGoodTypeState.boolState == boolState && modifyGoodTypeState.content.Equals(content);
					}
				}
				return false;
			}
			return base.Equals(obj);
		}

		public override int GetHashCode()
		{
			uint num = (boolState ? 1u : 0u);
			uint num2 = ((op == OperationType.SetTag) ? ((uint)EqualityComparer<string>.Default.GetHashCode(content)) : 0u);
			uint hashCode = (uint)op.GetHashCode();
			return (int)((num << 31) | ((hashCode & 3) << 29)) | ((int)num2 & -1);
		}

		public override string ToString()
		{
			int num = (boolState ? 1 : 0);
			string text = $"{num}_{op.ToString()}";
			if (op == OperationType.SetTag)
			{
				text = text + "_" + content;
			}
			return text;
		}

		public string ToInvString()
		{
			int num = ((!boolState) ? 1 : 0);
			string text = $"{num}_{op.ToString()}";
			if (op == OperationType.SetTag)
			{
				text = text + "_" + content;
			}
			return text;
		}
	}
	public class ModifyGoodTypeInfo
	{
		[JsonProperty]
		private string goodName;

		[JsonProperty]
		private ModifyGoodTypeState state;

		[JsonProperty]
		private readonly bool isOriginalState;

		[JsonProperty]
		internal int duplicateTimes = 0;

		[JsonIgnore]
		public string GoodName => goodName;

		[JsonIgnore]
		public ModifyGoodTypeState State => state;

		[JsonIgnore]
		public bool IsOriginalState => isOriginalState;

		public ModifyGoodTypeInfo()
		{
		}

		public ModifyGoodTypeInfo(string goodName, ModifyGoodTypeState state)
		{
			this.goodName = goodName;
			this.state = state;
			isOriginalState = state.IsAlreadyApplied(GetGoodModel());
		}

		public GoodModel GetGoodModel()
		{
			return Serviceable.Settings.GetGood(goodName);
		}

		public void ApplyState()
		{
			FLog.Info("+State " + ToString());
			state.ApplyState(GetGoodModel());
		}

		public void RemoveState()
		{
			if (!isOriginalState)
			{
				FLog.Info("-State " + ToString());
				state.RemoveState(GetGoodModel());
			}
		}

		public ModifyGoodTypeInfo GenerateInverseInfo()
		{
			return new ModifyGoodTypeInfo(goodName, state.GenerateInverseState());
		}

		public override string ToString()
		{
			return state.ToString() + "_" + goodName;
		}

		public string ToInvString()
		{
			return state.ToInvString() + "_" + goodName;
		}
	}
	public class ModifyGoodTypeStatesTracker
	{
		[JsonProperty]
		private Dictionary<string, ModifyGoodTypeInfo> duplicateTracker = new Dictionary<string, ModifyGoodTypeInfo>();

		public ModifyGoodTypeInfo GetExistingInfo(ModifyGoodTypeInfo info)
		{
			ModifyGoodTypeInfo value = null;
			string key = info.ToString();
			if (!duplicateTracker.TryGetValue(key, out value))
			{
				value = info;
				duplicateTracker[key] = value;
			}
			return value;
		}

		public ModifyGoodTypeInfo GetExistingInvInfo(ModifyGoodTypeInfo info)
		{
			ModifyGoodTypeInfo value = null;
			string key = info.ToInvString();
			if (!duplicateTracker.TryGetValue(key, out value))
			{
				value = info;
				duplicateTracker[key] = value.GenerateInverseInfo();
			}
			return value;
		}

		public void AddState(ModifyGoodTypeInfo stateInfo)
		{
			ModifyGoodTypeInfo existingInfo = GetExistingInfo(stateInfo);
			ModifyGoodTypeInfo existingInvInfo = GetExistingInvInfo(stateInfo);
			if (existingInfo.duplicateTimes == existingInvInfo.duplicateTimes)
			{
				FLog.Info($"Apply state {stateInfo}");
				existingInfo.ApplyState();
			}
			existingInfo.duplicateTimes++;
		}

		public void RemoveState(ModifyGoodTypeInfo stateInfo)
		{
			ModifyGoodTypeInfo existingInfo = GetExistingInfo(stateInfo);
			ModifyGoodTypeInfo existingInvInfo = GetExistingInvInfo(stateInfo);
			if (existingInfo.duplicateTimes == existingInvInfo.duplicateTimes)
			{
				FLog.Info($"Remove state {stateInfo}");
				existingInfo.RemoveState();
			}
			existingInfo.duplicateTimes--;
		}

		public void RemoveAllState()
		{
			FLog.Info("remove all dynamic good states");
			foreach (ModifyGoodTypeInfo value in duplicateTracker.Values)
			{
				ModifyGoodTypeInfo modifyGoodTypeInfo = duplicateTracker[value.ToInvString()];
				if (value.duplicateTimes > modifyGoodTypeInfo.duplicateTimes)
				{
					value.RemoveState();
				}
			}
			duplicateTracker.Clear();
		}

		public void RestoreState()
		{
			try
			{
				FLog.Info($"restore dynamic good states, total states type: {duplicateTracker.Count}");
				foreach (ModifyGoodTypeInfo value in duplicateTracker.Values)
				{
					ModifyGoodTypeInfo modifyGoodTypeInfo = duplicateTracker[value.ToInvString()];
					if (value.duplicateTimes > modifyGoodTypeInfo.duplicateTimes)
					{
						value.ApplyState();
					}
				}
				FLog.Info("finish restore dynamic good states");
			}
			catch (Exception obj)
			{
				FLog.Error(obj);
				FLog.Error("Failed to restore :(");
			}
		}
	}
	public class DynamicGoodTypeService : GameService, IDynamicGoodTypeService, IService
	{
		[ModSerializedField(SaveLoadType.Unknown, "")]
		protected ModifyGoodTypeStatesTracker modifyGoodState = new ModifyGoodTypeStatesTracker();

		private MethodInfo cacheMethod;

		public ModifyGoodTypeStatesTracker GetStateTracker => modifyGoodState;

		static DynamicGoodTypeService()
		{
			CustomServiceManager.RegGameService<DynamicGoodTypeService>();
		}

		private void RecomputeCache()
		{
			cacheMethod.Invoke(Serviceable.GoodsService, null);
		}

		public override UniTask OnLoading()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			FLog.Info("Load Dynamic Good State!");
			modifyGoodState.RestoreState();
			cacheMethod = AccessTools.Method(((object)Serviceable.GoodsService).GetType(), "Cache", (Type[])null, (Type[])null);
			FLog.AssertNotNull(cacheMethod);
			RecomputeCache();
			return UniTask.CompletedTask;
		}

		public override void OnDestroy()
		{
			modifyGoodState.RemoveAllState();
			((Service)this).OnDestroy();
		}

		public override IService[] GetDependencies()
		{
			return (IService[])(object)new IService[2]
			{
				(IService)Serviceable.GoodsService,
				CustomServiceManager.GetAsIService<IExtraStateService>()
			};
		}

		public void GoodSetEatable(string goodName, bool state)
		{
			FLog.Info($"Set Ediable {goodName} {state}");
			modifyGoodState.AddState(new ModifyGoodTypeInfo(goodName, ModifyGoodTypeState.GenSetEdiable(state)));
			RecomputeCache();
		}

		public void GoodAddTag(string goodName, string tagName)
		{
			FLog.Info("Add Tag " + goodName + " " + tagName);
			modifyGoodState.AddState(new ModifyGoodTypeInfo(goodName, ModifyGoodTypeState.GenAddTag(tagName)));
			RecomputeCache();
		}

		public void GoodRemoveTag(string goodName, string tagName)
		{
			FLog.Info("Remove Tag " + goodName + " " + tagName);
			modifyGoodState.AddState(new ModifyGoodTypeInfo(goodName, ModifyGoodTypeState.GenRemoveTag(tagName)));
			RecomputeCache();
		}
	}
	internal class DynamicHearthState
	{
		[JsonIgnore]
		public HubTier[] originalHubTiers = null;

		public float hubPopRequirePercent = 1f;

		public int hubPopRequireCount = 0;

		public void InitGame()
		{
			originalHubTiers = MB.Settings.hubsTiers.DeepClone<HubTier>();
		}

		public void ApplyStates()
		{
			HubTier[] hubsTiers = MB.Settings.hubsTiers;
			for (int i = 0; i < hubsTiers.Length; i++)
			{
				hubsTiers[i].minPopulation = (int)Mathf.Max((float)originalHubTiers[i].minPopulation * hubPopRequirePercent + (float)hubPopRequireCount, 0f);
			}
			IEnumerable<Hearth> enumerable = LinqExtensions.FilterCast<Hearth>((IEnumerable)Serviceable.BuildingsService.Buildings.Values);
			foreach (Hearth item in enumerable)
			{
				((Building)item).SlowUpdate();
			}
		}

		public void DestoryRestore()
		{
			HubTier[] hubsTiers = MB.Settings.hubsTiers;
			for (int i = 0; i < hubsTiers.Length; i++)
			{
				hubsTiers[i].minPopulation = originalHubTiers[i].minPopulation;
			}
		}
	}
	public class DynamicHearthService : GameService, IDynamicHearthService, IService
	{
		[ModSerializedField(SaveLoadType.Unknown, "")]
		private DynamicHearthState state = new DynamicHearthState();

		static DynamicHearthService()
		{
			CustomServiceManager.RegGameService<DynamicHearthService>();
		}

		public override IService[] GetDependencies()
		{
			return (IService[])(object)new IService[2]
			{
				(IService)Serviceable.HearthService,
				CustomServiceManager.GetAsIService<IExtraStateService>()
			};
		}

		public override void OnDestroy()
		{
			state.DestoryRestore();
			((Service)this).OnDestroy();
		}

		public override UniTask OnLoading()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			state.InitGame();
			state.ApplyStates();
			return UniTask.CompletedTask;
		}

		public void AddHearthRequirePopPercent(float v)
		{
			state.hubPopRequirePercent += v;
			state.ApplyStates();
		}

		public void AddHearthRequirePopCount(int v)
		{
			state.hubPopRequireCount += v;
			state.ApplyStates();
		}
	}
	public class ExtraStateService : GameService, IExtraStateService, IService
	{
		private class SaveInformation
		{
			[JsonProperty]
			public object obj;

			public Type type;

			public string name;

			public SaveInformation(object obj, Type type, string name)
			{
				this.obj = obj;
				this.type = type;
				this.name = name;
			}

			public void TryRecover()
			{
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				if (obj != null)
				{
					FLog.AssertType<JObject>(obj);
					obj = ((JToken)(JObject)obj).ToObject(type);
				}
			}
		}

		private class SaveInformations
		{
			public string versionName = "";

			public Dictionary<string, SaveInformation> extraStates = new Dictionary<string, SaveInformation>();

			public void OnSave()
			{
				versionName = Assembly.GetExecutingAssembly().GetName().Version.ToString();
			}

			public void OnDestory()
			{
				extraStates.Clear();
				versionName = "";
			}

			public static SaveInformations CreateNew()
			{
				return new SaveInformations();
			}
		}

		private class TrackedField
		{
			public string saveName;

			public object owner;

			public FieldInfo field;

			public TrackedField(string saveName, object owner, FieldInfo field)
			{
				this.saveName = saveName;
				this.owner = owner;
				this.field = field;
			}

			public void ApplyValue(object obj)
			{
				field.SetValue(owner, obj);
			}

			public object GetValue()
			{
				return field.GetValue(owner);
			}
		}

		[CompilerGenerated]
		private sealed class <LoadAllStates>d__13 : IAsyncStateMachine
		{
			public int <>1__state;

			public AsyncUniTaskMethodBuilder <>t__builder;

			public ExtraStateService <>4__this;

			private string <fullFilePath>5__1;

			private SaveInformations <>s__2;

			private Exception <e>5__3;

			private Dictionary<string, SaveInformation>.ValueCollection.Enumerator <>s__4;

			private SaveInformation <saveInfo>5__5;

			private Exception <e>5__6;

			private List<TrackedField>.Enumerator <>s__7;

			private TrackedField <trackedField>5__8;

			private Exception <e>5__9;

			private Awaiter<SaveInformations> <>u__1;

			private void MoveNext()
			{
				//IL_010c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0111: Unknown result type (might be due to invalid IL or missing references)
				//IL_0118: Unknown result type (might be due to invalid IL or missing references)
				//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
				int num = <>1__state;
				try
				{
					if (num == 0)
					{
						goto IL_00a5;
					}
					if (MB.GameSaveService.IsNewGame())
					{
						FLog.Info("ExtraStateService: New Game, do not load!");
						<>4__this.saveInformations = SaveInformations.CreateNew();
					}
					else
					{
						<fullFilePath>5__1 = Path.Combine(Serviceable.ProfilesService.GetProfileFolderPath(), SAVE_PATH);
						if (File.Exists(<fullFilePath>5__1))
						{
							goto IL_00a5;
						}
						FLog.Error("The Save not exists : " + <fullFilePath>5__1);
						FLog.Warning("We generate a new one instead");
						<>4__this.saveInformations = SaveInformations.CreateNew();
					}
					goto end_IL_0007;
					IL_00a5:
					try
					{
						Awaiter<SaveInformations> awaiter;
						if (num != 0)
						{
							awaiter = Serviceable.SavesIOService.Get<SaveInformations>(Path.Combine(Serviceable.ProfilesService.GetProfileFolderPath(), SAVE_PATH), "MOD_FORWINDZ_SAVE_GAME").GetAwaiter();
							if (!awaiter.IsCompleted)
							{
								num = (<>1__state = 0);
								<>u__1 = awaiter;
								<LoadAllStates>d__13 <LoadAllStates>d__ = this;
								((AsyncUniTaskMethodBuilder)(ref <>t__builder)).AwaitUnsafeOnCompleted<Awaiter<SaveInformations>, <LoadAllStates>d__13>(ref awaiter, ref <LoadAllStates>d__);
								return;
							}
						}
						else
						{
							awaiter = <>u__1;
							<>u__1 = default(Awaiter<SaveInformations>);
							num = (<>1__state = -1);
						}
						<>s__2 = awaiter.GetResult();
						<>4__this.saveInformations = <>s__2;
						<>s__2 = null;
					}
					catch (Exception ex)
					{
						<e>5__3 = ex;
						Log.Error((object)"Failed to load extra state", (Object)null);
						Log.Error((object)<e>5__3, (Object)null);
						Log.Warning((object)"We create a new one instead!", (Object)null);
						<>4__this.saveInformations = SaveInformations.CreateNew();
						goto end_IL_0007;
					}
					<>s__4 = <>4__this.saveInformations.extraStates.Values.GetEnumerator();
					try
					{
						while (<>s__4.MoveNext())
						{
							<saveInfo>5__5 = <>s__4.Current;
							try
							{
								<saveInfo>5__5.TryRecover();
							}
							catch (Exception ex)
							{
								<e>5__6 = ex;
								Log.Error((object)("Failed to load extra state " + <saveInfo>5__5.name), (Object)null);
								Log.Error((object)<e>5__6, (Object)null);
							}
							<saveInfo>5__5 = null;
						}
					}
					finally
					{
						if (num < 0)
						{
							((IDisposable)<>s__4).Dispose();
						}
					}
					<>s__4 = default(Dictionary<string, SaveInformation>.ValueCollection.Enumerator);
					<>s__7 = <>4__this.trackFieldList.GetEnumerator();
					try
					{
						while (<>s__7.MoveNext())
						{
							<trackedField>5__8 = <>s__7.Current;
							try
							{
								<trackedField>5__8.ApplyValue(<>4__this.saveInformations.extraStates[<trackedField>5__8.saveName].obj);
							}
							catch (Exception ex)
							{
								<e>5__9 = ex;
								Log.Error((object)("Failed to load & apply extra state " + <trackedField>5__8.saveName + " to field"), (Object)null);
								Log.Error((object)<e>5__9, (Object)null);
							}
							<trackedField>5__8 = null;
						}
					}
					finally
					{
						if (num < 0)
						{
							((IDisposable)<>s__7).Dispose();
						}
					}
					<>s__7 = default(List<TrackedField>.Enumerator);
					end_IL_0007:;
				}
				catch (Exception ex)
				{
					<>1__state = -2;
					<fullFilePath>5__1 = null;
					((AsyncUniTaskMethodBuilder)(ref <>t__builder)).SetException(ex);
					return;
				}
				<>1__state = -2;
				<fullFilePath>5__1 = null;
				((AsyncUniTaskMethodBuilder)(ref <>t__builder)).SetResult();
			}

			void IAsyncStateMachine.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				this.MoveNext();
			}

			[DebuggerHidden]
			private void SetStateMachine(IAsyncStateMachine stateMachine)
			{
			}

			void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
			{
				//ILSpy generated this explicit interface implementation from .override directive in SetStateMachine
				this.SetStateMachine(stateMachine);
			}
		}

		[CompilerGenerated]
		private sealed class <OnLoading>d__10 : IAsyncStateMachine
		{
			public int <>1__state;

			public AsyncUniTaskMethodBuilder <>t__builder;

			public ExtraStateService <>4__this;

			private Awaiter <>u__1;

			private void MoveNext()
			{
				//IL_0068: Unknown result type (might be due to invalid IL or missing references)
				//IL_006d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0074: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0031: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: Unknown result type (might be due to invalid IL or missing references)
				//IL_004d: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Unknown result type (might be due to invalid IL or missing references)
				int num = <>1__state;
				try
				{
					Awaiter awaiter;
					if (num != 0)
					{
						FLog.Info("Load Extra States!");
						<>4__this.ScanAttributes();
						UniTask val = <>4__this.LoadAllStates();
						awaiter = ((UniTask)(ref val)).GetAwaiter();
						if (!((Awaiter)(ref awaiter)).IsCompleted)
						{
							num = (<>1__state = 0);
							<>u__1 = awaiter;
							<OnLoading>d__10 <OnLoading>d__ = this;
							((AsyncUniTaskMethodBuilder)(ref <>t__builder)).AwaitUnsafeOnCompleted<Awaiter, <OnLoading>d__10>(ref awaiter, ref <OnLoading>d__);
							return;
						}
					}
					else
					{
						awaiter = <>u__1;
						<>u__1 = default(Awaiter);
						num = (<>1__state = -1);
					}
					((Awaiter)(ref awaiter)).GetResult();
				}
				catch (Exception exception)
				{
					<>1__state = -2;
					((AsyncUniTaskMethodBuilder)(ref <>t__builder)).SetException(exception);
					return;
				}
				<>1__state = -2;
				((AsyncUniTaskMethodBuilder)(ref <>t__builder)).SetResult();
			}

			void IAsyncStateMachine.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				this.MoveNext();
			}

			[DebuggerHidden]
			private void SetStateMachine(IAsyncStateMachine stateMachine)
			{
			}

			void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
			{
				//ILSpy generated this explicit interface implementation from .override directive in SetStateMachine
				this.SetStateMachine(stateMachine);
			}
		}

		public static string SAVE_PATH;

		public const string SAVE_KEY_INFO = "MOD_FORWINDZ_SAVE_GAME";

		private SaveInformations saveInformations;

		private List<TrackedField> trackFieldList = new List<TrackedField>();

		static ExtraStateService()
		{
			SAVE_PATH = "f9_mod\\ModGameSave.save";
			CustomServiceManager.RegGameService<ExtraStateService>();
			PatchesManager.RegPatch(typeof(ExtraStateService));
		}

		public override IService[] GetDependencies()
		{
			return (IService[])(object)new IService[3]
			{
				(IService)Serviceable.StateService,
				(IService)Serviceable.GameSaveService,
				(IService)Serviceable.SavesIOService
			};
		}

		[AsyncStateMachine(typeof(<OnLoading>d__10))]
		[DebuggerStepThrough]
		public override UniTask OnLoading()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			<OnLoading>d__10 <OnLoading>d__ = new <OnLoading>d__10();
			<OnLoading>d__.<>t__builder = AsyncUniTaskMethodBuilder.Create();
			<OnLoading>d__.<>4__this = this;
			<OnLoading>d__.<>1__state = -1;
			((AsyncUniTaskMethodBuilder)(ref <OnLoading>d__.<>t__builder)).Start<<OnLoading>d__10>(ref <OnLoading>d__);
			return ((AsyncUniTaskMethodBuilder)(ref <OnLoading>d__.<>t__builder)).Task;
		}

		public override void OnDestroy()
		{
			trackFieldList.Clear();
			saveInformations.OnDestory();
			((Service)this).OnDestroy();
		}

		private void ScanAttributes()
		{
			IReadOnlyList<IService> gameServicesList = CustomServiceManager.GameServicesList;
			foreach (IService item in gameServicesList)
			{
				FieldInfo[] fields = ((object)item).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				FieldInfo[] array = fields;
				foreach (FieldInfo fieldInfo in array)
				{
					ModSerializedFieldAttribute customAttribute = fieldInfo.GetCustomAttribute<ModSerializedFieldAttribute>();
					if (customAttribute != null && (customAttribute.SLType == SaveLoadType.Game || customAttribute.SLType == SaveLoadType.Unknown))
					{
						object value = fieldInfo.GetValue(item);
						string text = customAttribute.SaveName;
						if (text == null || text.Length == 0)
						{
							string input = ((object)item).GetType().FullName + "#" + fieldInfo.FieldType.FullName + "#" + fieldInfo.Name;
							text = ((object)item).GetType().Name + "." + fieldInfo.Name + "_" + Forwindz.Framework.Utils.Utils.GetMd5Hash(input);
						}
						trackFieldList.Add(new TrackedField(text, item, fieldInfo));
					}
				}
			}
		}

		[AsyncStateMachine(typeof(<LoadAllStates>d__13))]
		[DebuggerStepThrough]
		public UniTask LoadAllStates()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			<LoadAllStates>d__13 <LoadAllStates>d__ = new <LoadAllStates>d__13();
			<LoadAllStates>d__.<>t__builder = AsyncUniTaskMethodBuilder.Create();
			<LoadAllStates>d__.<>4__this = this;
			<LoadAllStates>d__.<>1__state = -1;
			((AsyncUniTaskMethodBuilder)(ref <LoadAllStates>d__.<>t__builder)).Start<<LoadAllStates>d__13>(ref <LoadAllStates>d__);
			return ((AsyncUniTaskMethodBuilder)(ref <LoadAllStates>d__.<>t__builder)).Task;
		}

		public void SaveAllStates()
		{
			FLog.Info("Try to save extra states");
			saveInformations.OnSave();
			foreach (TrackedField trackField in trackFieldList)
			{
				saveInformations.extraStates[trackField.saveName] = new SaveInformation(trackField.GetValue(), trackField.field.FieldType, trackField.saveName);
			}
			Serviceable.SavesIOService.SaveToFile((object)saveInformations, SAVE_PATH, (SaveLocation)1);
			FLog.Info("Saved extra states!");
		}

		public T GetStateSafe<T>(string name)
		{
			if (saveInformations.extraStates.TryGetValue(name, out var value))
			{
				if (value.obj is T result)
				{
					return result;
				}
				FLog.Warning("SafeGetState: Unable to convert " + value.obj.GetType().Name + " " + name + " to " + typeof(T).Name);
			}
			else
			{
				FLog.Warning("SafeGetState: Unable to find " + name + ", type <" + typeof(T).Name + ">");
			}
			return default(T);
		}

		public T GetState<T>(string name)
		{
			return (T)saveInformations.extraStates[name].obj;
		}

		[HarmonyPatch(typeof(GameSaveService), "SaveState")]
		[HarmonyPostfix]
		private static void GameSaveService_SaveState_PostPatch(GameService __instance, ref UniTask __result)
		{
			IExtraStateService service = CustomServiceManager.GetService<IExtraStateService>();
			service.SaveAllStates();
		}

		[HarmonyPatch(typeof(GameSaveService), "ForceSaveState")]
		[HarmonyPostfix]
		private static void GameSaveService_ForceSaveState_PostPatch(GameService __instance)
		{
			IExtraStateService service = CustomServiceManager.GetService<IExtraStateService>();
			service.SaveAllStates();
		}
	}
	public interface IDynamicBuildingStateService
	{
		void AddDecorationPercent(string decorationName, float percent);

		void AddAllDecorationPercent(float percent);

		float GetDecorationPercent(string decorationName);

		int GetDecorationAmount(DecorationTier tier);
	}
	public interface IDynamicGoodTypeService
	{
		ModifyGoodTypeStatesTracker GetStateTracker { get; }

		void GoodRemoveTag(string goodName, string tagName);

		void GoodAddTag(string goodName, string tagName);

		void GoodSetEatable(string goodName, bool state);
	}
	public interface IDynamicHearthService
	{
		void AddHearthRequirePopPercent(float v);

		void AddHearthRequirePopCount(int v);
	}
	public interface IDynamicTraderInfoService
	{
		DynamicTraderInfoData DynamicTraderState { get; }

		TraderModel GetForceTrader();

		void AddForceTrader(string name);

		void RemoveForceTrader(string name);

		void RemoveAssaultTrader(string name);

		void ResetNextTrader();

		void SetEffectFreeChance(string traderName, float chance);

		void AddEffectFreeChance(string traderName, float chance);
	}
	public interface IExtraStateService
	{
		T GetState<T>(string name);

		T GetStateSafe<T>(string name);

		void SaveAllStates();

		UniTask LoadAllStates();
	}
	public enum SaveLoadType
	{
		Game,
		App,
		Meta,
		World,
		Unknown
	}
	[AttributeUsage(AttributeTargets.Field)]
	public class ModSerializedFieldAttribute : Attribute
	{
		public SaveLoadType SLType { get; }

		public string SaveName { get; }

		public ModSerializedFieldAttribute(SaveLoadType type = SaveLoadType.Unknown, string saveName = "")
		{
			SLType = type;
			SaveName = saveName;
		}
	}
}
namespace Forwindz.Framework.Hooks
{
	public class CustomHookedEffectsController
	{
		private static CustomHookedEffectsController instance;

		private Dictionary<HookLogicType, IHookMonitor> typeMonitorMapping = new Dictionary<HookLogicType, IHookMonitor>();

		public static CustomHookedEffectsController Instance => instance;

		static CustomHookedEffectsController()
		{
			instance = new CustomHookedEffectsController();
			PatchesManager.RegPatch<CustomHookedEffectsController>();
		}

		public static T Register<T>(HookLogicType hookLogicType) where T : IHookMonitor, new()
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			T val = new T();
			Register(hookLogicType, (IHookMonitor)(object)val);
			return val;
		}

		public static void Register(HookLogicType hookLogicType, IHookMonitor monitor)
		{
			//IL_000d: 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_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<HookLogicType, IHookMonitor> dictionary = Instance.typeMonitorMapping;
			if (dictionary.ContainsKey(hookLogicType))
			{
				FLog.Error($"Already Registered HookLogicType {hookLogicType}! This will overwrite the previous reg!");
			}
			dictionary[hookLogicType] = monitor;
			FLog.Info($"Reg enum {hookLogicType} = {((object)monitor).GetType().Name}");
		}

		[HarmonyPatch(typeof(HookedEffectsController), "OnDestroy")]
		[HarmonyPostfix]
		private static void HookedEffectsController_OnDestroy_PostPatch(HookedEffectsController __instance)
		{
			Dictionary<HookLogicType, IHookMonitor> dictionary = Instance.typeMonitorMapping;
			foreach (IHookMonitor value in dictionary.Values)
			{
				value.Dispose();
			}
		}

		[HarmonyPatch(typeof(HookedEffectsController), "GetMonitorFor")]
		[HarmonyPrefix]
		private static bool HookedEffectsController_GetMonitorFor_PrePatch(HookLogicType type, ref IHookMonitor __result)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<HookLogicType, IHookMonitor> dictionary = Instance.typeMonitorMapping;
			if (dictionary.TryGetValue(type, out var value))
			{
				__result = value;
				return false;
			}
			return true;
		}
	}
	public class BuildingCompletedHook : HookLogic
	{
		[NewCustomEnum(null, null)]
		public static readonly HookLogicType EnumBuildingComplete;

		[Min(0f)]
		public int amount = 1;

		public bool ignoreDecorationBuildings = true;

		public bool ignoreRoads = true;

		public override HookLogicType Type => EnumBuildingComplete;

		static BuildingCompletedHook()
		{
			CustomIntEnumManager<HookLogicType>.ScanAndAssignEnumValues<BuildingCompletedHook>();
		}

		public override bool CanBeDrawn()
		{
			return true;
		}

		public override string GetAmountText()
		{
			return amount.ToString();
		}

		public override int GetIntAmount()
		{
			return amount;
		}

		public override bool HasImpactOn(BuildingModel building)
		{
			return false;
		}
	}
	public class BuildingCompletedMonitor : HookMonitor<BuildingCompletedHook, BuildingCompletedTracker>
	{
		static BuildingCompletedMonitor()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			CustomHookedEffectsController.Register<BuildingCompletedMonitor>(BuildingCompletedHook.EnumBuildingComplete);
		}

		public override void AddHandle(BuildingCompletedTracker tracker)
		{
			((HookTracker<BuildingCompletedHook>)tracker).handle.Add(ObservableExtensions.Subscribe<Building>(CustomServiceManager.GetService<BuildingMonitorService>().OnBuildingConstructionFinished, (Action<Building>)tracker.Update));
		}

		public override BuildingCompletedTracker CreateTracker(HookState state, BuildingCompletedHook model, HookedEffectModel effectModel, HookedEffectState effectState)
		{
			return new BuildingCompletedTracker(state, model, effectModel, effectState);
		}

		public override void InitValue(BuildingCompletedTracker tracker)
		{
			tracker.SetAmount(((HookMonitor<BuildingCompletedHook, BuildingCompletedTracker>)this).GetInitValueFor(((HookTracker<BuildingCompletedHook>)tracker).model));
		}

		public override int GetInitValueFor(BuildingCompletedHook model)
		{
			BuildingMonitorService service = CustomServiceManager.GetService<BuildingMonitorService>();
			int num = service.state.buildingsCompleted;
			if (model.ignoreDecorationBuildings)
			{
				num -= service.state.decorationBuildingsCompleted;
			}
			if (model.ignoreRoads)
			{
				num -= service.state.roadsCompleted;
			}
			return num;
		}

		public override int GetInitProgressFor(BuildingCompletedHook model)
		{
			return ((HookMonitor<BuildingCompletedHook, BuildingCompletedTracker>)this).GetInitValueFor(model) % model.amount;
		}

		public override int GetFiredAmountPreviewFor(BuildingCompletedHook model)
		{
			return ((HookMonitor<BuildingCompletedHook, BuildingCompletedTracker>)this).GetInitValueFor(model) / model.amount;
		}
	}
	public class BuildingCompletedTracker : HookTracker<BuildingCompletedHook>
	{
		public BuildingCompletedTracker(HookState hookState, BuildingCompletedHook model, HookedEffectModel effectModel, HookedEffectState effectState)
			: base(hookState, model, effectModel, effectState)
		{
		}

		public void Update(Building building)
		{
			string name = ((Object)building.BuildingModel.category).name;
			Debug.Log((object)("Building has category " + name));
			if ((!base.model.ignoreDecorationBuildings || !BuildingHelper.IsDecorationBuilding(building)) && (!base.model.ignoreRoads || !BuildingHelper.IsRoad(building)))
			{
				Update(1);
			}
		}

		public void SetAmount(int amount)
		{
			Update(amount - base.hookState.totalAmount);
		}

		private void Update(int amount)
		{
			HookState hookState = base.hookState;
			hookState.totalAmount += amount;
			HookState hookState2 = base.hookState;
			hookState2.currentAmount += amount;
			while (base.hookState.currentAmount >= base.model.amount)
			{
				base.Fire();
				HookState hookState3 = base.hookState;
				hookState3.currentAmount -= base.model.amount;
			}
		}
	}
	public class DecorationHook : HookLogic
	{
		[NewCustomEnum(null, null)]
		public static readonly HookLogicType EnumDecorationPoints;

		public DecorationTier decorationTier;

		public int amount;

		public override HookLogicType Type => EnumDecorationPoints;

		public override string FormatedDescription => ((Serviceable)this).TryFormat(base.description.Text, (object)((LabelModel)decorationTier).displayName.Text, (object)amount);

		public override string GetDescriptionInfo => "{0} - decoration tier, {1} - value";

		static DecorationHook()
		{
			CustomIntEnumManager<HookLogicType>.ScanAndAssignEnumValues<DecorationHook>();
		}

		public override string GetAmountText()
		{
			return amount.ToString();
		}

		public override int GetIntAmount()
		{
			return amount;
		}

		public override bool HasImpactOn(BuildingModel building)
		{
			return false;
		}
	}
	public class DecorationMonitor : HookMonitor<DecorationHook, DecorationTracker>
	{
		static DecorationMonitor()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			CustomHookedEffectsController.Register<DecorationMonitor>(DecorationHook.EnumDecorationPoints);
		}

		public override void AddHandle(DecorationTracker tracker)
		{
			BuildingMonitorService service = CustomServiceManager.GetService<BuildingMonitorService>();
			((HookTracker<DecorationHook>)tracker).handle.Add(ObservableExtensions.Subscribe<Building>(service.OnBuildingConstructionFinished, (Action<Building>)tracker.OnAddBuilding));
			((HookTracker<DecorationHook>)tracker).handle.Add(ObservableExtensions.Subscribe<Building>(service.OnBuildingRemovedFinished, (Action<Building>)tracker.OnRemoveBuilding));
			DynamicBuildingStateService service2 = CustomServiceManager.GetService<DynamicBuildingStateService>();
			((HookTracker<DecorationHook>)tracker).handle.Add(ObservableExtensions.Subscribe<Dictionary<string, DynamicDecorationStateInfo>>(service2.OnDecorationValueChange, (Action<Dictionary<string, DynamicDecorationStateInfo>>)delegate
			{
				tracker.Recalculate();
			}));
		}

		public override DecorationTracker CreateTracker(HookState state, DecorationHook model, HookedEffectModel effectModel, HookedEffectState effectState)
		{
			return new DecorationTracker(state, model, effectModel, effectState);
		}

		public override void InitValue(DecorationTracker tracker)
		{
			tracker.Recalculate();
		}

		public override int GetInitValueFor(DecorationHook model)
		{
			return BuildingHelper.CountDecorationValue(model.decorationTier);
		}

		public override int GetInitProgressFor(DecorationHook model)
		{
			return ((HookMonitor<DecorationHook, DecorationTracker>)this).GetInitValueFor(model) % model.amount;
		}

		public override int GetFiredAmountPreviewFor(DecorationHook model)
		{
			return ((HookMonitor<DecorationHook, DecorationTracker>)this).GetInitValueFor(model) / model.amount;
		}
	}
	public class DecorationTracker : HookTracker<DecorationHook>
	{
		public DecorationTracker(HookState hookState, DecorationHook model, HookedEffectModel effectModel, HookedEffectState effectState)
			: base(hookState, model, effectModel, effectState)
		{
			Recalculate();
		}

		public void OnAddBuilding(Building building)
		{
			Decoration val = (Decoration)(object)((building is Decoration) ? building : null);
			if (!((Object)(object)val == (Object)null) && val.model.hasDecorationTier && (Object)(object)val.model.tier == (Object)(object)base.model.decorationTier)
			{
				Recalculate();
			}
		}

		public void OnRemoveBuilding(Building building)
		{
			Decoration val = (Decoration)(object)((building is Decoration) ? building : null);
			if (!((Object)(object)val == (Object)null) && val.model.hasDecorationTier && (Object)(object)val.model.tier == (Object)(object)base.model.decorationTier)
			{
				Recalculate();
			}
		}

		public void Recalculate()
		{
			int num = BuildingHelper.CountDecorationValue(base.model.decorationTier);
			FLog.Info($"Decoration Tracker: {((Object)base.model.decorationTier).name} > CurNum={base.hookState.totalAmount} > {base.hookState.currentAmount} | UpdateToNum={num} | curFireCount={base.hookState.firedAmount}");
			UpdateTo(num);
		}

		private void UpdateTo(int amount)
		{
			Update(amount - base.hookState.totalAmount);
		}

		private void Update(int amount)
		{
			HookState hookState = base.hookState;
			hookState.totalAmount += amount;
			HookState hookState2 = base.hookState;
			hookState2.currentAmount += amount;
			while (base.hookState.currentAmount >= base.model.amount)
			{
				base.Fire();
				HookState hookState3 = base.hookState;
				hookState3.currentAmount -= base.model.amount;
			}
			while (base.hookState.currentAmount < 0)
			{
				base.Revert();
				HookState hookState4 = base.hookState;
				hookState4.currentAmount += base.model.amount;
			}
		}
	}
}
namespace Forwindz.Framework.Ef