using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using InventoryUX.Core; using InventoryUX.Runtime; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("CraftGuard")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("0.1.2.0")] [assembly: AssemblyInformationalVersion("0.1.2+519a49c399d64d3275a092e9dfe269a0696aaf8b")] [assembly: AssemblyProduct("CraftGuard")] [assembly: AssemblyTitle("CraftGuard")] [assembly: AssemblyVersion("0.1.2.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 InventoryUX { [BepInPlugin("com.inventoryux.valheim", "CraftGuard", "0.1.2")] public sealed class Plugin : BaseUnityPlugin { internal const string PluginGuid = "com.inventoryux.valheim"; internal const string PluginName = "CraftGuard"; internal const string PluginVersion = "0.1.2"; private Harmony? _harmony; internal static ManualLogSource LogInstance { get; private set; } internal static Plugin Instance { get; private set; } private void Awake() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown Instance = this; LogInstance = ((BaseUnityPlugin)this).Logger; ModConfig.Bind(((BaseUnityPlugin)this).Config); _harmony = new Harmony("com.inventoryux.valheim"); _harmony.PatchAll(typeof(Plugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"CraftGuard 0.1.2 loaded. Undiscovered content is never rendered."); } private void Update() { if (ModConfig.Enabled.Value && ModConfig.WriteDataInventoryOnStartup.Value) { DataInventoryWriter.TryWriteOnce(); } } private void OnDestroy() { HammerGroupDecorations.Shutdown(); HammerGridSizer.Restore(); Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } } namespace InventoryUX.Runtime { internal enum CraftingSection { Workbench, Forge, Cooking, Advanced, Processing, Utility } internal readonly struct CraftingPieceLayout { internal CraftingSection Section { get; } internal int SortOrder { get; } internal int Subgroup { get; } internal bool IsPrimaryStation { get; } internal CraftingPieceLayout(CraftingSection section, int sortOrder, int subgroup, bool isPrimaryStation = false) { Section = section; SortOrder = sortOrder; Subgroup = subgroup; IsPrimaryStation = isPrimaryStation; } } internal static class CraftingLayoutMetadata { private readonly struct PieceRule { internal CraftingPieceLayout Layout { get; } private string[] Markers { get; } internal PieceRule(CraftingPieceLayout layout, string[] markers) { Layout = layout; Markers = markers; } internal bool Matches(string id) { for (int i = 0; i < Markers.Length; i++) { if (id.Contains(Markers[i])) { return true; } } return false; } } private static readonly PieceRule[] Rules = new PieceRule[46] { Rule(CraftingSection.Workbench, 110, 0, "choppingblock"), Rule(CraftingSection.Workbench, 120, 0, "tanningrack"), Rule(CraftingSection.Workbench, 130, 0, "adze"), Rule(CraftingSection.Workbench, 140, 0, "toolshelf"), Rule(CraftingSection.Workbench, 100, 0, true, "workbench"), Rule(CraftingSection.Forge, 210, 0, "forgebellows", "bellows"), Rule(CraftingSection.Forge, 220, 0, "anvils"), Rule(CraftingSection.Forge, 230, 0, "grindingwheel"), Rule(CraftingSection.Forge, 240, 0, "smithsanvil"), Rule(CraftingSection.Forge, 250, 0, "forgecooler"), Rule(CraftingSection.Forge, 260, 0, "forgetoolrack", "toolrack"), Rule(CraftingSection.Forge, 100, 0, true, "forge"), Rule(CraftingSection.Cooking, 110, 0, "spicerack"), Rule(CraftingSection.Cooking, 120, 0, "butcherstable", "butchertable"), Rule(CraftingSection.Cooking, 130, 0, "potsandpans"), Rule(CraftingSection.Cooking, 140, 0, "mortarandpestle", "mortar"), Rule(CraftingSection.Cooking, 150, 0, "rollingpin", "cuttingboard"), Rule(CraftingSection.Cooking, 400, 3, true, "meadketill", "meadkettle", "ketill", "kettle"), Rule(CraftingSection.Cooking, 410, 3, "fermenter", "fermentationbarrel"), Rule(CraftingSection.Cooking, 100, 0, true, "cauldron"), Rule(CraftingSection.Cooking, 210, 1, "ironcookingstation", "cookingstationiron"), Rule(CraftingSection.Cooking, 200, 1, true, "cookingstation"), Rule(CraftingSection.Cooking, 300, 2, true, "foodpreparation", "foodprep", "preptable"), Rule(CraftingSection.Cooking, 310, 2, "stoneoven", "oven"), Rule(CraftingSection.Advanced, 110, 0, "artisanpress"), Rule(CraftingSection.Advanced, 100, 0, true, "artisantable", "artisan"), Rule(CraftingSection.Advanced, 210, 1, "blackforgecooler"), Rule(CraftingSection.Advanced, 200, 1, true, "blackforge"), Rule(CraftingSection.Advanced, 300, 2, "gemcutter"), Rule(CraftingSection.Advanced, 310, 2, "metalcutter"), Rule(CraftingSection.Advanced, 320, 2, "vice", "vise"), Rule(CraftingSection.Advanced, 410, 3, "unfadingcandles"), Rule(CraftingSection.Advanced, 420, 3, "featherywreath", "wreath"), Rule(CraftingSection.Advanced, 430, 3, "runetable"), Rule(CraftingSection.Advanced, 400, 3, true, "galdrtable", "galdr"), Rule(CraftingSection.Processing, 100, 0, "charcoalkiln", "kiln"), Rule(CraftingSection.Processing, 110, 0, "smelter"), Rule(CraftingSection.Processing, 120, 0, "blastfurnace"), Rule(CraftingSection.Processing, 130, 0, "windmill"), Rule(CraftingSection.Processing, 140, 0, "spinningwheel"), Rule(CraftingSection.Processing, 150, 0, "sapextractor", "sapcollector"), Rule(CraftingSection.Processing, 160, 0, "obliterator", "incinerator"), Rule(CraftingSection.Processing, 170, 0, "eitrrefinery", "refineryeitr"), Rule(CraftingSection.Utility, 100, 0, "stonecutter"), Rule(CraftingSection.Utility, 110, 0, "beehive"), Rule(CraftingSection.Utility, 120, 0, "wispfountain") }; internal static CraftingPieceLayout Resolve(Piece piece) { string text = Normalize(HammerOrganizer.GetLabel(piece)); string text2 = ((Localization.instance != null) ? Localization.instance.Localize(piece.m_name) : piece.m_name); string text3 = Normalize(text + " " + ((Object)((Component)piece).gameObject).name + " " + piece.m_name + " " + text2); if (ContainsAny(text3, "eitrrefinery", "refineryeitr")) { return ResolveWithin(text3, CraftingSection.Processing, 170, 0); } if (text.Contains("workbench")) { return ResolveWithin(text3, CraftingSection.Workbench, 900, 1); } if (text.Contains("artisan")) { return ResolveWithin(text3, CraftingSection.Advanced, 900, 0); } if (text.Contains("blackforge")) { return ResolveWithin(text3, CraftingSection.Advanced, 900, 1); } if (text.Contains("galdr")) { return ResolveWithin(text3, CraftingSection.Advanced, 900, 3); } if (text.Contains("forge")) { return ResolveWithin(text3, CraftingSection.Forge, 900, 1); } if (ContainsAny(text, "cauldron", "foodpreparation", "foodprep", "preptable", "cooking")) { return ResolveWithin(text3, CraftingSection.Cooking, 900, 3); } if (ContainsAny(text, "mead", "ketill", "kettle", "brewing")) { return ResolveWithin(text3, CraftingSection.Cooking, 900, 3); } for (int i = 0; i < Rules.Length; i++) { if (Rules[i].Matches(text3)) { return Rules[i].Layout; } } return new CraftingPieceLayout(CraftingSection.Utility, 900, 9); } internal static string Label(CraftingSection section) { return section switch { CraftingSection.Workbench => "WORKBENCH", CraftingSection.Forge => "FORGE", CraftingSection.Cooking => "COOKING", CraftingSection.Advanced => "ADVANCED", CraftingSection.Processing => "PROCESSING", _ => "UTILITY", }; } internal static bool IsRepair(Piece piece) { if (piece.m_repairPiece) { return true; } string text = Normalize(((Object)((Component)piece).gameObject).name); string text2 = Normalize(piece.m_name); switch (text) { default: if (!(text2 == "repair")) { return text2 == "piecerepair"; } break; case "repair": case "piecerepair": case "hammerrepair": case "repairpiece": break; } return true; } private static CraftingPieceLayout ResolveWithin(string id, CraftingSection section, int fallbackOrder, int fallbackSubgroup) { for (int i = 0; i < Rules.Length; i++) { PieceRule pieceRule = Rules[i]; if (pieceRule.Layout.Section == section && pieceRule.Matches(id)) { return pieceRule.Layout; } } return new CraftingPieceLayout(section, fallbackOrder, fallbackSubgroup); } private static PieceRule Rule(CraftingSection section, int order, int subgroup, params string[] markers) { return new PieceRule(new CraftingPieceLayout(section, order, subgroup), markers); } private static PieceRule Rule(CraftingSection section, int order, int subgroup, bool primary, params string[] markers) { return new PieceRule(new CraftingPieceLayout(section, order, subgroup, primary), markers); } private static bool ContainsAny(string value, params string[] markers) { for (int i = 0; i < markers.Length; i++) { if (value.Contains(markers[i])) { return true; } } return false; } private static string Normalize(string? value) { if (string.IsNullOrEmpty(value)) { return string.Empty; } char[] array = new char[value.Length]; int length = 0; foreach (char c in value) { if (char.IsLetterOrDigit(c)) { array[length++] = char.ToLower(c, CultureInfo.InvariantCulture); } } return new string(array, 0, length); } } internal static class DataInventoryWriter { private static bool _written; internal static void TryWriteOnce() { if (_written || (Object)(object)ObjectDB.instance == (Object)null || (Object)(object)ZNetScene.instance == (Object)null) { return; } try { string text = Path.Combine(Paths.ConfigPath, "CraftGuard"); Directory.CreateDirectory(text); string text2 = Path.Combine(text, "loaded-data-inventory.csv"); File.WriteAllText(text2, BuildCsv(), new UTF8Encoding(encoderShouldEmitUTF8Identifier: true)); _written = true; Plugin.LogInstance.LogInfo((object)("Wrote the loaded piece/recipe inventory to " + text2)); } catch (Exception arg) { _written = true; Plugin.LogInstance.LogError((object)$"Could not write the data inventory: {arg}"); } } private static string BuildCsv() { StringBuilder stringBuilder = new StringBuilder(); WriteRow(stringBuilder, "ContentType", "PrefabID", "DisplayName", "KnownUnlockMechanism", "HammerCategory", "PieceType", "CraftingStation", "StationExtensionParent", "StationLevelContribution", "ItemType", "WeaponFamily", "ArmorType", "Recipe", "Ingredients", "RequiredStation", "RequiredStationLevel", "FoodHP", "FoodStamina", "FoodEitr", "FoodDuration", "FoodRegen", "ProposedGroup", "ProposedBiome", "ProposedSortOrder"); WritePieces(stringBuilder); WriteRecipes(stringBuilder); return stringBuilder.ToString(); } private static void WritePieces(StringBuilder output) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) HashSet hashSet = new HashSet(StringComparer.Ordinal); List prefabs = ZNetScene.instance.m_prefabs; for (int i = 0; i < prefabs.Count; i++) { GameObject val = prefabs[i]; if (!((Object)(object)val == (Object)null)) { Piece component = val.GetComponent(); if (!((Object)(object)component == (Object)null) && hashSet.Add(((Object)val).name)) { CraftingStation component2 = val.GetComponent(); StationExtension component3 = val.GetComponent(); PieceGroup pieceGroup = HammerOrganizer.Classify(component, component.m_category); string text = (((Object)(object)component2 != (Object)null) ? "Crafting station" : (((Object)(object)component3 != (Object)null) ? "Station extension" : "Build piece")); WriteRow(output, "Piece", ((Object)val).name, Localize(component.m_name), "Piece.m_name in Player.m_knownRecipes", ((object)Unsafe.As(ref component.m_category)/*cast due to .constrained prefix*/).ToString(), text, ((Object)(object)component.m_craftingStation != (Object)null) ? Localize(component.m_craftingStation.m_name) : (((Object)(object)component2 != (Object)null) ? Localize(component2.m_name) : string.Empty), ((Object)(object)component3 != (Object)null && (Object)(object)component3.m_craftingStation != (Object)null) ? Localize(component3.m_craftingStation.m_name) : string.Empty, ((Object)(object)component3 != (Object)null) ? "Native unique attached extension (+1)" : string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, FormatPieceIngredients(component), string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, pieceGroup.Label, string.Empty, $"{pieceGroup.Order}:{pieceGroup.Suborder}"); } } } } private static void WriteRecipes(StringBuilder output) { //IL_0131: Unknown result type (might be due to invalid IL or missing references) List recipes = ObjectDB.instance.m_recipes; for (int i = 0; i < recipes.Count; i++) { Recipe val = recipes[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val.m_item == (Object)null)) { SharedData shared = val.m_item.m_itemData.m_shared; RecipeFacts recipeFacts = ToFacts(val, i); RecipeGroup recipeGroup = (recipeFacts.IsFeast ? new RecipeGroup("Feasts", 4) : (recipeFacts.IsFood ? FoodClassifier.ToGroup(FoodClassifier.Classify(recipeFacts.Health, recipeFacts.Stamina, recipeFacts.Eitr)) : RecipeClassifier.GetTypeGroup(recipeFacts))); ProgressionBiome biome = BiomeClassifier.Classify(recipeFacts.Id, recipeFacts.IngredientIds); WriteRow(output, "Recipe", recipeFacts.Id, recipeFacts.DisplayName, "Player.GetAvailableRecipes / Player.IsRecipeKnown", string.Empty, string.Empty, string.Empty, string.Empty, string.Empty, ((object)Unsafe.As(ref shared.m_itemType)/*cast due to .constrained prefix*/).ToString(), ((object)Unsafe.As(ref shared.m_skillType)/*cast due to .constrained prefix*/).ToString(), ArmorType(shared.m_itemType), ((Object)val).name, FormatRecipeIngredients(val), ((Object)(object)val.m_craftingStation != (Object)null) ? Localize(val.m_craftingStation.m_name) : string.Empty, val.m_minStationLevel.ToString(CultureInfo.InvariantCulture), shared.m_food.ToString(CultureInfo.InvariantCulture), shared.m_foodStamina.ToString(CultureInfo.InvariantCulture), shared.m_foodEitr.ToString(CultureInfo.InvariantCulture), shared.m_foodBurnTime.ToString(CultureInfo.InvariantCulture), shared.m_foodRegen.ToString(CultureInfo.InvariantCulture), recipeGroup.Label, biome.ToString(), $"{BiomeClassifier.ToGroup(biome).Order}:{recipeGroup.Order}"); } } } private static RecipeFacts ToFacts(Recipe recipe, int originalIndex) { SharedData shared = recipe.m_item.m_itemData.m_shared; List list = new List(); if (recipe.m_resources != null) { for (int i = 0; i < recipe.m_resources.Length; i++) { ItemDrop val = recipe.m_resources[i]?.m_resItem; if (!((Object)(object)val == (Object)null)) { list.Add(((Object)((Component)val).gameObject).name); list.Add(val.m_itemData.m_shared.m_name); } } } ResolvedFoodStats resolvedFoodStats = FoodStatsResolver.Resolve(recipe.m_item); float health = (resolvedFoodStats.Resolved ? resolvedFoodStats.Health : shared.m_food); float stamina = (resolvedFoodStats.Resolved ? resolvedFoodStats.Stamina : shared.m_foodStamina); float eitr = (resolvedFoodStats.Resolved ? resolvedFoodStats.Eitr : shared.m_foodEitr); return new RecipeFacts(((Object)((Component)recipe.m_item).gameObject).name, Localize(shared.m_name), ((object)Unsafe.As(ref shared.m_itemType)/*cast due to .constrained prefix*/).ToString(), ((object)Unsafe.As(ref shared.m_skillType)/*cast due to .constrained prefix*/).ToString(), list, health, stamina, eitr, originalIndex, resolvedFoodStats.IsFeast); } private static string FormatPieceIngredients(Piece piece) { if (piece.m_resources == null) { return string.Empty; } List list = new List(); for (int i = 0; i < piece.m_resources.Length; i++) { Requirement val = piece.m_resources[i]; if ((Object)(object)val?.m_resItem != (Object)null) { list.Add($"{Localize(val.m_resItem.m_itemData.m_shared.m_name)} x{val.m_amount}"); } } return string.Join("; ", list); } private static string FormatRecipeIngredients(Recipe recipe) { if (recipe.m_resources == null) { return string.Empty; } List list = new List(); for (int i = 0; i < recipe.m_resources.Length; i++) { Requirement val = recipe.m_resources[i]; if ((Object)(object)val?.m_resItem != (Object)null) { list.Add($"{Localize(val.m_resItem.m_itemData.m_shared.m_name)} x{val.m_amount}"); } } return string.Join("; ", list); } private static string ArmorType(ItemType itemType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected I4, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Invalid comparison between Unknown and I4 switch (itemType - 6) { default: if ((int)itemType != 17) { break; } return "Shoulder"; case 0: return "Helmet"; case 1: return "Chest"; case 5: return "Legs"; case 6: return "Hands"; case 2: case 3: case 4: break; } return string.Empty; } private static string Localize(string value) { if (Localization.instance == null) { return value; } return Localization.instance.Localize(value); } private static void WriteRow(StringBuilder output, params string[] values) { for (int i = 0; i < values.Length; i++) { if (i > 0) { output.Append(','); } output.Append(Escape(values[i])); } output.AppendLine(); } private static string Escape(string? value) { value = value ?? string.Empty; if (value.IndexOfAny(new char[4] { ',', '"', '\r', '\n' }) < 0) { return value; } return "\"" + value.Replace("\"", "\"\"") + "\""; } } internal static class FoodStatsResolver { private static readonly Dictionary CookedByInput = new Dictionary(StringComparer.Ordinal); private static readonly Dictionary FeastFoodByInput = new Dictionary(StringComparer.Ordinal); private static int _sceneInstanceId = int.MinValue; private static int _scenePrefabCount = -1; internal static ResolvedFoodStats Resolve(ItemDrop output) { EnsureIndex(); if (output == null || (Object)(object)output == (Object)null) { return default(ResolvedFoodStats); } Feast val = ((Component)output).GetComponent() ?? ((Component)output).GetComponentInChildren(true); ItemDrop val2 = (((Object)(object)val != (Object)null) ? GetFeastFood(val) : null); if ((Object)(object)val2 != (Object)null) { return FromItem(val2, resolved: true, isFeast: true); } string name = ((Object)((Component)output).gameObject).name; if (FeastFoodByInput.TryGetValue(name, out ItemDrop value) && (Object)(object)value != (Object)null) { return FromItem(value, resolved: true, isFeast: true); } ItemDrop val3 = output; bool resolved = false; HashSet hashSet = new HashSet(StringComparer.Ordinal); for (int i = 0; i < 4; i++) { string name2 = ((Object)((Component)val3).gameObject).name; if (!hashSet.Add(name2) || !CookedByInput.TryGetValue(name2, out ItemDrop value2) || (Object)(object)value2 == (Object)null) { break; } val3 = value2; resolved = true; } return FromItem(val3, resolved, isFeast: false); } private static void EnsureIndex() { //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Invalid comparison between Unknown and I4 ZNetScene instance = ZNetScene.instance; if ((Object)(object)instance == (Object)null || instance.m_prefabs == null) { return; } int instanceID = ((Object)instance).GetInstanceID(); int count = instance.m_prefabs.Count; if (_sceneInstanceId == instanceID && _scenePrefabCount == count) { return; } _sceneInstanceId = instanceID; _scenePrefabCount = count; CookedByInput.Clear(); FeastFoodByInput.Clear(); for (int i = 0; i < instance.m_prefabs.Count; i++) { GameObject val = instance.m_prefabs[i]; if ((Object)(object)val == (Object)null) { continue; } CookingStation[] componentsInChildren = val.GetComponentsInChildren(true); for (int j = 0; j < componentsInChildren.Length; j++) { List conversion = componentsInChildren[j].m_conversion; if (conversion == null) { continue; } for (int k = 0; k < conversion.Count; k++) { ItemConversion val2 = conversion[k]; if (!((Object)(object)val2?.m_from == (Object)null) && !((Object)(object)val2.m_to == (Object)null)) { string name = ((Object)((Component)val2.m_from).gameObject).name; if (!CookedByInput.ContainsKey(name)) { CookedByInput.Add(name, val2.m_to); } } } } Feast[] componentsInChildren2 = val.GetComponentsInChildren(true); foreach (Feast val3 in componentsInChildren2) { Piece val4 = ((Component)val3).GetComponent() ?? ((Component)val3).GetComponentInParent(); ItemDrop feastFood = GetFeastFood(val3); if ((Object)(object)feastFood == (Object)null) { continue; } ItemDrop val5 = ((Component)val3).GetComponent() ?? ((Component)val3).GetComponentInParent(); if ((Object)(object)val5 != (Object)null) { AddFeastMapping(((Object)((Component)val5).gameObject).name, feastFood); } ItemDrop component = val.GetComponent(); if ((Object)(object)component != (Object)null) { AddFeastMapping(((Object)((Component)component).gameObject).name, feastFood); } if ((Object)(object)val4 == (Object)null || (int)val4.m_category != 5 || val4.m_resources == null) { continue; } for (int m = 0; m < val4.m_resources.Length; m++) { ItemDrop val6 = val4.m_resources[m]?.m_resItem; if (!((Object)(object)val6 == (Object)null)) { AddFeastMapping(((Object)((Component)val6).gameObject).name, feastFood); } } } } } private static ItemDrop? GetFeastFood(Feast feast) { if ((Object)(object)feast.m_foodItem != (Object)null) { return feast.m_foodItem; } return ((Component)feast).GetComponent() ?? ((Component)feast).GetComponentInParent(); } private static void AddFeastMapping(string inputId, ItemDrop feastFood) { if (!string.IsNullOrEmpty(inputId) && !FeastFoodByInput.ContainsKey(inputId)) { FeastFoodByInput.Add(inputId, feastFood); } } private static ResolvedFoodStats FromItem(ItemDrop item, bool resolved, bool isFeast) { SharedData shared = item.m_itemData.m_shared; return new ResolvedFoodStats(shared.m_food, shared.m_foodStamina, shared.m_foodEitr, resolved, isFeast); } } internal readonly struct ResolvedFoodStats { internal float Health { get; } internal float Stamina { get; } internal float Eitr { get; } internal bool Resolved { get; } internal bool IsFeast { get; } internal ResolvedFoodStats(float health, float stamina, float eitr, bool resolved, bool isFeast) { Health = health; Stamina = stamina; Eitr = eitr; Resolved = resolved; IsFeast = isFeast; } } internal static class HammerGridDimensions { internal const int NativeWidth = 15; internal const int NativeHeight = 6; internal const int ExpandedWidth = 15; internal const int ExpandedHeight = 6; internal const float ReferenceCraftingRowScale = 1.1666666f; internal static int Width { get { if (!ModConfig.Enabled.Value) { return 15; } return 15; } } internal static int Height { get { if (!ModConfig.Enabled.Value) { return 6; } return 6; } } internal static int MaxX => Width - 1; internal static int MaxY => Height - 1; internal static float CraftingRowPitch(Hud hud) { return hud.m_pieceIconSpacing * 1.1666666f; } } internal static class HammerGridSizer { private sealed class RectState { private readonly RectTransform _rect; private readonly Vector2 _sizeDelta; private readonly Vector2 _anchoredPosition; internal RectState(RectTransform rect) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001b: 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) _rect = rect; _sizeDelta = rect.sizeDelta; _anchoredPosition = rect.anchoredPosition; } internal void Restore() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_rect == (Object)null)) { _rect.sizeDelta = _sizeDelta; _rect.anchoredPosition = _anchoredPosition; } } } private sealed class ReparentedRectState { private readonly RectTransform _rect; private readonly Transform _parent; private readonly int _siblingIndex; private readonly Vector2 _anchorMin; private readonly Vector2 _anchorMax; private readonly Vector2 _pivot; private readonly Vector2 _sizeDelta; private readonly Vector2 _anchoredPosition; internal ReparentedRectState(RectTransform rect) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) _rect = rect; _parent = ((Transform)rect).parent; _siblingIndex = ((Transform)rect).GetSiblingIndex(); _anchorMin = rect.anchorMin; _anchorMax = rect.anchorMax; _pivot = rect.pivot; _sizeDelta = rect.sizeDelta; _anchoredPosition = rect.anchoredPosition; } internal void Restore() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_rect == (Object)null) && !((Object)(object)_parent == (Object)null)) { ((Transform)_rect).SetParent(_parent, false); ((Transform)_rect).SetSiblingIndex(Mathf.Min(_siblingIndex, _parent.childCount - 1)); _rect.anchorMin = _anchorMin; _rect.anchorMax = _anchorMax; _rect.pivot = _pivot; _rect.sizeDelta = _sizeDelta; _rect.anchoredPosition = _anchoredPosition; } } } private static int _hudInstanceId = int.MinValue; private static RectState? _windowState; private static RectState? _maskState; private static RectState? _categoryState; private static ReparentedRectState? _previousCategoryControlState; internal static float RepairRailWidth { get; private set; } internal static void Apply(Hud hud) { //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: 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_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) int instanceID = ((Object)hud).GetInstanceID(); if (_hudInstanceId != instanceID) { Restore(); float pieceIconSpacing = hud.m_pieceIconSpacing; float num = 0f * pieceIconSpacing; float num2 = Mathf.Max(0f, 1f * pieceIconSpacing); RepairRailWidth = pieceIconSpacing + 28f; RectTransform val = (((Object)(object)hud.m_pieceSelectionWindow != (Object)null) ? hud.m_pieceSelectionWindow.GetComponent() : null); if ((Object)(object)val != (Object)null) { _windowState = new RectState(val); ExpandCentered(val, num + RepairRailWidth, num2); } RectTransform pieceListMask = hud.m_pieceListMask; if ((Object)(object)pieceListMask != (Object)null) { _maskState = new RectState(pieceListMask); float widthDelta = (Mathf.Approximately(pieceListMask.anchorMin.x, pieceListMask.anchorMax.x) ? num : 0f); float heightDelta = (Mathf.Approximately(pieceListMask.anchorMin.y, pieceListMask.anchorMax.y) ? num2 : 0f); ExpandKeepingTopLeft(pieceListMask, widthDelta, heightDelta); pieceListMask.anchoredPosition += new Vector2(RepairRailWidth, 0f); } RectTransform val2 = (((Object)(object)hud.m_pieceCategoryRoot != (Object)null) ? hud.m_pieceCategoryRoot.GetComponent() : null); if ((Object)(object)val2 != (Object)null) { _categoryState = new RectState(val2); val2.sizeDelta -= new Vector2(RepairRailWidth, 0f); val2.anchoredPosition += new Vector2(RepairRailWidth * (1f - val2.pivot.x), 0f); MovePreviousCategoryControl(val2, val, RepairRailWidth); } _hudInstanceId = instanceID; } } internal static void Restore() { _windowState?.Restore(); _maskState?.Restore(); _categoryState?.Restore(); _previousCategoryControlState?.Restore(); _windowState = null; _maskState = null; _categoryState = null; _previousCategoryControlState = null; _hudInstanceId = int.MinValue; RepairRailWidth = 0f; } private static void MovePreviousCategoryControl(RectTransform categoryRoot, RectTransform? window, float repairRailWidth) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)window == (Object)null)) { RectTransform val = FindInteractiveControl(categoryRoot, "Q") ?? FindInteractiveControl(window, "Q"); if (!((Object)(object)val == (Object)null)) { _previousCategoryControlState = new ReparentedRectState(val); ((Transform)val).SetParent((Transform)(object)window, false); ((Transform)val).SetAsLastSibling(); val.anchorMin = new Vector2(0f, 1f); val.anchorMax = new Vector2(0f, 1f); val.pivot = new Vector2(0f, 1f); val.anchoredPosition = new Vector2(repairRailWidth + 42f, -18f); } } } private static RectTransform? FindInteractiveControl(RectTransform root, string displayedText) { TextMeshProUGUI[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { if (string.Equals(((TMP_Text)componentsInChildren[i]).text?.Trim(), displayedText, StringComparison.OrdinalIgnoreCase)) { return InteractiveAncestor(root, ((TMP_Text)componentsInChildren[i]).transform); } } Text[] componentsInChildren2 = ((Component)root).GetComponentsInChildren(true); for (int j = 0; j < componentsInChildren2.Length; j++) { if (string.Equals(componentsInChildren2[j].text?.Trim(), displayedText, StringComparison.OrdinalIgnoreCase)) { return InteractiveAncestor(root, ((Component)componentsInChildren2[j]).transform); } } return null; } private static RectTransform? InteractiveAncestor(RectTransform root, Transform child) { Transform val = child; while ((Object)(object)val != (Object)(object)root && (Object)(object)val.parent != (Object)null) { if ((Object)(object)((Component)val).GetComponent() != (Object)null || (Object)(object)((Component)val).GetComponent