Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of DynamicStorageMaterials v1.0.1
plugins/DynamicStorageMaterials/DynamicStorageMaterials.dll
Decompiled 3 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Extensions; using Jotunn.Managers; using Jotunn.Utils; using Microsoft.CodeAnalysis; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: AssemblyCompany("DynamicStorageMaterials")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("DynamicStorageMaterials")] [assembly: AssemblyTitle("DynamicStorageMaterials")] [assembly: AssemblyVersion("1.0.1.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 DynamicStorageMaterials { internal sealed class AppearanceSettings { internal const string FlintExperimentalLayout = "Flint - Experimental"; internal const string ObsidianExperimentalLayout = "Obsidian - Experimental"; internal const string PyramidLayout = "Pyramid"; internal const string ModelDefaultMaterial = "Model Default"; internal static readonly Dictionary<string, string> MaterialSources = new Dictionary<string, string>(StringComparer.Ordinal) { { "Flint", "Flint" }, { "Obsidian", "Obsidian" }, { "Resin", "Resin" }, { "Greydwarf Eye", "GreydwarfEye" }, { "Surtling Core", "SurtlingCore" }, { "Crystal", "Crystal" }, { "Freeze Gland", "FreezeGland" }, { "Needle", "Needle" }, { "Soft Tissue", "Softtissue" }, { "Black Core", "BlackCore" }, { "Sulfur", "SulfurStone" }, { "Ice", "Ice" }, { "Frostcore", "FrostCore" }, { "Coal", "Coal" }, { "Stone", "Stone" }, { "Black Marble", "BlackMarble" }, { "Grausten", "Grausten" } }; internal static readonly Dictionary<string, string> ModelSources = new Dictionary<string, string>(StringComparer.Ordinal) { { "Flint", "Flint" }, { "Obsidian", "Obsidian" }, { "Resin", "Resin" }, { "Greydwarf Eye", "GreydwarfEye" }, { "Surtling Core", "SurtlingCore" }, { "Crystal", "Crystal" }, { "Freeze Gland", "FreezeGland" }, { "Needle", "Needle" }, { "Soft Tissue", "Softtissue" }, { "Black Core", "BlackCore" }, { "Sulfur", "SulfurStone" }, { "Ice", "Ice" }, { "Frostcore", "FrostCore" }, { "Coal", "Coal" }, { "Stone", "Stone" }, { "Black Marble", "BlackMarble" }, { "Grausten", "Grausten" } }; private readonly bool isBar; private readonly ConfigEntry<string> preset; private readonly ConfigEntry<string> shape; private readonly ConfigEntry<string> model; private readonly ConfigEntry<string> material; private readonly ConfigEntry<float> layoutScale; private readonly ConfigEntry<float> layoutHeight; private readonly ConfigEntry<float> modelScale; private readonly ConfigEntry<float> visualVerticalOffset; private readonly ConfigEntry<string> finish; private readonly ConfigEntry<string> barArrangement; private readonly ConfigEntry<int> barAcross; private readonly ConfigEntry<int> barDeep; private readonly ConfigEntry<int> barLayers; private readonly ConfigEntry<string> fillBasis; private readonly ConfigEntry<string> looksFullAt; private readonly List<PileAppearancePreset> pilePresets = new List<PileAppearancePreset>(); private bool updatingPreset; private string observedPresetValue; private string observedAppearanceSignature; private bool updatingBarDimensions; internal string SectionName { get; } internal static string DisplayLayoutName(string layout) { if (string.Equals(layout, "Flint", StringComparison.Ordinal)) { return "Flint - Experimental"; } if (string.Equals(layout, "Obsidian", StringComparison.Ordinal)) { return "Obsidian - Experimental"; } return layout; } internal static bool IsGeneratedPyramidLayout(string layout) { return string.Equals(layout, "Pyramid", StringComparison.Ordinal); } internal static string NormalizeGeneratedLayout(string layout) { if (string.Equals(layout, "Neat Stacked", StringComparison.Ordinal) || string.Equals(layout, "Misaligned Stacked", StringComparison.Ordinal)) { return "Pyramid"; } return layout; } internal static string ModelNameForPrefab(string prefabName) { foreach (KeyValuePair<string, string> modelSource in ModelSources) { if (string.Equals(modelSource.Value, prefabName, StringComparison.Ordinal)) { return modelSource.Key; } } return null; } internal AppearanceSettings(ConfigFile config, string section, bool isBar, string nativeShape, string defaultShape, string defaultModelPrefab, float defaultSize, float defaultHeight, string legacySection = null, float defaultModelScale = 1f, float defaultVerticalOffset = 0f, string defaultMaterial = null) { //IL_033e: Unknown result type (might be due to invalid IL or missing references) //IL_0348: Expected O, but got Unknown //IL_03d7: Unknown result type (might be due to invalid IL or missing references) //IL_03e1: Expected O, but got Unknown //IL_0421: Unknown result type (might be due to invalid IL or missing references) //IL_042b: Expected O, but got Unknown //IL_046b: Unknown result type (might be due to invalid IL or missing references) //IL_0475: Expected O, but got Unknown //IL_05cf: Unknown result type (might be due to invalid IL or missing references) //IL_05d9: Expected O, but got Unknown //IL_0613: Unknown result type (might be due to invalid IL or missing references) //IL_061d: Expected O, but got Unknown //IL_086b: Unknown result type (might be due to invalid IL or missing references) //IL_0875: Expected O, but got Unknown //IL_0710: Unknown result type (might be due to invalid IL or missing references) //IL_071a: Expected O, but got Unknown //IL_0793: Unknown result type (might be due to invalid IL or missing references) //IL_079d: Expected O, but got Unknown //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Expected O, but got Unknown //IL_08f9: Unknown result type (might be due to invalid IL or missing references) //IL_0903: Expected O, but got Unknown //IL_09d0: Unknown result type (might be due to invalid IL or missing references) //IL_09da: Expected O, but got Unknown //IL_0ce6: Unknown result type (might be due to invalid IL or missing references) //IL_0cf0: Expected O, but got Unknown //IL_0db9: Unknown result type (might be due to invalid IL or missing references) //IL_0dc3: Expected O, but got Unknown //IL_0afb: Unknown result type (might be due to invalid IL or missing references) //IL_0b05: Expected O, but got Unknown //IL_0b4d: Unknown result type (might be due to invalid IL or missing references) //IL_0b57: Expected O, but got Unknown //IL_0b9f: Unknown result type (might be due to invalid IL or missing references) //IL_0ba9: Expected O, but got Unknown //IL_0c38: Unknown result type (might be due to invalid IL or missing references) //IL_0c42: Expected O, but got Unknown this.isBar = isBar; SectionName = section; Func<string, string> func = delegate(string key) { object obj = ReadSavedValue(config, section, key); if (obj == null) { if (!string.IsNullOrEmpty(legacySection)) { return ReadSavedValue(config, legacySection, key); } obj = null; } return (string)obj; }; Func<string, float?> func2 = delegate(string key) { float? num9 = ReadSavedFloat(config, section, key); return (num9.HasValue || string.IsNullOrEmpty(legacySection)) ? num9 : ReadSavedFloat(config, legacySection, key); }; string defaultModel = ModelNameForPrefab(defaultModelPrefab) ?? ModelSources.Keys.First(); bool flag = string.Equals(section, "Obsidian Pile (Storage)", StringComparison.Ordinal); PileAppearancePreset pileAppearancePreset = null; if (!isBar) { pileAppearancePreset = CreateDefaultPreset(section, string.IsNullOrEmpty(defaultShape) ? nativeShape : defaultShape, defaultModel, defaultSize, defaultHeight, defaultModelScale, defaultVerticalOffset, defaultMaterial); pilePresets.Add(pileAppearancePreset); AddAdditionalPresets(section, pilePresets); } if (!isBar) { string text = DisplayLayoutName(nativeShape); List<string> list = new List<string> { text }; string[] array = new string[6] { "Coal", "Stone", "Black Marble", "Grausten", "Flint - Experimental", "Obsidian - Experimental" }; foreach (string text2 in array) { if (text2 != text) { list.Add(text2); } } bool num2 = string.Equals(section, "Surtling Core Pile (Storage)", StringComparison.Ordinal) || string.Equals(section, "Surtling Core", StringComparison.Ordinal); bool flag2 = string.Equals(section, "Black Core Pile (Storage)", StringComparison.Ordinal) || string.Equals(section, "Black Core", StringComparison.Ordinal) || string.Equals(section, "Frostcore Pile (Storage)", StringComparison.Ordinal) || string.Equals(section, "Frostcore", StringComparison.Ordinal); if (num2 && !list.Contains("Pyramid")) { list.Add("Pyramid"); } string text3 = NormalizeGeneratedLayout(DisplayLayoutName(func("Layout") ?? func("Mesh Shape"))); string text4 = (list.Contains(text3) ? text3 : pileAppearancePreset.Layout); shape = config.Bind<string>(section, "Layout", text4, new ConfigDescription("Pile placement / fill framework for the next pile. This changes where models sit, not which model is used.", (AcceptableValueBase)(object)new AcceptableValueList<string>(list.ToArray()), new object[1] { new ConfigurationManagerAttributes { Order = 90 } })); if (flag2 && string.Equals(shape.Value, "Pyramid", StringComparison.Ordinal)) { shape.Value = pileAppearancePreset.Layout; } } else { string text5 = func("Bar Arrangement"); barArrangement = config.Bind<string>(section, "Bar Arrangement", "Vanilla Cross-Stacked", new ConfigDescription("Visual arrangement saved into each newly placed bar stack. Cross-stacked styles alternate each layer by 90 degrees; Parallel Rows keeps every bar facing the same direction. Brick Stacked alternates full layers with centered N-1 layers so bars bridge the joins below instead of hanging over empty space. The Sideways brick variants use the same bond on the other horizontal axis. Misaligned variants keep the same structure but add small deterministic hand-stacked variation.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[8] { "Vanilla Cross-Stacked", "Misaligned Cross-Stacked", "Parallel Rows", "Misaligned Parallel Rows", "Brick Stacked", "Misaligned Brick Stacked", "Brick Stacked Sideways", "Misaligned Brick Stacked Sideways" }), new object[1] { new ConfigurationManagerAttributes { Order = 100 } })); barArrangement.Value = NormalizeBarArrangement(string.IsNullOrEmpty(text5) ? barArrangement.Value : text5); string value = func("Bars Across"); string value2 = func("Bars Deep"); string value3 = func("Layers High"); barAcross = config.Bind<int>(section, "Bars Across", 2, new ConfigDescription("Horizontal footprint from left to right. Cross-stacked arrangements use 2x2 woven modules, so odd values are rounded down to the nearest even value (minimum 2). The server-wide visual bar cap is set in General Settings.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 12), new object[1] { new ConfigurationManagerAttributes { Order = 90 } })); barDeep = config.Bind<int>(section, "Bars Deep", 2, new ConfigDescription("Horizontal footprint from front to back. Cross-stacked and Brick Stacked arrangements require an even depth, so odd values are rounded down to the nearest even value (minimum 2). Other arrangements can use any value from 1 to 12. The server-wide visual bar cap is set in General Settings.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 12), new object[1] { new ConfigurationManagerAttributes { Order = 80 } })); barLayers = config.Bind<int>(section, "Layers High", 5, new ConfigDescription("Number of vertical layers when the visual is full. The server-wide visual bar cap is set in General Settings.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), new object[1] { new ConfigurationManagerAttributes { Order = 70 } })); if (string.IsNullOrEmpty(value) && int.TryParse(func("Columns"), out var result)) { barAcross.Value = Mathf.Clamp(result, 1, 12); } if (string.IsNullOrEmpty(value3) && int.TryParse(func("Rows"), out var result2)) { barLayers.Value = Mathf.Clamp(result2, 1, 20); } if (string.IsNullOrEmpty(value2)) { barDeep.Value = 2; } barArrangement.Value = NormalizeBarArrangement(barArrangement.Value); SanitizeBarDimensions(); barArrangement.SettingChanged += OnBarLayoutValueChanged; barAcross.SettingChanged += OnBarLayoutValueChanged; barDeep.SettingChanged += OnBarLayoutValueChanged; barLayers.SettingChanged += OnBarLayoutValueChanged; } if (!isBar) { model = config.Bind<string>(section, "Model", pileAppearancePreset.Model, new ConfigDescription("Actual item model repeated through the selected pile layout for the next placement.", (AcceptableValueBase)(object)new AcceptableValueList<string>(ModelSources.Keys.ToArray()), new object[1] { new ConfigurationManagerAttributes { Order = 60, IsAdvanced = true } })); if (flag) { ConfigEntry<bool> val = config.Bind<bool>("Internal Migrations", "Obsidian Model POC Migrated 0.2.9", false, new ConfigDescription("Internal one-time migration marker.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Browsable = false } })); if (!val.Value) { if (string.Equals(model.Value, "Flint", StringComparison.Ordinal)) { model.Value = "Obsidian"; } val.Value = true; } } } if (isBar) { string value4 = func("Fill Based On") ?? ReadSavedValue(config, "Storage Capacity", "Ingot Stack Fill Based On") ?? "Occupied Slots"; string value5 = func("Looks Full At") ?? ReadSavedValue(config, "Storage Capacity", "Ingot Stack Looks Full At") ?? "100%"; fillBasis = config.Bind<string>(section, "Fill Based On", DynamicStorageMaterialsPlugin.NormalizeBarFillBasis(value4), new ConfigDescription("How this stack's visual growth is measured. Occupied Slots counts used inventory slots; Stored Bar Count uses the actual number of ingots stored. Saved into each placed stack.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[2] { "Occupied Slots", "Stored Bar Count" }), new object[1] { new ConfigurationManagerAttributes { Order = 50 } })); looksFullAt = config.Bind<string>(section, "Looks Full At", DynamicStorageMaterialsPlugin.NormalizeBarLooksFullAt(value5), new ConfigDescription("How quickly this stack reaches its fully configured visual. 50% means the visual is full at half of the selected fill basis; Always Full disables dynamic visual fill. Saved into each placed stack.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[6] { "10%", "25%", "50%", "75%", "100%", "Always Full" }), new object[1] { new ConfigurationManagerAttributes { Order = 45 } })); } else { string text6 = func("Looks Full At"); string value6 = ReadSavedValue(config, "Storage Capacity", "Ore Pile Looks Full At"); string value7 = text6; if (string.IsNullOrEmpty(value7)) { string text7 = DynamicStorageMaterialsPlugin.NormalizePileLooksFullAt(value6); value7 = (string.Equals(text7, "Always Full", StringComparison.Ordinal) ? "Match Storage Capacity" : text7); } looksFullAt = config.Bind<string>(section, "Looks Full At", DynamicStorageMaterialsPlugin.NormalizePileLooksFullAt(value7), new ConfigDescription("How quickly this pile reaches its full visual. Match Storage Capacity follows the real slot capacity; 10/20/40/60 slots reaches full at that many occupied slots; Always Full disables dynamic visual fill. Saved into each placed pile.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[6] { "Match Storage Capacity", "10 slots", "20 slots", "40 slots", "60 slots", "Always Full" }), new object[1] { new ConfigurationManagerAttributes { Order = 10 } })); if (string.Equals(section, "Flint Pile (Storage)", StringComparison.Ordinal) || string.Equals(section, "Obsidian Pile (Storage)", StringComparison.Ordinal) || string.Equals(section, "Frostcore Pile (Storage)", StringComparison.Ordinal)) { string text8 = section + " Looks Full At Migrated 1.0.1"; ConfigEntry<bool> val2 = config.Bind<bool>("Internal Migrations", text8, false, new ConfigDescription("Internal one-time migration marker.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Browsable = false } })); if (!val2.Value) { if (string.Equals(looksFullAt.Value, "Always Full", StringComparison.Ordinal)) { looksFullAt.Value = "Match Storage Capacity"; } val2.Value = true; } } } List<string> list2 = new List<string> { isBar ? "Default" : "Model Default" }; list2.AddRange(MaterialSources.Keys); material = config.Bind<string>(section, "Material", isBar ? "Default" : pileAppearancePreset.Material, new ConfigDescription(isBar ? "Vanilla material for the next placement. Default keeps the stack's native material." : "Material override for the next placement. Model Default uses the native material of whichever Model is selected.", (AcceptableValueBase)(object)new AcceptableValueList<string>(list2.ToArray()), new object[1] { new ConfigurationManagerAttributes { Order = 40, IsAdvanced = true } })); if (!isBar && string.Equals(func("Material"), "Default", StringComparison.Ordinal)) { material.Value = "Model Default"; } if (!isBar) { float num3 = func2("Size") ?? pileAppearancePreset.LayoutScale; float num4 = func2("Height") ?? pileAppearancePreset.LayoutHeight; float num5 = func2("Layout Scale") ?? num3; float num6 = func2("Layout Height") ?? num4; float num7 = func2("Model Scale") ?? pileAppearancePreset.ModelScale; layoutScale = config.Bind<float>(section, "Layout Scale", num5, new ConfigDescription("Scales the spacing / footprint of the pile layout without enlarging the individual models.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), new object[1] { new ConfigurationManagerAttributes { Order = 80 } })); layoutHeight = config.Bind<float>(section, "Layout Height", num6, new ConfigDescription("Scales only the vertical spacing of the pile layout. The individual item models are not stretched.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 1.5f), new object[1] { new ConfigurationManagerAttributes { Order = 70 } })); modelScale = config.Bind<float>(section, "Model Scale", num7, new ConfigDescription("Uniformly scales each repeated item model without changing the pile layout spacing. 1.0 matches that item's native dropped-world size.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 3f), new object[1] { new ConfigurationManagerAttributes { Order = 50 } })); float num8 = func2("Visual Vertical Offset") ?? func2("Visual Y Offset") ?? pileAppearancePreset.VisualVerticalOffset; visualVerticalOffset = config.Bind<float>(section, "Visual Vertical Offset", num8, new ConfigDescription("Moves only the pile visuals vertically after layout/model scaling. Negative values sink floating models; the piece root and container stay in place.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(-0.5f, 0.5f), new object[1] { new ConfigurationManagerAttributes { Order = 20 } })); } string text9 = func("Finish"); finish = config.Bind<string>(section, "Finish", isBar ? "As Material" : pileAppearancePreset.Finish, new ConfigDescription("Advanced material finish for the visible models. Matte/Satin/Glossy adjust smoothness; Metallic and Polished Metal also force a metallic response. Debug Emissive is an intentionally extreme bright test used to verify that finish changes are reaching the rendered model.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[7] { "As Material", "Matte", "Satin", "Glossy", "Metallic", "Polished Metal", "Debug Emissive" }), new object[1] { new ConfigurationManagerAttributes { Order = 30, IsAdvanced = true } })); if (text9 == "Original") { finish.Value = "As Material"; } if (text9 == "Shiny") { finish.Value = "Glossy"; } if (!isBar) { List<string> list3 = pilePresets.Select((PileAppearancePreset entry) => entry.Name).ToList(); list3.Add("Custom"); preset = config.Bind<string>(section, "Preset", pileAppearancePreset.Name, new ConfigDescription("Curated appearance recipe. Selecting a preset populates the settings below; changing any individual value automatically changes this to Custom.", (AcceptableValueBase)(object)new AcceptableValueList<string>(list3.ToArray()), new object[1] { new ConfigurationManagerAttributes { Order = 100 } })); RefreshPresetFromValues(); preset.SettingChanged += OnPresetChanged; shape.SettingChanged += OnAppearanceValueChanged; model.SettingChanged += OnAppearanceValueChanged; material.SettingChanged += OnAppearanceValueChanged; layoutScale.SettingChanged += OnAppearanceValueChanged; layoutHeight.SettingChanged += OnAppearanceValueChanged; modelScale.SettingChanged += OnAppearanceValueChanged; visualVerticalOffset.SettingChanged += OnAppearanceValueChanged; finish.SettingChanged += OnAppearanceValueChanged; looksFullAt.SettingChanged += OnAppearanceValueChanged; RememberObservedPresetState(); } } private static PileAppearancePreset CreateDefaultPreset(string section, string fallbackLayout, string defaultModel, float defaultLayoutScale, float defaultLayoutHeight, float defaultModelScale, float defaultVerticalOffset, string defaultMaterial) { string text = DisplayLayoutName(string.IsNullOrEmpty(fallbackLayout) ? "Stone" : fallbackLayout); string text2 = (string.IsNullOrEmpty(defaultMaterial) ? "Model Default" : defaultMaterial); return new PileAppearancePreset("Default (" + text + ")", text, defaultModel, text2, "As Material", defaultLayoutScale, defaultLayoutHeight, defaultModelScale, defaultVerticalOffset); } private static void AddAdditionalPresets(string section, List<PileAppearancePreset> presets) { } private void OnPresetChanged(object sender, EventArgs args) { if (!updatingPreset && !isBar && preset != null) { ApplySelectedPresetOrRefresh(); RememberObservedPresetState(); } } private void OnAppearanceValueChanged(object sender, EventArgs args) { if (!updatingPreset) { RefreshPresetFromValues(); RememberObservedPresetState(); } } internal void SynchronizePresetSelection() { if (updatingPreset || isBar || preset == null) { return; } string value = preset.Value; string a = BuildAppearanceSignature(); bool flag = !string.Equals(value, observedPresetValue, StringComparison.Ordinal); bool flag2 = !string.Equals(a, observedAppearanceSignature, StringComparison.Ordinal); if (flag || flag2) { if (flag) { ApplySelectedPresetOrRefresh(); } else { RefreshPresetFromValues(); } RememberObservedPresetState(); } } private void ApplySelectedPresetOrRefresh() { if (string.Equals(preset.Value, "Custom", StringComparison.Ordinal)) { RefreshPresetFromValues(); return; } PileAppearancePreset pileAppearancePreset = pilePresets.FirstOrDefault((PileAppearancePreset entry) => string.Equals(entry.Name, preset.Value, StringComparison.Ordinal)); if (pileAppearancePreset == null) { RefreshPresetFromValues(); } else { ApplyPreset(pileAppearancePreset); } } private void ApplyPreset(PileAppearancePreset selected) { if (selected == null) { return; } updatingPreset = true; try { shape.Value = selected.Layout; model.Value = selected.Model; material.Value = selected.Material; layoutScale.Value = selected.LayoutScale; layoutHeight.Value = selected.LayoutHeight; modelScale.Value = selected.ModelScale; visualVerticalOffset.Value = selected.VisualVerticalOffset; finish.Value = selected.Finish; looksFullAt.Value = selected.LooksFullAt; preset.Value = selected.Name; } finally { updatingPreset = false; } } private void RefreshPresetFromValues() { if (isBar || preset == null) { return; } PileAppearancePreset pileAppearancePreset = pilePresets.FirstOrDefault(MatchesPreset); string text = ((pileAppearancePreset != null) ? pileAppearancePreset.Name : "Custom"); if (string.Equals(preset.Value, text, StringComparison.Ordinal)) { return; } updatingPreset = true; try { preset.Value = text; } finally { updatingPreset = false; } } private void RememberObservedPresetState() { if (!isBar && preset != null) { observedPresetValue = preset.Value; observedAppearanceSignature = BuildAppearanceSignature(); } } private string BuildAppearanceSignature() { if (isBar) { return string.Empty; } return string.Join("|", shape.Value ?? string.Empty, model.Value ?? string.Empty, material.Value ?? string.Empty, finish.Value ?? string.Empty, layoutScale.Value.ToString("R", CultureInfo.InvariantCulture), layoutHeight.Value.ToString("R", CultureInfo.InvariantCulture), modelScale.Value.ToString("R", CultureInfo.InvariantCulture), visualVerticalOffset.Value.ToString("R", CultureInfo.InvariantCulture), looksFullAt.Value ?? string.Empty); } private bool MatchesPreset(PileAppearancePreset candidate) { if (candidate == null) { return false; } if (string.Equals(shape.Value, candidate.Layout, StringComparison.Ordinal) && string.Equals(model.Value, candidate.Model, StringComparison.Ordinal) && string.Equals(material.Value, candidate.Material, StringComparison.Ordinal) && string.Equals(finish.Value, candidate.Finish, StringComparison.Ordinal) && Mathf.Abs(layoutScale.Value - candidate.LayoutScale) <= 0.0005f && Mathf.Abs(layoutHeight.Value - candidate.LayoutHeight) <= 0.0005f && Mathf.Abs(modelScale.Value - candidate.ModelScale) <= 0.0005f && Mathf.Abs(visualVerticalOffset.Value - candidate.VisualVerticalOffset) <= 0.0005f) { return string.Equals(looksFullAt.Value, candidate.LooksFullAt, StringComparison.Ordinal); } return false; } internal static string NormalizeBarArrangement(string value) { if (string.IsNullOrEmpty(value)) { return "Vanilla Cross-Stacked"; } if (string.Equals(value, "Vanilla", StringComparison.Ordinal)) { return "Vanilla Cross-Stacked"; } if (string.Equals(value, "Irregular", StringComparison.Ordinal) || string.Equals(value, "Misaligned", StringComparison.Ordinal)) { return "Misaligned Parallel Rows"; } if (string.Equals(value, "Aligned", StringComparison.Ordinal) || string.Equals(value, "Side by Side", StringComparison.Ordinal) || string.Equals(value, "Long Side by Side", StringComparison.Ordinal)) { return "Parallel Rows"; } switch (value) { case "Misaligned Brick Stacked": case "Misaligned Cross-Stacked": case "Misaligned Parallel Rows": case "Brick Stacked": case "Parallel Rows": case "Vanilla Cross-Stacked": case "Brick Stacked Sideways": case "Misaligned Brick Stacked Sideways": return value; default: return "Vanilla Cross-Stacked"; } } internal static bool IsCrossStackedArrangement(string arrangement) { arrangement = NormalizeBarArrangement(arrangement); if (!(arrangement == "Vanilla Cross-Stacked")) { return arrangement == "Misaligned Cross-Stacked"; } return true; } internal static bool IsBrickStackedArrangement(string arrangement) { arrangement = NormalizeBarArrangement(arrangement); switch (arrangement) { default: return arrangement == "Misaligned Brick Stacked Sideways"; case "Brick Stacked": case "Misaligned Brick Stacked": case "Brick Stacked Sideways": return true; } } internal static bool IsBrickStackedSidewaysArrangement(string arrangement) { arrangement = NormalizeBarArrangement(arrangement); if (!(arrangement == "Brick Stacked Sideways")) { return arrangement == "Misaligned Brick Stacked Sideways"; } return true; } internal static bool IsMisalignedArrangement(string arrangement) { arrangement = NormalizeBarArrangement(arrangement); switch (arrangement) { default: return arrangement == "Misaligned Brick Stacked Sideways"; case "Misaligned Cross-Stacked": case "Misaligned Parallel Rows": case "Misaligned Brick Stacked": return true; } } internal static int NormalizeCrossStackDimension(int value) { value = Mathf.Clamp(value, 2, 12); if ((value & 1) != 0) { value--; } return Mathf.Max(2, value); } internal static int NormalizeBrickDeepDimension(int value) { value = Mathf.Clamp(value, 2, 12); if ((value & 1) != 0) { value--; } return Mathf.Max(2, value); } internal static int CalculateBarVisualCount(string arrangement, int across, int deep, int layers) { across = Mathf.Clamp(across, 1, 12); deep = Mathf.Clamp(deep, 1, 12); layers = Mathf.Clamp(layers, 1, 20); arrangement = NormalizeBarArrangement(arrangement); if (IsCrossStackedArrangement(arrangement)) { across = NormalizeCrossStackDimension(across); deep = NormalizeCrossStackDimension(deep); return across * deep / 2 * layers; } if (IsBrickStackedArrangement(arrangement)) { deep = NormalizeBrickDeepDimension(deep); bool num = IsBrickStackedSidewaysArrangement(arrangement); int num2 = (layers + 1) / 2; int num3 = layers / 2; int num4 = across * deep; int num5 = 0; int num6; if (num) { num6 = ((across > 1) ? (across - 1) : across) * deep; if (across > 1) { num5 = deep; } } else { num6 = across * ((deep > 1) ? (deep - 1) : deep); if (deep > 1) { num5 = (across + 1) / 2 * 2; } } return num2 * num4 + num3 * (num6 + num5); } return across * deep * layers; } internal static void SanitizeBarDimensionsToLimit(string arrangement, ref int across, ref int deep, ref int layers, int maxVisualBars) { arrangement = NormalizeBarArrangement(arrangement); bool flag = IsCrossStackedArrangement(arrangement); bool flag2 = IsBrickStackedArrangement(arrangement); across = Mathf.Clamp(across, 1, 12); deep = Mathf.Clamp(deep, 1, 12); layers = Mathf.Clamp(layers, 1, 20); if (flag) { across = NormalizeCrossStackDimension(across); deep = NormalizeCrossStackDimension(deep); } else if (flag2) { deep = NormalizeBrickDeepDimension(deep); } maxVisualBars = Mathf.Clamp(maxVisualBars, 10, 400); while (layers > 1 && CalculateBarVisualCount(arrangement, across, deep, layers) > maxVisualBars) { layers--; } int num = ((!(flag || flag2)) ? 1 : 2); int num2 = ((!(flag || flag2)) ? 1 : 2); int num3 = ((!flag) ? 1 : 2); int num4 = ((!flag) ? 1 : 2); while (deep > num && CalculateBarVisualCount(arrangement, across, deep, layers) > maxVisualBars) { deep -= num2; } while (across > num3 && CalculateBarVisualCount(arrangement, across, deep, layers) > maxVisualBars) { across -= num4; } while (layers > 1 && CalculateBarVisualCount(arrangement, across, deep, layers) > maxVisualBars) { layers--; } } private void OnBarLayoutValueChanged(object sender, EventArgs args) { if (!updatingBarDimensions) { SanitizeBarDimensions(); } } private void SanitizeBarDimensions() { if (!isBar || barAcross == null || barDeep == null || barLayers == null || barArrangement == null) { return; } updatingBarDimensions = true; try { barArrangement.Value = NormalizeBarArrangement(barArrangement.Value); int across = barAcross.Value; int deep = barDeep.Value; int layers = barLayers.Value; SanitizeBarDimensionsToLimit(barArrangement.Value, ref across, ref deep, ref layers, DynamicStorageMaterialsPlugin.CurrentMaxVisualBarsPerStack); barAcross.Value = across; barDeep.Value = deep; barLayers.Value = layers; } finally { updatingBarDimensions = false; } } private static string ReadSavedValue(ConfigFile config, string section, string key) { try { if (!File.Exists(config.ConfigFilePath)) { return null; } bool flag = false; string text = key + " = "; foreach (string item in File.ReadLines(config.ConfigFilePath)) { string text2 = item.Trim(); if (text2.StartsWith("[", StringComparison.Ordinal) && text2.EndsWith("]", StringComparison.Ordinal)) { flag = text2.Substring(1, text2.Length - 2) == section; } else if (flag && text2.StartsWith(text, StringComparison.Ordinal)) { return text2.Substring(text.Length).Trim(); } } } catch (IOException) { } catch (UnauthorizedAccessException) { } return null; } private static float? ReadSavedFloat(ConfigFile config, string section, string key) { string text = ReadSavedValue(config, section, key); if (string.IsNullOrEmpty(text)) { return null; } if (float.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return result; } if (float.TryParse(text, out var result2)) { return result2; } return null; } internal AppearanceSnapshot Capture() { AppearanceSnapshot appearanceSnapshot = new AppearanceSnapshot { Preset = ((preset == null) ? "Custom" : preset.Value), Shape = ((shape == null) ? "Default" : shape.Value), Model = ((model == null) ? "Default" : model.Value), Material = material.Value, Tint = "#FFFFFF", Finish = finish.Value, BarArrangement = ((barArrangement == null) ? "Vanilla Cross-Stacked" : NormalizeBarArrangement(barArrangement.Value)), BarAcross = ((barAcross == null) ? 2 : Mathf.Clamp(barAcross.Value, 1, 12)), BarDeep = ((barDeep == null) ? 2 : Mathf.Clamp(barDeep.Value, 1, 12)), BarLayers = ((barLayers == null) ? 5 : Mathf.Clamp(barLayers.Value, 1, 20)), FillBasis = ((isBar && fillBasis != null) ? DynamicStorageMaterialsPlugin.NormalizeBarFillBasis(fillBasis.Value) : "Occupied Slots"), LooksFullAt = (isBar ? DynamicStorageMaterialsPlugin.NormalizeBarLooksFullAt((looksFullAt != null) ? looksFullAt.Value : "100%") : DynamicStorageMaterialsPlugin.NormalizePileLooksFullAt((looksFullAt != null) ? looksFullAt.Value : "Match Storage Capacity")) }; if (isBar) { appearanceSnapshot.Scale = 1f; int across = appearanceSnapshot.BarAcross; int deep = appearanceSnapshot.BarDeep; int layers = appearanceSnapshot.BarLayers; SanitizeBarDimensionsToLimit(appearanceSnapshot.BarArrangement, ref across, ref deep, ref layers, DynamicStorageMaterialsPlugin.CurrentMaxVisualBarsPerStack); appearanceSnapshot.BarAcross = across; appearanceSnapshot.BarDeep = deep; appearanceSnapshot.BarLayers = layers; } else { appearanceSnapshot.LayoutScale = Mathf.Clamp(layoutScale.Value, 0.5f, 3f); appearanceSnapshot.LayoutHeight = Mathf.Clamp(layoutHeight.Value, 0.5f, 1.5f); appearanceSnapshot.ModelScale = Mathf.Clamp(modelScale.Value, 0.5f, 3f); appearanceSnapshot.VisualVerticalOffset = Mathf.Clamp(visualVerticalOffset.Value, -0.5f, 0.5f); } return appearanceSnapshot; } } internal sealed class PileAppearancePreset { internal string Name { get; } internal string Layout { get; } internal string Model { get; } internal string Material { get; } internal string Finish { get; } internal float LayoutScale { get; } internal float LayoutHeight { get; } internal float ModelScale { get; } internal float VisualVerticalOffset { get; } internal string LooksFullAt { get; } internal PileAppearancePreset(string name, string layout, string model, string material, string finish, float layoutScale, float layoutHeight, float modelScale, float visualVerticalOffset, string looksFullAt = "Match Storage Capacity") { Name = name; Layout = layout; Model = model; Material = material; Finish = finish; LayoutScale = layoutScale; LayoutHeight = layoutHeight; ModelScale = modelScale; VisualVerticalOffset = visualVerticalOffset; LooksFullAt = DynamicStorageMaterialsPlugin.NormalizePileLooksFullAt(looksFullAt); } } internal sealed class AppearanceSnapshot { internal string Preset = "Custom"; internal string Shape = "Default"; internal string Model = "Default"; internal string Material = "Default"; internal float Scale = 1f; internal float LayoutScale = 1f; internal float LayoutHeight = 1f; internal float ModelScale = 1f; internal float VisualVerticalOffset; internal string Tint = "#FFFFFF"; internal string Finish = "As Material"; internal string BarArrangement = "Vanilla Cross-Stacked"; internal int BarAcross = 2; internal int BarDeep = 2; internal int BarLayers = 5; internal string FillBasis = "Occupied Slots"; internal string LooksFullAt = "Match Storage Capacity"; internal string Identity => Shape + "|" + Model + "|" + Material + "|" + Scale.ToString("R", CultureInfo.InvariantCulture) + "|" + LayoutScale.ToString("R", CultureInfo.InvariantCulture) + "|" + LayoutHeight.ToString("R", CultureInfo.InvariantCulture) + "|" + ModelScale.ToString("R", CultureInfo.InvariantCulture) + "|" + VisualVerticalOffset.ToString("R", CultureInfo.InvariantCulture) + "|" + Tint + "|" + Finish + "|" + BarArrangement + "|" + BarAcross.ToString(CultureInfo.InvariantCulture) + "|" + BarDeep.ToString(CultureInfo.InvariantCulture) + "|" + BarLayers.ToString(CultureInfo.InvariantCulture) + "|" + FillBasis + "|" + LooksFullAt; internal static string NormalizeTint(string value) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) string text = (value ?? "").Trim(); if (!text.StartsWith("#", StringComparison.Ordinal)) { text = "#" + text; } Color val = default(Color); if (!ColorUtility.TryParseHtmlString(text, ref val)) { return "#FFFFFF"; } return "#" + ColorUtility.ToHtmlStringRGB(val); } } internal sealed class ConfigurationManagerAttributes { public int? Order; public bool? IsAdminOnly; public bool? ReadOnly; public bool? Browsable; public bool? IsAdvanced; } [BepInPlugin("com.muji.DynamicStorageMaterials", "Dynamic Storage Materials", "1.0.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal sealed class DynamicStorageMaterialsPlugin : BaseUnityPlugin { private sealed class BarDefinition { public string BasePiecePrefab { get; } public string DestroyedVfxPrefab { get; } public string ResourceItemPrefab { get; } public string NewPrefabName { get; } public string DisplayName { get; } public int BuildCost { get; } public BarDefinition(string basePiecePrefab, string destroyedVfxPrefab, string resourceItemPrefab, string newPrefabName, string displayName, int buildCost) { BasePiecePrefab = basePiecePrefab; DestroyedVfxPrefab = destroyedVfxPrefab; ResourceItemPrefab = resourceItemPrefab; NewPrefabName = newPrefabName; DisplayName = displayName; BuildCost = buildCost; } } private sealed class TemplateDefinition { public string BasePilePrefab { get; } public string MaterialSourcePrefab { get; } public string ResourceItemPrefab { get; } public string NewPrefabName { get; } public string DisplayName { get; } public int BuildCost { get; } public float LocalScaleMultiplier { get; } public string DefaultShape { get; } public float DefaultSize { get; } public float DefaultHeight { get; } public float DefaultModelScale { get; } public float DefaultVerticalOffset { get; } public string VisualModelPrefab { get; } public string DefaultMaterial { get; } public bool ForceResourceModelGeometry { get; } public string ConfigSectionName { get; } public string LegacyConfigSectionName { get; } public TemplateDefinition(string basePilePrefab, string materialSourcePrefab, string resourceItemPrefab, string newPrefabName, string displayName, int buildCost, float localScaleMultiplier = 1f, string defaultShape = null, float defaultSize = 1f, float defaultHeight = 1f, string configSectionName = null, string legacyConfigSectionName = null, float defaultModelScale = 1f, float defaultVerticalOffset = 0f, string visualModelPrefab = null, string defaultMaterial = null, bool forceResourceModelGeometry = false) { BasePilePrefab = basePilePrefab; MaterialSourcePrefab = materialSourcePrefab; ResourceItemPrefab = resourceItemPrefab; NewPrefabName = newPrefabName; DisplayName = displayName; BuildCost = buildCost; LocalScaleMultiplier = localScaleMultiplier; DefaultShape = defaultShape; DefaultSize = defaultSize; DefaultHeight = defaultHeight; DefaultModelScale = defaultModelScale; DefaultVerticalOffset = defaultVerticalOffset; VisualModelPrefab = (string.IsNullOrEmpty(visualModelPrefab) ? resourceItemPrefab : visualModelPrefab); DefaultMaterial = (string.IsNullOrEmpty(defaultMaterial) ? "Model Default" : defaultMaterial); ForceResourceModelGeometry = forceResourceModelGeometry; ConfigSectionName = (string.IsNullOrEmpty(configSectionName) ? displayName : configSectionName); LegacyConfigSectionName = legacyConfigSectionName; } } public const string PluginGuid = "com.muji.DynamicStorageMaterials"; public const string PluginName = "Dynamic Storage Materials"; public const string PluginVersion = "1.0.1"; private Harmony placementHarmony; private Harmony restrictionHarmony; private readonly List<CustomPiece> piecesNeedingIcons = new List<CustomPiece>(); private readonly List<GameObject> forgeBuildPiecePrefabs = new List<GameObject>(); private bool pieceIconsQueued; private ConfigEntry<bool> showMeshDebugHover; private ConfigEntry<bool> showTechnicalDebugHover; private ConfigEntry<bool> showDroppedModelDebugHover; private ConfigEntry<bool> enableApplyConfigDebug; private ConfigEntry<int> orePileStorageCapacity; private ConfigEntry<int> ingotStackStorageCapacity; private ConfigEntry<int> maxVisualBarsPerStack; private ConfigEntry<bool> showForgeBuildPieces; private PlacedAppearance configApplyHoverTarget; private float configApplyHoverTargetUntil; private PlacedAppearance debugHoverTarget; private float debugHoverTargetUntil; private PlacedAppearance debugOverrideTarget; private static bool hoverErrorLogged; private float nextPresetConfigSync; internal const float ObsidianVisualGroundOffset = -0.0508f; internal const int AbsoluteMaxVisualBarsPerStack = 400; private readonly List<BarDefinition> barDefinitions = new List<BarDefinition>(); private readonly List<TemplateDefinition> templateDefinitions = new List<TemplateDefinition> { new TemplateDefinition("flint_pile", "Flint", "Flint", "DSM_FlintPile", "Flint Pile (Storage)", 10, 1f, "Grausten", 0.75f, 0.75f), new TemplateDefinition("flint_pile", "Obsidian", "Obsidian", "DSM_ObsidianPile", "Obsidian Pile (Storage)", 10, 1f, "Flint - Experimental", 0.75f, 1.1f, null, null, 1f, 0f, null, "Obsidian", forceResourceModelGeometry: true), new TemplateDefinition("coal_pile", "Resin", "Resin", "DSM_ResinPile", "Resin Pile (Storage)", 10, 1f, "Coal", 0.85f, 0.75f, null, null, 1.3f), new TemplateDefinition("stone_pile", "GreydwarfEye", "GreydwarfEye", "DSM_GreydwarfEyePile", "Greydwarf Eye Pile (Storage)", 10, 1f, "Coal", 0.8f, 0.7f, null, null, 0.8f, 0.01f), new TemplateDefinition("coal_pile", "SurtlingCore", "SurtlingCore", "DSM_SurtlingCorePile", "Surtling Core Pile (Storage)", 5, 1f, "Pyramid", 1f, 0.83f, null, null, 1f, 0.1f), new TemplateDefinition("stone_pile", "Crystal", "Crystal", "DSM_CrystalPile", "Crystal Pile (Storage)", 5, 1f, "Obsidian - Experimental", 0.9f, 1.5f, null, null, 1.15f, 0.06f), new TemplateDefinition("stone_pile", "FreezeGland", "FreezeGland", "DSM_FreezeGlandPile", "Freeze Gland Pile (Storage)", 5, 1f, "Stone", 1f, 0.9f, null, null, 1.1f, 0.05f), new TemplateDefinition("coal_pile", "Needle", "Needle", "DSM_NeedlePile", "Needle Pile (Storage)", 10, 1f, "Grausten", 0.5f, 0.5f, null, null, 0.5f, 0.02f), new TemplateDefinition("stone_pile", "Softtissue", "Softtissue", "DSM_SoftTissuePile", "Soft Tissue Pile (Storage)", 10, 1f, "Black Marble", 1.08f, 0.93f), new TemplateDefinition("coal_pile", "BlackCore", "BlackCore", "DSM_BlackCorePile", "Black Core Pile (Storage)", 3, 1f, "Flint - Experimental", 0.54f, 1.5f, null, null, 1f, 0.05f), new TemplateDefinition("stone_pile", "SulfurStone", "SulfurStone", "DSM_SulfurPile", "Sulfur Pile (Storage)", 10, 1f, "Coal", 0.73f, 0.5f, null, null, 1f, 0.04f), new TemplateDefinition("stone_pile", "Ice", "Ice", "DSM_IcePile", "Ice Pile (Storage)", 10, 1f, "Obsidian - Experimental", 0.69f, 1.35f), new TemplateDefinition("coal_pile", "FrostCore", "FrostCore", "DSM_FrostcorePile", "Frostcore Pile (Storage)", 3, 1f, "Grausten", 0.5f, 0.74f) }; internal static DynamicStorageMaterialsPlugin Current { get; private set; } internal bool ShowAppearanceDebugHover => EnableApplyConfigDebug; internal bool ShowMeshDebugHover { get { if (showMeshDebugHover != null) { return showMeshDebugHover.Value; } return false; } } internal bool ShowTechnicalDebugHover { get { if (showTechnicalDebugHover != null) { return showTechnicalDebugHover.Value; } return false; } } internal bool ShowDroppedModelDebugHover { get { if (showDroppedModelDebugHover != null) { return showDroppedModelDebugHover.Value; } return false; } } internal bool EnableApplyConfigDebug { get { if (enableApplyConfigDebug != null) { return enableApplyConfigDebug.Value; } return false; } } internal int OrePileStorageCapacity => NormalizeStorageCapacity((orePileStorageCapacity != null) ? orePileStorageCapacity.Value : 20); internal int IngotStackStorageCapacity => NormalizeStorageCapacity((ingotStackStorageCapacity != null) ? ingotStackStorageCapacity.Value : 20); internal int MaxVisualBarsPerStack => Mathf.Clamp((maxVisualBarsPerStack != null) ? maxVisualBarsPerStack.Value : 120, 10, 400); internal static int CurrentMaxVisualBarsPerStack { get { if (!((Object)(object)Current != (Object)null)) { return 120; } return Current.MaxVisualBarsPerStack; } } internal bool ShowAnyDebugHover { get { if (!EnableApplyConfigDebug && !ShowMeshDebugHover) { return ShowTechnicalDebugHover; } return true; } } private void Awake() { //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Expected O, but got Unknown //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Expected O, but got Unknown Current = this; AcceptableValueList<int> val = new AcceptableValueList<int>(new int[4] { 10, 20, 40, 60 }); int value = ReadSavedInt("Storage Capacity", "Ore Pile Slots", 20); bool flag = ReadSavedBool("Build Menu", "Show Material Build Pieces", fallback: true); orePileStorageCapacity = ConfigFileExtensions.BindConfig<int>(((BaseUnityPlugin)this).Config, "General Settings", "Material Pile Slots", NormalizeStorageCapacity(value), "Server-controlled slot count for Dynamic Storage Materials piles. Options: 10, 20, 40, or 60.", true, (int?)100, (AcceptableValueBase)(object)val, (Action<ConfigEntryBase>)null, (ConfigurationManagerAttributes)null); showForgeBuildPieces = ((BaseUnityPlugin)this).Config.Bind<bool>("General Settings", "Show Material Build Pieces", flag, new ConfigDescription("Client-local only. Turn this off to hide Dynamic Storage Materials blueprints from the Hammer build menu. Existing placed storage remains registered and fully usable.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 90 } })); orePileStorageCapacity.SettingChanged += OnStorageCapacityChanged; showForgeBuildPieces.SettingChanged += OnShowForgeBuildPiecesChanged; BindAppearanceEditorSettings(); BindDebugSettings(); InstallPlacementHook(); InstallHoverHook(); restrictionHarmony = new Harmony("com.muji.DynamicStorageMaterials.restrictions"); if (!ForgeInventoryRestrictionPatches.Install(restrictionHarmony)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"One or more Materials item restriction hooks could not be installed."); } if (!ForgeStorageCapacityPatches.Install(restrictionHarmony)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Materials storage-capacity safety hook could not be installed."); } PrefabManager.OnPrefabsRegistered += OnPrefabsRegistered; PieceManager.OnPiecesRegistered += OnPiecesRegistered; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Dynamic Storage Materials 1.0.1 loaded; waiting for prefabs."); } private void BindAppearanceEditorSettings() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown enableApplyConfigDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("Appearance Editor", "Pile Appearance Editor", false, new ConfigDescription("Shows a colour-coded appearance summary while looking at Dynamic Storage Materials and enables R to apply the current configuration for that exact pile to the placed piece. Appearance changes are saved on the placed piece and replicated through its ZDO.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 100 } })); } private void BindDebugSettings() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Expected O, but got Unknown showMeshDebugHover = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Show Mesh Debug On Hover", false, new ConfigDescription("Mesh stage inspector used for Flint/Obsidian tuning. While looking at a Materials pile, [ and ] select the real fill sequence; Left/Right select a layer inside that sequence; Up locks that layer on; Down hides it; Right Ctrl resets all sequence/layer overrides.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { Order = 100 } })); showTechnicalDebugHover = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Show Technical Debug On Hover", false, new ConfigDescription("Show snapshot and ZDO ownership troubleshooting information.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { IsAdvanced = true } })); showDroppedModelDebugHover = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Show Dropped Model Debug On Hover", false, new ConfigDescription("Append DSM model-size diagnostics to supported loose/dropped items so Model Scale 1.0 can be verified against the actual world item.", (AcceptableValueBase)null, new object[1] { new ConfigurationManagerAttributes { IsAdvanced = true } })); } private void OnStorageCapacityChanged(object sender, EventArgs args) { ForgeStorageCapacity.RefreshAll(); ForgeVisualStack.RefreshAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Material pile storage capacity updated: {OrePileStorageCapacity} slots."); } private void OnMaximumVisualBarsChanged(object sender, EventArgs args) { PlacedAppearance[] array = Object.FindObjectsOfType<PlacedAppearance>(); foreach (PlacedAppearance placedAppearance in array) { if (Object.op_Implicit((Object)(object)placedAppearance)) { placedAppearance.ForceAppearanceRefresh(); } } } private void OnShowForgeBuildPiecesChanged(object sender, EventArgs args) { ApplyForgeBuildPieceVisibility(); } private void ApplyForgeBuildPieceVisibility() { if (showForgeBuildPieces == null || PieceManager.Instance == null) { return; } PieceTable pieceTable = PieceManager.Instance.GetPieceTable(PieceTables.Hammer); if (!Object.op_Implicit((Object)(object)pieceTable) || pieceTable.m_pieces == null) { return; } bool value = showForgeBuildPieces.Value; int num = 0; foreach (GameObject forgeBuildPiecePrefab in forgeBuildPiecePrefabs) { if (Object.op_Implicit((Object)(object)forgeBuildPiecePrefab)) { bool flag = pieceTable.m_pieces.Contains(forgeBuildPiecePrefab); if (value && !flag) { pieceTable.m_pieces.Add(forgeBuildPiecePrefab); num++; } else if (!value && flag) { pieceTable.m_pieces.Remove(forgeBuildPiecePrefab); num++; } } } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Materials Hammer blueprints " + (value ? "shown" : "hidden") + ((num > 0) ? $" ({num} menu entries updated)." : "."))); } private string ReadSavedValue(string section, string key) { try { if (!File.Exists(((BaseUnityPlugin)this).Config.ConfigFilePath)) { return null; } bool flag = false; string text = key + " = "; foreach (string item in File.ReadLines(((BaseUnityPlugin)this).Config.ConfigFilePath)) { string text2 = item.Trim(); if (text2.StartsWith("[", StringComparison.Ordinal) && text2.EndsWith("]", StringComparison.Ordinal)) { flag = text2.Substring(1, text2.Length - 2) == section; } else if (flag && text2.StartsWith(text, StringComparison.Ordinal)) { return text2.Substring(text.Length).Trim(); } } } catch (IOException) { } catch (UnauthorizedAccessException) { } return null; } private int ReadSavedInt(string section, string key, int fallback) { if (!int.TryParse(ReadSavedValue(section, key), out var result)) { return fallback; } return result; } private bool ReadSavedBool(string section, string key, bool fallback) { if (!bool.TryParse(ReadSavedValue(section, key), out var result)) { return fallback; } return result; } internal static string NormalizeBarFillBasis(string value) { if (!string.Equals(value, "Stored Bar Count", StringComparison.Ordinal)) { return "Occupied Slots"; } return "Stored Bar Count"; } internal static string NormalizeBarLooksFullAt(string value) { if (string.Equals(value, "Always Full", StringComparison.Ordinal)) { return "Always Full"; } switch (value) { case "10%": case "25%": case "50%": case "75%": case "100%": return value; default: return "100%"; } } internal static int ParseBarLooksFullPercent(string value) { return NormalizeBarLooksFullAt(value) switch { "Always Full" => -1, "10%" => 10, "25%" => 25, "50%" => 50, "75%" => 75, _ => 100, }; } internal static string NormalizePileLooksFullAt(string value) { string text = (value ?? string.Empty).Trim(); if (text.Length == 0 || string.Equals(text, "Match Storage Capacity", StringComparison.OrdinalIgnoreCase)) { return "Match Storage Capacity"; } if (string.Equals(text, "Always Full", StringComparison.OrdinalIgnoreCase)) { return "Always Full"; } if (string.Equals(text, "10", StringComparison.OrdinalIgnoreCase) || string.Equals(text, "10 slots", StringComparison.OrdinalIgnoreCase)) { return "10 slots"; } if (string.Equals(text, "20", StringComparison.OrdinalIgnoreCase) || string.Equals(text, "20 slots", StringComparison.OrdinalIgnoreCase)) { return "20 slots"; } if (string.Equals(text, "40", StringComparison.OrdinalIgnoreCase) || string.Equals(text, "40 slots", StringComparison.OrdinalIgnoreCase)) { return "40 slots"; } if (string.Equals(text, "60", StringComparison.OrdinalIgnoreCase) || string.Equals(text, "60 slots", StringComparison.OrdinalIgnoreCase)) { return "60 slots"; } return "Match Storage Capacity"; } internal static int ParsePileLooksFullSlots(string value) { return NormalizePileLooksFullAt(value) switch { "Always Full" => -1, "10 slots" => 10, "20 slots" => 20, "40 slots" => 40, "60 slots" => 60, _ => 0, }; } internal static int NormalizeStorageCapacity(int value) { return value switch { 10 => 10, 40 => 40, 60 => 60, _ => 20, }; } internal static void GetStorageGrid(int capacity, out int width, out int height) { switch (NormalizeStorageCapacity(capacity)) { case 10: width = 5; height = 2; break; case 40: width = 8; height = 5; break; case 60: width = 10; height = 6; break; default: width = 5; height = 4; break; } } private void LateUpdate() { if (Time.unscaledTime >= nextPresetConfigSync) { nextPresetConfigSync = Time.unscaledTime + 0.1f; PlacedAppearance.SynchronizeConfigPresets(); } bool flag = EnableApplyConfigDebug && Object.op_Implicit((Object)(object)configApplyHoverTarget) && Time.unscaledTime <= configApplyHoverTargetUntil; if (!EnableApplyConfigDebug) { configApplyHoverTarget = null; } else if (flag && Input.GetKeyDown((KeyCode)114)) { configApplyHoverTarget.ApplyCurrentConfigToPlacedPiece(); } if (!ShowMeshDebugHover) { if (Object.op_Implicit((Object)(object)debugOverrideTarget)) { debugOverrideTarget.ClearDebugMeshOverride(); } debugOverrideTarget = null; debugHoverTarget = null; return; } if (Object.op_Implicit((Object)(object)debugOverrideTarget) && !debugOverrideTarget.RefreshDebugMeshOverride()) { debugOverrideTarget = null; } if (!Object.op_Implicit((Object)(object)debugHoverTarget) || !(Time.unscaledTime <= debugHoverTargetUntil)) { return; } int num = (Input.GetKeyDown((KeyCode)275) ? 1 : (Input.GetKeyDown((KeyCode)276) ? (-1) : 0)); int num2 = (Input.GetKeyDown((KeyCode)93) ? 1 : (Input.GetKeyDown((KeyCode)91) ? (-1) : 0)); bool keyDown = Input.GetKeyDown((KeyCode)273); bool keyDown2 = Input.GetKeyDown((KeyCode)274); bool keyDown3 = Input.GetKeyDown((KeyCode)305); if (num != 0 || num2 != 0 || keyDown || keyDown2 || keyDown3) { if (Object.op_Implicit((Object)(object)debugOverrideTarget) && (Object)(object)debugOverrideTarget != (Object)(object)debugHoverTarget) { debugOverrideTarget.ClearDebugMeshOverride(); debugOverrideTarget = null; } if (num2 != 0 && debugHoverTarget.DebugSelectSequence(num2)) { debugOverrideTarget = debugHoverTarget; } if (num != 0) { debugHoverTarget.DebugSelectMesh(num); } if (keyDown3 && debugHoverTarget.DebugResetSequenceOverrides() && (Object)(object)debugOverrideTarget == (Object)(object)debugHoverTarget) { debugOverrideTarget = null; } if (keyDown && debugHoverTarget.DebugSetSelectedMeshVisible(visible: true)) { debugOverrideTarget = debugHoverTarget; } else if (keyDown2 && debugHoverTarget.DebugSetSelectedMeshVisible(visible: false)) { debugOverrideTarget = debugHoverTarget; } } } private void OnDestroy() { PrefabManager.OnPrefabsRegistered -= OnPrefabsRegistered; PieceManager.OnPiecesRegistered -= OnPiecesRegistered; Harmony obj = placementHarmony; if (obj != null) { obj.UnpatchSelf(); } Harmony obj2 = restrictionHarmony; if (obj2 != null) { obj2.UnpatchSelf(); } if ((Object)(object)Current == (Object)(object)this) { Current = null; } } private void InstallPlacementHook() { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown MethodInfo[] array = (from methodInfo2 in typeof(Piece).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) where methodInfo2.Name == "SetCreator" && methodInfo2.GetParameters().Length != 0 && methodInfo2.GetParameters()[0].ParameterType == typeof(long) select methodInfo2).ToArray(); if (array.Length == 0) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"No Piece.SetCreator overload with a long creator ID was found; appearance snapshots cannot be saved."); return; } if (placementHarmony == null) { placementHarmony = new Harmony("com.muji.DynamicStorageMaterials.appearance"); } MethodInfo method = typeof(DynamicStorageMaterialsPlugin).GetMethod("CaptureNewPiece", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo[] array2 = array; foreach (MethodInfo methodInfo in array2) { try { placementHarmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(method), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"Appearance placement hook installed on Piece.{methodInfo}."); } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Could not install appearance hook on Piece.{methodInfo}: {arg}"); } } } private void InstallHoverHook() { //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Expected O, but got Unknown //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Expected O, but got Unknown MethodInfo method = typeof(Container).GetMethod("GetHoverText", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (method == null || method.ReturnType != typeof(string)) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"Container.GetHoverText() not found; appearance hover debug is unavailable."); return; } try { if (placementHarmony == null) { placementHarmony = new Harmony("com.muji.DynamicStorageMaterials.appearance"); } MethodInfo method2 = typeof(DynamicStorageMaterialsPlugin).GetMethod("AddAppearanceDebugHover", BindingFlags.Static | BindingFlags.NonPublic); placementHarmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo method3 = typeof(ItemDrop).GetMethod("GetHoverText", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (method3 != null && method3.ReturnType == typeof(string)) { MethodInfo method4 = typeof(DynamicStorageMaterialsPlugin).GetMethod("AddDroppedModelDebugHover", BindingFlags.Static | BindingFlags.NonPublic); placementHarmony.Patch((MethodBase)method3, (HarmonyMethod)null, new HarmonyMethod(method4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"Could not install appearance editor hover: {arg}"); } } private static void AddAppearanceDebugHover(Container __instance, ref string __result) { if ((Object)(object)Current == (Object)null || !Current.ShowAnyDebugHover || !Object.op_Implicit((Object)(object)__instance)) { return; } try { PlacedAppearance component = ((Component)__instance).GetComponent<PlacedAppearance>(); if (Object.op_Implicit((Object)(object)component)) { if (Current.ShowMeshDebugHover) { Current.debugHoverTarget = component; Current.debugHoverTargetUntil = Time.unscaledTime + 0.35f; } if (Current.EnableApplyConfigDebug) { Current.configApplyHoverTarget = component; Current.configApplyHoverTargetUntil = Time.unscaledTime + 0.35f; } __result = (__result ?? string.Empty) + component.GetDebugHoverText(Current.ShowAppearanceDebugHover, Current.ShowMeshDebugHover, Current.ShowTechnicalDebugHover, Current.EnableApplyConfigDebug); } } catch (Exception arg) { if (!hoverErrorLogged) { ((BaseUnityPlugin)Current).Logger.LogWarning((object)$"Materials appearance/editor hover failed: {arg}"); hoverErrorLogged = true; } } } private static void AddDroppedModelDebugHover(ItemDrop __instance, ref string __result) { //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Current == (Object)null || !Current.ShowDroppedModelDebugHover || !Object.op_Implicit((Object)(object)__instance)) { return; } try { string text = null; if (__instance.m_itemData != null && Object.op_Implicit((Object)(object)__instance.m_itemData.m_dropPrefab)) { text = ((Object)__instance.m_itemData.m_dropPrefab).name; } if (string.IsNullOrEmpty(text)) { text = ((Object)((Component)__instance).gameObject).name ?? string.Empty; int num = text.IndexOfAny(new char[2] { '(', ' ' }); if (num > 0) { text = text.Substring(0, num); } } string value = AppearanceSettings.ModelNameForPrefab(text); if (string.IsNullOrEmpty(value)) { return; } Vector3 size; bool flag = ForgePileStageDefinitions.TryMeasureModelInstanceWorldSize(((Component)__instance).gameObject, out size); Vector3 size2; bool flag2 = ForgePileStageDefinitions.TryGetNativeModelWorldSize(text, out size2); if (flag || flag2) { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("\n<color=#8AD7FF>DSM DROPPED MODEL DEBUG — ").Append(value).Append("</color>"); if (flag) { stringBuilder.Append("\nDropped rendered size: ").Append(FormatDebugSize(size)).Append(" m"); } if (flag2) { stringBuilder.Append("\nDSM Model Scale 1.0: ").Append(FormatDebugSize(size2)).Append(" m"); } __result = (__result ?? string.Empty) + stringBuilder.ToString(); } } catch (Exception ex) { if (!hoverErrorLogged) { ((BaseUnityPlugin)Current).Logger.LogWarning((object)("DSM dropped-model hover debug failed: " + ex)); hoverErrorLogged = true; } } } private static string FormatDebugSize(Vector3 size) { return size.x.ToString("0.###", CultureInfo.InvariantCulture) + " × " + size.y.ToString("0.###", CultureInfo.InvariantCulture) + " × " + size.z.ToString("0.###", CultureInfo.InvariantCulture); } private static void CaptureNewPiece(Piece __instance) { try { if (Object.op_Implicit((Object)(object)__instance)) { PlacedAppearance component = ((Component)__instance).GetComponent<PlacedAppearance>(); if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)Player.m_localPlayer)) { component.SavePlacementDefaults(); } } } catch (Exception arg) { DynamicStorageMaterialsPlugin current = Current; if (current != null) { ((BaseUnityPlugin)current).Logger.LogError((object)$"Appearance could not be saved on new piece: {arg}"); } } } private void OnPiecesRegistered() { if (!pieceIconsQueued) { foreach (CustomPiece piecesNeedingIcon in piecesNeedingIcons) { if (piecesNeedingIcon != null && Object.op_Implicit((Object)(object)piecesNeedingIcon.PiecePrefab) && (Object)(object)piecesNeedingIcon.Piece != (Object)null) { ((MonoBehaviour)this).StartCoroutine(RenderPieceIcon(piecesNeedingIcon)); } } pieceIconsQueued = true; } ApplyForgeBuildPieceVisibility(); } private IEnumerator RenderPieceIcon(CustomPiece piece) { yield return null; ForgeVisualStack[] componentsInChildren = ((Component)piece.Piece).GetComponentsInChildren<ForgeVisualStack>(true); ForgeVisualStack[] array = componentsInChildren; foreach (ForgeVisualStack forgeVisualStack in array) { if (Object.op_Implicit((Object)(object)forgeVisualStack)) { forgeVisualStack.SetVisualsActive(55f); } } piece.Piece.m_icon = RenderManager.Instance.Render(new RenderRequest(piece.PiecePrefab) { Width = 64, Height = 64, Rotation = RenderManager.IsometricRotation * Quaternion.Euler(0f, -90f, 0f), UseCache = true, TargetPlugin = ((BaseUnityPlugin)this).Info.Metadata }); array = componentsInChildren; foreach (ForgeVisualStack forgeVisualStack2 in array) { if (Object.op_Implicit((Object)(object)forgeVisualStack2)) { forgeVisualStack2.SetVisualsActive(100f); } } } private void OnPrefabsRegistered() { PrefabManager.OnPrefabsRegistered -= OnPrefabsRegistered; int num = 0; PlacedAppearance.CacheSources(); foreach (TemplateDefinition templateDefinition in templateDefinitions) { try { if (TryRegisterTemplatePile(templateDefinition)) { num++; } } catch (Exception arg) { ((BaseUnityPlugin)this).Logger.LogError((object)$"{templateDefinition.NewPrefabName}: {arg}"); } } foreach (BarDefinition barDefinition in barDefinitions) { try { if (TryRegisterBarStack(barDefinition)) { num++; } } catch (Exception arg2) { ((BaseUnityPlugin)this).Logger.LogError((object)$"{barDefinition.NewPrefabName}: {arg2}"); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)(string.Format("{0}: registered {1} of ", "Dynamic Storage Materials", num) + $"{barDefinitions.Count + templateDefinitions.Count} storage pieces.")); } private bool TryRegisterBarStack(BarDefinition definition) { //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) GameObject prefab = PrefabManager.Instance.GetPrefab(definition.BasePiecePrefab); if (!Object.op_Implicit((Object)(object)prefab)) { return Fail(definition.NewPrefabName, "base piece '" + definition.BasePiecePrefab + "' not found"); } GameObject val = FindDestroyedVfx(prefab, definition.DestroyedVfxPrefab); if (!Object.op_Implicit((Object)(object)val)) { val = PrefabManager.Instance.GetPrefab(definition.DestroyedVfxPrefab); } if (!Object.op_Implicit((Object)(object)val)) { return Fail(definition.NewPrefabName, "destroyed VFX '" + definition.DestroyedVfxPrefab + "' not found"); } GameObject prefab2 = PrefabManager.Instance.GetPrefab(definition.ResourceItemPrefab); if (!Object.op_Implicit((Object)(object)prefab2)) { return Fail(definition.NewPrefabName, "resource item '" + definition.ResourceItemPrefab + "' not found"); } MeshRenderer componentInChildren = prefab2.GetComponentInChildren<MeshRenderer>(true); if (!Object.op_Implicit((Object)(object)componentInChildren) || !Object.op_Implicit((Object)(object)((Renderer)componentInChildren).sharedMaterial)) { return Fail(definition.NewPrefabName, "resource item '" + definition.ResourceItemPrefab + "' has no bar material"); } GameObject val2 = PrefabManager.Instance.CreateClonedPrefab(definition.NewPrefabName, prefab); if (!Object.op_Implicit((Object)(object)val2)) { return Fail(definition.NewPrefabName, "CreateClonedPrefab returned null"); } MeshRenderer[] componentsInChildren = val2.GetComponentsInChildren<MeshRenderer>(true); Component[] componentsInChildren2 = val2.GetComponentsInChildren<Component>(true); foreach (Component val3 in componentsInChildren2) { if (Object.op_Implicit((Object)(object)val3) && ((object)val3).GetType().Name == "SimpleMeshCombine") { Object.DestroyImmediate((Object)(object)val3); } } int layer = ((componentsInChildren.Length != 0) ? ((Component)componentsInChildren[0]).gameObject.layer : val2.layer); MeshRenderer[] array = componentsInChildren; for (int i = 0; i < array.Length; i++) { ((Renderer)array[i]).enabled = false; } Transform transform = new GameObject("dynamic_bar_visuals").transform; ((Component)transform).gameObject.layer = layer; transform.SetParent(val2.transform, false); transform.localPosition = val.transform.localPosition; transform.localRotation = val.transform.localRotation; transform.localScale = val.transform.localScale; int num = CopyBarMeshes(val, transform, ((Renderer)componentInChildren).sharedMaterial); if (num < 2) { return Fail(definition.NewPrefabName, $"destroyed VFX provided only {num} usable meshes"); } if (!PrepareAsDynamicStorage(val2, prefab, definition.DisplayName, requireMultipleMeshes: true, transform, stripDestroyedVfx: false, isBarStack: true)) { return Fail(definition.NewPrefabName, "failed to prepare dynamic storage prefab"); } AttachAppearance(val2, definition.NewPrefabName, definition.ResourceItemPrefab, definition.DisplayName, isBar: true); if (!RegisterStandalonePiece(val2, definition.ResourceItemPrefab, definition.BuildCost)) { return false; } ((BaseUnityPlugin)this).Logger.LogInfo((object)($"Registered {definition.DisplayName} with {num} active " + "meshes from " + definition.DestroyedVfxPrefab + ".")); return true; } private static int CopyBarMeshes(GameObject vfx, Transform targetRoot, Material barMaterial) { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) int num = 0; MeshRenderer[] componentsInChildren = vfx.GetComponentsInChildren<MeshRenderer>(true); foreach (MeshRenderer val in componentsInChildren) { MeshFilter component = ((Component)val).GetComponent<MeshFilter>(); if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.sharedMesh)) { continue; } List<Transform> list = new List<Transform>(); Transform val2 = ((Component)val).transform; while (Object.op_Implicit((Object)(object)val2) && (Object)(object)val2 != (Object)(object)vfx.transform) { list.Add(val2); val2 = val2.parent; } if (list.Count != 0) { Transform val3 = targetRoot; for (int num2 = list.Count - 1; num2 >= 0; num2--) { Transform val4 = list[num2]; GameObject val5 = new GameObject($"bar_{num:D2}_{((Object)val4).name}") { layer = ((Component)targetRoot).gameObject.layer }; Transform val6 = val3; val3 = val5.transform; val3.SetParent(val6, false); val3.localPosition = val4.localPosition; val3.localRotation = val4.localRotation; val3.localScale = val4.localScale; } ((Component)val3).gameObject.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh; MeshRenderer obj = ((Component)val3).gameObject.AddComponent<MeshRenderer>(); int count = Math.Max(1, ((Renderer)val).sharedMaterials.Length); ((Renderer)obj).sharedMaterials = Enumerable.Repeat<Material>(barMaterial, count).ToArray(); ((Renderer)obj).shadowCastingMode = ((Renderer)val).shadowCastingMode; ((Renderer)obj).receiveShadows = ((Renderer)val).receiveShadows; ((Renderer)obj).enabled = true; num++; } } return num; } private bool TryRegisterTemplatePile(TemplateDefinition definition) { //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) GameObject prefab = PrefabManager.Instance.GetPrefab(definition.BasePilePrefab); if (!Object.op_Implicit((Object)(object)prefab)) { return Fail(definition.NewPrefabName, "base pile '" + definition.BasePilePrefab + "' not found"); } GameObject prefab2 = PrefabManager.Instance.GetPrefab(definition.MaterialSourcePrefab); if (!Object.op_Implicit((Object)(object)prefab2)) { return Fail(definition.NewPrefabName, "material source '" + definition.MaterialSourcePrefab + "' not found"); } if (!Object.op_Implicit((Object)(object)PrefabManager.Instance.GetPrefab(definition.ResourceItemPrefab))) { return Fail(definition.NewPrefabName, "resource item '" + definition.ResourceItemPrefab + "' not found"); } MeshRenderer componentInChildren = prefab2.GetComponentInChildren<MeshRenderer>(true); if (!Object.op_Implicit((Object)(object)componentInChildren) || !Object.op_Implicit((Object)(object)((Renderer)componentInChildren).sharedMaterial)) { return Fail(definition.NewPrefabName, "'" + definition.MaterialSourcePrefab + "' has no usable material"); } GameObject val = PrefabManager.Instance.CreateClonedPrefab(definition.NewPrefabName, prefab); if (!Object.op_Implicit((Object)(object)val)) { return Fail(definition.NewPrefabName, "CreateClonedPrefab returned null"); } if (definition.LocalScaleMultiplier != 1f) { Transform transform = val.transform; transform.localScale *= definition.LocalScaleMultiplier; } if (!PrepareAsDynamicStorage(val, prefab, definition.DisplayName, requireMultipleMeshes: false)) { return Fail(definition.NewPrefabName, "failed to prepare dynamic storage prefab"); } if (!InstallNativePileVisuals(val, definition.BasePilePrefab, definition.VisualModelPrefab, definition.ForceResourceModelGeometry)) { return Fail(definition.NewPrefabName, "could not prepare native '" + definition.BasePilePrefab + "' fill stages"); } AttachAppearance(val, definition.NewPrefabName, definition.VisualModelPrefab, definition.ConfigSectionName, isBar: false, definition.BasePilePrefab, definition.DefaultShape, definition.DefaultSize, definition.DefaultHeight, definition.DefaultModelScale, definition.DefaultVerticalOffset, definition.DefaultMaterial); if (!RegisterStandalonePiece(val, definition.ResourceItemPrefab, definition.BuildCost)) { return false; } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Registered " + definition.DisplayName + " from vanilla base pile " + definition.BasePilePrefab + ".")); return true; } private bool InstallNativePileVisuals(GameObject prefab, string visualPrefabName, string resourceItemPrefab, bool forceResourceModelGeometry = false) { //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_05aa: Unknown result type (might be due to invalid IL or missing references) //IL_05c5: Unknown result type (might be due to invalid IL or missing references) //IL_05e1: Unknown result type (might be due to invalid IL or missing references) //IL_05ed: Unknown result type (might be due to invalid IL or missing references) GameObject prefab2 = PrefabManager.Instance.GetPrefab(visualPrefabName); GameObject prefab3 = PrefabManager.Instance.GetPrefab(resourceItemPrefab); MeshRenderer val = (Object.op_Implicit((Object)(object)prefab3) ? ((IEnumerable<MeshRenderer>)prefab3.GetComponentsInChildren<MeshRenderer>(true)).FirstOrDefault((Func<MeshRenderer, bool>)((MeshRenderer r) => Object.op_Implicit((Object)(object)((Component)r).GetComponent<MeshFilter>()) && Object.op_Implicit((Object)(object)((Component)r).GetComponent<MeshFilter>().sharedMesh))) : null); if (!Object.op_Implicit((Object)(object)val)) { return false; } ForgeVisualStack component = prefab.GetComponent<ForgeVisualStack>(); if (!Object.op_Implicit((Object)(object)component)) { return false; } List<Transform> stackMeshes = component.stackMeshes; if (stackMeshes == null || stackMeshes.Count == 0) { return false; } Component[] componentsInChildren = prefab.GetComponentsInChildren<Component>(true); foreach (Component val2 in componentsInChildren) { if (Object.op_Implicit((Object)(object)val2) && ((object)val2).GetType().Name == "SimpleMeshCombine") { Object.DestroyImmediate((Object)(object)val2); } } MeshRenderer[] componentsInChildren2 = prefab.GetComponentsInChildren<MeshRenderer>(true); for (int num = 0; num < componentsInChildren2.Length; num++) { ((Renderer)componentsInChildren2[num]).enabled = false; } foreach (Transform item in stackMeshes) { if (Object.op_Implicit((Object)(object)item)) { Collider[] componentsInChildren3 = ((Component)item).GetComponentsInChildren<Collider>(true); for (int num = 0; num < componentsInChildren3.Length; num++) { componentsInChildren3[num].enabled = false; } } } Transform transform = new GameObject("dynamic_native_pile_visuals").transform; transform.SetParent(prefab.transform, false); ((Component)transform).gameObject.layer = (Object.op_Implicit((Object)(object)stackMeshes[0]) ? ((Component)stackMeshes[0]).gameObject.layer : prefab.layer); if (string.Equals(visualPrefabName, "obsidian_pile", StringComparison.OrdinalIgnoreCase)) { transform.localPosition += Vector3.up * -0.0508f; } List<Transform> stages; string text; if (ForgePileStageDefinitions.HasAuthoredRendererOrder(visualPrefabName)) { if (ForgePileStageDefinitions.TryBuildAuthoredModelStages(prefab3, visualPrefabName, transform, null, ((Component)transform).gameObject.layer, "authored_fill_", out stages, out var diagnostic)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)(((Object)prefab).name + ": " + diagnostic)); text = visualPrefabName + " authored layout with " + resourceItemPrefab + " model"; } else { ((BaseUnityPlugin)this).Logger.LogError((object)(((Object)prefab).name + ": " + diagnostic + ". Falling back to generated item stages so the storage piece remains registered.")); stages = BuildGeneratedItemStages(transform, val, null, 16, ((Component)transform).gameObject.layer); text = resourceItemPrefab + " emergency item fallback"; } } else { List<MeshRenderer> nativePileCandidates = GetNativePileCandidates(prefab2); bool flag = nativePileCandidates.Count >= 2; if (forceResourceModelGeometry && flag) { List<Transform> templateStages = nativePileCandidates.Select((MeshRenderer renderer) => ((Component)renderer).transform).ToList(); if (ForgePileStageDefinitions.TryBuildModelStagesFromTemplates(prefab3, prefab2.transform, templateStages, transform, null, ((Component)transform).gameObject.layer, "native_model_fill_", 0, out stages, out var diagnostic2)) { ((BaseUnityPlugin)this).Logger.LogInfo((object)(((Object)prefab).name + ": " + diagnostic2)); text = visualPrefabName + " layout with " + resourceItemPrefab + " model"; } else { ((BaseUnityPlugin)this).Logger.LogError((object)(((Object)prefab).name + ": could not rebuild " + visualPrefabName + " templates with " + resourceItemPrefab + " geometry: " + diagnostic2 + ". Falling back to generated " + resourceItemPrefab + " stages; native " + visualPrefabName + " meshes will not be used.")); stages = BuildGeneratedItemStages(transform, val, null, 16, ((Component)transform).gameObject.layer); text = resourceItemPrefab + " generated item fallback"; } } else if (flag) { stages = BuildNativeRendererStages(transform, prefab2, nativePileCandidates, null, ((Component)transform).gameObject.layer); text = visualPrefabName; } else { stages = BuildGeneratedItemStages(transform, val, null, 16, ((Component)transform).gameObject.layer); text = resourceItemPrefab + " item fallback"; } if (flag) { for (int num2 = 0; num2 < nativePileCandidates.Count; num2++) { MeshRenderer val3 = nativePileCandidates[num2]; MeshFilter component2 = ((Component)val3).GetComponent<MeshFilter>(); ((BaseUnityPlugin)this).Logger.LogInfo((object)($"{((Object)prefab).name}: native candidate {num2 + 1:00}/" + $"{nativePileCandidates.Count:00} lod={GetRendererLodLabel(prefab2, (Renderer)(object)val3)} " + "mesh=" + ((Object)component2.sharedMesh).name + " path=" + RelativePath(((Component)val3).transform, prefab2.transform) + " " + $"minY={LocalMeshBoundsMinY(val3, prefab2.transform):0.###}")); } } } if (stages == null || stages.Count == 0) { Object.DestroyImmediate((Object)(object)((Component)transform).gameObject); return false; } component.stackMeshes = stages; int num3 = (Object.op_Implicit((Object)(object)prefab2) ? prefab2.GetComponentsInChildren<MeshRenderer>(true).Count((MeshRenderer r) => Object.op_Implicit((Object)(object)r) && Object.op_Implicit((Object)(object)((Component)r).GetComponent<MeshFilter>()) && Object.op_Implicit((Object)(object)((Component)r).GetComponent<MeshFilter>().sharedMesh)) : 0); ((BaseUnityPlugin)this).Logger.LogInfo((object)($"{((Object)prefab).name}: {stages.Count} pile stages from " + text + $"; renderers(raw)={num3}; " + "native root scale=" + (Object.op_Implicit((Object)(object)prefab2) ? FormatVector(prefab2.transform.localScale) : "missing") + "; storage root scale=" + FormatVector(prefab.transform.localScale) + "; " + $"visual scale={FormatVector(transform.localScale)}; visual Y offset={transform.localPosition.y:0.###}")); return true; } private static List<Transform> BuildGeneratedItemStages(Transform holder, MeshRenderer itemRenderer, Material itemMaterial, int count, int layer) { //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) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) List<Transform> list = new List<Transform>(); if (!Object.op_Implicit((Object)(object)holder) || !Object.op_Implicit((Object)(object)itemRenderer)) { return list; } MeshFilter component = ((Component)itemRenderer).GetComponent<MeshFilter>(); Mesh val = (Object.op_Implicit((Object)(object)component) ? component.sharedMesh : null); if (!Object.op_Implicit((Object)(object)val)) { return list; } for (int i = 0; i < count; i++) { Transform transform = new GameObject("generated_fill_" + i) { layer = layer }.transform; transform.SetParent(holder, false); int num = i / 6; int num2 = i % 6; transform.localPosition = new Vector3((float)(num2 % 3 - 1) * 0.36f + (float)(num % 2) * 0.08f, (float)num * 0.17f, ((float)(num2 / 3) - 0.5f) * 0.38f); transform.localRotation = Quaternion.Euler(0f, (float)(i * 53 % 360), (float)(i % 3 - 1) * 12f); Bounds bounds = ((Renderer)itemRenderer).bounds; float x = ((Bounds)(ref bounds)).size.x; bounds = ((Renderer)itemRenderer).bounds; float num3 = Mathf.Max(x, ((Bounds)(ref bounds)).size.z); transform.localScale = Vector3.one * Mathf.Clamp(0.43f / Mathf.Max(num3, 0.01f), 0.35f, 1.8f); ((Component)transform).gameObject.AddComponent<MeshFilter>().sharedMesh = val; MeshRenderer val2 = ((Component)transform).gameObject.AddComponent<MeshRenderer>(); if (Object.op_Implicit((Object)(object)itemMaterial)) { ((Renderer)val2).sharedMaterials = Enumerable.Repeat<Material>(itemMaterial, Math.Max(1, ((Renderer)itemRenderer).sharedMaterials.Length)).ToArray(); } else { ((Renderer)val2).sharedMaterials = ((Renderer)itemRenderer).sharedMaterials; } ((Renderer)val2).shadowCastingMode = ((Renderer)itemRenderer).shadowCastingMode; ((Renderer)val2).receiveShadows = ((Renderer)itemRenderer).receiveShadows; list.Add(transform); } return list; } private static List<Transform> BuildNativeRendererStages(Transform holder, GameObject native, List<MeshRenderer> nativePieces, Material itemMaterial, int layer) { //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Expected O, but got Unknown //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: 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) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0134: 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_01df: Unknown result type (might be due to invalid IL or missing references) List<Transform> list = new List<Transform>(); if (!Object.op_Implicit((Object)(object)holder) || !Object.op_Implicit((Object)(object)native) || nativePieces == null) { return list; } for (int i = 0; i < nativePieces.Count; i++) { MeshRenderer val = nativePieces[i]; MeshFilter val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<MeshFilter>() : null); Mesh val3 = (Object.op_Implicit((Object)(object)val2) ? val2.sharedMesh : null); if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val3)) { GameObject val4 = new GameObject("native_fill_" + i); val4.layer = layer; Transform transform = val4.transform; transform.SetParent(holder, false); List<Transform> list2 = new List<Transform>(); Transform val5 = ((Component)val).transform; while (Object.op_Implicit((Object)(object)val5) && (Object)(object)val5 != (Object)(object)native.transform) { list2.Add(val5); val5 = val5.parent; } Transform val6 = transform; for (int num = list2.Count - 1; num >= 0; num--) { Transform val7 = list2[num]; Transform transform2 = new GameObject(((Object)val7).name) { layer = val4.layer }.transform; transform2.SetParent(val6, false); transform2.localPosition = val7.localPosition; transform2.localRotation = val7.localRotation; transform2.localScale = val7.localScale; val6 = transform2; } if ((Object)(object)val6 == (Object)(object)transform) { val6 = new GameObject("native_pile_mesh").transform; val6.SetParent(transform, false); ((Component)val6).gameObject.layer = val4.layer; } ((Component)val6).gameObject.AddComponent<MeshFilter>().sharedMesh = val3; MeshRenderer val8 = ((Component)val6).gameObject.AddComponent<MeshRenderer>(); if (Object.op_Implicit((Object)(object)itemMaterial)) { ((Renderer)val8).sharedMaterials = Enumerable.Repeat<Material>(itemMaterial, Math.Max(1, ((Renderer)val).sharedMaterials.Length)).ToArray(); } else { ((Renderer)val8).sharedMaterials = ((Renderer)val).sharedMaterials; } ((Renderer)val8).shadowCastingMode = ((Renderer)val).shadowCastingMode; ((Renderer)val8).receiveShadows = ((Renderer)val).receiveShadows; val4.AddComponent<MeshDebugMetadata>().Setup(RelativePath(((Component)val).transform, native.transform), GetRendererLodLabel(native, (Renderer)(object)val), ((Object)val3).name, val3.vertexCount); list.Add(transform); } } return list; } internal static List<MeshRenderer> GetNativePileCandidates(GameObject native) { if (!Object.op_Implicit((Object)(object)native)) { return new List<MeshRenderer>(); } List<MeshRenderer> source = (from r in native.GetComponentsInChildren<MeshRenderer>(true) where Object.op_Implicit((Object)(object)r) && Object.op_Implicit((Object)(object)((Component)r).GetComponent<MeshFilter>()) && Object.op_Implicit((Object)(object)((Component)r).GetComponent<MeshFilter>().sharedMesh) select r).ToList(); HashSet<Renderer> lodControlled = new HashSet<Renderer>(); HashSet<Renderer> lodZero = new HashSet<Renderer>(); LODGroup[] componentsInChildren = native.GetComponentsInChildren<LODGroup>(true); for (int num = 0; num < componentsInChildren.Length; num++) { LOD[] lODs = componentsInChildren[num].GetLODs(); for (int num2 = 0; num2 < lODs.Length; num2++) { Renderer[] renderers = lODs[num2].renderers; foreach (Renderer val in renderers) { if (Object.op_Implicit((Object)(object)val)) { lodControlled.Add(val); if (num2 == 0) { lodZero.Add(val); } } } } } List<MeshRenderer> list = source.Where((MeshRenderer r) => !lodControlled.Contains((Renderer)(object)r)).ToList(); IEnumerable<MeshRenderer> source2; if (list.Count < 2) { source2 = source.Where((MeshRenderer r) => !lodControlled.Contains((Renderer)(object)r) || lodZero.Contains((Renderer)(object)r)); } else { IEnumerable<MeshRenderer> enumerable = list; source2 = enumerable; } return (from g in source2.GroupBy(delegate(MeshRenderer r) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) Vector3 val2 = native.transform.InverseTransformPoint(((Component)r).transform.position); return Mathf.RoundToInt(val2.x * 100f) + ":" + Mathf.RoundToInt(val2.y * 100f) + ":" + Mathf.RoundToInt(val2.z * 100f); }) select g.OrderByDescending((MeshRenderer r) => ((Component)r).GetComponent<MeshFilter>().sharedMesh.vertexCount).First() into r orderby LocalMeshBoundsMinY(r, native.transform) select r).ToList(); } internal static string GetRendererLodLabel(GameObject root, Renderer target) { if (!Object.op_Implicit((Object)(object)root) || !Object.op_Implicit((Object)(object)target)) { return "none"; } LODGroup[] componentsInChildren = root.GetComponentsInChildren<LODGroup>(true); for (int i = 0; i < componentsInChildren.Length; i++) { LOD[] lODs = componentsInChildren[i].GetLODs(); for (int j = 0; j < lODs.Length; j++) { if (lODs[j].renderers.Any((Renderer renderer) => (Object)(object)renderer == (Object)(object)target)) { return "LOD" + j; } } } return "none"; } private static string FormatVector(Vector3 value) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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) return $"({value.x:0.###},{value.y:0.###},{value.z:0.###})"; } internal static string RelativePath(Transform child, Transform root) { if (!Object.op_Implicit((Object)(object)child)) { return "missing"; } List<string> list = new List<string>(); Transform val = child; while (Object.op_Implicit((Object)(object)val) && (Object)(object)val != (Object)(object)root) { list.Add(((Object)val).name); val = val.parent; } list.Reverse(); return string.Join("/", list.ToArray()); } internal static float LocalMeshBoundsMinY(MeshRenderer renderer, Transform relativeTo) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)renderer) || !Object.op_Implicit((Object)(object)relativeTo)) { return float.NaN; } MeshFilter component = ((Component)renderer).GetComponent<MeshFilter>(); Mesh val = (Object.op_Implicit((Object)(object)component) ? component.sharedMesh : null); if (!Object.op_Implicit((Object)(object)val)) { return float.NaN; } Bounds bounds = val.bounds; Vector3 center = ((Bounds)(ref bounds)).center; Vector3 extents = ((Bounds)(ref bounds)).extents; float num = float.PositiveInfinity; for (int i = -1; i <= 1; i += 2) { for (int j = -1; j <= 1; j += 2) { for (int k = -1; k <= 1; k += 2) { Vector3 val2 = center + Vector3.Scale(extents, new Vector3((float)i, (float)j, (float)k)); Vector3 val3 = ((Component)renderer).transform.TransformPoint(val2); float y = relativeTo.InverseTransformPoint(val3).y; num = Mathf.Min(num, y); } } } return num; } private static string FindLegacyConfigSection(string prefabName) { return (Current?.templateDefinitions.FirstOrDefault((TemplateDefinition entry) => entry.NewPrefabName == prefabName))?.LegacyConfigSectionName; } private static void AttachAppearance(GameObject prefab, string prefabName, string materialPrefa