using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using DynamicStoragePiles.Compatibility; using HarmonyLib; using Jotunn; using Jotunn.Configs; using Jotunn.Entities; using Jotunn.Managers; using Jotunn.Utils; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("DynamicStoragePiles")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("DynamicStoragePiles")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")] [assembly: AssemblyFileVersion("0.8.0")] [assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.8.0.0")] [module: UnverifiableCode] namespace DynamicStoragePiles { public static class ConfigSettings { public enum RecipeSetting { AllStoragePiles, OnlyDynamicStoragePiles, OnlyOriginalStoragePiles } private static ConfigFile config; public static ConfigEntry azuAutoStoreCompat; public static ConfigEntry azuAutoStoreItemWhitelist; public static ConfigEntry restrictDynamicPiles; public static ConfigEntry VanillaRecipeSetting { get; private set; } public static ConfigEntry IngotStacksRecipeSetting { get; private set; } public static ConfigEntry StackedBarsRecipeSetting { get; private set; } public static ConfigEntry MoreStacksRecipeSetting { get; private set; } public static ConfigEntry RefinedStonePiecesSetting { get; private set; } public static void Init(ConfigFile configFile) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Expected O, but got Unknown config = configFile; ConfigurationManagerAttributes val = new ConfigurationManagerAttributes { IsAdminOnly = true }; string text = "\nCheats or world modifiers can ignore this setting. Existing pieces in the world are not affected"; string text2 = "\nRequires a restart to take effect"; string text3 = "1 - General"; VanillaRecipeSetting = config.Bind(text3, "Vanilla Stack Recipes", RecipeSetting.AllStoragePiles, "Sets which pieces are placeable." + text); VanillaRecipeSetting.SettingChanged += delegate { DynamicStoragePiles.UpdateAllRecipes(); }; restrictDynamicPiles = config.Bind(text3, "Restrict Container Item Type", true, new ConfigDescription("Only allows the respective items to be stored in stack piles, so wood piles only accept wood etc.\nSynced with server", (AcceptableValueBase)null, new object[1] { val })); text3 = "2.0 - Compatibility AzuAutoStore"; azuAutoStoreCompat = config.Bind(text3, "Enable Compatibility", true, "Enables compatibility with AzuAutoStore." + text2); azuAutoStoreItemWhitelist = config.Bind(text3, "Enable Item Whitelist", true, "Only allows the respective items to be stored in stack piles"); text3 = "2.1 - Compatibility IngotStacks"; IngotStacksRecipeSetting = config.Bind(text3, "IngotStacks Stack Recipes", RecipeSetting.AllStoragePiles, "Sets which pieces are placeable." + text); IngotStacksRecipeSetting.SettingChanged += delegate { DynamicStoragePiles.UpdateAllRecipes(); }; text3 = "2.2 - Compatibility StackedBars"; StackedBarsRecipeSetting = config.Bind(text3, "StackedBars Stack Recipes", RecipeSetting.AllStoragePiles, "Sets which pieces are placeable." + text); StackedBarsRecipeSetting.SettingChanged += delegate { DynamicStoragePiles.UpdateAllRecipes(); }; text3 = "2.3 - Compatibility MoreStacks"; MoreStacksRecipeSetting = config.Bind(text3, "MoreStacks Stack Recipes", RecipeSetting.AllStoragePiles, "Sets which pieces are placeable." + text); MoreStacksRecipeSetting.SettingChanged += delegate { DynamicStoragePiles.UpdateAllRecipes(); }; text3 = "2.4 - Compatibility RefinedStonePieces"; RefinedStonePiecesSetting = config.Bind(text3, "RefinedStonePieces Stack Recipes", RecipeSetting.AllStoragePiles, "Sets which pieces are placeable." + text); RefinedStonePiecesSetting.SettingChanged += delegate { DynamicStoragePiles.UpdateAllRecipes(); }; } public static bool IsEnabled(this ConfigEntry configEntry, bool isOriginal) { if (isOriginal) { return configEntry.Value == RecipeSetting.AllStoragePiles || configEntry.Value == RecipeSetting.OnlyOriginalStoragePiles; } return configEntry.Value == RecipeSetting.AllStoragePiles || configEntry.Value == RecipeSetting.OnlyDynamicStoragePiles; } } public static class InventoryHelper { public static string PrefabName(this ItemData item) { if (Object.op_Implicit((Object)(object)item.m_dropPrefab)) { return ((Object)item.m_dropPrefab).name; } Logger.LogWarning((object)("Item has missing prefab " + item.m_shared.m_name)); return item.m_shared.m_name; } } public static class PieceHelper { public static GameObject PreparePiecePrefab(GameObject prefab, GameObject basePrefab, string nameToken) { Object.Destroy((Object)(object)prefab.GetComponent()); Object.Destroy((Object)(object)prefab.GetComponent()); if (Object.op_Implicit((Object)(object)prefab.transform.Find("collider"))) { Object.Destroy((Object)(object)((Component)prefab.transform.Find("collider")).gameObject); } ZNetView component = prefab.GetComponent(); component.m_persistent = true; if (!Object.op_Implicit((Object)(object)prefab.GetComponent())) { ExposedGameObjectExtension.AddComponentCopy(prefab, basePrefab.GetComponent()); } if (!Object.op_Implicit((Object)(object)prefab.GetComponent())) { ExposedGameObjectExtension.AddComponentCopy(prefab, basePrefab.GetComponent()); } Container val = prefab.AddComponent(); val.m_name = nameToken; val.m_width = 5; val.m_height = 2; VisualStack visualStack = prefab.AddComponent(); MeshRenderer[] componentsInChildren = prefab.GetComponentsInChildren(); foreach (MeshRenderer val2 in componentsInChildren) { if (!Object.op_Implicit((Object)(object)((Component)val2).gameObject.GetComponent())) { ((Component)val2).gameObject.AddComponent(); } visualStack.stackMeshes.Add(((Component)val2).transform); } return prefab; } public static GameObject FindDestroyVFX(GameObject prefab, string vfxName) { WearNTear val = default(WearNTear); if (prefab.TryGetComponent(ref val)) { EffectData[] effectPrefabs = val.m_destroyedEffect.m_effectPrefabs; foreach (EffectData val2 in effectPrefabs) { if (Object.op_Implicit((Object)(object)val2.m_prefab) && ((Object)val2.m_prefab).name == vfxName) { return val2.m_prefab; } } } return null; } public static AssetBundle GetAssetBundle(string bundleName) { foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles()) { if (((Object)allLoadedAssetBundle).name == bundleName) { return allLoadedAssetBundle; } } return null; } } [BepInPlugin("com.maxsch.valheim.DynamicStoragePiles", "DynamicStoragePiles", "0.8.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] internal class DynamicStoragePiles : BaseUnityPlugin { [CompilerGenerated] private sealed class d__26 : IEnumerator, IDisposable, IEnumerator { private int <>1__state; private object <>2__current; public CustomPiece piece; public DynamicStoragePiles <>4__this; private VisualStack[] 5__1; private VisualStack[] <>s__2; private int <>s__3; private VisualStack 5__4; private VisualStack[] <>s__5; private int <>s__6; private VisualStack 5__7; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__26(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__1 = null; <>s__2 = null; 5__4 = null; <>s__5 = null; 5__7 = null; <>1__state = -2; } private bool MoveNext() { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00de: 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_00e8: 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_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; 5__1 = ((Component)piece.Piece).GetComponentsInChildren(); <>s__2 = 5__1; for (<>s__3 = 0; <>s__3 < <>s__2.Length; <>s__3++) { 5__4 = <>s__2[<>s__3]; 5__4.SetVisualsActive(55f); 5__4 = null; } <>s__2 = null; 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)<>4__this).Info.Metadata }); <>s__5 = 5__1; for (<>s__6 = 0; <>s__6 < <>s__5.Length; <>s__6++) { 5__7 = <>s__5[<>s__6]; 5__7.SetVisualsActive(100f); 5__7 = null; } <>s__5 = null; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginName = "DynamicStoragePiles"; public const string PluginGuid = "com.maxsch.valheim.DynamicStoragePiles"; public const string PluginVersion = "0.8.0"; public const string PLUGIN_MORESTACKS_GUID = "ujhik.MoreStacks"; public static Harmony harmony; private static AssetBundle assetBundle; private List renderSprites = new List(); public static Dictionary allowedItemsByStack = new Dictionary(); public static Dictionary allowedItemsByContainer = new Dictionary(); private static List vanillaStacks = new List { "wood_stack", "wood_fine_stack", "wood_core_stack", "wood_yggdrasil_stack", "blackwood_stack", "stone_pile", "coal_pile", "blackmarble_pile", "grausten_pile", "skull_pile", "treasure_stack", "bone_stack" }; private static List dynamicStacks = new List(); public static DynamicStoragePiles Instance { get; private set; } private void Awake() { //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Expected O, but got Unknown Instance = this; assetBundle = AssetUtils.LoadAssetBundleFromResources("containerstacks"); AddStackPiece("MS_container_wood_stack", "Wood"); AddStackPiece("MS_container_finewood_stack", "FineWood"); AddStackPiece("MS_container_corewood_stack", "RoundLog"); AddStackPiece("MS_container_yggdrasil_wood_stack", "YggdrasilWood"); AddStackPiece("MS_container_blackwood_stack", "Blackwood"); AddStackPiece("MS_container_stone_pile", "Stone"); AddStackPiece("MS_container_coal_pile", "Coal"); AddStackPiece("MS_container_blackmarble_pile", "BlackMarble"); AddStackPiece("MS_container_grausten_pile", "Grausten"); AddStackPiece("MS_container_skull_pile", "Charredskull"); AddStackPiece("MS_container_bone_stack", "BoneFragments"); AddStackPiece("MS_container_coin_pile", "Coins"); ConfigSettings.Init(((BaseUnityPlugin)this).Config); PrefabManager.OnPrefabsRegistered += OnPrefabsRegistered; PieceManager.OnPiecesRegistered += OnPiecesRegistered; harmony = new Harmony("com.maxsch.valheim.DynamicStoragePiles"); harmony.PatchAll(); } private void Start() { if (Chainloader.PluginInfos.ContainsKey("Azumatt.AzuAutoStore") && ConfigSettings.azuAutoStoreCompat.Value) { AzuAutoStore.Init(); } if (Chainloader.PluginInfos.ContainsKey("Richard.IngotStacks")) { IngotStacks.Init(); } if (Chainloader.PluginInfos.ContainsKey("Azumatt.StackedBars")) { StackedBars.Init(); } if (Chainloader.PluginInfos.ContainsKey("blacks7ar.RefinedStonePieces")) { RefinedStonePieces.Init(); } } public static void UpdateAllRecipes() { if (Object.op_Implicit((Object)(object)ZNetScene.instance)) { UpdateRecipes(vanillaStacks, dynamicStacks, ConfigSettings.VanillaRecipeSetting); UpdateRecipes(IngotStacks.ingotStacks, IngotStacks.dynamicIngotStacks, ConfigSettings.IngotStacksRecipeSetting); UpdateRecipes(StackedBars.stackedBars, StackedBars.dynamicStackedBars, ConfigSettings.StackedBarsRecipeSetting); UpdateRecipes(MoreStacks.staticStacks, MoreStacks.dynamicStacks, ConfigSettings.MoreStacksRecipeSetting); UpdateRecipes(RefinedStonePieces.staticStacks, RefinedStonePieces.dynamicStacks, ConfigSettings.RefinedStonePiecesSetting); if (Object.op_Implicit((Object)(object)Player.m_localPlayer)) { Player.m_localPlayer.UpdateAvailablePiecesList(); } } } private static void UpdateRecipes(List originalStackNames, List dynamicStackNames, ConfigEntry config) { foreach (string originalStackName in originalStackNames) { EnablePieceRecipes(originalStackName, config.IsEnabled(isOriginal: true)); } foreach (string dynamicStackName in dynamicStackNames) { EnablePieceRecipes(dynamicStackName, config.IsEnabled(isOriginal: false)); } } public static void EnablePieceRecipes(string prefabName, bool enabled) { GameObject prefab = ZNetScene.instance.GetPrefab(prefabName); Piece val = default(Piece); if (Object.op_Implicit((Object)(object)prefab) && prefab.TryGetComponent(ref val)) { val.m_enabled = enabled; } else { Logger.LogWarning((object)("Could not find Piece " + prefabName + " to toggle recipes")); } } private void AddStackPiece(string pieceName, string craftItem) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Expected O, but got Unknown CustomPiece val = new CustomPiece(assetBundle, pieceName, true, StackConfig(craftItem, 10)); renderSprites.Add(val); dynamicStacks.Add(pieceName); AddPiece(val, craftItem); } public void AddCompatPiece(GameObject prefab, string craftItem, int amount) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown CustomPiece piece = new CustomPiece(prefab, false, StackConfig(craftItem, amount)); AddPiece(piece, craftItem); } public void AddCompatPiece(GameObject prefab, string craftItem, int amount, bool addGraphics) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown CustomPiece val = new CustomPiece(prefab, true, StackConfig(craftItem, amount)); if (addGraphics) { renderSprites.Add(val); } AddPiece(val, craftItem); } private void AddPiece(CustomPiece piece, string craftItem) { PieceManager.Instance.AddPiece(piece); allowedItemsByStack.Add(((Object)piece.PiecePrefab).name, craftItem); allowedItemsByContainer.Add(piece.PiecePrefab.GetComponent().m_name, craftItem); } private void OnPrefabsRegistered() { if (Chainloader.PluginInfos.ContainsKey("ujhik.MoreStacks")) { MoreStacks.Init(); } } private void OnPiecesRegistered() { PieceManager.OnPiecesRegistered -= OnPiecesRegistered; foreach (CustomPiece renderSprite in renderSprites) { ((MonoBehaviour)this).StartCoroutine(RenderSprite(renderSprite)); } UpdateAllRecipes(); } [IteratorStateMachine(typeof(d__26))] private IEnumerator RenderSprite(CustomPiece piece) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__26(0) { <>4__this = this, piece = piece }; } private PieceConfig StackConfig(string item, int amount) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown PieceConfig val = new PieceConfig(); val.PieceTable = PieceTables.Hammer; val.Category = PieceCategories.Misc; val.AddRequirement(new RequirementConfig(item, amount, 0, true)); return val; } public static bool IsStackPiece(string pieceName, out string allowedItem) { return allowedItemsByStack.TryGetValue(pieceName, out allowedItem); } } [HarmonyPatch] internal static class RestrictContainers { private static string _loadingContainer; private static string _targetContainer; private static string _allowedItem; [HarmonyPrefix] [HarmonyPatch(typeof(InventoryGrid), "DropItem")] private static bool DropItemPrefix(InventoryGrid __instance, Inventory fromInventory, ItemData item, Vector2i pos) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!CanAddItem(__instance.m_inventory, item)) { return false; } ItemData itemAt = __instance.m_inventory.GetItemAt(pos.x, pos.y); if (itemAt != null) { return CanAddItem(fromInventory, itemAt); } return true; } private static bool CanAddItem(Inventory inventory, ItemData item) { if (inventory == null || item == null) { return false; } if (inventory.m_name == _loadingContainer) { return true; } if (IsRestrictedContainer(inventory.m_name, out var allowedItem)) { bool flag = item.PrefabName() == allowedItem; if (!flag) { string text = item.m_shared.m_name + " cannot be placed in " + inventory.m_name; Player localPlayer = Player.m_localPlayer; if (localPlayer != null) { ((Character)localPlayer).Message((MessageType)2, text, 0, (Sprite)null); } } return flag; } return true; } public static bool IsRestrictedContainer(string containerName, out string allowedItem) { if (!ConfigSettings.restrictDynamicPiles.Value) { allowedItem = null; return false; } return DynamicStoragePiles.allowedItemsByContainer.TryGetValue(containerName, out allowedItem); } [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData) })] [HarmonyPatch(typeof(Inventory), "AddItem", new Type[] { typeof(ItemData), typeof(int), typeof(int), typeof(int) })] [HarmonyPriority(800)] private static bool AddItemPrefix(Inventory __instance, ItemData item, ref bool __result) { if (!CanAddItem(__instance, item)) { __result = false; return __result; } return true; } [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "MoveItemToThis", new Type[] { typeof(Inventory), typeof(ItemData) })] [HarmonyPatch(typeof(Inventory), "MoveItemToThis", new Type[] { typeof(Inventory), typeof(ItemData), typeof(int), typeof(int), typeof(int) })] [HarmonyPriority(800)] private static bool MoveItemToThisPrefix(Inventory __instance, Inventory fromInventory, ItemData item) { if (__instance == null || fromInventory == null || item == null) { return false; } return CanAddItem(__instance, item); } [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "MoveAll", new Type[] { typeof(Inventory) })] [HarmonyPriority(800)] private static void MoveAllPrefix(Inventory __instance, Inventory fromInventory) { if (__instance != null && fromInventory != null && IsRestrictedContainer(__instance.m_name, out var allowedItem)) { _targetContainer = __instance.m_name; _allowedItem = allowedItem; } } [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "MoveAll", new Type[] { typeof(Inventory) })] [HarmonyPriority(800)] private static void MoveAllPostfix() { _targetContainer = null; _allowedItem = null; } [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(ItemData) })] [HarmonyPatch(typeof(Inventory), "RemoveItem", new Type[] { typeof(ItemData), typeof(int) })] [HarmonyPriority(800)] private static bool RemoveItemPrefix(Inventory __instance, ItemData item) { return ShouldRemoveItem(__instance, item); } [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "RemoveOneItem", new Type[] { typeof(ItemData) })] [HarmonyPriority(800)] private static bool RemoveOneItemPrefix(Inventory __instance, ItemData item) { return ShouldRemoveItem(__instance, item); } private static bool ShouldRemoveItem(Inventory __instance, ItemData item) { if (__instance == null || item == null) { return false; } bool flag = !string.IsNullOrEmpty(_targetContainer); bool flag2 = !string.IsNullOrEmpty(_allowedItem); if (flag && flag2) { return item.PrefabName() != _allowedItem; } return true; } [HarmonyPrefix] [HarmonyPatch(typeof(Inventory), "Load")] private static void LoadPrefix(Inventory __instance) { if (__instance != null) { _loadingContainer = __instance.m_name; } } [HarmonyPostfix] [HarmonyPatch(typeof(Inventory), "Load")] private static void LoadPostfix() { _loadingContainer = null; } } public class VisualStack : MonoBehaviour { public List stackMeshes = new List(); private Container container; private Inventory inventory; private void Start() { container = ((Component)this).GetComponentInParent(); if (Object.op_Implicit((Object)(object)container)) { inventory = container.GetInventory(); } if (inventory != null) { Inventory obj = inventory; obj.m_onChanged = (Action)Delegate.Combine(obj.m_onChanged, new Action(UpdateVisuals)); UpdateVisuals(); } } private void UpdateVisuals() { SetVisualsActive(inventory.SlotsUsedPercentage()); } public void SetVisualsActive(float fillPercentage) { float num = Mathf.Ceil(fillPercentage / 100f * (float)stackMeshes.Count); for (int i = 0; i < stackMeshes.Count; i++) { bool active = i == 0 || (float)i < num; ((Component)stackMeshes[i]).gameObject.SetActive(active); } } } } namespace DynamicStoragePiles.Patches { [HarmonyPatch] public class PlacementPatch { [HarmonyPatch(typeof(Player), "SetupPlacementGhost")] [HarmonyPostfix] public static void SetupPlacementGhostPatch(Player __instance) { if (Object.op_Implicit((Object)(object)__instance.m_placementGhost)) { VisualStack[] componentsInChildren = __instance.m_placementGhost.GetComponentsInChildren(); foreach (VisualStack visualStack in componentsInChildren) { Object.Destroy((Object)(object)visualStack); } } } } } namespace DynamicStoragePiles.Compatibility { public static class AzuAutoStore { private static class AzuAutoStore_After_2_0_0 { [HarmonyPatch("AzuAutoStore.Util.Boxes, AzuAutoStore", "CanItemBeStored")] [HarmonyPostfix] private static void CanItemBeStoredPatch(string container, string prefab, ref bool __result) { if (__result && ConfigSettings.azuAutoStoreItemWhitelist.Value && DynamicStoragePiles.IsStackPiece(container, out var allowedItem) && prefab != allowedItem) { __result = false; } } } private static class AzuAutoStore_Before_2_0_0 { [HarmonyPatch("AzuAutoStore.Util.Functions, AzuAutoStore", "CheckDisallowedItems")] [HarmonyPostfix] private static void CheckDisallowedItemsPatch(Container container, ItemData item, ref bool __result) { if (!__result && ConfigSettings.azuAutoStoreItemWhitelist.Value && Object.op_Implicit((Object)(object)container) && item != null && Object.op_Implicit((Object)(object)item.m_dropPrefab)) { string prefabName = Utils.GetPrefabName(((Object)container).name); if (DynamicStoragePiles.IsStackPiece(prefabName, out var allowedItem) && ((Object)item.m_dropPrefab).name != allowedItem) { __result = true; } } } } public static void Init() { PluginInfo val = Chainloader.PluginInfos["Azumatt.AzuAutoStore"]; if (val.Metadata.Version >= new Version(2, 0, 0)) { DynamicStoragePiles.harmony.PatchAll(typeof(AzuAutoStore_After_2_0_0)); } else { DynamicStoragePiles.harmony.PatchAll(typeof(AzuAutoStore_Before_2_0_0)); } } } public static class IngotStacks { private static AssetBundle assetBundle; public static List ingotStacks = new List(); public static List dynamicIngotStacks = new List(); public static void Init() { assetBundle = PieceHelper.GetAssetBundle("stackedingots"); ConvertToPiece("ingot_copper_stack", "vfx_copper_stack_destroyed", "MS_IngotStacks_Copper", "Copper"); ConvertToPiece("ingot_tin_stack", "vfx_tin_stack_destroyed", "MS_IngotStacks_Tin", "Tin"); ConvertToPiece("ingot_bronze_stack", "vfx_bronze_stack_destroyed", "MS_IngotStacks_Bronze", "Bronze"); ConvertToPiece("ingot_iron_stack", "vfx_iron_stack_destroyed", "MS_IngotStacks_Iron", "Iron"); ConvertToPiece("ingot_silver_stack", "vfx_silver_stack_destroyed", "MS_IngotStacks_Silver", "Silver"); ConvertToPiece("ingot_blackmetal_stack", "vfx_blackmetal_stack_destroyed", "MS_IngotStacks_Blackmetal", "BlackMetal"); ConvertToPiece("ingot_flametal_stack", "vfx_flametal_stack_destroyed", "MS_IngotStacks_FlametalNew", "FlametalNew"); } public static void ConvertToPiece(string baseAssetName, string vfxName, string newPrefabName, string resource) { ingotStacks.Add(baseAssetName); dynamicIngotStacks.Add(newPrefabName); GameObject val = assetBundle.LoadAsset(baseAssetName); GameObject val2 = PieceHelper.FindDestroyVFX(val, vfxName); GameObject prefab = PrefabManager.Instance.CreateClonedPrefab(newPrefabName, val2); prefab = PieceHelper.PreparePiecePrefab(prefab, val, "$" + baseAssetName); ((Object)prefab).name = newPrefabName; DynamicStoragePiles.Instance.AddCompatPiece(prefab, resource, 3); } } public static class MoreStacks { public static List staticStacks = new List(); public static List dynamicStacks = new List(); private static BaseUnityPlugin moreStacksInstance = null; private static Dictionary vanillaNameToDynamicStorageNameMap = new Dictionary { { "wood_fine_stack", "finewood_stack" }, { "wood_core_stack", "corewood_stack" }, { "wood_yggdrasil_stack", "yggdrasil_wood_stack" }, { "treasure_stack", "coin_pile" } }; public static void Init() { if (!Object.op_Implicit((Object)(object)moreStacksInstance) && Chainloader.PluginInfos.TryGetValue("ujhik.MoreStacks", out var value)) { moreStacksInstance = value.Instance; if (!Object.op_Implicit((Object)(object)moreStacksInstance)) { Logger.LogWarning((object)"Failed to cast mod instance for 'ujhik.MoreStacks'."); return; } } FieldInfo field = ((object)moreStacksInstance).GetType().GetField("stackInfoList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object value2 = field.GetValue(moreStacksInstance); if (!(value2 is IEnumerable enumerable)) { return; } { foreach (object item in enumerable) { Type type = item.GetType(); PropertyInfo property = type.GetProperty("idStackToDuplicate"); PropertyInfo property2 = type.GetProperty("idStackMaterial"); string stackToCloneId = property?.GetValue(item) as string; string materialPrefabId = property2?.GetValue(item) as string; ConvertToPiece(stackToCloneId, materialPrefabId); } return; } } Logger.LogWarning((object)"ujhik.MoreStacks: Failed to retrieve stackInfoList field via reflection, dynamic piles could not be generated"); } public static void ConvertToPiece(string stackToCloneId, string materialPrefabId) { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) if (vanillaNameToDynamicStorageNameMap.TryGetValue(stackToCloneId, out var value)) { stackToCloneId = value; } string text = (string)((object)moreStacksInstance).GetType().GetMethod("getStackName", BindingFlags.Static | BindingFlags.Public)?.Invoke(moreStacksInstance, new object[1] { materialPrefabId }); string text2 = "MS_container_MoreStacks"; string text3 = text2 + "_" + materialPrefabId + "_pile"; string text4 = "MS_container_" + stackToCloneId; staticStacks.Add(text); dynamicStacks.Add(text3); GameObject prefab = PrefabManager.Instance.GetPrefab(text4); GameObject prefab2 = PrefabManager.Instance.GetPrefab(text); GameObject prefab3 = PrefabManager.Instance.GetPrefab(materialPrefabId); GameObject val = PrefabManager.Instance.CreateClonedPrefab(text3, prefab); Object.DestroyImmediate((Object)(object)val.GetComponent()); val.transform.localScale = prefab2.transform.localScale; string name = prefab2.GetComponent().m_name; val = PieceHelper.PreparePiecePrefab(val, prefab, name); val.GetComponent().m_name = name; Material sharedMaterial = ((Renderer)prefab2.GetComponentInChildren()).sharedMaterial; MeshRenderer[] componentsInChildren = val.GetComponentsInChildren(); foreach (MeshRenderer val2 in componentsInChildren) { ((Renderer)val2).sharedMaterial = sharedMaterial; } DynamicStoragePiles.Instance.AddCompatPiece(val, materialPrefabId, GetMaterialCostForPiece(materialPrefabId), addGraphics: true); } public static int GetMaterialCostForPiece(string materialPrefabId) { if (materialPrefabId.Contains("Ore") || materialPrefabId.Contains("Scrap")) { return 3; } return 10; } } public static class RefinedStonePieces { private static AssetBundle assetBundle; public static List staticStacks = new List(); public static List dynamicStacks = new List(); public static void Init() { assetBundle = PieceHelper.GetAssetBundle("refinedstonepieces"); ConvertRefinedStoneStackToPiece("BRP_RefinedStone_Stack", "MS_RefinedStonePieces_RefinedStone_Stack", "BRP_RefinedStone"); } public static void ConvertRefinedStoneStackToPiece(string baseAssetName, string newPrefabName, string resource) { staticStacks.Add(baseAssetName); dynamicStacks.Add(newPrefabName); GameObject val = assetBundle.LoadAsset(baseAssetName); GameObject prefab = PrefabManager.Instance.CreateClonedPrefab(newPrefabName, val); prefab = PieceHelper.PreparePiecePrefab(prefab, val, "$brp_refinedstone_stack"); ((Object)prefab).name = newPrefabName; List source = prefab.GetComponent().stackMeshes.OrderBy((Transform t) => t.position.y).ToList(); IOrderedEnumerable first = from t in source.Skip(0).Take(6) orderby t.position.z select t; IOrderedEnumerable second = from t in source.Skip(6).Take(6) orderby t.position.x select t; IOrderedEnumerable second2 = from t in source.Skip(12).Take(6) orderby t.position.z select t; prefab.GetComponent().stackMeshes = first.Concat(second).Concat(second2).ToList(); DynamicStoragePiles.Instance.AddCompatPiece(prefab, resource, 10, addGraphics: true); } } public static class StackedBars { private static AssetBundle assetBundle; public static List stackedBars = new List(); public static List dynamicStackedBars = new List(); public static void Init() { assetBundle = PieceHelper.GetAssetBundle("stackedbars"); ConvertToPiece("stack_tinbars", "MS_StackedBars_Tin", "Tin"); ConvertToPiece("stack_copperbars", "MS_StackedBars_Copper", "Copper"); ConvertToPiece("stack_bronzebars", "MS_StackedBars_Bronze", "Bronze"); ConvertToPiece("stack_ironbars", "MS_StackedBars_Iron", "Iron"); ConvertToPiece("stack_silverbars", "MS_StackedBars_Silver", "Silver"); ConvertToPiece("stack_blackmetalbars", "MS_StackedBars_BlackMetal", "BlackMetal"); ConvertToPiece("stack_flametalbars", "MS_StackedBars_FlameMetalNew", "FlametalNew"); } public static void ConvertToPiece(string baseAssetName, string newPrefabName, string resource) { stackedBars.Add(baseAssetName); dynamicStackedBars.Add(newPrefabName); GameObject val = assetBundle.LoadAsset(baseAssetName); GameObject prefab = PrefabManager.Instance.CreateClonedPrefab(newPrefabName, val); prefab = PieceHelper.PreparePiecePrefab(prefab, val, "$piece_" + baseAssetName); ((Object)prefab).name = newPrefabName; DynamicStoragePiles.Instance.AddCompatPiece(prefab, resource, 3); } } }