diff --git a/Hooks/GetItemVoidVaultHook.cs b/Hooks/GetItemVoidVaultHook.cs new file mode 100644 index 0000000..800ed09 --- /dev/null +++ b/Hooks/GetItemVoidVaultHook.cs @@ -0,0 +1,62 @@ +using MagicStorage; +using MagicStorage.Components; +using MagicStorageVoidBag.Items; +using System.Linq; +using Terraria; +using Terraria.Audio; +using Terraria.DataStructures; +using Terraria.GameContent.Achievements; +using Terraria.ID; +using Terraria.ModLoader; + +namespace MagicStorageVoidBag.Hooks { + internal class GetItemVoidVaultHook { + private static readonly log4net.ILog Logger = MagicStorageVoidBag.Instance.Logger; + public static bool Hook(On.Terraria.Player.orig_GetItem_VoidVault orig, Player player, int plr, Item[] inventory, Item newItem, GetItemSettings settings, Item returnItem) { + var i = player.inventory.FirstOrDefault(i => i.type == ModContent.ItemType(), null); + + newItem = newItem.Clone(); + + if (i == null) goto original; + + var bag = (MSVoidBag)i.ModItem; + + if (bag.location.X < 0 || bag.location.Y < 0) goto original; + + Tile tile = Main.tile[bag.location.X, bag.location.Y]; + + if (!tile.HasTile || tile.TileType != ModContent.TileType() || tile.TileFrameX != 0 || tile.TileFrameY != 0) goto original; + if (!TileEntity.ByPosition.TryGetValue(bag.location, out TileEntity te)) goto original; + if (te.type != ModContent.TileEntityType()) goto original; + + TEStorageHeart heart = (TEStorageHeart)te; + + heart.TryDeposit(returnItem); + heart.ResetCompactStage(); + StorageGUI.modSearchBox.OnChanged(); + + if (returnItem.stack != newItem.stack) { + if (newItem.IsACoin) { + SoundEngine.PlaySound(SoundID.CoinPickup, player.position); + } else { + SoundEngine.PlaySound(SoundID.Grab, player.position); + } + + if (!settings.NoText) { + PopupText.NewText(PopupTextContext.ItemPickupToVoidContainer, newItem, returnItem.stack, noStack: false, settings.LongText); + } + + AchievementsHelper.NotifyItemPickup(player, returnItem); + } + + if (returnItem.stack == 0) return true; + + original: + if (player.HasItem(ItemID.VoidLens)) { + return orig(player, plr, inventory, newItem, settings, returnItem); + } else { + return false; + } + } + } +} diff --git a/Hooks/ItemSpaceForCofveveHook.cs b/Hooks/ItemSpaceForCofveveHook.cs new file mode 100644 index 0000000..2f97029 --- /dev/null +++ b/Hooks/ItemSpaceForCofveveHook.cs @@ -0,0 +1,45 @@ +using MagicStorage.Components; +using MagicStorageVoidBag.Items; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Terraria; +using Terraria.DataStructures; +using Terraria.ModLoader; +using MagicStorage; +using Terraria.ID; + +namespace MagicStorageVoidBag.Hooks { + internal class ItemSpaceForCofveveHook { + private static readonly log4net.ILog Logger = MagicStorageVoidBag.Instance.Logger; + + // Despite the constant negative press cofveve + public static bool Hook(On.Terraria.Player.orig_ItemSpaceForCofveve orig, Player player, Item newItem) { + var i = player.inventory.FirstOrDefault(i => i.type == ModContent.ItemType(), null); + if (i == null) goto original; + + newItem = newItem.Clone(); + + var bag = (MSVoidBag)i.ModItem; + + if (bag.location.X < 0 || bag.location.Y < 0) goto original; + + Tile tile = Main.tile[bag.location.X, bag.location.Y]; + + if (!tile.HasTile || tile.TileType != ModContent.TileType() || tile.TileFrameX != 0 || tile.TileFrameY != 0) goto original; + if (!TileEntity.ByPosition.TryGetValue(bag.location, out TileEntity te)) goto original; + if (te.type != ModContent.TileEntityType()) goto original; + + if (Utility.HeartHasSpaceFor(newItem, (TEStorageHeart)te)) return true; + + original: + if (player.HasItem(ItemID.VoidLens)) { + return orig(player, newItem); + } else { + return false; + } + } + } +} diff --git a/Hooks/StorageHeartRightClickHook.cs b/Hooks/StorageHeartRightClickHook.cs new file mode 100644 index 0000000..5ca186b --- /dev/null +++ b/Hooks/StorageHeartRightClickHook.cs @@ -0,0 +1,33 @@ +using MagicStorage.Components; +using MagicStorageVoidBag.Items; +using Terraria; +using Terraria.DataStructures; +using Terraria.Localization; +using Terraria.ModLoader; + + +namespace MagicStorageVoidBag.Hooks { + internal class StorageHeartRightClickHook { + private static readonly log4net.ILog Logger = MagicStorageVoidBag.Instance.Logger; + public static bool Hook(On.MagicStorage.Components.StorageHeart.orig_RightClick orig, StorageHeart heart, int i, int j) { + // https://github.com/blushiemagic/MagicStorage/blob/1.4-stable/Components/StorageHeart.cs#L23 + Player player = Main.LocalPlayer; + Item item = player.HeldItem; + if (item.type == ModContent.ItemType()) { + if (Main.tile[i, j].TileFrameX % 36 == 18) i--; + if (Main.tile[i, j].TileFrameY % 36 == 18) j--; + + MSVoidBag bag = (MSVoidBag)item.ModItem; + bag.location = new Point16(i, j); + if (player.selectedItem == 58) { + Main.mouseItem = item.Clone(); + } + + Main.NewText(Language.GetTextValue("Mods.MagicStorage.LocatorSet", i, j)); + return true; + } + + return orig(heart, i, j); + } + } +} diff --git a/ILPatches/ILPatch.cs b/ILPatches/ILPatch.cs new file mode 100644 index 0000000..601dc25 --- /dev/null +++ b/ILPatches/ILPatch.cs @@ -0,0 +1,12 @@ +using MonoMod.Cil; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace MagicStorageVoidBag.ILPatches { + internal interface ILPatch { + public abstract void Patch(ILContext il); + } +} diff --git a/ILPatches/PlayerUpdatePatch.cs b/ILPatches/PlayerUpdatePatch.cs new file mode 100644 index 0000000..6ee5d89 --- /dev/null +++ b/ILPatches/PlayerUpdatePatch.cs @@ -0,0 +1,39 @@ +using MagicStorageVoidBag.Items; +using Mono.Cecil.Cil; +using MonoMod.Cil; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Terraria; +using Terraria.ModLoader; + +namespace MagicStorageVoidBag.ILPatches { + internal class PlayerUpdatePatch : ILPatch { + private static readonly log4net.ILog Logger = MagicStorageVoidBag.Instance.Logger; + public void Patch(ILContext il) { + if (il == null) { + Logger.Error("ILContext null!"); + return; + } + + Logger.Debug("Patching Terraria.Player.Update IL..."); + + var c = new ILCursor(il); + var setterMethod = typeof(Player).GetProperty(nameof(Player.IsVoidVaultEnabled)).GetSetMethod(); + if (!c.TryGotoNext(i => i.MatchCallOrCallvirt(setterMethod))) { + Logger.Warn("Failed to go to next call or callvirt! :("); + return; + } + + c.Emit(OpCodes.Ldarg_0); + c.Emit(OpCodes.Ldc_I4, ModContent.ItemType()); + var hasItemMethod = typeof(Player).GetMethod(nameof(Player.HasItem)); + c.Emit(OpCodes.Call, hasItemMethod); + c.Emit(OpCodes.Or); + + Logger.Debug("...Complete!"); + } + } +} diff --git a/Items/GlobalItem.cs b/Items/GlobalItem.cs deleted file mode 100644 index 0658918..0000000 --- a/Items/GlobalItem.cs +++ /dev/null @@ -1,38 +0,0 @@ -using MagicStorage.Components; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Terraria; -using Terraria.DataStructures; -using Terraria.Localization; -using Terraria.ModLoader; - -namespace MagicStorageVoidBag.Items { - internal class GlobalItem : Terraria.ModLoader.GlobalItem { - public override bool OnPickup(Item item, Player player) { - var i = player.inventory.Where(i => i.type == ModContent.ItemType()).DefaultIfEmpty(null).First(); - if (i != null && !player.ItemSpace(item).CanTakeItem) { - var bag = (MSVoidBag)i.ModItem; - - if (bag.location.X < 0 || bag.location.Y < 0) return false; - - Tile tile = Main.tile[bag.location.X, bag.location.Y]; - - if (!tile.HasTile || tile.TileType != ModContent.TileType() || tile.TileFrameX != 0 || tile.TileFrameY != 0) return false; - if (!TileEntity.ByPosition.TryGetValue(bag.location, out TileEntity te)) return false; - if (te.type != ModContent.TileEntityType()) return false; - - TEStorageHeart heart = (TEStorageHeart)te; - - int oldStack = item.stack; - heart.TryDeposit(item); - if (item.stack == 0) return true; - - } - - return base.OnPickup(item, player); - } - } -} diff --git a/Items/MSVoidBag.cs b/Items/MSVoidBag.cs index c918e90..c1d2e56 100644 --- a/Items/MSVoidBag.cs +++ b/Items/MSVoidBag.cs @@ -11,33 +11,6 @@ namespace MagicStorageVoidBag.Items { [ExtendsFromMod("MagicStorage")] public class MSVoidBag : PortableAccess { - /* - Code here largely thanks to original MagicStorage source, which can be found at - https://github.com/blushiemagic/MagicStorage/ - License: - MIT License - - Copyright(c) 2017 Kaylee Minsuh Kim - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files(the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - */ - public override void SetStaticDefaults() { CreativeItemSacrificesCatalog.Instance.SacrificeCountNeededByItemId[Type] = 1; } diff --git a/MagicStorage-LICENSE.txt b/MagicStorage-LICENSE.txt new file mode 100644 index 0000000..8123551 --- /dev/null +++ b/MagicStorage-LICENSE.txt @@ -0,0 +1,23 @@ +This mod uses various pieces of code from the original MagicStorage mod, the license for which is below: + +MIT License + +Copyright (c) 2017 Kaylee Minsuh Kim + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/MagicStorageVoidBag.cs b/MagicStorageVoidBag.cs index 1500f8e..18bf333 100644 --- a/MagicStorageVoidBag.cs +++ b/MagicStorageVoidBag.cs @@ -1,57 +1,31 @@ -using Mono.Cecil.Cil; -using Mono.Cecil; -using MonoMod.Cil; + using Terraria.ModLoader; -using MagicStorageVoidBag.Items; +using MagicStorageVoidBag.ILPatches; +using MagicStorageVoidBag.Hooks; namespace MagicStorageVoidBag { public class MagicStorageVoidBag : Mod { + public static MagicStorageVoidBag Instance => ModContent.GetInstance(); + + // IL Patches + private PlayerUpdatePatch playerUpdatePatch = new(); + public override void Load() { - IL.MagicStorage.Components.StorageHeart.RightClick += HeartRightClickPatch; + IL.Terraria.Player.Update += playerUpdatePatch.Patch; + + On.Terraria.Player.GetItem_VoidVault += GetItemVoidVaultHook.Hook; + On.Terraria.Player.ItemSpaceForCofveve += ItemSpaceForCofveveHook.Hook; + On.MagicStorage.Components.StorageHeart.RightClick += StorageHeartRightClickHook.Hook; } public override void Unload() { + IL.Terraria.Player.Update -= playerUpdatePatch.Patch; + + On.Terraria.Player.GetItem_VoidVault -= GetItemVoidVaultHook.Hook; + On.Terraria.Player.ItemSpaceForCofveve -= ItemSpaceForCofveveHook.Hook; + On.MagicStorage.Components.StorageHeart.RightClick -= StorageHeartRightClickHook.Hook; + base.Unload(); } - - // Patch MagicStorage IL to change the Storage Heart right click handler to also work with - // MSVoidBag. - private void HeartRightClickPatch(ILContext il) { - if (il == null) { - Logger.Error("ILContext null!"); - return; - } - - Logger.Debug("Patching MagicStorage IL..."); - - var c = new ILCursor(il); - - if (!c.TryGotoNext(i => i.MatchCallOrCallvirt("Terraria.ModLoader.ModContent", "ItemType"))) { - Logger.Warn("IL patching failed! :("); - } - c = c.GotoPrev().GotoPrev(); - - var c2 = c.Clone(); - - // copy IL up to call - while (c2.Next.OpCode != OpCodes.Call) { - if (c2.Next.Operand != null) { - c.Emit(c2.Next.OpCode, c2.Next.Operand); - } else { - c.Emit(c2.Next.OpCode); - } - - c2 = c2.GotoNext(); - } - - var method = typeof(ModContent).GetMethod("ItemType").MakeGenericMethod(typeof(MSVoidBag)); - - c.Emit(c2.Next.OpCode, method); - c2.GotoNext(); - c.Emit(c2.Next.OpCode, c2.Next.Operand); - - Logger.Debug("...MagicStorage IL patching complete!"); - } - } } \ No newline at end of file diff --git a/MagicStorageVoidBag.csproj b/MagicStorageVoidBag.csproj index 9ca5cab..e31521e 100644 --- a/MagicStorageVoidBag.csproj +++ b/MagicStorageVoidBag.csproj @@ -1,6 +1,6 @@ - + MagicStorageVoidBag net6.0 @@ -12,10 +12,10 @@ - ..\Mod Libraries\MagicStorage.dll + ../Mod Libraries/MagicStorage.dll - - lib\MMHOOK_MagicStorage.dll + + lib\MagicStorageHooks.dll \ No newline at end of file diff --git a/Utility.cs b/Utility.cs new file mode 100644 index 0000000..dcdce9f --- /dev/null +++ b/Utility.cs @@ -0,0 +1,25 @@ +using MagicStorage; +using MagicStorage.Components; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Terraria; + +namespace MagicStorageVoidBag { + internal static class Utility { + internal static bool HeartHasSpaceFor(Item newItem, TEStorageHeart heart) { + foreach (TEAbstractStorageUnit storageUnit in heart.GetStorageUnits()) { + if (!storageUnit.Inactive) { + var unitItems = storageUnit.GetItems(); + + if (!storageUnit.IsFull) return true; + if (storageUnit.HasSpaceInStackFor(newItem)) return true; + } + } + + return false; + } + } +} diff --git a/build.txt b/build.txt index 0a082fc..addf245 100644 --- a/build.txt +++ b/build.txt @@ -1,8 +1,8 @@ displayName = MagicStorage Void Bag author = jack -version = 0.3 +version = 1.1 modReferences = MagicStorage -dllReferences = MMHOOK_MagicStorage +dllReferences = MagicStorageHooks sortAfter = MagicStorage includeSource = true homepage = https://github.com/jackbondpreston/MagicStorageVoidBag diff --git a/description_workshop.txt b/description_workshop.txt index e6f7a4e..7472d7b 100644 --- a/description_workshop.txt +++ b/description_workshop.txt @@ -1,2 +1,4 @@ Adds an upgraded void bag that combines functionality of the Void Bag and Portable Remote Storage Access, by putting items into a magic storage system when your inventory is full (and allowing remote access as usual). -This item is crafted by combining a Void Bag with a Portable Remote Storage Access. To link it with your storage system, right click the Storage Heart with the bag equipped. \ No newline at end of file +This item is crafted by combining a Void Bag with a Portable Remote Storage Access. To link it with your storage system, right click the Storage Heart with the bag equipped. + +Thanks to the original MagicStorage mod for some code and of course the functionality of the original mod! \ No newline at end of file diff --git a/lib/MMHOOK_MagicStorage.dll b/lib/MMHOOK_MagicStorage.dll deleted file mode 100644 index 07472b6..0000000 Binary files a/lib/MMHOOK_MagicStorage.dll and /dev/null differ diff --git a/lib/MagicStorageHooks.dll b/lib/MagicStorageHooks.dll new file mode 100644 index 0000000..d877b81 Binary files /dev/null and b/lib/MagicStorageHooks.dll differ