Skip to content

Commit 2571606

Browse files
committed
Add WildBoar spawn egg
1 parent 294a405 commit 2571606

File tree

5 files changed

+101
-2
lines changed

5 files changed

+101
-2
lines changed

src/main/java/io/github/cadiboo/examplemod/ModEventSubscriber.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,15 @@
55
import io.github.cadiboo.examplemod.init.ModBlocks;
66
import io.github.cadiboo.examplemod.init.ModItemGroups;
77
import io.github.cadiboo.examplemod.item.ModdedSpawnEggItem;
8+
import net.minecraft.entity.EntityType;
89
import net.minecraft.item.BlockItem;
910
import net.minecraft.item.Item;
1011
import net.minecraftforge.event.RegistryEvent;
12+
import net.minecraftforge.eventbus.api.EventPriority;
1113
import net.minecraftforge.eventbus.api.SubscribeEvent;
1214
import net.minecraftforge.fml.RegistryObject;
1315
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
1416
import net.minecraftforge.fml.config.ModConfig;
15-
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
1617
import net.minecraftforge.registries.IForgeRegistry;
1718
import org.apache.logging.log4j.LogManager;
1819
import org.apache.logging.log4j.Logger;
@@ -69,4 +70,16 @@ public static void onModConfigEvent(final ModConfig.ModConfigEvent event) {
6970
}
7071
}
7172

73+
/**
74+
* Exists to work around a limitation with Spawn Eggs:
75+
* Spawn Eggs require an EntityType, but EntityTypes are created AFTER Items.
76+
* Therefore it is "impossible" for modded spawn eggs to exist.
77+
* To get around this we have our own custom SpawnEggItem, but it needs
78+
* some extra setup after Item and EntityType registration completes.
79+
*/
80+
@SubscribeEvent(priority = EventPriority.LOWEST)
81+
public static void onPostRegisterEntities(final RegistryEvent.Register<EntityType<?>> event) {
82+
ModdedSpawnEggItem.initUnaddedEggs();
83+
}
84+
7285
}

src/main/java/io/github/cadiboo/examplemod/init/ModItems.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.github.cadiboo.examplemod.init;
22

33
import io.github.cadiboo.examplemod.ExampleMod;
4+
import io.github.cadiboo.examplemod.item.ModdedSpawnEggItem;
45
import net.minecraft.item.Item;
56
import net.minecraftforge.fml.RegistryObject;
67
import net.minecraftforge.registries.DeferredRegister;
@@ -23,5 +24,6 @@ public final class ModItems {
2324

2425
// This is a very simple Item. It has no special properties except for being on our creative tab.
2526
public static final RegistryObject<Item> EXAMPLE_CRYSTAL = ITEMS.register("example_crystal", () -> new Item(new Item.Properties().group(ModItemGroups.MOD_ITEM_GROUP)));
27+
public static final RegistryObject<ModdedSpawnEggItem> WILD_BOAR_SPAWN_EGG = ITEMS.register("wild_boar_spawn_egg", () -> new ModdedSpawnEggItem(ModEntityTypes.WILD_BOAR, 0xF0A5A2, 0xA9672B, new Item.Properties().group(ModItemGroups.MOD_ITEM_GROUP)));
2628

2729
}
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
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+
}

src/main/resources/assets/examplemod/lang/en_us.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
"block.examplemod.heat_collector": "Heat Collector",
66
"block.examplemod.electric_furnace": "Electric Furnace",
77
"block.examplemod.mod_furnace": "Mod Furnace",
8-
"item.examplemod.example_crystal": "Example Crystal",
98
"itemGroup.examplemod": "Example Mod",
9+
"item.examplemod.example_crystal": "Example Crystal",
10+
"item.examplemod.wild_boar_spawn_egg": "Wild Boar Spawn Egg",
1011
"gui.examplemod.refresh_mini_model": "Refresh Mini Model",
1112
"gui.examplemod.energy": "Energy %s",
1213
"gui.examplemod.smeltTimeProgress": "Smelt time %s/%s",
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"parent": "item/template_spawn_egg"
3+
}

0 commit comments

Comments
 (0)