|
| 1 | +package io.github.cadiboo.examplemod.item; |
| 2 | + |
| 3 | +import net.minecraft.block.DispenserBlock; |
| 4 | +import net.minecraft.dispenser.DefaultDispenseItemBehavior; |
| 5 | +import net.minecraft.dispenser.IBlockSource; |
| 6 | +import net.minecraft.entity.EntityType; |
| 7 | +import net.minecraft.entity.SpawnReason; |
| 8 | +import net.minecraft.item.ItemStack; |
| 9 | +import net.minecraft.item.SpawnEggItem; |
| 10 | +import net.minecraft.nbt.CompoundNBT; |
| 11 | +import net.minecraft.util.Direction; |
| 12 | +import net.minecraftforge.common.util.Lazy; |
| 13 | +import net.minecraftforge.common.util.NonNullSupplier; |
| 14 | +import net.minecraftforge.fml.RegistryObject; |
| 15 | +import net.minecraftforge.fml.common.ObfuscationReflectionHelper; |
| 16 | + |
| 17 | +import javax.annotation.Nullable; |
| 18 | +import java.util.ArrayList; |
| 19 | +import java.util.List; |
| 20 | +import java.util.Map; |
| 21 | + |
| 22 | +/** |
| 23 | + * Exists to work around a limitation with Spawn Eggs: |
| 24 | + * Spawn Eggs require an EntityType, but EntityTypes are created AFTER Items. |
| 25 | + * Therefore it is "impossible" for modded spawn eggs to exist. |
| 26 | + * This class gets around it by passing "null" to the SpawnEggItem constructor |
| 27 | + * and doing the initialisation after registry events have finished firing. |
| 28 | + * <p> |
| 29 | + * TODO: Remove once Forge adds this stuff in itself. |
| 30 | + * |
| 31 | + * @author Cadiboo |
| 32 | + */ |
| 33 | +public class ModdedSpawnEggItem extends SpawnEggItem { |
| 34 | + |
| 35 | + protected static final List<ModdedSpawnEggItem> UNADDED_EGGS = new ArrayList<>(); |
| 36 | + private final Lazy<? extends EntityType<?>> entityTypeSupplier; |
| 37 | + |
| 38 | + public ModdedSpawnEggItem(final NonNullSupplier<? extends EntityType<?>> entityTypeSupplier, final int p_i48465_2_, final int p_i48465_3_, final Properties p_i48465_4_) { |
| 39 | + super(null, p_i48465_2_, p_i48465_3_, p_i48465_4_); |
| 40 | + this.entityTypeSupplier = Lazy.of(entityTypeSupplier::get); |
| 41 | + UNADDED_EGGS.add(this); |
| 42 | + } |
| 43 | + |
| 44 | + public ModdedSpawnEggItem(final RegistryObject<? extends EntityType<?>> entityTypeSupplier, final int p_i48465_2_, final int p_i48465_3_, final Properties p_i48465_4_) { |
| 45 | + super(null, p_i48465_2_, p_i48465_3_, p_i48465_4_); |
| 46 | + this.entityTypeSupplier = Lazy.of(entityTypeSupplier); |
| 47 | + UNADDED_EGGS.add(this); |
| 48 | + } |
| 49 | + |
| 50 | + /** |
| 51 | + * Adds all the supplier based spawn eggs to vanilla's map and registers an |
| 52 | + * IDispenseItemBehavior for each of them as normal spawn eggs have one |
| 53 | + * registered for each of them during {@link net.minecraft.dispenser.IDispenseItemBehavior#init()} |
| 54 | + * but supplier based ones won't have had their EntityTypes created yet. |
| 55 | + */ |
| 56 | + public static void initUnaddedEggs() { |
| 57 | + final Map<EntityType<?>, SpawnEggItem> EGGS = ObfuscationReflectionHelper.getPrivateValue(SpawnEggItem.class, null, "field_195987_b"); |
| 58 | + DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior() { |
| 59 | + public ItemStack dispenseStack(IBlockSource source, ItemStack stack) { |
| 60 | + Direction direction = source.getBlockState().get(DispenserBlock.FACING); |
| 61 | + EntityType<?> entitytype = ((SpawnEggItem) stack.getItem()).getType(stack.getTag()); |
| 62 | + entitytype.spawn(source.getWorld(), stack, null, source.getBlockPos().offset(direction), SpawnReason.DISPENSER, direction != Direction.UP, false); |
| 63 | + stack.shrink(1); |
| 64 | + return stack; |
| 65 | + } |
| 66 | + }; |
| 67 | + for (final SpawnEggItem egg : UNADDED_EGGS) { |
| 68 | + EGGS.put(egg.getType(null), egg); |
| 69 | + DispenserBlock.registerDispenseBehavior(egg, defaultDispenseItemBehavior); |
| 70 | + // ItemColors for each spawn egg don't need to be registered because this method is called before ItemColors is created |
| 71 | + } |
| 72 | + UNADDED_EGGS.clear(); |
| 73 | + } |
| 74 | + |
| 75 | + @Override |
| 76 | + public EntityType<?> getType(@Nullable final CompoundNBT p_208076_1_) { |
| 77 | + return entityTypeSupplier.get(); |
| 78 | + } |
| 79 | + |
| 80 | +} |
0 commit comments