Decompiled source of Stormwalker v0.8.0

Stormwalker.dll

Decompiled 2 months ago
using System;
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.Permissions;
using ATS_API;
using BepInEx;
using BepInEx.Configuration;
using Eremite;
using Eremite.Buildings;
using Eremite.Buildings.UI;
using Eremite.Buildings.UI.Trade;
using Eremite.Characters;
using Eremite.Characters.Villagers;
using Eremite.Controller;
using Eremite.Controller.Generator;
using Eremite.MapObjects;
using Eremite.Model;
using Eremite.Model.State;
using Eremite.Services;
using Eremite.Services.Monitors;
using Eremite.View;
using Eremite.View.Cameras;
using Eremite.View.HUD;
using Eremite.View.HUD.Construction;
using Eremite.View.HUD.Woodcutters;
using Eremite.View.Popups.GameMenu;
using Eremite.View.Popups.Recipes;
using Eremite.View.Utils;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Stormwalker;
using TMPro;
using UniRx;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("Stormwalker")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("An Against the Storm Tweakpack")]
[assembly: AssemblyFileVersion("0.8.0.0")]
[assembly: AssemblyInformationalVersion("0.8.0+2e49d70c427d417ebc7fe92b9c3459d6a53dda2a")]
[assembly: AssemblyProduct("Stormwalker")]
[assembly: AssemblyTitle("Stormwalker")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.8.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 ATS_API
{
	[HarmonyPatch]
	public static class Hotkeys
	{
		public class Hotkey
		{
			public string keyName;

			public string displayName;

			public List<string> codes;

			public Action<CallbackContext> onCallback;
		}

		[Serializable]
		private class SavedInputMap
		{
			public string modName;

			public string actionMap;

			public string bindings;
		}

		public static InputActionAsset MasterInputAsset;

		private static Dictionary<string, List<Hotkey>> pendingHotkeys = new Dictionary<string, List<Hotkey>>();

		private static Dictionary<string, InputActionMap> modNameToActionMaps = new Dictionary<string, InputActionMap>();

		private static Dictionary<string, Hotkey> modNameActionNameToAddedHotkey = new Dictionary<string, Hotkey>();

		private static HashSet<InputAction> activeActions = new HashSet<InputAction>();

		private static HashSet<string> activeActionMaps = new HashSet<string>();

		private static readonly Dictionary<KeyCode, string> KeyCodeToPathMap = new Dictionary<KeyCode, string>
		{
			{
				(KeyCode)32,
				"<Keyboard>/space"
			},
			{
				(KeyCode)306,
				"<Keyboard>/leftCtrl"
			},
			{
				(KeyCode)305,
				"<Keyboard>/rightCtrl"
			},
			{
				(KeyCode)304,
				"<Keyboard>/leftShift"
			},
			{
				(KeyCode)303,
				"<Keyboard>/rightShift"
			},
			{
				(KeyCode)97,
				"<Keyboard>/a"
			},
			{
				(KeyCode)98,
				"<Keyboard>/b"
			},
			{
				(KeyCode)99,
				"<Keyboard>/c"
			},
			{
				(KeyCode)100,
				"<Keyboard>/d"
			},
			{
				(KeyCode)101,
				"<Keyboard>/e"
			},
			{
				(KeyCode)102,
				"<Keyboard>/f"
			},
			{
				(KeyCode)103,
				"<Keyboard>/g"
			},
			{
				(KeyCode)104,
				"<Keyboard>/h"
			},
			{
				(KeyCode)105,
				"<Keyboard>/i"
			},
			{
				(KeyCode)106,
				"<Keyboard>/j"
			},
			{
				(KeyCode)107,
				"<Keyboard>/k"
			},
			{
				(KeyCode)108,
				"<Keyboard>/l"
			},
			{
				(KeyCode)109,
				"<Keyboard>/m"
			},
			{
				(KeyCode)110,
				"<Keyboard>/n"
			},
			{
				(KeyCode)111,
				"<Keyboard>/o"
			},
			{
				(KeyCode)112,
				"<Keyboard>/p"
			},
			{
				(KeyCode)113,
				"<Keyboard>/q"
			},
			{
				(KeyCode)114,
				"<Keyboard>/r"
			},
			{
				(KeyCode)115,
				"<Keyboard>/s"
			},
			{
				(KeyCode)116,
				"<Keyboard>/t"
			},
			{
				(KeyCode)117,
				"<Keyboard>/u"
			},
			{
				(KeyCode)118,
				"<Keyboard>/v"
			},
			{
				(KeyCode)119,
				"<Keyboard>/w"
			},
			{
				(KeyCode)120,
				"<Keyboard>/x"
			},
			{
				(KeyCode)121,
				"<Keyboard>/y"
			},
			{
				(KeyCode)122,
				"<Keyboard>/z"
			},
			{
				(KeyCode)27,
				"<Keyboard>/escape"
			},
			{
				(KeyCode)13,
				"<Keyboard>/enter"
			},
			{
				(KeyCode)8,
				"<Keyboard>/backspace"
			},
			{
				(KeyCode)9,
				"<Keyboard>/tab"
			},
			{
				(KeyCode)127,
				"<Keyboard>/delete"
			},
			{
				(KeyCode)273,
				"<Keyboard>/upArrow"
			},
			{
				(KeyCode)274,
				"<Keyboard>/downArrow"
			},
			{
				(KeyCode)276,
				"<Keyboard>/leftArrow"
			},
			{
				(KeyCode)275,
				"<Keyboard>/rightArrow"
			},
			{
				(KeyCode)308,
				"<Keyboard>/leftAlt"
			},
			{
				(KeyCode)307,
				"<Keyboard>/rightAlt"
			},
			{
				(KeyCode)277,
				"<Keyboard>/insert"
			},
			{
				(KeyCode)278,
				"<Keyboard>/home"
			},
			{
				(KeyCode)279,
				"<Keyboard>/end"
			},
			{
				(KeyCode)280,
				"<Keyboard>/pageUp"
			},
			{
				(KeyCode)281,
				"<Keyboard>/pageDown"
			},
			{
				(KeyCode)300,
				"<Keyboard>/numLock"
			},
			{
				(KeyCode)301,
				"<Keyboard>/capsLock"
			},
			{
				(KeyCode)302,
				"<Keyboard>/scrollLock"
			},
			{
				(KeyCode)282,
				"<Keyboard>/f1"
			},
			{
				(KeyCode)283,
				"<Keyboard>/f2"
			},
			{
				(KeyCode)284,
				"<Keyboard>/f3"
			},
			{
				(KeyCode)285,
				"<Keyboard>/f4"
			},
			{
				(KeyCode)286,
				"<Keyboard>/f5"
			},
			{
				(KeyCode)287,
				"<Keyboard>/f6"
			},
			{
				(KeyCode)288,
				"<Keyboard>/f7"
			},
			{
				(KeyCode)289,
				"<Keyboard>/f8"
			},
			{
				(KeyCode)290,
				"<Keyboard>/f9"
			},
			{
				(KeyCode)291,
				"<Keyboard>/f10"
			},
			{
				(KeyCode)292,
				"<Keyboard>/f11"
			},
			{
				(KeyCode)293,
				"<Keyboard>/f12"
			},
			{
				(KeyCode)19,
				"<Keyboard>/pause"
			},
			{
				(KeyCode)316,
				"<Keyboard>/printScreen"
			},
			{
				(KeyCode)256,
				"<Keyboard>/numpad0"
			},
			{
				(KeyCode)257,
				"<Keyboard>/numpad1"
			},
			{
				(KeyCode)258,
				"<Keyboard>/numpad2"
			},
			{
				(KeyCode)259,
				"<Keyboard>/numpad3"
			},
			{
				(KeyCode)260,
				"<Keyboard>/numpad4"
			},
			{
				(KeyCode)261,
				"<Keyboard>/numpad5"
			},
			{
				(KeyCode)262,
				"<Keyboard>/numpad6"
			},
			{
				(KeyCode)263,
				"<Keyboard>/numpad7"
			},
			{
				(KeyCode)264,
				"<Keyboard>/numpad8"
			},
			{
				(KeyCode)265,
				"<Keyboard>/numpad9"
			},
			{
				(KeyCode)271,
				"<Keyboard>/numpadEnter"
			},
			{
				(KeyCode)270,
				"<Keyboard>/numpadPlus"
			},
			{
				(KeyCode)269,
				"<Keyboard>/numpadMinus"
			},
			{
				(KeyCode)268,
				"<Keyboard>/numpadMultiply"
			},
			{
				(KeyCode)267,
				"<Keyboard>/numpadDivide"
			},
			{
				(KeyCode)266,
				"<Keyboard>/numpadPeriod"
			},
			{
				(KeyCode)272,
				"<Keyboard>/numpadEquals"
			},
			{
				(KeyCode)126,
				"<Keyboard>/backquote"
			},
			{
				(KeyCode)45,
				"<Keyboard>/minus"
			},
			{
				(KeyCode)61,
				"<Keyboard>/equals"
			},
			{
				(KeyCode)91,
				"<Keyboard>/leftBracket"
			},
			{
				(KeyCode)93,
				"<Keyboard>/rightBracket"
			},
			{
				(KeyCode)59,
				"<Keyboard>/semicolon"
			},
			{
				(KeyCode)39,
				"<Keyboard>/quote"
			},
			{
				(KeyCode)44,
				"<Keyboard>/comma"
			},
			{
				(KeyCode)46,
				"<Keyboard>/period"
			},
			{
				(KeyCode)47,
				"<Keyboard>/slash"
			},
			{
				(KeyCode)92,
				"<Keyboard>/backslash"
			},
			{
				(KeyCode)49,
				"<Keyboard>/1"
			},
			{
				(KeyCode)50,
				"<Keyboard>/2"
			},
			{
				(KeyCode)51,
				"<Keyboard>/3"
			},
			{
				(KeyCode)52,
				"<Keyboard>/4"
			},
			{
				(KeyCode)53,
				"<Keyboard>/5"
			},
			{
				(KeyCode)54,
				"<Keyboard>/6"
			},
			{
				(KeyCode)55,
				"<Keyboard>/7"
			},
			{
				(KeyCode)56,
				"<Keyboard>/8"
			},
			{
				(KeyCode)57,
				"<Keyboard>/9"
			},
			{
				(KeyCode)48,
				"<Keyboard>/0"
			}
		};

		private static string CustomBindingsPath => Path.Combine(Application.persistentDataPath, "API");

		public static void Update()
		{
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Expected O, but got Unknown
			if ((Object)(object)MasterInputAsset == (Object)null || pendingHotkeys.Count == 0)
			{
				return;
			}
			MasterInputAsset.Disable();
			foreach (KeyValuePair<string, List<Hotkey>> pendingHotkey in pendingHotkeys)
			{
				activeActionMaps.Add(pendingHotkey.Key);
				InputActionMap val = MasterInputAsset.FindActionMap(pendingHotkey.Key, false);
				if (val == null)
				{
					val = new InputActionMap(pendingHotkey.Key);
					InputActionSetupExtensions.AddActionMap(MasterInputAsset, val);
				}
				modNameToActionMaps[pendingHotkey.Key] = val;
				LogInfo($"Adding action map {pendingHotkey.Key} with {pendingHotkey.Value.Count} hotkeys.");
				foreach (Hotkey item in pendingHotkey.Value)
				{
					AddHotkey(pendingHotkey.Key, val, item);
				}
			}
			pendingHotkeys.Clear();
			MasterInputAsset.Enable();
		}

		public static void RegisterKey(string modName, Hotkey hotkey)
		{
			LogInfo("Registering key " + hotkey.keyName + " with code " + string.Join(",", hotkey.codes));
			if (!pendingHotkeys.TryGetValue(modName, out var value))
			{
				value = new List<Hotkey>();
				pendingHotkeys.Add(modName, value);
			}
			value.Add(hotkey);
		}

		public static void RegisterKey(string modName, string keyName, string displayName, List<KeyCode> codes, Action onPress = null, Action onRelease = null)
		{
			Action<CallbackContext> onCallback = null;
			if (onPress != null || onRelease != null)
			{
				onCallback = delegate(CallbackContext ctx)
				{
					if (((CallbackContext)(ref ctx)).performed)
					{
						onPress?.Invoke();
					}
					else if (((CallbackContext)(ref ctx)).canceled)
					{
						onRelease?.Invoke();
					}
				};
			}
			Hotkey hotkey = new Hotkey();
			hotkey.keyName = keyName;
			hotkey.displayName = displayName;
			hotkey.codes = KeyCodesToString(codes);
			hotkey.onCallback = onCallback;
			RegisterKey(modName, hotkey);
		}

		public static void RegisterKey(string modName, string keyName, string displayName, List<KeyCode> codes, Action<CallbackContext> callback = null)
		{
			Hotkey hotkey = new Hotkey();
			hotkey.keyName = keyName;
			hotkey.displayName = displayName;
			hotkey.codes = KeyCodesToString(codes);
			hotkey.onCallback = callback;
			RegisterKey(modName, hotkey);
		}

		private static void AddHotkey(string modName, InputActionMap actionMap, Hotkey hotkey)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01da: Unknown result type (might be due to invalid IL or missing references)
			LogInfo("Adding hotkey " + hotkey.keyName + " with code " + string.Join(",", hotkey.codes));
			List<string> codes = hotkey.codes;
			string keyName = hotkey.keyName;
			Action<CallbackContext> onCallback = hotkey.onCallback;
			string key = modName + "_" + keyName;
			modNameActionNameToAddedHotkey[key] = hotkey;
			InputAction val = ((IEnumerable<InputAction>)(object)actionMap.actions).FirstOrDefault((Func<InputAction, bool>)((InputAction a) => a.name == keyName));
			if (val == null)
			{
				CompositeSyntax val2;
				if (codes.Count == 1)
				{
					val = InputActionSetupExtensions.AddAction(actionMap, keyName, (InputActionType)0, codes[0] ?? "", (string)null, (string)null, (string)null, (string)null);
				}
				else if (codes.Count == 2)
				{
					val = InputActionSetupExtensions.AddAction(actionMap, keyName, (InputActionType)0, (string)null, (string)null, (string)null, (string)null, (string)null);
					val2 = InputActionSetupExtensions.AddCompositeBinding(val, "OneModifier", (string)null, (string)null);
					val2 = ((CompositeSyntax)(ref val2)).With("Modifier", codes[0] ?? "", (string)null, (string)null);
					((CompositeSyntax)(ref val2)).With("Binding", codes[1] ?? "", (string)null, (string)null);
				}
				else
				{
					if (codes.Count != 3)
					{
						LogError("More than 3 key codes are not supported.");
						return;
					}
					val = InputActionSetupExtensions.AddAction(actionMap, keyName, (InputActionType)0, (string)null, (string)null, (string)null, (string)null, (string)null);
					val2 = InputActionSetupExtensions.AddCompositeBinding(val, "TwoModifiers", (string)null, (string)null);
					val2 = ((CompositeSyntax)(ref val2)).With("Modifier1", codes[0] ?? "", (string)null, (string)null);
					val2 = ((CompositeSyntax)(ref val2)).With("Modifier2", codes[1] ?? "", (string)null, (string)null);
					((CompositeSyntax)(ref val2)).With("Binding", codes[2] ?? "", (string)null, (string)null);
				}
			}
			if (onCallback != null)
			{
				CallbackAction(val, keyName, onCallback);
			}
			activeActions.Add(val);
		}

		private static void CallbackAction(InputAction action, string keyName, Action<CallbackContext> callback)
		{
			action.performed += delegate(CallbackContext ctx)
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				LogInfo(keyName + " action performed!");
				callback(ctx);
			};
			action.canceled += delegate(CallbackContext ctx)
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				LogInfo(keyName + " action canceled!");
				callback(ctx);
			};
			action.started += delegate(CallbackContext ctx)
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				LogInfo(keyName + " action started!");
				callback(ctx);
			};
		}

		private static List<string> KeyCodesToString(List<KeyCode> codes)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			foreach (KeyCode code in codes)
			{
				KeyCode current = code;
				if (KeyCodeToPathMap.TryGetValue(current, out var value))
				{
					list.Add(value);
				}
				else
				{
					list.Add(((object)(KeyCode)(ref current)).ToString());
				}
			}
			return list;
		}

		public static bool IsActionActive(InputAction action)
		{
			return activeActions.Contains(action);
		}

		private static void LogError(string message)
		{
			Plugin.Error(message);
		}

		private static void LogInfo(string message)
		{
			Plugin.Log(message);
		}

		private static void LogWarning(string message)
		{
			Plugin.Warning(message);
		}

		[HarmonyPatch(typeof(KeyBindingsPanel), "OnEnable")]
		[HarmonyPrefix]
		public static void KeyBindingsPanel_Start_Postfix(KeyBindingsPanel __instance)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			ModdedKeyboardSlots[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<ModdedKeyboardSlots>(true);
			foreach (KeyValuePair<string, InputActionMap> pair in modNameToActionMaps)
			{
				if (!activeActionMaps.Contains(pair.Key))
				{
					continue;
				}
				InputActionMap val = MasterInputAsset.FindActionMap(pair.Key, false);
				if (val == null || val.actions.Count == 0)
				{
					LogInfo("Action map is null for modName " + pair.Key + ", skipping.");
					continue;
				}
				ModdedKeyboardSlots moddedKeyboardSlots = componentsInChildren.FirstOrDefault((ModdedKeyboardSlots a) => a.ModName == pair.Key);
				if ((Object)(object)moddedKeyboardSlots == (Object)null)
				{
					LogInfo("Slots are null for " + val.name + ", creating new slots.");
					Transform parent = ((Component)__instance.slots[0]).transform.parent;
					Transform val2 = Object.Instantiate<Transform>(parent, parent.parent);
					((Object)((Component)val2).gameObject).name = "Modded";
					moddedKeyboardSlots = ((Component)val2).gameObject.AddComponent<ModdedKeyboardSlots>();
					moddedKeyboardSlots.Initialize(pair.Key, val2);
					Transform val3 = val2.Find("Header");
					TMP_Text component = ((Component)val3).GetComponent<TMP_Text>();
					Object.Destroy((Object)(object)((Component)val3).GetComponent<LocalizationText>());
					Object.Destroy((Object)(object)((Component)val3).GetComponent<TextFontFeaturesHelper>());
					component.text = pair.Key;
					LogInfo($"Slots created for {pair.Key} with {val.actions.Count} actions.");
				}
				else
				{
					LogInfo("Slots are already set up.");
				}
			}
		}

		[HarmonyPatch(typeof(KeyBindingsPanel), "SetUpSlots")]
		[HarmonyPostfix]
		public static void KeyBindingsPanel_SetUpSlots_Postfix(KeyBindingsPanel __instance)
		{
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			LogInfo("Setting up slots.");
			ModdedKeyboardSlots[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<ModdedKeyboardSlots>(true);
			foreach (KeyValuePair<string, InputActionMap> pair in modNameToActionMaps)
			{
				InputActionMap val = MasterInputAsset.FindActionMap(pair.Key, false);
				if (val == null)
				{
					LogInfo("Action map is null for mod " + pair.Key + ", skipping.");
					continue;
				}
				ModdedKeyboardSlots moddedKeyboardSlots = componentsInChildren.FirstOrDefault((ModdedKeyboardSlots a) => a.ModName == pair.Key);
				if ((Object)(object)moddedKeyboardSlots == (Object)null)
				{
					LogInfo("Modded keyboard is null for " + pair.Key + ", returning.");
					continue;
				}
				LogInfo($"Setting up keyboard slots for {pair.Key} with {val.actions.Count} actions.");
				moddedKeyboardSlots.SetupKeyboardSlots(val, __instance);
			}
		}

		[HarmonyPatch(typeof(KeyBindingsPanel), "ResetCounter")]
		[HarmonyPostfix]
		private static void KeyBindingsPanel_ResetCounter(KeyBindingsPanel __instance)
		{
			LogInfo("Reset counter.");
			ModdedKeyboardSlots[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<ModdedKeyboardSlots>(true);
			if (componentsInChildren != null)
			{
				ModdedKeyboardSlots[] array = componentsInChildren;
				foreach (ModdedKeyboardSlots moddedKeyboardSlots in array)
				{
					moddedKeyboardSlots.ResetCounter();
				}
			}
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		[HarmonyPostfix]
		private static void HookMainControllerSetup(InputConfig __instance)
		{
			LogInfo("Setting up custom action map.");
			MasterInputAsset = __instance.asset;
		}

		[HarmonyPatch(typeof(KeyBindingsPanel), "EnableInput")]
		[HarmonyPostfix]
		private static void KeyBindingsPanel_EnableInput()
		{
			foreach (InputActionMap value in modNameToActionMaps.Values)
			{
				value.Enable();
			}
		}

		[HarmonyPatch(typeof(KeyBindingsPanel), "DisableInput")]
		[HarmonyPostfix]
		private static void KeyBindingsPanel_DisableInput()
		{
			foreach (InputActionMap value in modNameToActionMaps.Values)
			{
				value.Disable();
			}
		}

		[HarmonyPatch(typeof(InputService), "GetShortcutLabel")]
		[HarmonyPrefix]
		private static bool InputService_GetShortcutLabel(InputAction action, ref string __result)
		{
			string key = action.actionMap.name + "_" + action.name;
			if (modNameActionNameToAddedHotkey.TryGetValue(key, out var value))
			{
				__result = value.displayName;
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(ClientPrefsService), "Reset")]
		[HarmonyPrefix]
		private static void ClientPrefsService_Reset()
		{
			foreach (InputActionMap value in modNameToActionMaps.Values)
			{
				LogInfo("Resetting input config for " + value.name);
				InputActionRebindingExtensions.RemoveAllBindingOverrides((IInputActionCollection2)(object)value);
			}
		}

		[HarmonyPatch(typeof(ClientPrefsService), "SaveInputConfig")]
		[HarmonyPostfix]
		private static void ClientPrefsService_SaveInputConfig()
		{
			if (!Directory.Exists(CustomBindingsPath))
			{
				Directory.CreateDirectory(CustomBindingsPath);
			}
			foreach (KeyValuePair<string, InputActionMap> modNameToActionMap in modNameToActionMaps)
			{
				string text = InputActionRebindingExtensions.SaveBindingOverridesAsJson((IInputActionCollection2)(object)modNameToActionMap.Value);
				LogInfo("Saving input config for " + modNameToActionMap.Key + " with value " + text);
				SavedInputMap savedInputMap = new SavedInputMap
				{
					modName = modNameToActionMap.Key,
					actionMap = modNameToActionMap.Value.ToJson(),
					bindings = text
				};
				string text2 = Path.Combine(CustomBindingsPath, modNameToActionMap.Key + ".custombindings");
				LogInfo("Saving keybinds for " + modNameToActionMap.Key + " to " + text2);
				JsonIO.SaveToFile((object)savedInputMap, text2, 3);
			}
		}

		[HarmonyPatch(typeof(ClientPrefsService), "LoadInputConfig")]
		[HarmonyPostfix]
		private static void ClientPrefsService_LoadInputConfig()
		{
			//IL_01be: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_0228: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			if (Serviceable.CommandLineArgsService.HasKey("-resetkeybinds"))
			{
				LogError("Clearing keybinds!");
				return;
			}
			if (!Directory.Exists(CustomBindingsPath))
			{
				LogInfo("No custombindings folder found.");
				return;
			}
			string[] files = Directory.GetFiles(CustomBindingsPath, "*.custombindings");
			if (files.Length == 0)
			{
				LogInfo("No saved custombindings files found.");
				return;
			}
			MasterInputAsset.Disable();
			string[] array = files;
			foreach (string text in array)
			{
				if (!File.Exists(text))
				{
					LogError("No saved inputs found.");
					continue;
				}
				SavedInputMap fromFile = JsonIO.GetFromFile<SavedInputMap>(text, 3);
				if (fromFile == null)
				{
					LogError("Couldn't load custom input json at path " + text);
					continue;
				}
				LogInfo("Loading keybinds for " + fromFile.modName + " with value " + fromFile.bindings);
				string actionMap = fromFile.actionMap;
				InputActionMap[] array2 = InputActionMap.FromJson(actionMap);
				if (array2.Length == 0)
				{
					LogError("Failed to load " + fromFile.modName + " action map from json: " + actionMap);
					continue;
				}
				if (array2.Length > 1)
				{
					LogWarning($"Loaded {array2.Length} action maps for {fromFile.modName}, using the first one.");
				}
				InputActionMap val = array2[0];
				if (MasterInputAsset.FindActionMap(val.name, false) == null)
				{
					LogInfo("Added action map " + val.name);
					InputActionSetupExtensions.AddActionMap(MasterInputAsset, val);
					Enumerator<InputAction> enumerator = val.actions.GetEnumerator();
					try
					{
						while (enumerator.MoveNext())
						{
							InputAction current = enumerator.Current;
							LogInfo("\tAdded action " + current.name);
						}
					}
					finally
					{
						((IDisposable)enumerator).Dispose();
					}
					InputActionRebindingExtensions.LoadBindingOverridesFromJson((IInputActionCollection2)(object)val, fromFile.bindings, true);
					Enumerator<InputBinding> enumerator2 = val.bindings.GetEnumerator();
					try
					{
						while (enumerator2.MoveNext())
						{
							InputBinding current2 = enumerator2.Current;
							LogInfo("\tAdded binding " + ((InputBinding)(ref current2)).path);
						}
					}
					finally
					{
						((IDisposable)enumerator2).Dispose();
					}
				}
				else
				{
					LogWarning("Action map " + val.name + " already exists. Likely another mod already loaded this so your hotkeys may differ!");
				}
				modNameToActionMaps[fromFile.modName] = val;
			}
			MasterInputAsset.Enable();
		}
	}
	[HarmonyPatch]
	public class ModdedKeyboardSlots : MonoBehaviour
	{
		public string ModName = "Hotkey";

		public List<KeyBindingSlot> slots = new List<KeyBindingSlot>();

		public int usedSlots = 0;

		public void Initialize(string hotkeyName, Transform clone)
		{
			ModName = hotkeyName;
			slots.AddRange(((Component)clone).GetComponentsInChildren<KeyBindingSlot>(true));
		}

		public void ResetCounter()
		{
			usedSlots = 0;
		}

		public void SetupKeyboardSlots(InputActionMap actionMap, KeyBindingsPanel panel)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			Plugin.Log("Setting up keyboard slots for " + ModName + ".");
			Enumerator<InputAction> enumerator = actionMap.actions.GetEnumerator();
			try
			{
				while (enumerator.MoveNext())
				{
					InputAction current = enumerator.Current;
					if (!Hotkeys.IsActionActive(current))
					{
						Plugin.Log("Skipping action " + current.name + " because it's not active.");
						continue;
					}
					Plugin.Log("Setting up action " + current.name + " for " + ModName + ".");
					KeyBindingSlot orCreate = ((BaseMB)panel).GetOrCreate<KeyBindingSlot>(slots, usedSlots++);
					orCreate.SetUp(current, (Action<InputAction>)panel.OnChangeRequested);
				}
			}
			finally
			{
				((IDisposable)enumerator).Dispose();
			}
		}
	}
}
namespace Stormwalker
{
	[BepInPlugin("Stormwalker", "Stormwalker", "0.8.0")]
	public class Plugin : BaseUnityPlugin
	{
		public static readonly float SUPER_SPEED_SCALE = 5f;

