diff --git a/patches/minecraft/net/minecraft/world/item/SpawnEggItem.java.patch b/patches/minecraft/net/minecraft/world/item/SpawnEggItem.java.patch new file mode 100644 index 0000000000..82abe55bc3 --- /dev/null +++ b/patches/minecraft/net/minecraft/world/item/SpawnEggItem.java.patch @@ -0,0 +1,26 @@ +--- a/net/minecraft/world/item/SpawnEggItem.java ++++ b/net/minecraft/world/item/SpawnEggItem.java +@@ -39,11 +_,14 @@ + private final int f_151201_; + private final EntityType f_43204_; + ++ /** @deprecated Forge: Use {@link net.minecraftforge.common.ForgeSpawnEggItem} instead for suppliers */ ++ @Deprecated + public SpawnEggItem(EntityType p_43207_, int p_43208_, int p_43209_, Item.Properties p_43210_) { + super(p_43210_); + this.f_43204_ = p_43207_; + this.f_151200_ = p_43208_; + this.f_151201_ = p_43209_; ++ if (p_43207_ != null) + f_43201_.put(p_43207_, this); + } + +@@ -125,6 +_,8 @@ + return p_43212_ == 0 ? this.f_151200_ : this.f_151201_; + } + ++ /** @deprecated Forge: call {@link net.minecraftforge.common.ForgeSpawnEggItem#fromEntityType(EntityType)} instead */ ++ @Deprecated + @Nullable + public static SpawnEggItem m_43213_(@Nullable EntityType p_43214_) { + return f_43201_.get(p_43214_); diff --git a/src/main/java/net/minecraftforge/common/ForgeSpawnEggItem.java b/src/main/java/net/minecraftforge/common/ForgeSpawnEggItem.java new file mode 100644 index 0000000000..cfd6bdfc17 --- /dev/null +++ b/src/main/java/net/minecraftforge/common/ForgeSpawnEggItem.java @@ -0,0 +1,132 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2021. + * + * 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.common; + +import net.minecraft.core.Direction; +import net.minecraft.core.dispenser.DispenseItemBehavior; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.Mob; +import net.minecraft.world.entity.MobSpawnType; +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.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.ColorHandlerEvent; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.IdentityHashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Supplier; + +public class ForgeSpawnEggItem extends SpawnEggItem +{ + private static final List MOD_EGGS = new ArrayList<>(); + private static final Map, ForgeSpawnEggItem> TYPE_MAP = new IdentityHashMap<>(); + private final Supplier> typeSupplier; + + public ForgeSpawnEggItem(Supplier> type, int backgroundColor, int highlightColor, Properties props) + { + super((EntityType) null, backgroundColor, highlightColor, props); + this.typeSupplier = type; + + MOD_EGGS.add(this); + } + + @Override + public EntityType getType(@Nullable CompoundTag tag) + { + EntityType type = super.getType(tag); + return type != null ? type : typeSupplier.get(); + } + + @Nullable + protected DispenseItemBehavior createDispenseBehavior() + { + return DEFAULT_DISPENSE_BEHAVIOR; + } + + @Nullable + public static SpawnEggItem fromEntityType(@Nullable EntityType type) + { + SpawnEggItem ret = TYPE_MAP.get(type); + return ret != null ? ret : SpawnEggItem.byId(type); + } + + + + private static final DispenseItemBehavior DEFAULT_DISPENSE_BEHAVIOR = (source, stack) -> + { + Direction face = source.getBlockState().getValue(DispenserBlock.FACING); + EntityType type = ((SpawnEggItem)stack.getItem()).getType(stack.getTag()); + + try + { + type.spawn(source.getLevel(), stack, null, source.getPos().relative(face), MobSpawnType.DISPENSER, face != Direction.UP, false); + } + catch (Exception exception) + { + DispenseItemBehavior.LOGGER.error("Error while dispensing spawn egg from dispenser at {}", source.getPos(), exception); + return ItemStack.EMPTY; + } + + stack.shrink(1); + source.getLevel().gameEvent(GameEvent.ENTITY_PLACE, source.getPos()); + return stack; + }; + + @Mod.EventBusSubscriber(modid = "forge", bus = Mod.EventBusSubscriber.Bus.MOD) + private static class CommonHandler + { + @SubscribeEvent + public static void onCommonSetup(FMLCommonSetupEvent event) + { + MOD_EGGS.forEach(egg -> + { + DispenseItemBehavior dispenseBehavior = egg.createDispenseBehavior(); + if (dispenseBehavior != null) + { + DispenserBlock.registerBehavior(egg, dispenseBehavior); + } + + TYPE_MAP.put(egg.typeSupplier.get(), egg); + }); + } + } + + @Mod.EventBusSubscriber(value = Dist.CLIENT, modid = "forge", bus = Mod.EventBusSubscriber.Bus.MOD) + private static class ColorRegisterHandler + { + @SubscribeEvent(priority = EventPriority.HIGHEST) + public static void registerSpawnEggColors(ColorHandlerEvent.Item event) + { + MOD_EGGS.forEach(egg -> + event.getItemColors().register((stack, layer) -> egg.getColor(layer), egg) + ); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/minecraftforge/common/extensions/IForgeEntity.java b/src/main/java/net/minecraftforge/common/extensions/IForgeEntity.java index 5f821af565..aa52348b6f 100644 --- a/src/main/java/net/minecraftforge/common/extensions/IForgeEntity.java +++ b/src/main/java/net/minecraftforge/common/extensions/IForgeEntity.java @@ -30,6 +30,7 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.nbt.CompoundTag; import net.minecraft.core.BlockPos; import net.minecraft.world.phys.HitResult; +import net.minecraftforge.common.ForgeSpawnEggItem; import net.minecraftforge.common.capabilities.ICapabilitySerializable; import net.minecraftforge.entity.PartEntity; @@ -87,7 +88,7 @@ public interface IForgeEntity extends ICapabilitySerializable { ItemStack result = self().getPickResult(); if (result == null) { - SpawnEggItem egg = SpawnEggItem.byId(self().getType()); + SpawnEggItem egg = ForgeSpawnEggItem.fromEntityType(self().getType()); if (egg != null) result = new ItemStack(egg); else diff --git a/src/test/java/net/minecraftforge/debug/item/ForgeSpawnEggItemTest.java b/src/test/java/net/minecraftforge/debug/item/ForgeSpawnEggItemTest.java new file mode 100644 index 0000000000..514332b384 --- /dev/null +++ b/src/test/java/net/minecraftforge/debug/item/ForgeSpawnEggItemTest.java @@ -0,0 +1,83 @@ +/* + * Minecraft Forge + * Copyright (c) 2016-2021. + * + * 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.entity.PigRenderer; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.MobCategory; +import net.minecraft.world.entity.animal.Pig; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.Item; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.client.event.EntityRenderersEvent; +import net.minecraftforge.common.ForgeSpawnEggItem; +import net.minecraftforge.event.entity.EntityAttributeCreationEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.fmllegacy.RegistryObject; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; + +@Mod(value = ForgeSpawnEggItemTest.MODID) +public class ForgeSpawnEggItemTest +{ + static final String MODID = "forge_spawnegg_test"; + static final boolean ENABLED = true; + + private static final DeferredRegister> ENTITIES = DeferredRegister.create(ForgeRegistries.ENTITIES, MODID); + private static final RegistryObject> ENTITY = ENTITIES.register("test_entity", () -> + EntityType.Builder.of(Pig::new, MobCategory.CREATURE).sized(1, 1).build("test_entity") + ); + + private static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID); + private static final RegistryObject EGG = ITEMS.register("test_spawn_egg", () -> + new ForgeSpawnEggItem(ENTITY, 0x0000FF, 0xFF0000, new Item.Properties().tab(CreativeModeTab.TAB_MISC)) + ); + + public ForgeSpawnEggItemTest() + { + if (ENABLED) + { + ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus()); + ENTITIES.register(FMLJavaModLoadingContext.get().getModEventBus()); + + FMLJavaModLoadingContext.get().getModEventBus().register(this); + } + } + + @SubscribeEvent + public void onRegisterAttributes(final EntityAttributeCreationEvent event) + { + event.put(ENTITY.get(), Pig.createAttributes().build()); + } + + @Mod.EventBusSubscriber(modid = MODID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD) + private static class ClientEvents + { + @SubscribeEvent + public static void onRegisterRenderers(final EntityRenderersEvent.RegisterRenderers event) + { + if (!ENABLED) { return; } + + event.registerEntityRenderer(ENTITY.get(), PigRenderer::new); + } + } +} \ No newline at end of file diff --git a/src/test/resources/META-INF/mods.toml b/src/test/resources/META-INF/mods.toml index 6a0b43d17b..89f86d09cb 100644 --- a/src/test/resources/META-INF/mods.toml +++ b/src/test/resources/META-INF/mods.toml @@ -162,5 +162,7 @@ license="LGPL v2.1" modId="add_pack_finders_test" [[mods]] modId="be_onload_test" +[[mods]] + modId="forge_spawnegg_test" # ADD ABOVE THIS LINE diff --git a/src/test/resources/assets/forge_spawnegg_test/models/item/test_spawn_egg.json b/src/test/resources/assets/forge_spawnegg_test/models/item/test_spawn_egg.json new file mode 100644 index 0000000000..9b3d01ac8a --- /dev/null +++ b/src/test/resources/assets/forge_spawnegg_test/models/item/test_spawn_egg.json @@ -0,0 +1,3 @@ +{ + "parent": "minecraft:item/template_spawn_egg" +}