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("GoblinStudio")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Warm, rustic decoration pieces for Valheim.")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0")] [assembly: AssemblyProduct("CozyHearth")] [assembly: AssemblyTitle("CozyHearth")] [assembly: AssemblyVersion("0.1.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [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.CozyHearth { [BepInPlugin("GoblinStudio.CozyHearth", "Cozy Hearth", "0.1.0")] public sealed class CozyHearthPlugin : BaseUnityPlugin { private enum ObjectDbLifecycle { Awake, CopyOtherDB } [HarmonyPatch(typeof(ZNetScene), "Awake")] private static class ZNetSceneAwakePatch { [HarmonyPrefix] private static void Prefix(ZNetScene __instance) { if (!PrefabValid || (Object)(object)CushionPrefab == (Object)null) { return; } try { RegisterZNetScenePrefab(__instance); } catch (Exception ex) { PrefabValid = false; ManualLogSource? log = Log; if (log != null) { log.LogError((object)("ZNetScene-Registrierung fail-closed abgebrochen: " + ex.Message)); } } } } [HarmonyPatch(typeof(ObjectDB), "Awake")] private static class ObjectDbAwakePatch { [HarmonyPostfix] private static void Postfix(ObjectDB __instance) { RegisterHammerAndLocalization(__instance, ObjectDbLifecycle.Awake); } } [HarmonyPatch(typeof(ObjectDB), "CopyOtherDB")] private static class ObjectDbCopyOtherDbPatch { [HarmonyPostfix] private static void Postfix(ObjectDB __instance) { RegisterHammerAndLocalization(__instance, ObjectDbLifecycle.CopyOtherDB); } } [HarmonyPatch(typeof(Player), "Load", new Type[] { typeof(ZPackage) })] private static class PlayerLoadDiscoveryPatch { [HarmonyPostfix] private static void Postfix(Player __instance) { if (PlayerLoadDiscoveryLogged || (Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || !PrefabValid || (Object)(object)CushionPrefab == (Object)null || (Object)(object)BlanketPrefab == (Object)null || UpdateKnownRecipesListMethod == null) { return; } try { UpdateKnownRecipesListMethod.Invoke(__instance, null); PlayerLoadDiscoveryLogged = true; } catch (Exception ex) { ManualLogSource? log = Log; if (log != null) { log.LogError((object)("Player.Load Known-Piece-Discovery fail-closed abgebrochen: " + ex.Message)); } } } } public const string PluginId = "GoblinStudio.CozyHearth"; public const string PluginName = "Cozy Hearth"; public const string PluginVersion = "0.1.0"; private const string BundleResourceName = "CozyHearth.assets.goblinstudio_cozyhearth"; private const string PrefabAssetPath = "Assets/CozyHearth/Prefabs/GoblinStudio_CozyCushion.prefab"; private const string BlanketPrefabAssetPath = "Assets/CozyHearth/Prefabs/GoblinStudio_FoldedBlanket.prefab"; private const string PrefabName = "GoblinStudio_CozyCushion"; private const string BlanketPrefabName = "GoblinStudio_FoldedBlanket"; private const string PieceName = "$piece_goblinstudio_cozycushion"; private const string PieceDescription = "$piece_goblinstudio_cozycushion_description"; private const string BlanketPieceName = "$piece_goblinstudio_foldedblanket"; private const string BlanketPieceDescription = "$piece_goblinstudio_foldedblanket_description"; private const string HammerName = "Hammer"; private const string HammerPieceTableName = "_HammerPieceTable"; private const string DeerHideName = "DeerHide"; private const string LeatherScrapsName = "LeatherScraps"; private static ManualLogSource? Log; private static AssetBundle? Bundle; private static GameObject? CushionPrefab; private static GameObject? BlanketPrefab; private static bool LocalizationSubscribed; private static bool BundleLoadAttempted; private static bool PrefabValid; private static bool ObjectDbAwakeNotReadyLogged; private static bool PlayerLoadDiscoveryLogged; private static MethodInfo? UpdateKnownRecipesListMethod; private static bool HammerRegistrationSuccessLogged; private void Awake() { //IL_0072: Unknown result type (might be due to invalid IL or missing references) Log = ((BaseUnityPlugin)this).Logger; if (!LoadAndValidatePrefab()) { ((BaseUnityPlugin)this).Logger.LogError((object)"Cozy Hearth wird fail-closed nicht registriert."); return; } RegisterLocalizationIfReady(); UpdateKnownRecipesListMethod = typeof(Player).GetMethod("UpdateKnownRecipesList", BindingFlags.Instance | BindingFlags.NonPublic); if (UpdateKnownRecipesListMethod == null || UpdateKnownRecipesListMethod.GetParameters().Length != 0) { ((BaseUnityPlugin)this).Logger.LogError((object)"Player.UpdateKnownRecipesList wurde nicht mit der erwarteten Signatur gefunden; Load-Discovery-Fix bleibt fail-closed deaktiviert."); } new Harmony("GoblinStudio.CozyHearth").PatchAll(typeof(CozyHearthPlugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Cozy Hearth 0.1.0: Cozy-Cushion-Runtime-Candidate bereit."); } private static bool LoadAndValidatePrefab() { if (BundleLoadAttempted) { return PrefabValid; } BundleLoadAttempted = true; try { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("CozyHearth.assets.goblinstudio_cozyhearth"); if (stream == null || stream.Length <= 0) { throw new InvalidDataException("EmbeddedResource 'CozyHearth.assets.goblinstudio_cozyhearth' fehlt oder ist leer."); } byte[] array = new byte[stream.Length]; int num; for (int i = 0; i < array.Length; i += num) { num = stream.Read(array, i, array.Length - i); if (num <= 0) { throw new EndOfStreamException("Embedded AssetBundle wurde nicht vollstaendig gelesen."); } } Bundle = AssetBundle.LoadFromMemory(array); if ((Object)(object)Bundle == (Object)null) { throw new InvalidDataException("Embedded AssetBundle konnte nicht geladen werden."); } CushionPrefab = Bundle.LoadAsset("Assets/CozyHearth/Prefabs/GoblinStudio_CozyCushion.prefab"); BlanketPrefab = Bundle.LoadAsset("Assets/CozyHearth/Prefabs/GoblinStudio_FoldedBlanket.prefab"); ValidatePrefab(CushionPrefab); ValidateBlanketPrefab(BlanketPrefab); PrefabValid = true; ManualLogSource? log = Log; if (log != null) { log.LogInfo((object)"Embedded AssetBundle und GoblinStudio_CozyCushion statisch validiert."); } return true; } catch (Exception ex) { PrefabValid = false; CushionPrefab = null; BlanketPrefab = null; if ((Object)(object)Bundle != (Object)null) { Bundle.Unload(false); } Bundle = null; ManualLogSource? log2 = Log; if (log2 != null) { log2.LogError((object)("AssetBundle-/Prefab-Validierung fehlgeschlagen: " + ex.Message)); } return false; } } private static void ValidateBlanketPrefab(GameObject? prefab) { //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Invalid comparison between Unknown and I4 Require((Object)(object)prefab != (Object)null && ((Object)prefab).name == "GoblinStudio_FoldedBlanket", "Folded-Blanket-Prefabname oder Assetpfad ist ungueltig."); Require(prefab.layer == 10, "Folded-Blanket-Root-Layer muss 10 sein."); Piece[] componentsInChildren = prefab.GetComponentsInChildren(true); ZNetView[] componentsInChildren2 = prefab.GetComponentsInChildren(true); BoxCollider[] componentsInChildren3 = prefab.GetComponentsInChildren(true); Require(componentsInChildren.Length == 1 && (Object)(object)((Component)componentsInChildren[0]).gameObject == (Object)(object)prefab, "Folded Blanket benoetigt exakt eine Root-Piece-Komponente."); Require(componentsInChildren2.Length == 1 && (Object)(object)((Component)componentsInChildren2[0]).gameObject == (Object)(object)prefab, "Folded Blanket benoetigt exakt eine Root-ZNetView-Komponente."); Require(componentsInChildren3.Length == 1 && !((Collider)componentsInChildren3[0]).isTrigger, "Folded Blanket benoetigt exakt einen nicht-ausloesenden BoxCollider."); Require(prefab.GetComponentsInChildren(true).Length == 0, "Folded Blanket WearNTear ist nicht erlaubt."); Require(prefab.GetComponentsInChildren(true).Length == 0, "Folded Blanket Rigidbody ist nicht erlaubt."); Require(prefab.GetComponentsInChildren(true).Length == 0, "Folded Blanket ZSyncTransform ist nicht erlaubt."); Require(prefab.GetComponentsInChildren(true).Length == 0, "Folded Blanket ZSyncAnimation ist nicht erlaubt."); Transform val = prefab.transform.Find("Visual"); Transform val2 = ((val != null) ? val.Find("BlanketMesh") : null); Transform val3 = prefab.transform.Find("Collider"); Require((Object)(object)val != (Object)null && ((Component)val).gameObject.layer == 10, "Folded-Blanket-Visual-Layer muss 10 sein."); Require((Object)(object)val2 != (Object)null && ((Component)val2).gameObject.layer == 10, "Folded-Blanket-Mesh-Layer muss 10 sein."); Require((Object)(object)val3 != (Object)null && ((Component)val3).gameObject.layer == 16 && (Object)(object)((Component)componentsInChildren3[0]).transform == (Object)(object)val3, "Folded-Blanket-Collider-Layer muss 16 sein."); Component[] componentsInChildren4 = prefab.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren4.Length; i++) { Require((Object)(object)componentsInChildren4[i] != (Object)null, "Folded Blanket Missing Script gefunden."); } Piece val4 = componentsInChildren[0]; Require((Object)(object)val4.m_icon != (Object)null, "Folded-Blanket-Piece-Icon fehlt."); Require(val4.m_name == "$piece_goblinstudio_foldedblanket", "Folded-Blanket-Piece.m_name ist ungueltig."); Require(val4.m_description == "$piece_goblinstudio_foldedblanket_description", "Folded-Blanket-Piece.m_description ist ungueltig."); Require((int)val4.m_category == 4, "Folded Blanket Kategorie muss Furniture sein."); Require(val4.m_comfort == 0 && val4.m_canRotate && val4.m_canBeRemoved, "Folded Blanket Piece-Werte sind ungueltig."); Require((Object)(object)val4.m_craftingStation == (Object)null, "Folded Blanket darf keine Crafting Station verlangen."); Require(val4.m_resources != null && val4.m_resources.Length == 0, "Folded-Blanket-Requirements muessen initial leer sein."); } private static void ValidatePrefab(GameObject? prefab) { //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Invalid comparison between Unknown and I4 Require((Object)(object)prefab != (Object)null && ((Object)prefab).name == "GoblinStudio_CozyCushion", "Prefabname oder Assetpfad ist ungueltig."); Require(prefab.layer == 10, "Root-Layer muss 10 sein."); Piece[] componentsInChildren = prefab.GetComponentsInChildren(true); ZNetView[] componentsInChildren2 = prefab.GetComponentsInChildren(true); BoxCollider[] componentsInChildren3 = prefab.GetComponentsInChildren(true); Require(componentsInChildren.Length == 1 && (Object)(object)((Component)componentsInChildren[0]).gameObject == (Object)(object)prefab, "Exakt eine Root-Piece-Komponente erforderlich."); Require(componentsInChildren2.Length == 1 && (Object)(object)((Component)componentsInChildren2[0]).gameObject == (Object)(object)prefab, "Exakt eine Root-ZNetView-Komponente erforderlich."); Require(componentsInChildren3.Length == 1 && !((Collider)componentsInChildren3[0]).isTrigger, "Exakt ein nicht-ausloesender BoxCollider erforderlich."); Require(prefab.GetComponentsInChildren(true).Length == 0, "WearNTear ist nicht erlaubt."); Require(prefab.GetComponentsInChildren(true).Length == 0, "Rigidbody ist nicht erlaubt."); Require(prefab.GetComponentsInChildren(true).Length == 0, "ZSyncTransform ist nicht erlaubt."); Require(prefab.GetComponentsInChildren(true).Length == 0, "ZSyncAnimation ist nicht erlaubt."); Transform val = prefab.transform.Find("Visual"); Transform val2 = ((val != null) ? val.Find("CushionMesh") : null); Transform val3 = prefab.transform.Find("Collider"); Require((Object)(object)val != (Object)null && ((Component)val).gameObject.layer == 10, "Visual-Layer muss 10 sein."); Require((Object)(object)val2 != (Object)null && ((Component)val2).gameObject.layer == 10, "CushionMesh-Layer muss 10 sein."); Require((Object)(object)val3 != (Object)null && ((Component)val3).gameObject.layer == 16 && (Object)(object)((Component)componentsInChildren3[0]).transform == (Object)(object)val3, "Collider-Layer muss 16 sein."); Component[] componentsInChildren4 = prefab.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren4.Length; i++) { Require((Object)(object)componentsInChildren4[i] != (Object)null, "Missing Script gefunden."); } Piece val4 = componentsInChildren[0]; Require((Object)(object)val4.m_icon != (Object)null, "Piece-Icon fehlt."); Require(val4.m_name == "$piece_goblinstudio_cozycushion", "Piece.m_name ist ungueltig."); Require(val4.m_description == "$piece_goblinstudio_cozycushion_description", "Piece.m_description ist ungueltig."); Require((int)val4.m_category == 4, "Piece-Kategorie muss Furniture sein."); Require(val4.m_comfort == 0, "Comfort muss 0 sein."); Require(val4.m_canRotate, "Piece muss rotierbar sein."); Require(val4.m_canBeRemoved, "Piece muss entfernbar sein."); Require(val4.m_resources != null && val4.m_resources.Length == 0, "Requirements muessen nicht-null und leer sein."); } private static void Require(bool condition, string message) { if (!condition) { throw new InvalidDataException(message); } } private static void RegisterZNetScenePrefab(ZNetScene scene) { Require(scene.m_prefabs != null, "ZNetScene.m_prefabs fehlt."); Require(scene.m_nonNetViewPrefabs != null, "ZNetScene.m_nonNetViewPrefabs fehlt."); RegisterOneZNetScenePrefab(scene, CushionPrefab, "GoblinStudio_CozyCushion", "Cozy Cushion"); RegisterOneZNetScenePrefab(scene, BlanketPrefab, "GoblinStudio_FoldedBlanket", "Folded Blanket"); } private static void RegisterOneZNetScenePrefab(ZNetScene scene, GameObject prefab, string prefabName, string label) { int stableHashCode = StringExtensionMethods.GetStableHashCode(prefabName); bool exactReferenceFound = false; CheckPrefabList(scene.m_prefabs, stableHashCode, netViewList: true, prefab, prefabName, ref exactReferenceFound); CheckPrefabList(scene.m_nonNetViewPrefabs, stableHashCode, netViewList: false, prefab, prefabName, ref exactReferenceFound); if (exactReferenceFound) { ManualLogSource? log = Log; if (log != null) { log.LogInfo((object)(label + " ist bereits idempotent in ZNetScene vorhanden.")); } return; } scene.m_prefabs.Add(prefab); ManualLogSource? log2 = Log; if (log2 != null) { log2.LogInfo((object)(label + " vor ZNetScene.Awake genau einmal zu m_prefabs hinzugefuegt.")); } } private static void CheckPrefabList(List prefabs, int wantedHash, bool netViewList, GameObject wantedPrefab, string wantedName, ref bool exactReferenceFound) { foreach (GameObject prefab in prefabs) { if (!((Object)(object)prefab == (Object)null)) { bool num = prefab == wantedPrefab; bool flag = ((Object)prefab).name == wantedName; bool flag2 = StringExtensionMethods.GetStableHashCode(((Object)prefab).name) == wantedHash; if (num) { Require(netViewList, "Das CozyHearth-Prefab steht ungueltig in m_nonNetViewPrefabs."); exactReferenceFound = true; } else if (flag || flag2) { throw new InvalidDataException("Prefabname-/Stable-Hash-Konflikt mit '" + ((Object)prefab).name + "'."); } } } } private static void RegisterHammerAndLocalization(ObjectDB? objectDb, ObjectDbLifecycle lifecycle) { if (!PrefabValid || (Object)(object)CushionPrefab == (Object)null) { return; } RegisterLocalizationIfReady(); if ((Object)(object)objectDb == (Object)null) { ManualLogSource? log = Log; if (log != null) { log.LogError((object)$"ObjectDB.{lifecycle}: ObjectDB-Instanz fehlt; Hammer-PieceTable-Registrierung fail-closed abgebrochen."); } return; } try { GameObject val = null; if (lifecycle == ObjectDbLifecycle.Awake && (Object)(object)((Component)objectDb).gameObject != (Object)null && ((Object)((Component)objectDb).gameObject).name == "StartGui") { bool num = objectDb.m_items != null && objectDb.m_items.Exists((GameObject item) => (Object)(object)item != (Object)null && ((Object)item).name == "Hammer"); val = objectDb.GetItemPrefab("Hammer"); if (!num && (Object)(object)val == (Object)null) { if (!ObjectDbAwakeNotReadyLogged) { ObjectDbAwakeNotReadyLogged = true; ManualLogSource? log2 = Log; if (log2 != null) { log2.LogInfo((object)"ObjectDB.Awake/StartGui: Vanilla-Daten noch nicht vollstaendig uebernommen; Hammer-PieceTable-Registrierung wird nach CopyOtherDB erneut versucht."); } } return; } } if (val == null) { val = objectDb.GetItemPrefab("Hammer"); } Require((Object)(object)val != (Object)null, "Vanilla-Hammer fehlt."); ItemDrop component = val.GetComponent(); Require((Object)(object)component != (Object)null, "Vanilla-Hammer ItemDrop fehlt."); Require(component.m_itemData != null, "Vanilla-Hammer ItemData fehlt."); Require(component.m_itemData.m_shared != null, "Vanilla-Hammer SharedData fehlt."); PieceTable buildPieces = component.m_itemData.m_shared.m_buildPieces; Require((Object)(object)buildPieces != (Object)null, "Vanilla-Hammer PieceTable fehlt."); Require(((Object)buildPieces).name == "_HammerPieceTable", "Vanilla-Hammer PieceTable ist nicht '_HammerPieceTable'."); Require(buildPieces.m_pieces != null, "Hammer PieceTable.m_pieces fehlt."); Piece component2 = CushionPrefab.GetComponent(); Piece component3 = BlanketPrefab.GetComponent(); if (lifecycle == ObjectDbLifecycle.CopyOtherDB) { ConfigureDeerRequirements(objectDb, component2, 2, 1, "Cozy Cushion"); ConfigureDeerRequirements(objectDb, component3, 4, 2, "Folded Blanket"); } RequireDeerRequirements(component2, 2, 1, "Cozy Cushion"); RequireDeerRequirements(component3, 4, 2, "Folded Blanket"); Require((Object)(object)component2.m_craftingStation == (Object)null && (Object)(object)component3.m_craftingStation == (Object)null, "Cozy Hearth Pieces duerfen keine Crafting Station verlangen."); RegisterHammerPiece(buildPieces, CushionPrefab, "GoblinStudio_CozyCushion", "$piece_goblinstudio_cozycushion", "Cozy Cushion"); RegisterHammerPiece(buildPieces, BlanketPrefab, "GoblinStudio_FoldedBlanket", "$piece_goblinstudio_foldedblanket", "Folded Blanket"); } catch (Exception ex) { ManualLogSource? log3 = Log; if (log3 != null) { log3.LogError((object)$"ObjectDB.{lifecycle}: Hammer-PieceTable-Registrierung fail-closed abgebrochen: {ex.Message}"); } } } private static void RegisterHammerPiece(PieceTable table, GameObject prefab, string prefabName, string pieceName, string label) { foreach (GameObject piece in table.m_pieces) { if (piece == prefab) { return; } if (!((Object)(object)piece == (Object)null)) { Piece component = piece.GetComponent(); if (((Object)piece).name == prefabName || component?.m_name == pieceName) { throw new InvalidDataException("Hammer-PieceTable-Konflikt mit '" + ((Object)piece).name + "'."); } } } table.m_pieces.Add(prefab); ManualLogSource? log = Log; if (log != null) { log.LogInfo((object)(label + " genau einmal zu _HammerPieceTable.m_pieces hinzugefuegt.")); } } private static void ConfigureDeerRequirements(ObjectDB objectDb, Piece cushionPiece, int deerAmount, int scrapsAmount, string label) { //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: 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) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Expected O, but got Unknown Require((Object)(object)cushionPiece.m_craftingStation == (Object)null, "Cozy Cushion darf keine Crafting Station verlangen."); Require(cushionPiece.m_resources != null, "Piece.m_resources fehlt."); if (cushionPiece.m_resources.Length == 2) { RequireDeerRequirements(cushionPiece, deerAmount, scrapsAmount, label); return; } Require(cushionPiece.m_resources.Length == 0, "Requirements enthalten einen unerwarteten Zwischenzustand."); GameObject itemPrefab = objectDb.GetItemPrefab("DeerHide"); GameObject itemPrefab2 = objectDb.GetItemPrefab("LeatherScraps"); Require((Object)(object)itemPrefab != (Object)null, "Vanilla-Material 'DeerHide' fehlt."); Require((Object)(object)itemPrefab2 != (Object)null, "Vanilla-Material 'LeatherScraps' fehlt."); ItemDrop component = itemPrefab.GetComponent(); ItemDrop component2 = itemPrefab2.GetComponent(); Require((Object)(object)component != (Object)null, "Vanilla-Material 'DeerHide' besitzt kein ItemDrop."); Require((Object)(object)component2 != (Object)null, "Vanilla-Material 'LeatherScraps' besitzt kein ItemDrop."); Requirement[] resources = (Requirement[])(object)new Requirement[2] { new Requirement { m_resItem = component, m_amount = deerAmount, m_extraAmountOnlyOneIngredient = 0, m_amountPerLevel = 0, m_recover = true }, new Requirement { m_resItem = component2, m_amount = scrapsAmount, m_extraAmountOnlyOneIngredient = 0, m_amountPerLevel = 0, m_recover = true } }; cushionPiece.m_resources = resources; RequireDeerRequirements(cushionPiece, deerAmount, scrapsAmount, label); ManualLogSource? log = Log; if (log != null) { log.LogInfo((object)$"{label} Requirements atomar gesetzt: {deerAmount} DeerHide, {scrapsAmount} LeatherScraps, beide recoverable."); } } private static void RequireDeerRequirements(Piece cushionPiece, int deerAmount, int scrapsAmount, string label) { Require(cushionPiece.m_resources != null && cushionPiece.m_resources.Length == 2, label + " muss exakt zwei Requirements besitzen."); Requirement val = cushionPiece.m_resources[0]; Requirement val2 = cushionPiece.m_resources[1]; Require(val != null && (Object)(object)val.m_resItem != (Object)null && ((Object)((Component)val.m_resItem).gameObject).name == "DeerHide", "Requirement 1 muss DeerHide sein."); Require(val.m_amount == deerAmount && val.m_amountPerLevel == 0 && val.m_extraAmountOnlyOneIngredient == 0 && val.m_recover, label + " DeerHide-Requirement ist ungueltig."); Require(val2 != null && (Object)(object)val2.m_resItem != (Object)null && ((Object)((Component)val2.m_resItem).gameObject).name == "LeatherScraps", "Requirement 2 muss LeatherScraps sein."); Require(val2.m_amount == scrapsAmount && val2.m_amountPerLevel == 0 && val2.m_extraAmountOnlyOneIngredient == 0 && val2.m_recover, label + " LeatherScraps-Requirement ist ungueltig."); } private static void RegisterLocalizationIfReady() { Localization instance = Localization.instance; if (instance != null) { if (!LocalizationSubscribed) { Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, new Action(OnLanguageChange)); LocalizationSubscribed = true; } AddLocalizationWords(instance); } } private static void OnLanguageChange() { RegisterLocalizationIfReady(); } private static void AddLocalizationWords(Localization localization) { MethodInfo method = typeof(Localization).GetMethod("AddWord", BindingFlags.Instance | BindingFlags.NonPublic); if (method == null) { ManualLogSource? log = Log; if (log != null) { log.LogError((object)"Localization.AddWord wurde lokal nicht gefunden."); } return; } method.Invoke(localization, new object[2] { "piece_goblinstudio_cozycushion", "Cozy Cushion" }); method.Invoke(localization, new object[2] { "piece_goblinstudio_cozycushion_description", "A soft handmade cushion for a warmer, cozier home." }); method.Invoke(localization, new object[2] { "piece_goblinstudio_foldedblanket", "Folded Blanket" }); method.Invoke(localization, new object[2] { "piece_goblinstudio_foldedblanket_description", "A neatly folded blanket for a warm and welcoming home." }); } } }