		public static Plugin Instance;

		public static BuildingsPanel buildingPanel = null;

		private Harmony harmony;

		private Vector2? zoomLimit = null;

		public static PluginState State { get; private set; } = new PluginState();


		public static void Log(object obj)
		{
			((BaseUnityPlugin)Instance).Logger.LogInfo(obj);
		}

		public static void Warning(object obj)
		{
			((BaseUnityPlugin)Instance).Logger.LogWarning(obj);
		}

		public static void Error(object obj)
		{
			((BaseUnityPlugin)Instance).Logger.LogError(obj);
		}

		private void Awake()
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Loading Plugin Stormwalker...");
			Instance = this;
			harmony = Harmony.CreateAndPatchAll(typeof(Patches).Assembly, "Stormwalker");
			Configs.Initialize();
			Hotkeys.RegisterKey("Stormwalker", "zoom", "Zoom Overview", new List<KeyCode>(1) { (KeyCode)8 }, ZoomToggled);
			Hotkeys.RegisterKey("Stormwalker", "5X", "5X Speed", new List<KeyCode>(1) { (KeyCode)53 }, SuperSpeedToggled);
			((Component)this).gameObject.AddComponent<Woodcutters>();
			((Component)this).gameObject.AddComponent<BuildingCopier>();
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin Stormwalker is loaded!");
		}

