diff --git a/patches/net/minecraft/client/color/item/ItemColors.java.patch b/patches/net/minecraft/client/color/item/ItemColors.java.patch index afe4aac398..e98475f291 100644 --- a/patches/net/minecraft/client/color/item/ItemColors.java.patch +++ b/patches/net/minecraft/client/color/item/ItemColors.java.patch @@ -10,7 +10,7 @@ public static ItemColors createDefault(BlockColors p_92684_) { ItemColors itemcolors = new ItemColors(); -@@ -101,17 +_,20 @@ +@@ -101,17 +_,28 @@ (p_359075_, p_359076_) -> p_359076_ == 0 ? -1 : ARGB.opaque(p_359075_.getOrDefault(DataComponents.MAP_COLOR, MapItemColor.DEFAULT).rgb()), Items.FILLED_MAP ); @@ -24,6 +24,14 @@ return itemcolor == null ? -1 : itemcolor.getColor(p_92677_, p_92678_); } ++ /** ++ * Neo: returns the color handler for the given {@code item}, or {@code null} if one isn't registered. ++ */ ++ @org.jetbrains.annotations.Nullable ++ public ItemColor get(Item item) { ++ return itemColors.get(item); ++ } ++ + /** @deprecated Register via {@link net.neoforged.neoforge.client.event.RegisterColorHandlersEvent.Item} */ + @Deprecated public void register(ItemColor p_92690_, ItemLike... p_92691_) { diff --git a/patches/net/minecraft/world/item/SpawnEggItem.java.patch b/patches/net/minecraft/world/item/SpawnEggItem.java.patch index b3a50e656b..5154845a82 100644 --- a/patches/net/minecraft/world/item/SpawnEggItem.java.patch +++ b/patches/net/minecraft/world/item/SpawnEggItem.java.patch @@ -1,51 +1,48 @@ --- a/net/minecraft/world/item/SpawnEggItem.java +++ b/net/minecraft/world/item/SpawnEggItem.java -@@ -41,11 +_,14 @@ - private final int highlightColor; - private final EntityType defaultType; - -+ /** @deprecated Forge: Use {@link net.neoforged.neoforge.common.DeferredSpawnEggItem} instead for suppliers */ -+ @Deprecated - public SpawnEggItem(EntityType p_43207_, int p_43208_, int p_43209_, Item.Properties p_43210_) { - super(p_43210_); - this.defaultType = p_43207_; - this.backgroundColor = p_43208_; - this.highlightColor = p_43209_; -+ if (p_43207_ != null) - BY_ID.put(p_43207_, this); - } - -@@ -133,6 +_,8 @@ - - @Nullable - public static SpawnEggItem byId(@Nullable EntityType p_43214_) { -+ var ret = net.neoforged.neoforge.common.DeferredSpawnEggItem.deferredOnlyById(p_43214_); -+ if (ret != null) return ret; - return BY_ID.get(p_43214_); - } - -@@ -142,12 +_,12 @@ - - public EntityType getType(ItemStack p_330335_) { - CustomData customdata = p_330335_.getOrDefault(DataComponents.ENTITY_DATA, CustomData.EMPTY); -- return !customdata.isEmpty() ? customdata.read(ENTITY_TYPE_FIELD_CODEC).result().orElse(this.defaultType) : this.defaultType; -+ return !customdata.isEmpty() ? customdata.read(ENTITY_TYPE_FIELD_CODEC).result().orElse(getDefaultType()) : getDefaultType(); - } - - @Override - public FeatureFlagSet requiredFeatures() { -- return this.defaultType.requiredFeatures(); -+ return this.getDefaultType().requiredFeatures(); - } - - public Optional spawnOffspringFromSpawnEgg( -@@ -178,5 +_,9 @@ - } +@@ -179,4 +_,45 @@ } } + } ++ ++ public static final net.minecraft.core.dispenser.DispenseItemBehavior DEFAULT_DISPENSE_BEHAVIOR = new net.minecraft.core.dispenser.DefaultDispenseItemBehavior() { ++ @Override ++ protected ItemStack execute(net.minecraft.core.dispenser.BlockSource source, ItemStack egg) { ++ Direction direction = source.state().getValue(net.minecraft.world.level.block.DispenserBlock.FACING); ++ EntityType entitytype = ((SpawnEggItem)egg.getItem()).getType(egg); ++ ++ try { ++ entitytype.spawn( ++ source.level(), egg, null, source.pos().relative(direction), EntitySpawnReason.DISPENSER, direction != Direction.UP, false ++ ); ++ } catch (Exception exception) { ++ LOGGER.error("Error while dispensing spawn egg from dispenser at {}", source.pos(), exception); ++ return ItemStack.EMPTY; ++ } ++ ++ egg.shrink(1); ++ source.level().gameEvent(null, GameEvent.ENTITY_PLACE, source.pos()); ++ return egg; ++ } ++ }; ++ ++ /** ++ * {@return the dispense behavior to register by default} ++ */ ++ @Nullable ++ protected net.minecraft.core.dispenser.DispenseItemBehavior createDispenseBehavior() { ++ return DEFAULT_DISPENSE_BEHAVIOR; + } + -+ protected EntityType getDefaultType() { -+ return defaultType; - } ++ @net.neoforged.bus.api.SubscribeEvent(priority = net.neoforged.bus.api.EventPriority.LOWEST) ++ private static void registerDispenseBehavior(final net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent event) { ++ event.enqueueWork(() -> eggs().forEach(egg -> { ++ if (!net.minecraft.world.level.block.DispenserBlock.DISPENSER_REGISTRY.containsKey(egg)) { ++ var beh = egg.createDispenseBehavior(); ++ if (beh != null) { ++ net.minecraft.world.level.block.DispenserBlock.registerBehavior(egg, beh); ++ } ++ } ++ })); ++ } } diff --git a/src/main/java/net/neoforged/neoforge/client/ClientNeoForgeMod.java b/src/main/java/net/neoforged/neoforge/client/ClientNeoForgeMod.java index c378194405..d55c15caec 100644 --- a/src/main/java/net/neoforged/neoforge/client/ClientNeoForgeMod.java +++ b/src/main/java/net/neoforged/neoforge/client/ClientNeoForgeMod.java @@ -10,9 +10,12 @@ import net.minecraft.client.renderer.RenderType; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.ARGB; +import net.minecraft.world.item.SpawnEggItem; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.material.FluidState; import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.EventPriority; import net.neoforged.bus.api.IEventBus; import net.neoforged.bus.api.SubscribeEvent; import net.neoforged.fml.ModContainer; @@ -22,6 +25,7 @@ import net.neoforged.neoforge.client.event.ClientPlayerNetworkEvent; import net.neoforged.neoforge.client.event.ModelEvent; import net.neoforged.neoforge.client.event.RegisterClientReloadListenersEvent; +import net.neoforged.neoforge.client.event.RegisterColorHandlersEvent; import net.neoforged.neoforge.client.event.RegisterNamedRenderTypesEvent; import net.neoforged.neoforge.client.event.RegisterSpriteSourceTypesEvent; import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; @@ -157,4 +161,13 @@ public ResourceLocation getFlowingTexture() { } }, milkType)); } + + @SubscribeEvent(priority = EventPriority.LOWEST) + static void registerSpawnEggColors(RegisterColorHandlersEvent.Item event) { + SpawnEggItem.eggs().forEach(egg -> { + if (event.getItemColors().get(egg) == null) { + event.register((stack, layer) -> ARGB.opaque(egg.getColor(layer)), egg); + } + }); + } } diff --git a/src/main/java/net/neoforged/neoforge/common/DeferredSpawnEggItem.java b/src/main/java/net/neoforged/neoforge/common/DeferredSpawnEggItem.java deleted file mode 100644 index 67c84ef09a..0000000000 --- a/src/main/java/net/neoforged/neoforge/common/DeferredSpawnEggItem.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) Forge Development LLC and contributors - * SPDX-License-Identifier: LGPL-2.1-only - */ - -package net.neoforged.neoforge.common; - -import java.util.ArrayList; -import java.util.IdentityHashMap; -import java.util.List; -import java.util.Map; -import java.util.function.Supplier; -import net.minecraft.core.Direction; -import net.minecraft.core.dispenser.DispenseItemBehavior; -import net.minecraft.util.ARGB; -import net.minecraft.world.entity.EntitySpawnReason; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.Mob; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.SpawnEggItem; -import net.minecraft.world.level.block.DispenserBlock; -import net.minecraft.world.level.gameevent.GameEvent; -import net.neoforged.api.distmarker.Dist; -import net.neoforged.bus.api.EventPriority; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.common.EventBusSubscriber; -import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; -import net.neoforged.neoforge.client.event.RegisterColorHandlersEvent; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.Nullable; - -public class DeferredSpawnEggItem extends SpawnEggItem { - private static final List MOD_EGGS = new ArrayList<>(); - private static final Map, DeferredSpawnEggItem> TYPE_MAP = new IdentityHashMap<>(); - private final Supplier> typeSupplier; - - public DeferredSpawnEggItem(Supplier> type, int backgroundColor, int highlightColor, Properties props) { - super((EntityType) null, backgroundColor, highlightColor, props); - this.typeSupplier = type; - - MOD_EGGS.add(this); - } - - @Nullable - protected DispenseItemBehavior createDispenseBehavior() { - return DEFAULT_DISPENSE_BEHAVIOR; - } - - @ApiStatus.Internal - @Nullable - public static SpawnEggItem deferredOnlyById(@Nullable EntityType type) { - return TYPE_MAP.get(type); - } - - @Override - protected EntityType getDefaultType() { - return this.typeSupplier.get(); - } - - private static final DispenseItemBehavior DEFAULT_DISPENSE_BEHAVIOR = (source, stack) -> { - Direction face = source.state().getValue(DispenserBlock.FACING); - EntityType type = ((SpawnEggItem) stack.getItem()).getType(stack); - - try { - type.spawn(source.level(), stack, null, source.pos().relative(face), EntitySpawnReason.DISPENSER, face != Direction.UP, false); - } catch (Exception exception) { - DispenseItemBehavior.LOGGER.error("Error while dispensing spawn egg from dispenser at {}", source.pos(), exception); - return ItemStack.EMPTY; - } - - stack.shrink(1); - source.level().gameEvent(GameEvent.ENTITY_PLACE, source.pos(), GameEvent.Context.of(source.state())); - return stack; - }; - - @EventBusSubscriber(modid = "neoforge", bus = EventBusSubscriber.Bus.MOD) - private static class CommonHandler { - @SubscribeEvent - public static void onCommonSetup(FMLCommonSetupEvent event) { - event.enqueueWork(() -> { - MOD_EGGS.forEach(egg -> { - DispenseItemBehavior dispenseBehavior = egg.createDispenseBehavior(); - if (dispenseBehavior != null) { - DispenserBlock.registerBehavior(egg, dispenseBehavior); - } - - TYPE_MAP.put(egg.typeSupplier.get(), egg); - }); - }); - } - } - - @EventBusSubscriber(value = Dist.CLIENT, modid = "neoforge", bus = EventBusSubscriber.Bus.MOD) - private static class ColorRegisterHandler { - @SubscribeEvent(priority = EventPriority.HIGHEST) - public static void registerSpawnEggColors(RegisterColorHandlersEvent.Item event) { - MOD_EGGS.forEach(egg -> event.register((stack, layer) -> ARGB.opaque(egg.getColor(layer)), egg)); - } - } -} diff --git a/src/main/java/net/neoforged/neoforge/common/NeoForgeMod.java b/src/main/java/net/neoforged/neoforge/common/NeoForgeMod.java index c19d9e788f..b2a4298e12 100644 --- a/src/main/java/net/neoforged/neoforge/common/NeoForgeMod.java +++ b/src/main/java/net/neoforged/neoforge/common/NeoForgeMod.java @@ -52,6 +52,7 @@ import net.minecraft.world.entity.ai.attributes.RangedAttribute; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.item.Items; +import net.minecraft.world.item.SpawnEggItem; import net.minecraft.world.item.crafting.display.SlotDisplay; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.GameRules; @@ -588,6 +589,8 @@ public NeoForgeMod(IEventBus modEventBus, Dist dist, ModContainer container) { modEventBus.register(NeoForgeDataMaps.class); + modEventBus.register(SpawnEggItem.class); // Registers dispenser behaviour for eggs + if (isPRBuild(container.getModInfo().getVersion().toString())) { isPRBuild = true; ModLoader.addLoadingIssue(ModLoadingIssue.warning("loadwarning.neoforge.prbuild").withAffectedMod(container.getModInfo())); diff --git a/tests/src/main/java/net/neoforged/neoforge/debug/item/ItemTests.java b/tests/src/main/java/net/neoforged/neoforge/debug/item/ItemTests.java index 25954a3f0d..36b4caf085 100644 --- a/tests/src/main/java/net/neoforged/neoforge/debug/item/ItemTests.java +++ b/tests/src/main/java/net/neoforged/neoforge/debug/item/ItemTests.java @@ -37,6 +37,7 @@ import net.minecraft.world.item.MobBucketItem; import net.minecraft.world.item.PickaxeItem; import net.minecraft.world.item.Rarity; +import net.minecraft.world.item.SpawnEggItem; import net.minecraft.world.item.ToolMaterial; import net.minecraft.world.item.context.UseOnContext; import net.minecraft.world.item.equipment.ArmorMaterials; @@ -48,7 +49,6 @@ import net.minecraft.world.level.material.Fluids; import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; import net.neoforged.neoforge.client.model.generators.ModelFile; -import net.neoforged.neoforge.common.DeferredSpawnEggItem; import net.neoforged.testframework.DynamicTest; import net.neoforged.testframework.annotation.ForEachTest; import net.neoforged.testframework.annotation.TestHolder; @@ -117,7 +117,7 @@ static void forgeSpawnEggTest(final DynamicTest test, final RegistrationHelper r .withRenderer(() -> PigRenderer::new) .withLang("Test Pig spawn egg"); - final var egg = reg.items().registerItem("test_spawn_egg", props -> new DeferredSpawnEggItem(testEntity, 0x0000FF, 0xFF0000, props) { + final var egg = reg.items().registerItem("test_spawn_egg", props -> new SpawnEggItem(testEntity.get(), 0x0000FF, 0xFF0000, props) { @Override public InteractionResult useOn(UseOnContext ctx) { final var result = super.useOn(ctx);