Decompiled source of HammerTime v0.3.9

HammerTime.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HammerTime.Compatibility;
using HarmonyLib;
using Jotunn;
using Jotunn.Managers;
using Jotunn.Utils;
using UnityEngine;
using UnityEngine.SceneManagement;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("HammerTime")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HammerTime")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("FE8B42E3-7082-4DFF-A5CC-6B62B0315ACA")]
[assembly: AssemblyFileVersion("0.3.9")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.3.9.0")]
[module: UnverifiableCode]
namespace HammerTime
{
	public static class Config
	{
		public static ConfigEntry<bool> disableRecipes;

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

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

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

		private const string CategoryDescription = "A new category is getting created if it is not a vanilla value. If two categories have the same name the pieces will be combined, even from different hammers. Can be changed at runtime. ";

		private static Regex invalidConfigChars = new Regex("[=\\n\\t\\\\\"\\'\\[\\]]*");

		public static void InitBaseConfig()
		{
			disableRecipes = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>("1 - General", "Disable Hammer Recipes", true, "Disables crafting recipes of custom hammers that are enabled in this mod. Only deactivates the recipes, existing items will not be removed. Can be changed at runtime. ".Trim());
			disableRecipes.SettingChanged += delegate
			{
				Plugin.UpdateDisabledRecipes();
			};
		}

		public static bool CombineModCategories(string pieceTable, string modName, bool combineByDefault, Action settingChanged)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			string cacheKey = pieceTable + "_" + modName;
			if (!CombineCategories.ContainsKey(cacheKey))
			{
				string text = CleanKeySection(modName + " " + pieceTable);
				ConfigurationManagerAttributes val = new ConfigurationManagerAttributes
				{
					Order = 4
				};
				ConfigEntry<bool> combine = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>(text, "Combine Categories", combineByDefault, new ConfigDescription("Combines all categories from this custom hammer into one category. Can be changed at runtime. ".Trim(), (AcceptableValueBase)null, new object[1] { val }));
				CombineCategories.Add(cacheKey, combine.Value);
				combine.SettingChanged += delegate
				{
					CombineCategories[cacheKey] = combine.Value;
					settingChanged?.Invoke();
				};
			}
			return CombineCategories[cacheKey];
		}

		public static bool IsHammerEnabled(string pieceTable, string modName, Action settingChanged)
		{
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Expected O, but got Unknown
			string cacheKey = pieceTable + "_" + modName;
			if (!EnabledHammers.ContainsKey(cacheKey))
			{
				bool flag = modName == "PlanBuild" || pieceTable == "_RuneFocusPieceTable" || Helper.IsVanillaPieceTable(pieceTable);
				string text = CleanKeySection(modName + " " + pieceTable);
				ConfigurationManagerAttributes val = new ConfigurationManagerAttributes
				{
					Order = 5
				};
				ConfigEntry<bool> enabled = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<bool>(text, "Enable Hammer", !flag, new ConfigDescription("Enables moving pieces from this custom hammer into the vanilla hammer. Can be changed at runtime. ".Trim(), (AcceptableValueBase)null, new object[1] { val }));
				EnabledHammers.Add(cacheKey, enabled.Value);
				enabled.SettingChanged += delegate
				{
					EnabledHammers[cacheKey] = enabled.Value;
					settingChanged?.Invoke();
				};
			}
			return EnabledHammers[cacheKey];
		}

		public static bool IsHammerEnabled(string pieceTable)
		{
			if (Helper.IsVanillaPieceTable(pieceTable))
			{
				return true;
			}
			foreach (KeyValuePair<string, bool> enabledHammer in EnabledHammers)
			{
				if (enabledHammer.Key.StartsWith(pieceTable))
				{
					return enabledHammer.Value;
				}
			}
			Logger.LogWarning((object)("Config 'Enable Hammer' for " + pieceTable + " not found"));
			return false;
		}

		public static string GetCategoryName(string pieceTable, string modName, string originalCategory, Action settingChanged)
		{
			if (originalCategory == "All")
			{
				return "All";
			}
			string key = "Single_" + pieceTable + "_" + modName + "_" + originalCategory;
			if (!CategoryNames.ContainsKey(key))
			{
				string text = CleanKeySection(modName + " " + pieceTable);
				string text2 = CleanKeySection("Category Name " + originalCategory);
				string text3 = modName + " " + originalCategory;
				string text4 = "Used category name if categories are not combined. A new category is getting created if it is not a vanilla value. If two categories have the same name the pieces will be combined, even from different hammers. Can be changed at runtime. ".Trim();
				if (modName == "Vanilla")
				{
					text3 = originalCategory;
				}
				ConfigEntry<string> entry = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<string>(text, text2, text3, text4);
				InitCategoryName(key, entry, settingChanged);
			}
			return CategoryNames[key];
		}

		public static string GetCombinedCategoryName(string pieceTable, string modName, Action settingChanged)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Expected O, but got Unknown
			string key = "Combined_" + pieceTable + "_" + modName;
			if (!CategoryNames.ContainsKey(key))
			{
				string text = CleanKeySection(modName + " " + pieceTable);
				string text2 = "Combined Category Name";
				ConfigurationManagerAttributes val = new ConfigurationManagerAttributes
				{
					Order = 3
				};
				ConfigDescription val2 = new ConfigDescription("Used category name if categories are combined. A new category is getting created if it is not a vanilla value. If two categories have the same name the pieces will be combined, even from different hammers. Can be changed at runtime. ".Trim(), (AcceptableValueBase)null, new object[1] { val });
				ConfigEntry<string> entry = ((BaseUnityPlugin)Plugin.Instance).Config.Bind<string>(text, text2, modName ?? "", val2);
				InitCategoryName(key, entry, settingChanged);
			}
			return CategoryNames[key];
		}

		private static void InitCategoryName(string key, ConfigEntry<string> entry, Action settingChanged)
		{
			entry.SettingChanged += delegate
			{
				string text = CategoryNames[key];
				CategoryNames[key] = entry.Value;
				PieceManager.Instance.RemovePieceCategory("_HammerPieceTable", text);
				settingChanged?.Invoke();
			};
			CategoryNames[key] = entry.Value;
		}

		private static string CleanKeySection(string section)
		{
			return invalidConfigChars.Replace(section, "").Trim();
		}
	}
	public class Helper
	{
		public static Dictionary<PieceCategory, string> GetCategories()
		{
			return PieceManager.Instance.GetPieceCategoriesMap();
		}

		public static Dictionary<string, PieceTable> GetPieceTables()
		{
			return ((IEnumerable<KeyValuePair<string, Object>>)Cache.GetPrefabs(typeof(PieceTable))).ToDictionary((Func<KeyValuePair<string, Object>, string>)((KeyValuePair<string, Object> k) => k.Key), (Func<KeyValuePair<string, Object>, PieceTable>)((KeyValuePair<string, Object> v) => (PieceTable)v.Value));
		}

		public static bool IsVanillaPieceTable(string pieceTable)
		{
			return pieceTable == "_HammerPieceTable" || pieceTable == "_HoePieceTable" || pieceTable == "_CultivatorPieceTable";
		}
	}
	[HarmonyPatch]
	public static class Patches
	{
		public class ObjectDBPatch
		{
			[HarmonyPatch(typeof(DungeonDB), "Start")]
			[HarmonyPostfix]
			[HarmonyPriority(0)]
			public static void ObjectDBAwake()
			{
				Plugin.IndexPrefabs();
			}
		}

		[HarmonyPatch(typeof(Game), "Logout")]
		[HarmonyPostfix]
		public static void GameShutdown()
		{
			Plugin.Undo();
		}
	}
	public class PieceItem
	{
		public GameObject gameObject;

		public Piece piece;

		public int nameHash;

		public string modName;

		public PieceCategory originalCategory;

		public string overrideCategory;

		public PieceItem(GameObject gameObject, Piece piece, string modName, string overrideCategory)
		{
			//IL_0029: 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)
			this.gameObject = gameObject;
			this.piece = piece;
			nameHash = StringExtensionMethods.GetStableHashCode(((Object)gameObject).name);
			originalCategory = piece.m_category;
			this.overrideCategory = overrideCategory;
			this.modName = modName;
		}
	}
	[BepInPlugin("com.maxsch.valheim.HammerTime", "HammerTime", "0.3.9")]
	[BepInDependency("com.jotunn.jotunn", "2.12.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string ModName = "HammerTime";

		public const string ModGuid = "com.maxsch.valheim.HammerTime";

		public const string ModVersion = "0.3.9";

		public Harmony harmony;

		private static Dictionary<string, PieceTable> pieceTables;

		private static Dictionary<string, List<PieceItem>> piecesByTable = new Dictionary<string, List<PieceItem>>();

		private static readonly List<ItemDrop> ToolItems = new List<ItemDrop>();

		public static Plugin Instance { get; private set; }

		public static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			harmony = new Harmony("com.maxsch.valheim.HammerTime");
			harmony.PatchAll();
			ModQuery.Enable();
			Config.InitBaseConfig();
		}

		private void Start()
		{
			if (Chainloader.PluginInfos.ContainsKey("WackyMole.WackysDatabase"))
			{
				WackysDatabase.InitCompat();
			}
			if (Chainloader.PluginInfos.ContainsKey("marcopogo.PlanBuild"))
			{
				PlanBuild.InitCompat();
			}
			else
			{
				harmony.PatchAll(typeof(Patches.ObjectDBPatch));
			}
		}

		public static void IndexPrefabs()
		{
			//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)
			Scene activeScene = SceneManager.GetActiveScene();
			if (((Scene)(ref activeScene)).name != "main")
			{
				return;
			}
			Log.LogInfo((object)"Indexing Pieces");
			pieceTables = Helper.GetPieceTables();
			piecesByTable.Clear();
			foreach (KeyValuePair<string, PieceTable> pieceTable in pieceTables)
			{
				if (Helper.IsVanillaPieceTable(pieceTable.Key) && pieceTable.Key != "_HammerPieceTable")
				{
					continue;
				}
				piecesByTable.Add(pieceTable.Key, new List<PieceItem>());
				foreach (GameObject piece in pieceTable.Value.m_pieces)
				{
					if (!Object.op_Implicit((Object)(object)piece))
					{
						Log.LogWarning((object)("PieceTable '" + pieceTable.Key + "' pieces contains a null entry"));
						continue;
					}
					IModPrefab prefab = ModQuery.GetPrefab(((Object)piece).name);
					Piece component;
					string modName;
					if (prefab != null && Object.op_Implicit((Object)(object)prefab.Prefab))
					{
						component = prefab.Prefab.GetComponent<Piece>();
						modName = prefab.SourceMod.Name;
					}
					else
					{
						component = piece.GetComponent<Piece>();
						modName = "Vanilla";
					}
					if (Object.op_Implicit((Object)(object)component))
					{
						piecesByTable[pieceTable.Key].Add(new PieceItem(piece, component, modName, string.Empty));
					}
				}
			}
			Cookie.IndexPrefabs(piecesByTable);
			UpdatePieceTables();
			IndexToolItems();
			UpdateDisabledRecipes();
		}

		private static void IndexToolItems()
		{
			ToolItems.Clear();
			ItemDrop val = default(ItemDrop);
			foreach (GameObject item in ObjectDB.instance.m_items)
			{
				if (!Object.op_Implicit((Object)(object)item) || !item.TryGetComponent<ItemDrop>(ref val) || val.m_itemData?.m_shared == null)
				{
					continue;
				}
				PieceTable buildPieces = val.m_itemData.m_shared.m_buildPieces;
				if (Object.op_Implicit((Object)(object)buildPieces))
				{
					Recipe recipe = ObjectDB.instance.GetRecipe(val.m_itemData);
					if (Object.op_Implicit((Object)(object)recipe) && recipe.m_enabled)
					{
						ToolItems.Add(val);
					}
				}
			}
		}

		public static void UpdateDisabledRecipes()
		{
			foreach (ItemDrop toolItem in ToolItems)
			{
				PieceTable pieceTable = toolItem.m_itemData.m_shared.m_buildPieces;
				string key = pieceTables.FirstOrDefault((KeyValuePair<string, PieceTable> x) => (Object)(object)x.Value == (Object)(object)pieceTable).Key;
				if (!Helper.IsVanillaPieceTable(key) && !string.IsNullOrEmpty(key))
				{
					bool flag = Config.IsHammerEnabled(key);
					bool flag2 = Config.disableRecipes.Value && flag;
					Recipe recipe = ObjectDB.instance.GetRecipe(toolItem.m_itemData);
					recipe.m_enabled = !flag2;
				}
			}
			if (Object.op_Implicit((Object)(object)Player.m_localPlayer) && Object.op_Implicit((Object)(object)InventoryGui.instance))
			{
				Player.m_localPlayer.UpdateKnownRecipesList();
				InventoryGui.instance.UpdateCraftingPanel(false);
			}
		}

		public static void Undo()
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<PieceCategory, string> categories = Helper.GetCategories();
			foreach (KeyValuePair<string, List<PieceItem>> item in piecesByTable)
			{
				foreach (PieceItem item2 in item.Value)
				{
					MovePieceItemToTable(category: (!categories.TryGetValue(item2.originalCategory, out var value)) ? ((object)(PieceCategory)(ref item2.originalCategory)).ToString() : value, pieceItem: item2, pieceTableFrom: "_HammerPieceTable", pieceTableTo: item.Key);
				}
			}
		}

		public static void UpdatePieceTables()
		{
			//IL_0211: Unknown result type (might be due to invalid IL or missing references)
			if (piecesByTable == null || piecesByTable.Count == 0)
			{
				Log.LogWarning((object)"Cannot run UpdatePieceTables, no pieces indexed yet");
				return;
			}
			Dictionary<PieceCategory, string> categories = Helper.GetCategories();
			HashSet<string> hashSet = new HashSet<string>();
			HashSet<string> hashSet2 = new HashSet<string>();
			hashSet.Add(" ");
			for (int i = 0; i < 4; i++)
			{
				hashSet.Add(Enum.GetName(typeof(PieceCategory), i));
			}
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			foreach (List<PieceItem> value in piecesByTable.Values)
			{
				foreach (PieceItem item in value)
				{
					if (!dictionary.ContainsKey(item.modName))
					{
						dictionary.Add(item.modName, 0);
					}
					dictionary[item.modName]++;
				}
			}
			((BaseUnityPlugin)Instance).Config.SaveOnConfigSet = false;
			foreach (KeyValuePair<string, List<PieceItem>> item2 in piecesByTable)
			{
				string key = item2.Key;
				foreach (PieceItem item3 in item2.Value)
				{
					bool flag = Config.IsHammerEnabled(key, item3.modName, delegate
					{
						UpdatePieceTables();
						UpdateDisabledRecipes();
					});
					bool combineByDefault = dictionary[item3.modName] <= 60;
					bool flag2 = Config.CombineModCategories(key, item3.modName, combineByDefault, UpdatePieceTables);
					string text = ((!string.IsNullOrEmpty(item3.overrideCategory)) ? item3.overrideCategory : categories[item3.originalCategory]);
					string combinedCategoryName = Config.GetCombinedCategoryName(key, item3.modName, UpdatePieceTables);
					string categoryName = Config.GetCategoryName(key, item3.modName, text, UpdatePieceTables);
					hashSet.Add(text);
					hashSet.Add(combinedCategoryName);
					hashSet.Add(categoryName);
					string text2;
					if (!flag)
					{
						text2 = text;
						if (key == "_HammerPieceTable")
						{
							hashSet2.Add(text2);
						}
						MovePieceItemToTable(item3, "_HammerPieceTable", key, text2);
						continue;
					}
					text2 = (flag2 ? combinedCategoryName : categoryName);
					if (string.IsNullOrEmpty(text2))
					{
						text2 = " ";
					}
					hashSet2.Add(text2);
					MovePieceItemToTable(item3, key, "_HammerPieceTable", text2);
				}
			}
			((BaseUnityPlugin)Instance).Config.Save();
			((BaseUnityPlugin)Instance).Config.SaveOnConfigSet = true;
			foreach (string item4 in hashSet)
			{
				if (!hashSet2.Contains(item4))
				{
					PieceManager.Instance.RemovePieceCategory("_HammerPieceTable", item4);
				}
			}
		}

		private static void MovePieceItemToTable(PieceItem pieceItem, string pieceTableFrom, string pieceTableTo, string category)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Invalid comparison between Unknown and I4
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Invalid comparison between Unknown and I4
			GameObject gameObject = pieceItem.gameObject;
			if (pieceTableFrom != pieceTableTo && pieceTables.TryGetValue(pieceTableFrom, out var value))
			{
				value.m_pieces.Remove(gameObject);
			}
			if (pieceTables.TryGetValue(pieceTableTo, out var value2))
			{
				if ((int)pieceItem.originalCategory != 100)
				{
					pieceItem.piece.m_category = PieceManager.Instance.AddPieceCategory(pieceTableTo, category);
				}
				int nameHash = pieceItem.nameHash;
				if (!value2.m_pieces.Contains(gameObject) && ((int)pieceItem.originalCategory != 100 || !value2.m_pieces.Any((GameObject i) => StringExtensionMethods.GetStableHashCode(((Object)i).name) == nameHash)))
				{
					value2.m_pieces.Add(gameObject);
				}
			}
		}
	}
}
namespace HammerTime.Compatibility
{
	public class Cookie
	{
		public static void IndexPrefabs(Dictionary<string, List<PieceItem>> piecesByTable)
		{
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Expected O, but got Unknown
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			Transform val = Chainloader.ManagerObject.transform.Find("CookieHammerUI");
			if (!Object.op_Implicit((Object)(object)val))
			{
				return;
			}
			Transform val2 = ((Component)val).transform.Find("Canvas/MainTab/ItemList/ListPanel/Scroll View/Viewport/Content");
			if (!Object.op_Implicit((Object)(object)val2))
			{
				Plugin.Log.LogWarning((object)"CookieMilk HammerUI found but no piece parent");
				return;
			}
			foreach (Transform item in val2)
			{
				Transform val3 = item;
				if (!Object.op_Implicit((Object)(object)val3))
				{
					continue;
				}
				string name = ((Object)val3).name;
				foreach (Transform item2 in val3)
				{
					Transform val4 = item2;
					if (!Object.op_Implicit((Object)(object)val4))
					{
						continue;
					}
					string name2 = ((Object)val4).name;
					IModPrefab prefab = ModQuery.GetPrefab(name2);
					if (prefab == null)
					{
						Plugin.Log.LogWarning((object)("CookieMilk Prefab " + name2 + " not found"));
						continue;
					}
					string name3 = prefab.SourceMod.Name;
					if (!piecesByTable.TryGetValue(name3, out var value))
					{
						value = new List<PieceItem>();
						piecesByTable.Add(name3, value);
					}
					Piece component = prefab.Prefab.GetComponent<Piece>();
					value.Add(new PieceItem(prefab.Prefab, component, name3, name));
				}
			}
		}
	}
	public static class PlanBuild
	{
		private static class PlanBuildPatches
		{
			[HarmonyPatch("PlanBuild.Plans.PlanDB, PlanBuild", "ScanPieceTables")]
			[HarmonyPostfix]
			public static void ScanPieceTables()
			{
				Plugin.IndexPrefabs();
			}
		}

		public static void InitCompat()
		{
			Plugin.Instance.harmony.PatchAll(typeof(PlanBuildPatches));
		}
	}
	public static class WackysDatabase
	{
		public static void InitCompat()
		{
		}

		private static void SubscribeToReload()
		{
			EventInfo @event = Type.GetType("wackydatabase.SetData.Reload, WackysDatabase").GetEvent("OnAllReloaded");
			@event.AddEventHandler(null, (Action)delegate
			{
				Plugin.IndexPrefabs();
				Plugin.UpdatePieceTables();
			});
		}
	}
}