		private void Update()
		{
			Hotkeys.Update();
		}

		public static void SetupState(bool noGameState)
		{
			if (noGameState || MB.GameSaveService.IsNewGame())
			{
				State = new PluginState();
			}
			else
			{
				State = Load();
			}
			ObservableExtensions.Subscribe<bool>(Observable.Where<bool>((IObservable<bool>)MB.GameSaveService.IsSaving, (Func<bool, bool>)((bool isStarting) => !isStarting)), (Action<bool>)delegate
			{
				Save();
			});
		}

		private static void Save()
		{
			string text = Path.Combine(Application.persistentDataPath, "Stormwalker.save");
			Log("Saving state to " + text);
			JsonIO.SaveToFile((object)State, text, 3);
		}

		private static PluginState Load()
		{
			string text = Path.Combine(Application.persistentDataPath, "Stormwalker.save");
			if (!File.Exists(text))
			{
				Log("No save state found, creating new one!");
				return new PluginState();
			}
			try
			{
				PluginState fromFile = JsonIO.GetFromFile<PluginState>(text, 3);
				Log("Loaded state from " + text);
				return fromFile;
			}
			catch
			{
				Error("Error while trying to load save state from " + text);
				return new PluginState();
			}
		}

		private static void SuperSpeedToggled(CallbackContext context)
		{
			if (((CallbackContext)(ref context)).performed)
			{
				GameMB.TimeScaleService.Change(SUPER_SPEED_SCALE, true, false);
			}
		}

