Decompiled source of Ewigschlag v0.1.0

Ewigschlag.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("Ewigschlag")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Ewigschlag")]
[assembly: AssemblyTitle("Ewigschlag")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace GoblinStudio.Ewigschlag
{
	[BepInPlugin("GoblinStudio.Ewigschlag", "Ewigschlag", "0.1.0")]
	[BepInDependency("blacks7ar.FineWoodPieces", "1.6.5")]
	public sealed class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(ObjectDB), "Awake")]
		[HarmonyAfter(new string[] { "blacks7ar.FineWoodPieces", "org.bepinex.helpers.ItemManager", "org.bepinex.helpers.PieceManager" })]
		private static class ObjectDBInitPatch
		{
			private static void Postfix(ObjectDB __instance)
			{
				TryInitialize(__instance);
				LogObjectDbState("ObjectDB.Awake/Postfix", __instance);
			}
		}

		[HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")]
		[HarmonyAfter(new string[] { "blacks7ar.FineWoodPieces", "org.bepinex.helpers.ItemManager", "org.bepinex.helpers.PieceManager" })]
		private static class ObjectDbCopyDiagnosticPatch
		{
			private static void Postfix(ObjectDB __instance, ObjectDB __0)
			{
				LogObjectDbState("ObjectDB.CopyOtherDB/Postfix", __instance, __0);
			}
		}

		[HarmonyPatch(typeof(Player), "Awake")]
		private static class PlayerAwakePatch
		{
			private static void Postfix(Player __instance)
			{
				LogObjectDbState("Player.Awake", ObjectDB.instance);
			}
		}

		[HarmonyPatch(typeof(Player), "Load")]
		private static class PlayerLoadPatch
		{
			private static void Postfix(Player __instance)
			{
				RefreshKnownRecipes(__instance);
			}
		}

		[HarmonyPatch(typeof(InventoryGui), "SetupCrafting")]
		private static class CraftingVisibilityDiagnosticPatch
		{
			private static void Postfix()
			{
				LogObjectDbState("InventoryGui.SetupCrafting", ObjectDB.instance);
				if (!visibilityDiagnosticLogged && initialized && !((Object)(object)Player.m_localPlayer == (Object)null))
				{
					visibilityDiagnosticLogged = true;
					DiagnoseCraftingVisibility(Player.m_localPlayer);
				}
			}
		}

		private sealed class PieceCollector
		{
			private readonly HashSet<GameObject> references = new HashSet<GameObject>(ReferenceEqualityComparer<GameObject>.Instance);

			private readonly Dictionary<string, GameObject> names = new Dictionary<string, GameObject>(StringComparer.Ordinal);

			public List<GameObject> Pieces { get; } = new List<GameObject>();

			public int ReferenceDuplicates { get; private set; }

			public int NameDuplicates { get; private set; }

			public int NameConflicts { get; private set; }

			public void AddTable(PieceTable table)
			{
				foreach (GameObject piece in table.m_pieces)
				{
					if ((Object)(object)piece == (Object)null)
					{
						continue;
					}
					GameObject value;
					if (references.Contains(piece))
					{
						ReferenceDuplicates++;
					}
					else if (names.TryGetValue(((Object)piece).name, out value))
					{
						NameDuplicates++;
						if (value != piece)
						{
							NameConflicts++;
							Debug.LogWarning((object)("Ewigschlag: Namenskonflikt bei Piece '" + ((Object)piece).name + "'; erste Referenz bleibt erhalten."));
						}
					}
					else
					{
						references.Add(piece);
						names.Add(((Object)piece).name, piece);
						Pieces.Add(piece);
					}
				}
			}
		}

		private sealed class ReferenceEqualityComparer<T> : IEqualityComparer<T> where T : class
		{
			public static readonly ReferenceEqualityComparer<T> Instance = new ReferenceEqualityComparer<T>();

			public bool Equals(T x, T y)
			{
				return x == y;
			}

			public int GetHashCode(T obj)
			{
				return RuntimeHelpers.GetHashCode(obj);
			}
		}

		public const string PluginGuid = "GoblinStudio.Ewigschlag";

		public const string PluginName = "Ewigschlag";

		public const string PluginVersion = "0.1.0";

		public const string FineWoodGuid = "blacks7ar.FineWoodPieces";

		private const string VanillaHammerName = "Hammer";

		private const string FineHammerName = "BFP_FineHammer";

		private const string FineHammerTableName = "BFP_FineHammerPieceTable";

		private const string EwigschlagName = "GoblinStudio_Ewigschlag";

		private const string EwigschlagTableName = "GoblinStudio_EwigschlagPieceTable";

		private const string EwigschlagBundleResourceName = "Ewigschlag.assets.ewigschlagbundle";

		private const string EwigschlagPrefabAssetPath = "assets/generated/goblinstudio_ewigschlag.prefab";

		private const string EwigschlagIconAssetPath = "assets/icons/everstrike_icon.png";

		private static bool initialized;

		private static bool initializationInProgress;

		private static bool earlyLifecycleLogged;

		private static bool knownRecipesRefreshPending;

		private static bool knownRecipesRefreshCompleted;

		private static bool visibilityDiagnosticLogged;

		private static bool ewigschlagBundleLoadAttempted;

		private static AssetBundle ewigschlagBundle;

		private static GameObject ewigschlagAssetPrefab;

		private static ManualLogSource Log;

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			new Harmony("GoblinStudio.Ewigschlag").PatchAll(typeof(Plugin).Assembly);
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Ewigschlag 0.1.0 geladen; Initialisierung wird nach ObjectDB.Awake versucht.");
		}

		private static void LogObjectDbState(string phase, ObjectDB concreteInstance, ObjectDB sourceInstance = null)
		{
			ObjectDB instance = ObjectDB.instance;
			bool value = (Object)(object)instance != (Object)null;
			bool num = (Object)(object)concreteInstance != (Object)null;
			int num2 = ((num && concreteInstance.m_recipes != null) ? concreteInstance.m_recipes.Count : (-1));
			int num3 = ((num && concreteInstance.m_items != null) ? concreteInstance.m_items.Count : (-1));
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)("Instanzdiagnose: Phase=" + phase + "; ObjectDB.instance != null=" + YesNo(value) + "; activeInstanceID=" + InstanceId(instance) + "; concreteInstanceID=" + InstanceId(concreteInstance) + "; m_recipes.Count=" + num2 + "; Ewigschlag-Rezept=" + YesNo(ContainsEwigschlagRecipe(concreteInstance)) + "; m_items.Count=" + num3 + "; Ewigschlag-Item=" + YesNo(ContainsEwigschlagItem(concreteInstance)) + (((Object)(object)sourceInstance == (Object)null) ? string.Empty : ("; sourceInstanceID=" + InstanceId(sourceInstance))) + "."));
			}
		}

		private static string InstanceId(ObjectDB objectDb)
		{
			if (!((Object)(object)objectDb == (Object)null))
			{
				return ((Object)objectDb).GetInstanceID().ToString();
			}
			return "<null>";
		}

		private static string YesNo(bool value)
		{
			if (!value)
			{
				return "nein";
			}
			return "ja";
		}

		private static bool ContainsEwigschlagRecipe(ObjectDB objectDb)
		{
			if ((Object)(object)objectDb == (Object)null || objectDb.m_recipes == null)
			{
				return false;
			}
			foreach (Recipe recipe in objectDb.m_recipes)
			{
				if (recipe?.m_item?.m_itemData?.m_shared?.m_name == "$item_goblinstudio_ewigschlag")
				{
					return true;
				}
			}
			return false;
		}

		private static bool ContainsEwigschlagItem(ObjectDB objectDb)
		{
			if ((Object)(object)objectDb == (Object)null || objectDb.m_items == null)
			{
				return false;
			}
			foreach (GameObject item in objectDb.m_items)
			{
				if ((Object)(object)item != (Object)null && ((Object)item).name == "GoblinStudio_Ewigschlag")
				{
					return true;
				}
			}
			return false;
		}

		private static bool TryLoadEwigschlagPrefab(out GameObject prefab)
		{
			prefab = ewigschlagAssetPrefab;
			if ((Object)(object)prefab != (Object)null)
			{
				return true;
			}
			if (ewigschlagBundleLoadAttempted)
			{
				return false;
			}
			ewigschlagBundleLoadAttempted = true;
			try
			{
				using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Ewigschlag.assets.ewigschlagbundle"))
				{
					if (stream == null)
					{
						throw new FileNotFoundException("EmbeddedResource nicht gefunden.", "Ewigschlag.assets.ewigschlagbundle");
					}
					using MemoryStream memoryStream = new MemoryStream();
					stream.CopyTo(memoryStream);
					byte[] array = memoryStream.ToArray();
					if (array.Length == 0)
					{
						throw new InvalidDataException("EmbeddedResource ist leer.");
					}
					ewigschlagBundle = AssetBundle.LoadFromMemory(array);
				}
				if ((Object)(object)ewigschlagBundle == (Object)null)
				{
					throw new InvalidDataException("AssetBundle konnte nicht aus dem EmbeddedResource geladen werden.");
				}
				ewigschlagAssetPrefab = ewigschlagBundle.LoadAsset<GameObject>("assets/generated/goblinstudio_ewigschlag.prefab");
				if ((Object)(object)ewigschlagAssetPrefab == (Object)null || ((Object)ewigschlagAssetPrefab).name != "GoblinStudio_Ewigschlag")
				{
					throw new InvalidDataException("Ewigschlag-Prefab konnte unter dem erwarteten Assetpfad nicht geladen werden.");
				}
				ItemDrop component = ewigschlagAssetPrefab.GetComponent<ItemDrop>();
				if ((Object)(object)component == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null)
				{
					throw new InvalidDataException("Ewigschlag-Prefab enthaelt keine gueltige ItemDrop/ItemData/SharedData-Struktur.");
				}
				prefab = ewigschlagAssetPrefab;
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)"Ewigschlag AssetBundle geladen; Prefab geladen; Prefab Unity-gueltig; ItemDrop gueltig; ItemData vorhanden; SharedData vorhanden; Asset-Prefab nicht ueber Instantiate(Hammer) erzeugt.");
				}
				return true;
			}
			catch (Exception ex)
			{
				if ((Object)(object)ewigschlagBundle != (Object)null)
				{
					ewigschlagBundle.Unload(false);
				}
				ewigschlagBundle = null;
				ewigschlagAssetPrefab = null;
				prefab = null;
				LogFailClosed("Ewigschlag AssetBundle/Prefab konnte nicht geladen werden: " + ex.Message);
				return false;
			}
		}

		private static void ConfigureEwigschlagItemData(GameObject itemPrefab, ItemDrop itemDrop, ItemDrop vanillaHammer, PieceTable combinedTable)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)itemPrefab == (Object)null || (Object)(object)itemDrop == (Object)null || itemDrop.m_itemData == null || itemDrop.m_itemData.m_shared == null || (Object)(object)vanillaHammer == (Object)null || vanillaHammer.m_itemData == null || vanillaHammer.m_itemData.m_shared == null || (Object)(object)combinedTable == (Object)null)
			{
				throw new InvalidDataException("Ewigschlag-Itemdaten konnten nicht sicher konfiguriert werden.");
			}
			SharedData shared = itemDrop.m_itemData.m_shared;
			SharedData shared2 = vanillaHammer.m_itemData.m_shared;
			shared.m_itemType = (ItemType)19;
			shared.m_name = "$item_goblinstudio_ewigschlag";
			shared.m_description = "$item_goblinstudio_ewigschlag_description";
			Sprite val = ewigschlagBundle.LoadAsset<Sprite>("assets/icons/everstrike_icon.png");
			if ((Object)(object)val == (Object)null)
			{
				throw new InvalidDataException("Everstrike-Icon konnte nicht aus dem Embedded Bundle geladen werden.");
			}
			shared.m_icons = (Sprite[])(object)new Sprite[1] { val };
			shared.m_equipDuration = shared2.m_equipDuration;
			shared.m_animationState = shared2.m_animationState;
			shared.m_attack.m_attackAnimation = shared2.m_attack.m_attackAnimation;
			shared.m_toolTier = shared2.m_toolTier;
			shared.m_centerCamera = shared2.m_centerCamera;
			shared.m_buildPieces = combinedTable;
			shared.m_useDurability = false;
			shared.m_useDurabilityDrain = 0f;
			shared.m_destroyBroken = false;
			itemDrop.m_itemData.m_dropPrefab = itemPrefab;
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)"Ewigschlag-Itemdaten konfiguriert; ItemType=Tool; Vanilla-Animation und Icon uebernommen; eigene SharedData bleibt erhalten; PieceTable=GoblinStudio_EwigschlagPieceTable; Haltbarkeit deaktiviert.");
			}
		}

		private static void TryInitialize(ObjectDB objectDb)
		{
			if (initialized || initializationInProgress)
			{
				return;
			}
			if ((Object)(object)objectDb == (Object)null)
			{
				LogFailClosed("Die aktuelle ObjectDB-Instanz ist ungueltig.");
				return;
			}
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null)
			{
				if (!earlyLifecycleLogged)
				{
					earlyLifecycleLogged = true;
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogInfo((object)"Ewigschlag Initialisierung noch nicht bereit; warte auf eine spaetere ObjectDB-Instanz.");
					}
				}
				return;
			}
			GameObject itemPrefab = objectDb.GetItemPrefab("Hammer");
			GameObject itemPrefab2 = objectDb.GetItemPrefab("BFP_FineHammer");
			GameObject prefab = instance.GetPrefab("BFP_FineHammerPieceTable");
			if ((Object)(object)itemPrefab == (Object)null)
			{
				LogFailClosed("Vanilla-Hammer 'Hammer' nicht gefunden.");
				return;
			}
			if ((Object)(object)itemPrefab2 == (Object)null)
			{
				LogFailClosed("FineHammer 'BFP_FineHammer' nicht gefunden.");
				return;
			}
			if ((Object)(object)prefab == (Object)null || (Object)(object)prefab.GetComponent<PieceTable>() == (Object)null)
			{
				LogFailClosed("FineHammer-PieceTable 'BFP_FineHammerPieceTable' nicht gefunden oder ungueltig.");
				return;
			}
			ItemDrop component = itemPrefab.GetComponent<ItemDrop>();
			ItemDrop component2 = itemPrefab2.GetComponent<ItemDrop>();
			if ((Object)(object)component == (Object)null || (Object)(object)component2 == (Object)null || component.m_itemData == null || component.m_itemData.m_shared == null || component2.m_itemData == null || component2.m_itemData.m_shared == null)
			{
				LogFailClosed("Hammer-ItemData konnte nicht gelesen werden.");
				return;
			}
			PieceTable buildPieces = component.m_itemData.m_shared.m_buildPieces;
			PieceTable buildPieces2 = component2.m_itemData.m_shared.m_buildPieces;
			PieceTable component3 = prefab.GetComponent<PieceTable>();
			if ((Object)(object)buildPieces == (Object)null)
			{
				LogFailClosed("Vanilla-PieceTable fehlt.");
				return;
			}
			if ((Object)(object)buildPieces2 == (Object)null)
			{
				LogFailClosed("FineHammer-PieceTable fehlt.");
				return;
			}
			if ((Object)(object)component3 == (Object)null)
			{
				LogFailClosed("Registrierte FineHammer-PieceTable fehlt.");
				return;
			}
			if (buildPieces.m_pieces == null || buildPieces.m_pieces.Count == 0)
			{
				LogFailClosed("Vanilla-PieceTable ist noch nicht befuellt.");
				return;
			}
			if (buildPieces2.m_pieces == null || buildPieces2.m_pieces.Count == 0)
			{
				LogFailClosed("FineHammer-PieceTable ist noch nicht befuellt.");
				return;
			}
			if (buildPieces2 != component3)
			{
				LogFailClosed("BFP_FineHammer verweist nicht auf die registrierte FineHammer-PieceTable.");
				return;
			}
			ManualLogSource log2 = Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("Vanilla-Hammer gefunden: " + buildPieces.m_pieces.Count + " Pieces."));
			}
			ManualLogSource log3 = Log;
			if (log3 != null)
			{
				log3.LogInfo((object)("FineHammer gefunden: " + buildPieces2.m_pieces.Count + " Pieces."));
			}
			initializationInProgress = true;
			GameObject val = null;
			GameObject prefab2 = null;
			bool flag = false;
			try
			{
				val = Object.Instantiate<GameObject>(((Component)buildPieces).gameObject);
				((Object)val).name = "GoblinStudio_EwigschlagPieceTable";
				PieceTable component4 = val.GetComponent<PieceTable>();
				if ((Object)(object)component4 == (Object)null)
				{
					LogFailClosed("Eigene PieceTable konnte nicht erzeugt werden.");
					Object.Destroy((Object)(object)val);
					return;
				}
				Object.DontDestroyOnLoad((Object)(object)val);
				CopyTableMetadata(buildPieces, buildPieces2, component4);
				PieceCollector pieceCollector = new PieceCollector();
				pieceCollector.AddTable(buildPieces);
				pieceCollector.AddTable(buildPieces2);
				component4.m_pieces = pieceCollector.Pieces;
				if (!TryLoadEwigschlagPrefab(out prefab2))
				{
					Object.Destroy((Object)(object)val);
					return;
				}
				ItemDrop component5 = prefab2.GetComponent<ItemDrop>();
				if ((Object)(object)component5 == (Object)null || component5.m_itemData == null || component5.m_itemData.m_shared == null)
				{
					LogFailClosed("Geladenes Ewigschlag-AssetPrefab ist unvollstaendig.");
					Object.Destroy((Object)(object)val);
					return;
				}
				if (component5.m_itemData == component.m_itemData || component5.m_itemData.m_shared == component.m_itemData.m_shared)
				{
					LogFailClosed("Das technische ItemPrefab teilt ItemData oder SharedData mit dem Vanilla-Hammer.");
					Object.Destroy((Object)(object)val);
					return;
				}
				ConfigureEwigschlagItemData(prefab2, component5, component, component4);
				if (!objectDb.m_items.Contains(prefab2))
				{
					objectDb.m_items.Add(prefab2);
					flag = true;
					ManualLogSource log4 = Log;
					if (log4 != null)
					{
						log4.LogInfo((object)"Ewigschlag zu ObjectDB.m_items hinzugefuegt.");
					}
				}
				UpdateObjectDbRegisters(objectDb);
				ManualLogSource log5 = Log;
				if (log5 != null)
				{
					log5.LogInfo((object)"ObjectDB.UpdateRegisters() ausgefuehrt.");
				}
				GameObject itemPrefab3 = objectDb.GetItemPrefab("GoblinStudio_Ewigschlag");
				ItemDrop val2 = (((Object)(object)itemPrefab3 == (Object)null) ? null : itemPrefab3.GetComponent<ItemDrop>());
				if (itemPrefab3 != prefab2 || val2 != component5)
				{
					LogFailClosed("Ewigschlag nach ObjectDB.UpdateRegisters() nicht ueber ObjectDB auffindbar.");
					if (flag)
					{
						RemoveObjectDbItem(objectDb, prefab2);
					}
					Object.Destroy((Object)(object)val);
					return;
				}
				ManualLogSource log6 = Log;
				if (log6 != null)
				{
					log6.LogInfo((object)"Ewigschlag nach Registerupdate ueber ObjectDB auffindbar: ja.");
				}
				if (!AddLocalization())
				{
					LogFailClosed("Localization-Registrierung fehlgeschlagen.");
					if (flag)
					{
						RemoveObjectDbItem(objectDb, prefab2);
					}
					Object.Destroy((Object)(object)val);
					return;
				}
				ManualLogSource log7 = Log;
				if (log7 != null)
				{
					log7.LogInfo((object)"Localization erfolgreich registriert.");
				}
				if (!AddRecipe(objectDb, prefab2))
				{
					LogFailClosed("Rezeptregistrierung fehlgeschlagen.");
					if (flag)
					{
						RemoveObjectDbItem(objectDb, prefab2);
					}
					Object.Destroy((Object)(object)val);
					return;
				}
				ManualLogSource log8 = Log;
				if (log8 != null)
				{
					log8.LogInfo((object)("Ewigschlag Piece-Anzahl: " + pieceCollector.Pieces.Count + "; Referenzduplikate: " + pieceCollector.ReferenceDuplicates + "; Namensduplikate: " + pieceCollector.NameDuplicates + "; Namenskonflikte: " + pieceCollector.NameConflicts + "."));
				}
				ManualLogSource log9 = Log;
				if (log9 != null)
				{
					log9.LogInfo((object)"GoblinStudio_EwigschlagPieceTable erfolgreich; Originaltabellen wurden nur gelesen.");
				}
				ManualLogSource log10 = Log;
				if (log10 != null)
				{
					log10.LogInfo((object)"Ewigschlag registriert; Haltbarkeit deaktiviert.");
				}
				initialized = true;
				knownRecipesRefreshPending = true;
				if ((Object)(object)Player.m_localPlayer != (Object)null)
				{
					ManualLogSource log11 = Log;
					if (log11 != null)
					{
						log11.LogInfo((object)"Lokaler Player bereits vorhanden: ja.");
					}
					RefreshKnownRecipes(Player.m_localPlayer);
					return;
				}
				ManualLogSource log12 = Log;
				if (log12 != null)
				{
					log12.LogInfo((object)"Lokaler Player bereits vorhanden: nein.");
				}
				ManualLogSource log13 = Log;
				if (log13 != null)
				{
					log13.LogInfo((object)"KnownRecipe-Registrierung fuer Player.Load vorgemerkt.");
				}
			}
			catch (Exception ex)
			{
				if (flag)
				{
					RemoveObjectDbItem(objectDb, prefab2);
				}
				if ((Object)(object)val != (Object)null)
				{
					Object.Destroy((Object)(object)val);
				}
				LogFailClosed("Ausnahme waehrend der Initialisierung: " + ex);
			}
			finally
			{
				initializationInProgress = false;
			}
		}

		private static void RefreshKnownRecipes(Player player)
		{
			if (!initialized || !knownRecipesRefreshPending || knownRecipesRefreshCompleted || (Object)(object)player == (Object)null)
			{
				return;
			}
			try
			{
				if ((Object)(object)Player.m_localPlayer != (Object)null && Player.m_localPlayer != player)
				{
					return;
				}
				Recipe val = FindEwigschlagRecipe(ObjectDB.instance);
				string text = val?.m_item?.m_itemData?.m_shared?.m_name;
				if ((Object)(object)val == (Object)null || string.IsNullOrEmpty(text))
				{
					throw new InvalidOperationException("Ewigschlag-Rezept ist fuer KnownRecipe-Registrierung nicht verfuegbar.");
				}
				FieldInfo field = typeof(Player).GetField("m_knownRecipes", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field?.GetValue(player) is HashSet<string> hashSet && hashSet.Contains(text))
				{
					knownRecipesRefreshPending = false;
					knownRecipesRefreshCompleted = true;
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogInfo((object)("KnownRecipe bereits vorhanden: " + text + "."));
					}
					return;
				}
				MethodInfo? method = typeof(Player).GetMethod("AddKnownRecipe", BindingFlags.Instance | BindingFlags.NonPublic);
				if (method == null)
				{
					throw new MissingMethodException(typeof(Player).FullName, "AddKnownRecipe");
				}
				method.Invoke(player, new object[1] { val });
				if (!(field?.GetValue(player) is HashSet<string> hashSet2) || !hashSet2.Contains(text))
				{
					throw new InvalidOperationException("Vanilla AddKnownRecipe hat den Ewigschlag-Schluessel nicht registriert.");
				}
				knownRecipesRefreshPending = false;
				knownRecipesRefreshCompleted = true;
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogInfo((object)("KnownRecipe ueber Vanilla AddKnownRecipe registriert: " + text + "."));
				}
			}
			catch (Exception ex)
			{
				LogFailClosed("KnownRecipes-Refresh fehlgeschlagen: " + ex);
			}
		}

		private static Recipe FindEwigschlagRecipe(ObjectDB objectDb)
		{
			if ((Object)(object)objectDb == (Object)null || objectDb.m_recipes == null)
			{
				return null;
			}
			foreach (Recipe recipe in objectDb.m_recipes)
			{
				if (recipe?.m_item?.m_itemData?.m_shared?.m_name == "$item_goblinstudio_ewigschlag")
				{
					return recipe;
				}
			}
			return null;
		}

		private static void DiagnoseCraftingVisibility(Player player)
		{
			try
			{
				ObjectDB instance = ObjectDB.instance;
				if ((Object)(object)instance == (Object)null || instance.m_recipes == null)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogError((object)"Sichtbarkeitsdiagnose: ObjectDB oder Rezeptliste fehlt.");
					}
					return;
				}
				GameObject itemPrefab = instance.GetItemPrefab("GoblinStudio_Ewigschlag");
				ItemDrop val = (((Object)(object)itemPrefab == (Object)null) ? null : itemPrefab.GetComponent<ItemDrop>());
				string text = val?.m_itemData?.m_shared?.m_name;
				Recipe val2 = null;
				if (!string.IsNullOrEmpty(text))
				{
					foreach (Recipe recipe in instance.m_recipes)
					{
						if (recipe?.m_item?.m_itemData?.m_shared?.m_name == text)
						{
							val2 = recipe;
							break;
						}
					}
				}
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogInfo((object)("Sichtbarkeitsdiagnose: Rezept in ObjectDB.m_recipes: " + (((Object)(object)val2 != (Object)null) ? "ja" : "nein") + "."));
				}
				if ((Object)(object)val2 == (Object)null || (Object)(object)val == (Object)null)
				{
					return;
				}
				string text2 = (((Object)(object)val2.m_craftingStation == (Object)null) ? "<null>" : val2.m_craftingStation.m_name);
				ManualLogSource log3 = Log;
				if (log3 != null)
				{
					log3.LogInfo((object)("Sichtbarkeitsdiagnose: m_enabled=" + val2.m_enabled + "; m_item gueltig=" + ((Object)(object)val2.m_item != (Object)null) + "; CraftingStation gueltig=" + ((Object)(object)val2.m_craftingStation != (Object)null) + "; erwartete Station=piece_workbench; tatsaechliche Station=" + text2 + "; Mindestlevel=" + val2.m_minStationLevel + "."));
				}
				ManualLogSource log4 = Log;
				if (log4 != null)
				{
					log4.LogInfo((object)("Sichtbarkeitsdiagnose: Recipe-Key=" + text + "."));
				}
				FieldInfo? field = typeof(Player).GetField("m_knownRecipes", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field2 = typeof(Player).GetField("m_knownMaterial", BindingFlags.Instance | BindingFlags.NonPublic);
				FieldInfo field3 = typeof(Player).GetField("m_knownStations", BindingFlags.Instance | BindingFlags.NonPublic);
				HashSet<string> hashSet = field?.GetValue(player) as HashSet<string>;
				HashSet<string> hashSet2 = field2?.GetValue(player) as HashSet<string>;
				Dictionary<string, int> dictionary = field3?.GetValue(player) as Dictionary<string, int>;
				bool flag = hashSet?.Contains(text) ?? false;
				ManualLogSource log5 = Log;
				if (log5 != null)
				{
					log5.LogInfo((object)("Sichtbarkeitsdiagnose: Player.m_knownRecipes enthaelt Recipe-Key=" + (flag ? "ja" : "nein") + "."));
				}
				GameObject itemPrefab2 = instance.GetItemPrefab("Wood");
				string text3 = (((Object)(object)itemPrefab2 == (Object)null) ? null : itemPrefab2.GetComponent<ItemDrop>())?.m_itemData?.m_shared?.m_name;
				bool flag2 = !string.IsNullOrEmpty(text3) && hashSet2 != null && hashSet2.Contains(text3);
				int num = 0;
				Inventory inventory = ((Humanoid)player).GetInventory();
				if (inventory != null && !string.IsNullOrEmpty(text3))
				{
					num = inventory.CountItems(text3, -1, false);
				}
				ManualLogSource log6 = Log;
				if (log6 != null)
				{
					log6.LogInfo((object)("Sichtbarkeitsdiagnose: Wood-Key=" + (text3 ?? "<null>") + "; KnownMaterial=" + (flag2 ? "ja" : "nein") + "; Inventarmenge=" + num + "; benoetigt=1."));
				}
				CraftingStation currentCraftingStation = player.GetCurrentCraftingStation();
				bool flag3 = !string.IsNullOrEmpty(text2) && dictionary != null && dictionary.ContainsKey(text2);
				ManualLogSource log7 = Log;
				if (log7 != null)
				{
					log7.LogInfo((object)("Sichtbarkeitsdiagnose: Werkbankkenntnis=" + (flag3 ? "ja" : "nein") + "; aktuelle CraftingStation=" + (((Object)(object)currentCraftingStation == (Object)null) ? "<null>" : currentCraftingStation.m_name) + "."));
				}
				List<string> list = typeof(Player).GetField("s_FilterCraft", BindingFlags.Static | BindingFlags.NonPublic)?.GetValue(null) as List<string>;
				bool flag4 = list != null && list.Count > 0;
				bool flag5 = !flag4;
				if (flag4)
				{
					string text4 = ((Localization.instance == null) ? string.Empty : Localization.instance.Localize(text));
					foreach (string item in list)
					{
						if (!string.IsNullOrEmpty(item))
						{
							string value = item.ToLowerInvariant();
							if ((((Object)itemPrefab).name ?? string.Empty).ToLowerInvariant().Contains(value) || text.ToLowerInvariant().Contains(value) || (text4 ?? string.Empty).ToLowerInvariant().Contains(value))
							{
								flag5 = true;
								break;
							}
						}
					}
				}
				List<Recipe> list2 = new List<Recipe>();
				player.GetAvailableRecipes(ref list2);
				bool flag6 = false;
				foreach (Recipe item2 in list2)
				{
					if ((Object)(object)item2 == (Object)(object)val2 || item2?.m_item?.m_itemData?.m_shared?.m_name == text)
					{
						flag6 = true;
						break;
					}
				}
				ManualLogSource log8 = Log;
				if (log8 != null)
				{
					log8.LogInfo((object)("Sichtbarkeitsdiagnose: GetAvailableRecipes enthaelt Ewigschlag=" + (flag6 ? "ja" : "nein") + "; Crafting-Filter aktiv=" + (flag4 ? "ja" : "nein") + "; Filter-Treffer=" + (flag5 ? "ja" : "nein") + "."));
				}
				if (!flag6)
				{
					string text5 = "unbekannt";
					if (!val2.m_enabled)
					{
						text5 = "Recipe.m_enabled ist false";
					}
					else if ((Object)(object)val2.m_item == (Object)null)
					{
						text5 = "Recipe.m_item ist ungueltig";
					}
					else if (flag4 && !flag5)
					{
						text5 = "aktiver Crafting-Filter passt nicht";
					}
					else if (!flag)
					{
						text5 = "Recipe-Key fehlt in Player.m_knownRecipes";
					}
					else if ((Object)(object)currentCraftingStation == (Object)null)
					{
						text5 = "keine aktuelle CraftingStation";
					}
					else if (currentCraftingStation.m_name != text2)
					{
						text5 = "aktuelle CraftingStation stimmt nicht mit der Rezeptstation ueberein";
					}
					ManualLogSource log9 = Log;
					if (log9 != null)
					{
						log9.LogInfo((object)("Sichtbarkeitsdiagnose: erster belegbarer Filtergrund=" + text5 + "."));
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log10 = Log;
				if (log10 != null)
				{
					log10.LogError((object)("Sichtbarkeitsdiagnose fehlgeschlagen: " + ex));
				}
			}
		}

		private static void RemoveObjectDbItem(ObjectDB objectDb, GameObject itemPrefab)
		{
			if ((Object)(object)objectDb == (Object)null || objectDb.m_items == null || (Object)(object)itemPrefab == (Object)null || !objectDb.m_items.Remove(itemPrefab))
			{
				return;
			}
			try
			{
				UpdateObjectDbRegisters(objectDb);
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)"Ewigschlag aus ObjectDB.m_items entfernt; Register wiederhergestellt.");
				}
			}
			catch (Exception ex)
			{
				LogFailClosed("ObjectDB-Register konnten nach Abbruch nicht wiederhergestellt werden: " + ex);
			}
		}

		private static void UpdateObjectDbRegisters(ObjectDB objectDb)
		{
			MethodInfo? method = typeof(ObjectDB).GetMethod("UpdateRegisters", BindingFlags.Instance | BindingFlags.NonPublic);
			if (method == null)
			{
				throw new MissingMethodException(typeof(ObjectDB).FullName, "UpdateRegisters");
			}
			method.Invoke(objectDb, null);
		}

		private static void CopyTableMetadata(PieceTable vanilla, PieceTable fineHammer, PieceTable target)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			target.m_canRemovePieces = vanilla.m_canRemovePieces;
			target.m_canRemoveFeasts = vanilla.m_canRemoveFeasts;
			target.m_selectedPiece = (Vector2Int[])(object)new Vector2Int[0];
			target.m_lastSelectedPiece = (Vector2Int[])(object)new Vector2Int[0];
			target.m_categories = new List<PieceCategory>();
			target.m_categoryLabels = new List<string>();
			target.m_categoriesFolded = new List<PieceCategory>();
			target.m_skill = vanilla.m_skill;
			AppendCategories(vanilla, target);
			AppendCategories(fineHammer, target);
		}

		private static void AppendCategories(PieceTable source, PieceTable target)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: 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)
			if (source.m_categories == null)
			{
				return;
			}
			for (int i = 0; i < source.m_categories.Count; i++)
			{
				PieceCategory item = source.m_categories[i];
				if (!target.m_categories.Contains(item))
				{
					target.m_categories.Add(item);
					string item2 = ((source.m_categoryLabels != null && i < source.m_categoryLabels.Count) ? source.m_categoryLabels[i] : string.Empty);
					target.m_categoryLabels.Add(item2);
				}
			}
		}

		private static bool AddLocalization()
		{
			if (Localization.instance == null)
			{
				return false;
			}
			MethodInfo method = typeof(Localization).GetMethod("AddWord", BindingFlags.Instance | BindingFlags.NonPublic);
			if (method == null)
			{
				return false;
			}
			method.Invoke(Localization.instance, new object[2] { "item_goblinstudio_ewigschlag", "Everstrike" });
			method.Invoke(Localization.instance, new object[2] { "item_goblinstudio_ewigschlag_description", "Ein unzerstörbarer Bauhammer für große und kleine Wikingerprojekte." });
			return true;
		}

		private static bool AddRecipe(ObjectDB objectDb, GameObject itemPrefab)
		{
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: 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_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Expected O, but got Unknown
			//IL_0230: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_024b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Expected O, but got Unknown
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0262: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_0270: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Expected O, but got Unknown
			ItemDrop itemDrop = itemPrefab.GetComponent<ItemDrop>();
			if ((Object)(object)itemDrop == (Object)null)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogError((object)"Rezeptregistrierung: Ewigschlag-ItemDrop fehlt.");
				}
				return false;
			}
			if ((Object)(object)objectDb == (Object)null || objectDb.m_recipes == null)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogError((object)"Rezeptregistrierung: ObjectDB-Rezeptliste fehlt.");
				}
				return false;
			}
			if (objectDb.m_recipes.Exists((Recipe recipe) => (Object)(object)recipe != (Object)null && (Object)(object)recipe.m_item == (Object)(object)itemDrop))
			{
				ManualLogSource log3 = Log;
				if (log3 != null)
				{
					log3.LogInfo((object)"Rezept bereits vorhanden.");
				}
				return true;
			}
			GameObject itemPrefab2 = objectDb.GetItemPrefab("FineWood");
			ItemDrop val = (((Object)(object)itemPrefab2 == (Object)null) ? null : itemPrefab2.GetComponent<ItemDrop>());
			GameObject itemPrefab3 = objectDb.GetItemPrefab("RoundLog");
			ItemDrop val2 = (((Object)(object)itemPrefab3 == (Object)null) ? null : itemPrefab3.GetComponent<ItemDrop>());
			GameObject itemPrefab4 = objectDb.GetItemPrefab("Copper");
			ItemDrop val3 = (((Object)(object)itemPrefab4 == (Object)null) ? null : itemPrefab4.GetComponent<ItemDrop>());
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null)
			{
				ManualLogSource log4 = Log;
				if (log4 != null)
				{
					log4.LogError((object)"Rezeptregistrierung: FineWood, RoundLog oder Copper fehlt in ObjectDB.");
				}
				return false;
			}
			ZNetScene instance = ZNetScene.instance;
			if ((Object)(object)instance == (Object)null)
			{
				ManualLogSource log5 = Log;
				if (log5 != null)
				{
					log5.LogError((object)"Rezeptregistrierung: ZNetScene ist nicht verfuegbar.");
				}
				return false;
			}
			GameObject prefab = instance.GetPrefab("piece_workbench");
			CraftingStation val4 = (((Object)(object)prefab == (Object)null) ? null : prefab.GetComponent<CraftingStation>());
			if ((Object)(object)val4 == (Object)null)
			{
				ManualLogSource log6 = Log;
				if (log6 != null)
				{
					log6.LogError((object)"Rezeptregistrierung: piece_workbench oder CraftingStation fehlt in ZNetScene.");
				}
				return false;
			}
			ManualLogSource log7 = Log;
			if (log7 != null)
			{
				log7.LogInfo((object)"Rezeptregistrierung: piece_workbench gefunden.");
			}
			Recipe val5 = ScriptableObject.CreateInstance<Recipe>();
			if ((Object)(object)val5 == (Object)null)
			{
				ManualLogSource log8 = Log;
				if (log8 != null)
				{
					log8.LogError((object)"Rezeptregistrierung: Rezeptobjekt konnte nicht erzeugt werden.");
				}
				return false;
			}
			((Object)val5).name = "Recipe_GoblinStudio_Ewigschlag";
			val5.m_item = itemDrop;
			val5.m_amount = 1;
			val5.m_craftingStation = val4;
			val5.m_minStationLevel = 1;
			val5.m_resources = (Requirement[])(object)new Requirement[3]
			{
				new Requirement
				{
					m_resItem = val,
					m_amount = 10,
					m_amountPerLevel = 0,
					m_recover = true
				},
				new Requirement
				{
					m_resItem = val2,
					m_amount = 5,
					m_amountPerLevel = 0,
					m_recover = true
				},
				new Requirement
				{
					m_resItem = val3,
					m_amount = 3,
					m_amountPerLevel = 0,
					m_recover = true
				}
			};
			if ((Object)(object)val5.m_item == (Object)null || (Object)(object)val5.m_craftingStation == (Object)null || val5.m_resources == null || val5.m_resources.Length != 3 || (Object)(object)val5.m_resources[0].m_resItem == (Object)null || (Object)(object)val5.m_resources[1].m_resItem == (Object)null || (Object)(object)val5.m_resources[2].m_resItem == (Object)null)
			{
				ManualLogSource log9 = Log;
				if (log9 != null)
				{
					log9.LogError((object)"Rezeptregistrierung: Rezeptobjekt ist unvollstaendig.");
				}
				Object.Destroy((Object)(object)val5);
				return false;
			}
			objectDb.m_recipes.Add(val5);
			ManualLogSource log10 = Log;
			if (log10 != null)
			{
				log10.LogInfo((object)"Rezept erfolgreich registriert: 10 FineWood, 5 RoundLog, 3 Copper an der Werkbank.");
			}
			return true;
		}

		private static void LogFailClosed(string message)
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogError((object)("Ewigschlag Initialisierung abgebrochen: " + message));
			}
		}
	}
}