From 5da16e67190d168a1724bfe7d5fbed8bb8e34c29 Mon Sep 17 00:00:00 2001 From: RealMangoRage Date: Tue, 14 May 2024 23:02:58 -0700 Subject: [PATCH] Add GatherComponentsEvent (#9944) --- build_forge.gradle | 3 + .../net/minecraft/world/item/Item.java.patch | 22 ++++++- .../net/minecraftforge/common/ForgeHooks.java | 6 ++ .../event/ForgeEventFactory.java | 6 ++ .../event/GatherComponentsEvent.java | 62 +++++++++++++++++++ .../item/GatherComponentsEventTest.java | 45 ++++++++++++++ 6 files changed, 143 insertions(+), 1 deletion(-) create mode 100644 src/main/java/net/minecraftforge/event/GatherComponentsEvent.java create mode 100644 src/test/java/net/minecraftforge/debug/gameplay/item/GatherComponentsEventTest.java diff --git a/build_forge.gradle b/build_forge.gradle index f6952705f1..c4089ff7b9 100644 --- a/build_forge.gradle +++ b/build_forge.gradle @@ -180,6 +180,7 @@ patcher { forge_client_test { parent runs.forge_client + source sourceSets.test } forge_server { @@ -188,6 +189,7 @@ patcher { forge_server_test { parent runs.forge_server + source sourceSets.test } forge_server_gametest { @@ -196,6 +198,7 @@ patcher { forge_server_gametest_test { parent runs.forge_server_gametest + source sourceSets.test } forge_data { diff --git a/patches/minecraft/net/minecraft/world/item/Item.java.patch b/patches/minecraft/net/minecraft/world/item/Item.java.patch index 6a596d8c56..16004b1a8d 100644 --- a/patches/minecraft/net/minecraft/world/item/Item.java.patch +++ b/patches/minecraft/net/minecraft/world/item/Item.java.patch @@ -23,7 +23,27 @@ } @Deprecated -@@ -111,6 +_,7 @@ +@@ -100,17 +_,25 @@ + return this.builtInRegistryHolder; + } + ++ @Nullable ++ private DataComponentMap builtComponents = null; ++ + public DataComponentMap components() { +- return this.components; ++ if (builtComponents == null) { ++ builtComponents = net.minecraftforge.common.ForgeHooks.gatherItemComponents(this, components); ++ } ++ ++ return builtComponents; + } + + public int getDefaultMaxStackSize() { +- return this.components.getOrDefault(DataComponents.MAX_STACK_SIZE, 1); ++ return builtComponents == null ? this.components.getOrDefault(DataComponents.MAX_STACK_SIZE, 1) : this.builtComponents.getOrDefault(DataComponents.MAX_STACK_SIZE, 1); + } + public void onUseTick(Level p_41428_, LivingEntity p_41429_, ItemStack p_41430_, int p_41431_) { } diff --git a/src/main/java/net/minecraftforge/common/ForgeHooks.java b/src/main/java/net/minecraftforge/common/ForgeHooks.java index f849cc11f2..7be934c8a4 100644 --- a/src/main/java/net/minecraftforge/common/ForgeHooks.java +++ b/src/main/java/net/minecraftforge/common/ForgeHooks.java @@ -49,6 +49,7 @@ import net.minecraft.core.Holder; import net.minecraft.core.HolderLookup; import net.minecraft.core.HolderSet; import net.minecraft.core.NonNullList; +import net.minecraft.core.component.DataComponentMap; import net.minecraft.core.component.DataComponents; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.network.Connection; @@ -130,6 +131,7 @@ import net.minecraftforge.entity.IEntityAdditionalSpawnData; import net.minecraftforge.event.AnvilUpdateEvent; import net.minecraftforge.event.BuildCreativeModeTabContentsEvent; import net.minecraftforge.event.ForgeEventFactory; +import net.minecraftforge.event.GatherComponentsEvent; import net.minecraftforge.event.GrindstoneEvent; import net.minecraftforge.event.ModMismatchEvent; import net.minecraftforge.event.ServerChatEvent; @@ -1299,4 +1301,8 @@ public final class ForgeHooks { return null; } + + public static DataComponentMap gatherItemComponents(Item item, DataComponentMap dataComponents) { + return DataComponentMap.composite(dataComponents, ForgeEventFactory.gatherItemComponentsEvent(item, dataComponents).getDataComponentMap()); + } } \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/event/ForgeEventFactory.java b/src/main/java/net/minecraftforge/event/ForgeEventFactory.java index 350660613c..c019382a1b 100644 --- a/src/main/java/net/minecraftforge/event/ForgeEventFactory.java +++ b/src/main/java/net/minecraftforge/event/ForgeEventFactory.java @@ -14,6 +14,8 @@ import java.util.Optional; import java.util.function.BooleanSupplier; import java.util.function.Consumer; +import net.minecraft.core.component.DataComponentMap; +import net.minecraft.world.item.Item; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.eventbus.api.Cancelable; import net.minecraftforge.eventbus.api.Event; @@ -1088,4 +1090,8 @@ public final class ForgeEventFactory { public static void onPlayerTradeWithVillager(Player player, MerchantOffer offer, AbstractVillager villager) { post(new TradeWithVillagerEvent(player, offer, villager)); } + + public static GatherComponentsEvent.Item gatherItemComponentsEvent(Item item, DataComponentMap dataComponents) { + return fire(new GatherComponentsEvent.Item(item, dataComponents)); + } } diff --git a/src/main/java/net/minecraftforge/event/GatherComponentsEvent.java b/src/main/java/net/minecraftforge/event/GatherComponentsEvent.java new file mode 100644 index 0000000000..011651fa6a --- /dev/null +++ b/src/main/java/net/minecraftforge/event/GatherComponentsEvent.java @@ -0,0 +1,62 @@ +package net.minecraftforge.event; + +import net.minecraft.core.component.DataComponentMap; +import net.minecraft.core.component.DataComponentType; +import net.minecraft.core.component.DataComponents; +import net.minecraft.world.item.Item; +import net.minecraftforge.eventbus.api.Event; +import org.jetbrains.annotations.ApiStatus; + +import javax.annotation.Nullable; + +/** + Where all the events fore Gathering Components will exist. + */ + +public abstract class GatherComponentsEvent extends Event { + private final DataComponentMap.Builder components = DataComponentMap.builder(); + private final DataComponentMap originalComponents; + private final Object owner; + + protected GatherComponentsEvent(Object owner, DataComponentMap originalComponents) { + this.originalComponents = originalComponents; + this.owner = owner; + } + + public void register(DataComponentType componentType, @Nullable T value) { + components.set(componentType, value); + } + + @ApiStatus.Internal + public DataComponentMap getDataComponentMap() { + return components.build(); + } + + public DataComponentMap getOriginalComponentMap() { + return originalComponents; + } + + public Object getOwner() { + return owner; + } + + /** + * Used to get additional Components for any {@link net.minecraft.world.item.Item} + * + * Fired once for every {@link net.minecraft.world.item.Item} instance, only once, Lazily. + * + * Recursion is not supported. Cant call {@link net.minecraft.world.item.Item#components()} as that would cause a loop. + * + * References in {@link net.minecraft.world.item.Items} may not be valid at the current time. + */ + public static class Item extends GatherComponentsEvent { + public Item(net.minecraft.world.item.Item item, DataComponentMap dataComponents) { + super(item, dataComponents); + } + + @Override + public net.minecraft.world.item.Item getOwner() { + return (net.minecraft.world.item.Item) super.getOwner(); + } + } +} diff --git a/src/test/java/net/minecraftforge/debug/gameplay/item/GatherComponentsEventTest.java b/src/test/java/net/minecraftforge/debug/gameplay/item/GatherComponentsEventTest.java new file mode 100644 index 0000000000..aaf3d99eea --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/gameplay/item/GatherComponentsEventTest.java @@ -0,0 +1,45 @@ +package net.minecraftforge.debug.gameplay.item; + +import net.minecraft.core.component.DataComponents; +import net.minecraft.gametest.framework.GameTest; +import net.minecraft.gametest.framework.GameTestHelper; +import net.minecraft.world.food.FoodProperties; +import net.minecraft.world.item.Items; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.GatherComponentsEvent; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.gametest.GameTestHolder; +import net.minecraftforge.test.BaseTestMod; + +import java.util.List; + +@GameTestHolder("forge." + GatherComponentsEventTest.MOD_ID) +@Mod(GatherComponentsEventTest.MOD_ID) +public class GatherComponentsEventTest extends BaseTestMod { + public static final String MOD_ID = "gather_components_test_event"; + + public GatherComponentsEventTest() { + IEventBus bus = MinecraftForge.EVENT_BUS; + bus.addListener(this::onItem); + } + + public void onItem(GatherComponentsEvent.Item itemEvent) { + if (!itemEvent.getOriginalComponentMap().has(DataComponents.FOOD) && itemEvent.getOwner() == Items.IRON_NUGGET) { + itemEvent.register(DataComponents.FOOD, new FoodProperties( + 2, + 7, + true, + 3, + List.of() + )); + } + } + + @GameTest(template = "forge:empty3x3x3") + public static void onTestForFood(GameTestHelper helper) { + helper.assertTrue(Items.IRON_NUGGET.components().has(DataComponents.FOOD), "Iron Nugget is not edible, failed to apply DataComponents.FOOD to it."); + helper.assertFalse(Items.IRON_INGOT.components().has(DataComponents.FOOD), "Iron Ingot is edible, should not have DataComponents.FOOD"); + helper.succeed(); + } +}