From 817546e4c8a56764a705edfb3a3841e2627e98af Mon Sep 17 00:00:00 2001 From: Ben Staddon Date: Tue, 23 Apr 2019 15:12:55 -0400 Subject: [PATCH] Add a hook to allow continuously using items through stack changes (#4834) --- .../entity/EntityLivingBase.java.patch | 18 ++- .../net/minecraftforge/common/ForgeHooks.java | 9 ++ .../common/extensions/IForgeItem.java | 14 ++ .../debug/item/ContinuousUseItemTest.java | 133 ++++++++++++++++++ 4 files changed, 167 insertions(+), 7 deletions(-) create mode 100644 src/test/java/net/minecraftforge/debug/item/ContinuousUseItemTest.java diff --git a/patches/minecraft/net/minecraft/entity/EntityLivingBase.java.patch b/patches/minecraft/net/minecraft/entity/EntityLivingBase.java.patch index bc8f369f7a..4f156f59a3 100644 --- a/patches/minecraft/net/minecraft/entity/EntityLivingBase.java.patch +++ b/patches/minecraft/net/minecraft/entity/EntityLivingBase.java.patch @@ -349,10 +349,14 @@ if (!itemstack.func_190926_b()) { this.func_110140_aT().func_111148_a(itemstack.func_111283_C(entityequipmentslot)); } -@@ -2134,11 +2186,18 @@ +@@ -2133,12 +2185,21 @@ + protected void func_184608_ct() { if (this.func_184587_cr()) { - if (this.func_184586_b(this.func_184600_cs()) == this.field_184627_bm) { +- if (this.func_184586_b(this.func_184600_cs()) == this.field_184627_bm) { ++ ItemStack itemstack = this.func_184586_b(this.func_184600_cs()); ++ if (net.minecraftforge.common.ForgeHooks.canContinueUsing(this.field_184627_bm, itemstack)) this.field_184627_bm = itemstack; ++ if (itemstack == this.field_184627_bm) { + + if (!this.field_184627_bm.func_190926_b()) { + field_184628_bn = net.minecraftforge.event.ForgeEventFactory.onItemUseTick(this, field_184627_bm, field_184628_bn); @@ -369,7 +373,7 @@ this.func_71036_o(); } } else { -@@ -2172,8 +2231,10 @@ +@@ -2172,8 +2233,10 @@ public void func_184598_c(EnumHand p_184598_1_) { ItemStack itemstack = this.func_184586_b(p_184598_1_); if (!itemstack.func_190926_b() && !this.func_184587_cr()) { @@ -381,7 +385,7 @@ if (!this.field_70170_p.field_72995_K) { this.func_204802_c(1, true); this.func_204802_c(2, p_184598_1_ == EnumHand.OFF_HAND); -@@ -2229,6 +2290,9 @@ +@@ -2229,6 +2292,9 @@ vec3d1 = vec3d1.func_178789_a(-this.field_70125_A * ((float)Math.PI / 180F)); vec3d1 = vec3d1.func_178785_b(-this.field_70177_z * ((float)Math.PI / 180F)); vec3d1 = vec3d1.func_72441_c(this.field_70165_t, this.field_70163_u + (double)this.func_70047_e(), this.field_70161_v); @@ -391,7 +395,7 @@ this.field_70170_p.func_195594_a(new ItemParticleData(Particles.field_197591_B, p_195062_1_), vec3d1.field_72450_a, vec3d1.field_72448_b, vec3d1.field_72449_c, vec3d.field_72450_a, vec3d.field_72448_b + 0.05D, vec3d.field_72449_c); } -@@ -2237,7 +2301,9 @@ +@@ -2237,7 +2303,9 @@ protected void func_71036_o() { if (!this.field_184627_bm.func_190926_b() && this.func_184587_cr()) { this.func_184584_a(this.field_184627_bm, 16); @@ -402,7 +406,7 @@ this.func_184602_cy(); } -@@ -2257,6 +2323,7 @@ +@@ -2257,6 +2325,7 @@ public void func_184597_cx() { if (!this.field_184627_bm.func_190926_b()) { @@ -410,7 +414,7 @@ this.field_184627_bm.func_77974_b(this.field_70170_p, this, this.func_184605_cv()); } -@@ -2363,4 +2430,62 @@ +@@ -2363,4 +2432,62 @@ @OnlyIn(Dist.CLIENT) public void func_191987_a(BlockPos p_191987_1_, boolean p_191987_2_) { } diff --git a/src/main/java/net/minecraftforge/common/ForgeHooks.java b/src/main/java/net/minecraftforge/common/ForgeHooks.java index e7621b00c0..3044c9abbd 100644 --- a/src/main/java/net/minecraftforge/common/ForgeHooks.java +++ b/src/main/java/net/minecraftforge/common/ForgeHooks.java @@ -183,6 +183,15 @@ public class ForgeHooks return entry.getStack(rand, fortune); } + public static boolean canContinueUsing(@Nonnull ItemStack from, @Nonnull ItemStack to) + { + if (!from.isEmpty() && !to.isEmpty()) + { + return from.getItem().canContinueUsing(from, to); + } + return false; + } + public static boolean canHarvestBlock(@Nonnull IBlockState state, @Nonnull EntityPlayer player, @Nonnull IBlockReader world, @Nonnull BlockPos pos) { //state = state.getActualState(world, pos); diff --git a/src/main/java/net/minecraftforge/common/extensions/IForgeItem.java b/src/main/java/net/minecraftforge/common/extensions/IForgeItem.java index 1c047dfa17..e14ee36bed 100644 --- a/src/main/java/net/minecraftforge/common/extensions/IForgeItem.java +++ b/src/main/java/net/minecraftforge/common/extensions/IForgeItem.java @@ -647,6 +647,20 @@ public interface IForgeItem && (newStack.isDamageable() || newStack.getDamage() == oldStack.getDamage())); } + /** + * Called while an item is in 'active' use to determine if usage should + * continue. Allows items to continue being used while sustaining damage, for + * example. + * + * @param oldStack the previous 'active' stack + * @param newStack the stack currently in the active hand + * @return true to set the new stack to active and continue using it + */ + default boolean canContinueUsing(ItemStack oldStack, ItemStack newStack) + { + return oldStack.equals(newStack); + } + /** * Called to get the Mod ID of the mod that *created* the ItemStack, instead of * the real Mod ID that *registered* it. diff --git a/src/test/java/net/minecraftforge/debug/item/ContinuousUseItemTest.java b/src/test/java/net/minecraftforge/debug/item/ContinuousUseItemTest.java new file mode 100644 index 0000000000..02c02db268 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/item/ContinuousUseItemTest.java @@ -0,0 +1,133 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2018. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version 2.1 + * of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +package net.minecraftforge.debug.item; + +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.EnumAction; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.world.World; +import net.minecraftforge.client.event.ModelRegistryEvent; +import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.registry.GameRegistry; +import net.minecraftforge.fml.relauncher.Side; + +@Mod(modid = ContinuousUseItemTest.MOD_ID, name = "Test for canContinueUsing", version = "1.0", acceptableRemoteVersions = "*") +@Mod.EventBusSubscriber +public class ContinuousUseItemTest +{ + static final String MOD_ID = "continuous_use_item_test"; + static final boolean ENABLED = false; + + @GameRegistry.ObjectHolder(TestItem.NAME) + public static final Item TEST_ITEM = null; + + @SubscribeEvent + public static void registerItem(RegistryEvent.Register event) + { + if (ENABLED) + { + event.getRegistry().register( + new TestItem().setRegistryName(MOD_ID, TestItem.NAME) + .setUnlocalizedName(MOD_ID + "." + TestItem.NAME) + .setCreativeTab(CreativeTabs.MISC) + ); + } + } + + @Mod.EventBusSubscriber(value = Side.CLIENT, modid = MOD_ID) + public static class ClientEventHandler + { + @SubscribeEvent + public static void registerModels(ModelRegistryEvent event) + { + if (ENABLED) + { + ModelLoader.setCustomModelResourceLocation(TEST_ITEM, 0, new ModelResourceLocation("minecraft:stick", "inventory")); + } + } + } + + static class TestItem extends Item + { + static final String NAME = "test_item"; + + TestItem() + { + maxStackSize = 1; + setMaxDamage(60); + } + + @Override + public boolean hasEffect(ItemStack stack) + { + return true; + } + + @Override + public EnumAction getItemUseAction(ItemStack stack) + { + return EnumAction.BOW; + } + + @Override + public int getMaxItemUseDuration(ItemStack stack) + { + return 72000; + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) + { + playerIn.setActiveHand(handIn); + return new ActionResult<>(EnumActionResult.SUCCESS, playerIn.getHeldItem(handIn)); + } + + @Override + public void onUsingTick(ItemStack stack, EntityLivingBase living, int count) + { + if (count % 10 == 0) + { + stack.damageItem(1, living); + } + } + + @Override + public boolean shouldCauseReequipAnimation(ItemStack oldStack, ItemStack newStack, boolean slotChanged) + { + return slotChanged || oldStack.getItem() != newStack.getItem(); + } + + @Override + public boolean canContinueUsing(ItemStack oldStack, ItemStack newStack) + { + return oldStack.getItem() == newStack.getItem(); + } + } +}