		private void ZoomToggled(CallbackContext context)
		{
			//IL_0033: 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_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			if (((CallbackContext)(ref context)).performed)
			{
				if (!zoomLimit.HasValue)
				{
					zoomLimit = GameController.Instance.CameraController.zoomLimit;
				}
				int num = Configs.ZoomLimit;
				CameraController cameraController = GameController.Instance.CameraController;
				if (cameraController.zoomLimit.x == (float)num && cameraController.zoomLimit.y == (float)num)
				{
					cameraController.zoomLimit = zoomLimit.Value;
					return;
				}
				zoomLimit = cameraController.zoomLimit;
				cameraController.zoomLimit = new Vector2((float)num, (float)num);
			}
		}

		private void OnDestroy()
		{
			harmony.UnpatchSelf();
		}
	}
	public class BuildingCopier : GameMB
	{
		private void Update()
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			if (!GameController.IsGameActive || ShouldIgnoreInput())
			{
				return;
			}
			IInputService inputService = MB.InputService;
			DefaultActions inputConfig = MB.InputConfig;
			if (!inputService.WasTriggered(((DefaultActions)(ref inputConfig)).CopyBuilding, false))
			{
				return;
			}
			IMapObject value = GameMB.GameInputService.MouseoverObject.Value;
			Plugin.Log(((object)value).ToString() + " [" + ((object)value).GetType().Name + "]");
			IMapObject val = value;
			IMapObject val2 = val;
			ResourceDeposit val3 = (ResourceDeposit)(object)((val2 is ResourceDeposit) ? val2 : null);
			if (val3 == null)
			{
				NaturalResource val4 = (NaturalResource)(object)((val2 is NaturalResource) ? val2 : null);
				if (val4 == null)
				{
					Spring val5 = (Spring)(object)((val2 is Spring) ? val2 : null);
					if (val5 == null)
					{
						Field val6 = (Field)(object)((val2 is Field) ? val2 : null);
						if (val6 == null)
						{
							Lake val7 = (Lake)(object)((val2 is Lake) ? val2 : null);
							if (val7 == null)
							{
								Ore val8 = (Ore)(object)((val2 is Ore) ? val2 : null);
								if (val8 != null)
								{
									BuildConditional(MB.Settings.GetBuilding("Mine"));
								}
							}
							else if (val7.State.isAvailable)
							{
								BuildConditional(MB.Settings.GetBuilding("Fishing Hut"));
							}
						}
						else
						{
							if (!GameMB.OreService.HasAvailableOre(val6.Pos))
							{
								return;
							}
							Ore ore = GameMB.OreService.GetOre(val6.Pos);
							foreach (MineModel item in GameMB.OreService.MinesMatrix[ore.Model.refGood.Name])
							{
								if (BuildConditional((BuildingModel)(object)item))
								{
									break;
								}
							}
						}
					}
					else if (val5.State.isAvailable)
					{
						BuildConditional((BuildingModel)(object)MB.Settings.rainpunkConfig.extractor);
					}
				}
				else if (val4.State.isAvailable)
				{
					BuildConditional(MB.Settings.GetBuilding("Woodcutters Camp"));
				}
			}
			else
			{
				if (!val3.State.isAvailable || !GameMB.DepositsService.HutsMatrix.ContainsKey(val3.Model))
				{
					return;
				}
				foreach (GathererHutModel item2 in GameMB.DepositsService.HutsMatrix[val3.Model])
				{
					if (BuildConditional((BuildingModel)(object)item2))
					{
						break;
					}
				}
			}
		}

		private bool ShouldIgnoreInput()
		{
			return (Object)(object)BuildingPanel.currentBuilding != (Object)null || !GameMB.ModeService.Idle.Value || MB.InputService.IsOverUI();
		}

		private bool BuildConditional(BuildingModel building)
		{
			if (GameMB.GameContentService.IsUnlocked(building) && GameMB.ConstructionService.CanConstruct(building))
			{
				GameMB.GameBlackboardService.BuildingConstructionRequested.OnNext(building);
				return true;
			}
			return false;
		}
	}
	public static class Configs
	{
		private static ConfigEntry<int> m_zoomLimit = Bind("Zoom", "Zoom Height", -60, "The zoom heights the hotkey will move the camera to.", -100, -8);

		public static int ZoomLimit => m_zoomLimit.Value;

		public static void Initialize()
		{
		}

		private static ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, string description)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			return ((BaseUnityPlugin)Plugin.Instance).Config.Bind<T>(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()));
		}

		private static ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, string description, T min, T max) where T : IComparable
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			return ((BaseUnityPlugin)Plugin.Instance).Config.Bind<T>(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<T>(min, max), Array.Empty<object>()));
		}
	}
	public static class HousePatches
	{
		private static GameObject residentSlider;

		public static HouseLimiter houseLimiter;

		public static void PatchPanel(HousePanel panel)
		{
			GameObject val = ((BaseMB)panel).FindChild("Content/ResidentsPanel");
			residentSlider = CreateResidentSlider(val);
			houseLimiter = residentSlider.AddComponent<HouseLimiter>();
			houseLimiter.SetUp();
			val.GetComponent<SimpleVerticalResizer>().minHeight = 200f;
		}

		private static GameObject CreateResidentSlider(GameObject parent)
		{
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = Utils.MakeGameObject(parent, "StormwalkerSlots");
			GameObject original = GameObject.Find("/HUD/WorkshopPanel/Content/RecipesPanel/Slots/RecipeSlot/Prio");
			Copy(original, val, "Plus");
			Copy(original, val, "Minus");
			Transform val2 = Copy(original, val, "Counter");
			SimpleTooltipTrigger component = ((Component)val2).GetComponent<SimpleTooltipTrigger>();
			component.headerKey = Utils.Text("Allowed Residents", "Stormwalker_residents_tooltip_head").key;
			component.descKey = Utils.Text("Use the buttons to limit the amount of villagers that may live in this house", "Stormwalker_residents_tooltip_desc").key;
			val.transform.localPosition = new Vector3(-200f, -125f, 0f);
			return val;
		}

		public static void Show(House house)
		{
			houseLimiter.Show(house);
		}

		private static Transform Copy(GameObject original, GameObject target, string name)
		{
			Transform val = Object.Instantiate<Transform>(original.transform.Find(name), target.transform);
			((Object)val).name = name;
			return val;
		}
	}
	public class HouseLimiter : GameMB
	{
		public HouseLimitState state = new HouseLimitState();

		private Button plusButton;

		private Button minusButton;

		private TextMeshProUGUI counter;

		private House house;

		private int Count => state.GetAllowedResidents(house);

		public void SetUp()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Expected O, but got Unknown
			((BaseMB)this).EnsureComponent<TextMeshProUGUI>(counter, ref counter, "Counter/Text", 0);
			((BaseMB)this).EnsureComponent<Button>(plusButton, ref plusButton, "Plus", 0);
			((BaseMB)this).EnsureComponent<Button>(minusButton, ref minusButton, "Minus", 0);
			ButtonExtensions.AddCallback(plusButton, new UnityAction(OnPlusClicked));
			ButtonExtensions.AddCallback(minusButton, new UnityAction(OnMinusClicked));
		}

		private void PrepareForEvents()
		{
			DisposableExtensions.AddTo<IDisposable>(ObservableExtensions.Subscribe<House>((IObservable<House>)GameMB.GameBlackboardService.HouseRemoved, (Action<House>)delegate(House h)
			{
				state.Remove(h);
			}), (Component)(object)this);
		}

		public void Show(House house)
		{
			this.house = house;
			RefreshCounter();
			RefreshButtons();
		}

		private void OnPlusClicked()
		{
			AdjustResidents(1);
		}

		private void OnMinusClicked()
		{
			int num = AdjustResidents(-1);
			if (num < house.state.residents.Count)
			{
				house.Leave(house.state.residents.First());
			}
		}

		private int AdjustResidents(int delta)
		{
			int num = Count + delta;
			state.SetAllowedResidents(house, num);
			RefreshCounter();
			RefreshButtons();
			return num;
		}

		private void RefreshCounter()
		{
			((TMP_Text)counter).text = Count.ToString();
		}

		private void RefreshButtons()
		{
			if (((BuildingState)house.state).finished)
			{
				int count = Count;
				((Selectable)plusButton).interactable = count < house.GetHousingPlaces();
				((Selectable)minusButton).interactable = count > 0;
			}
			else
			{
				((Selectable)minusButton).interactable = false;
				((Selectable)plusButton).interactable = false;
			}
		}
	}
	public class HouseLimitState
	{
		private Dictionary<int, int> slotsPerHouse => Plugin.State.slotsPerHouse;

		public void SetAllowedResidents(House house, int amount)
		{
			if (amount == house.GetHousingPlaces())
			{
				slotsPerHouse.Remove(((Building)house).Id);
			}
			else
			{
				slotsPerHouse[((Building)house).Id] = amount;
			}
		}

		public int GetAllowedResidents(House house)
		{
			if (!slotsPerHouse.TryGetValue(((Building)house).Id, out var value))
			{
				value = 10;
			}
			return Math.Min(house.GetHousingPlaces(), value);
		}

		public void Remove(House house)
		{
			slotsPerHouse.Remove(((Building)house).Id);
		}
	}
	[HarmonyPatch]
	internal static class Patches
	{
		[HarmonyPatch(typeof(GameLoader), "LoadState")]
		[HarmonyPostfix]
		private static void Load(GameLoader __instance)
		{
			Plugin.SetupState(__instance.state == null);
		}

		[HarmonyPatch(typeof(WoodcuttersHUD), "SetUp")]
		[HarmonyPostfix]
		private static void SetUpHousePanel(WoodcuttersHUD __instance)
		{
			Woodcutters component = ((Component)Plugin.Instance).gameObject.GetComponent<Woodcutters>();
			component.PatchPanel(__instance);
		}

		[HarmonyPatch(typeof(HousePanel), "Awake")]
		[HarmonyPostfix]
		private static void SetUpHousePanel(HousePanel __instance)
		{
			HousePatches.PatchPanel(__instance);
		}

		[HarmonyPatch(typeof(HousePanel), "Show")]
		[HarmonyPostfix]
		private static void House__Show(House house)
		{
			HousePatches.Show(house);
		}

		[HarmonyPatch(typeof(House), "GetPlacesLeft")]
		[HarmonyPrefix]
		private static bool House__GetPlacesLeft(House __instance, ref int __result)
		{
			__result = HousePatches.houseLimiter.state.GetAllowedResidents(__instance) - __instance.state.residents.Count;
			return false;
		}

		[HarmonyPatch(typeof(BuildingWorkerSlot), "Unassign")]
		[HarmonyPrefix]
		private static bool BuildingWorkerSlot__Unassign(BuildingWorkerSlot __instance)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			IInputService inputService = MB.InputService;
			DefaultActions inputConfig = MB.InputConfig;
			if (inputService.IsTriggering(((DefaultActions)(ref inputConfig)).InputModifierControl))
			{
				WorkerSlotPatches.QueueToggleUnassign(__instance);
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(ProductionBuilding), "DispatchProductionFinished")]
		[HarmonyPostfix]
		private static void UnassignSinceDone(ProductionState production)
		{
			WorkerSlotPatches.TryUnassign(production);
		}

		[HarmonyPatch(typeof(WorkerStatusSlot), "SetUpActor")]
		[HarmonyPrefix]
		private static void OverrideProduction(WorkerStatusSlot __instance)
		{
			WorkerSlotPatches.UpdateMarkerStatus(__instance);
		}

		[HarmonyPatch(typeof(VillagersService), "RemoveFromProfession")]
		[HarmonyPostfix]
		private static void SyncStateVillagerGone(Villager villager)
		{
			WorkerSlotPatches.Remove(villager);
		}

		[HarmonyPatch(typeof(IngredientsMenu), "OnIngredientClicked")]
		[HarmonyPrefix]
		private static bool OnIngredientClicked(IngredientState state)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			IInputService inputService = MB.InputService;
			DefaultActions inputConfig = MB.InputConfig;
			if (inputService.IsTriggering(((DefaultActions)(ref inputConfig)).InputModifierControl))
			{
				GoodModel good = Serviceable.Settings.GetGood(state.good);
				GameMB.GameBlackboardService.RecipesPopupRequested.OnNext(new RecipesPopupRequest(good, true));
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(IngredientSlot), "OnClick")]
		[HarmonyPrefix]
		private static bool IngredientSlot__OnClick(IngredientSlot __instance)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			IInputService inputService = MB.InputService;
			DefaultActions inputConfig = MB.InputConfig;
			if (inputService.IsTriggering(((DefaultActions)(ref inputConfig)).InputModifierControl))
			{
				GameMB.GameBlackboardService.RecipesPopupRequested.OnNext(new RecipesPopupRequest(__instance.GetGood(), true));
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(TimeScalePanel), "SetUp")]
		[HarmonyPostfix]
		private static void TimeScalePanel__SetUp(TimeScalePanel __instance)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)__instance).gameObject.transform;
			Transform val = Object.Instantiate<Transform>(transform.Find("Slot (5)"), transform);
			((Object)val).name = "Slot (6)";
			val.localPosition = new Vector3(90f, 90f, 0f);
			((Component)val).GetComponent<TimeScaleSlot>().timeScale = 5f;
			((TMP_Text)((Component)val.Find("Desc")).GetComponent<TextMeshProUGUI>()).text = $"x{Plugin.SUPER_SPEED_SCALE:0.}";
		}

		[HarmonyPatch(typeof(TimeScaleService), "SpeedUp")]
		[HarmonyPrefix]
		private static bool TimeScaleService__SpeedUp(TimeScaleService __instance)
		{
			float value = __instance.Scale.Value;
			if (value == Plugin.SUPER_SPEED_SCALE)
			{
				Serviceable.SoundsManager.PlayFailedSound();
				return false;
			}
			if (value == TimeScaleService.Speeds.Last())
			{
				__instance.Change(5f, true, false);
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(TimeScaleService), "SlowDown")]
		[HarmonyPrefix]
		private static bool TimeScaleService__SlowDown(TimeScaleService __instance)
		{
			float value = __instance.Scale.Value;
			if (value == Plugin.SUPER_SPEED_SCALE)
			{
				__instance.Change(TimeScaleService.Speeds.Last(), true, false);
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(BuildingsPanel), "SetUp")]
		[HarmonyPostfix]
		private static void BuildingPanel__SetUp(BuildingsPanel __instance)
		{
			Plugin.buildingPanel = __instance;
		}

		[HarmonyPatch(typeof(TraderPanel), "Show")]
		[HarmonyPostfix]
		private static void TraderPanel__Show(TraderPanel __instance)
		{
			GameObject parent = ((BaseMB)__instance).FindChild("Content");
			TextMeshProUGUI val = Utils.PatchInGameObject<TextMeshProUGUI>(parent, "StormwalkerCityScore", (Action<TextMeshProUGUI>)delegate(TextMeshProUGUI t)
			{
				//IL_002e: Unknown result type (might be due to invalid IL or missing references)
				((TMP_Text)t).fontSize = 24f;
				((TMP_Text)t).fontSizeMax = 24f;
				((TMP_Text)t).transform.localPosition = new Vector3(460f, 328f, 0f);
			});
			ITradeService tradeService = Serviceable.TradeService;
			int score = ((TradeService)((tradeService is TradeService) ? tradeService : null)).GetScore();
			((TMP_Text)val).text = $"City Score: {score}";
		}
	}
	public class PluginState
	{
		public Dictionary<int, int> slotsPerHouse = new Dictionary<int, int>();

		public HashSet<int> workersToUnassign = new HashSet<int>();
	}
	public static class Utils
	{
		public static T CopyComponent<T>(T original, GameObject destination) where T : Component
		{
			Type type = ((object)original).GetType();
			Component component = destination.GetComponent(type);
			T val = (T)(object)((component is T) ? component : null);
			if (!Object.op_Implicit((Object)(object)val))
			{
				Component obj = destination.AddComponent(type);
				val = (T)(object)((obj is T) ? obj : null);
			}
			FieldInfo[] fields = type.GetFields();
			FieldInfo[] array = fields;
			foreach (FieldInfo fieldInfo in array)
			{
				if (!fieldInfo.IsStatic)
				{
					fieldInfo.SetValue(val, fieldInfo.GetValue(original));
				}
			}
			PropertyInfo[] properties = type.GetProperties();
			PropertyInfo[] array2 = properties;
			foreach (PropertyInfo propertyInfo in array2)
			{
				if (propertyInfo.CanWrite && propertyInfo.CanWrite && !(propertyInfo.Name == "name"))
				{
					propertyInfo.SetValue(val, propertyInfo.GetValue(original, null), null);
				}
			}
			return val;
		}

		public static GameObject MakeGameObject(GameObject parent, string name, bool hide = true)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Expected O, but got Unknown
			GameObject val = new GameObject();
			GameObject val2 = Object.Instantiate<GameObject>(val, (parent != null) ? parent.transform : null);
			((Object)val2).name = name;
			if (hide)
			{
				((Object)val2).hideFlags = (HideFlags)61;
			}
			ObjectExtensions.Destroy((Object)(object)val);
			return val2;
		}

		public static T PatchInGameObject<T>(GameObject parent, string name, Action<T> setupScript = null) where T : Component
		{
			Transform obj = parent.transform.Find(name);
			GameObject val = ((obj != null) ? ((Component)obj).gameObject : null);
			if ((Object)(object)val != (Object)null)
			{
				return val.GetComponent<T>();
			}
			val = MakeGameObject(parent, name);
			T val2 = val.AddComponent<T>();
			setupScript?.Invoke(val2);
			return val2;
		}

		public static T StealComponent<T>(string path) where T : Component
		{
			GameObject val = GameObject.Find(path);
			return val.GetComponent<T>();
		}

		public static LocaText Text(string value, string key)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Expected O, but got Unknown
			TextsService val = (TextsService)MainController.Instance.AppServices.TextsService;
			if (!val.texts.ContainsKey(key))
			{
				val.texts.Add(key, value);
			}
			return new LocaText
			{
				key = key
			};
		}

		public static Sprite LoadSprite(string file)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			string path = Path.Combine(Paths.PluginPath, "assets", file);
			byte[] array = File.ReadAllBytes(path);
			Texture2D val = new Texture2D(4, 4, (TextureFormat)12, false);
			ImageConversion.LoadImage(val, array);
			return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 50f);
		}
	}
	public class Woodcutters : GameMB
	{
		private WoodcuttersHUD woodcuttersHUD;

		private void Awake()
		{
			Hotkeys.RegisterKey("Stormwalker", "assign1", "Assign one Villager", new List<KeyCode>(2)
			{
				(KeyCode)306,
				(KeyCode)120
			}, delegate(CallbackContext ctx)
			{
				if (((CallbackContext)(ref ctx)).performed)
				{
					woodcuttersHUD.OnRightClick();
				}
			});
			Hotkeys.RegisterKey("Stormwalker", "unassignAll", "Unassign all Villagers", new List<KeyCode>(2)
			{
				(KeyCode)304,
				(KeyCode)120
			}, delegate(CallbackContext ctx)
			{
				if (((CallbackContext)(ref ctx)).performed)
				{
					woodcuttersHUD.OnClick();
				}
			});
			Hotkeys.RegisterKey("Stormwalker", "balanceHostility", "Unassign Villagers to lower Hostility", new List<KeyCode>(2)
			{
				(KeyCode)308,
				(KeyCode)120
			}, delegate(CallbackContext ctx)
			{
				if (((CallbackContext)(ref ctx)).performed)
				{
					UnassignSomePressed();
				}
			});
		}

		public void PatchPanel(WoodcuttersHUD hud)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			woodcuttersHUD = hud;
			((Component)hud).transform.localPosition = new Vector3(120f, -71f, 0f);
		}

		private void UnassignSomePressed()
		{
			if (canLowerHostility(out var amount))
			{
				UnassignSome(amount);
				Publish(amount);
			}
		}

		private bool canLowerHostility(out int amount)
		{
			IHostilityService hostilityService = GameMB.HostilityService;
			if (((HostilityService)((hostilityService is HostilityService) ? hostilityService : null)).IsFirstLevel())
			{
				amount = -1;
				return false;
			}
			int pointsFor = GameMB.HostilityService.GetPointsFor((HostilitySource)70);
			if (pointsFor <= 0)
			{
				amount = -1;
				return false;
			}
			int num = GameMB.HostilityService.Points.Value + 1;
			int sourceAmount = GameMB.HostilityService.GetSourceAmount((HostilitySource)70);
			amount = (int)Math.Ceiling((double)num * (double)sourceAmount / (double)pointsFor);
			return sourceAmount >= amount;
		}

		private void UnassignSome(int toUnassign)
		{
			for (int i = 0; i < 6; i++)
			{
				foreach (Camp value in GameMB.BuildingsService.Camps.Values)
				{
					toUnassign -= TryUnassignOne(value);
					if (toUnassign == 0)
					{
						return;
					}
				}
			}
		}

		private int TryUnassignOne(Camp camp)
		{
			for (int i = 0; i < ((ProductionBuilding)camp).Workers.Length; i++)
			{
				int num = ((ProductionBuilding)camp).Workers[i];
				if (GameMB.ActorsService.HasActor(num))
				{
					Actor actor = GameMB.ActorsService.GetActor(num);
					if (!actor.IsBoundToWorkplace)
					{
						GameMB.VillagersService.ReleaseFromProfession(GameMB.VillagersService.GetVillager(((ProductionBuilding)camp).Workers[i]), true);
						return 1;
					}
				}
			}
			return 0;
		}

		private void Publish(int number)
		{
			if (number > 0)
			{
				GameMB.NewsService.PublishNews($"Unassigned {number} woodcutters", (AlertSeverity)1, (Sprite)null, (IBroadcaster)null);
			}
		}
	}
	public static class WorkerSlotPatches
	{
		private static readonly string MARKER_NAME = "StormwalkerMarker";

		private static Sprite marker = null;

		private static HashSet<int> toUnassign => Plugin.State.workersToUnassign;

		public static void PutMarkerIn(BuildingWorkerSlot slot)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			Transform obj = ((Component)slot).transform.Find("StatusIcon");
			GameObject val = ((obj != null) ? ((Component)obj).gameObject : null);
			if (!((Object)(object)val.transform.Find(MARKER_NAME) != (Object)null))
			{
				GameObject val2 = Utils.MakeGameObject(val, MARKER_NAME);
				val2.SetActive(false);
				val2.transform.localPosition = new Vector3(-10f, 10f, 0f);
				TransformExtensions.SetScale(val2.transform, 0.2f);
				Image val3 = val2.AddComponent<Image>();
				if ((Object)(object)marker == (Object)null)
				{
					Image val4 = Utils.StealComponent<Image>("/HUD/GoodsHUD/SacrificeMarker/Content");
					marker = val4.sprite;
				}
				val3.sprite = marker;
			}
		}

		public static void QueueToggleUnassign(BuildingWorkerSlot slot)
		{
			PutMarkerIn(slot);
			if (!toUnassign.Remove(slot.actor.Id))
			{
				toUnassign.Add(slot.actor.Id);
			}
		}

		public static void TryUnassign(ProductionState production)
		{
			if (toUnassign.Remove(production.worker))
			{
				IVillagersService villagersService = GameMB.VillagersService;
				Villager villager = villagersService.GetVillager(production.worker);
				villagersService.ReleaseFromProfession(villager, false);
			}
		}

		public static void Remove(Villager villager)
		{
			toUnassign.Remove(((Actor)villager).Id);
		}

		public static bool UpdateMarkerStatus(WorkerStatusSlot slot)
		{
			Transform val = ((Component)slot).transform.Find("StatusIcon/" + MARKER_NAME);
			if ((Object)(object)val == (Object)null || (Object)(object)slot.actor == (Object)null)
			{
				return false;
			}
			bool flag = toUnassign.Contains(slot.actor.Id);
			ComponentExtensions.SetActive((Component)(object)val, flag);
			return flag;
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "Stormwalker";

		public const string PLUGIN_NAME = "Stormwalker";

		public const string PLUGIN_VERSION = "0.8.0";
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}