Hi everyone, I'm a bit confused on how Forge handles the spawn of custom entities. I have created a test project to show what confuses me (GitHub repository).
In my test mod I have created an entity called TestEntity that only has one extra boolean parameter called shorty that controls if the entity is rendered as block or as a slab (TestEntityRenderer checks this flag and renders one of two models accordingly). Here is the code for the Entity class, readAdditional is overridden to read shorty from the NBT.
package com.github.neutrinokillerino.entitytest.entity;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.network.IPacket;
import net.minecraft.world.World;
import net.minecraftforge.fml.network.NetworkHooks;
public class TestEntity extends Entity {
public boolean shorty = false;
public TestEntity(EntityType<?> entityTypeIn, World worldIn) {
super(entityTypeIn, worldIn);
// TODO Auto-generated constructor stub
}
@Override
protected void registerData() {
// TODO Auto-generated method stub
}
@Override
protected void readAdditional(CompoundNBT compound) {
// TODO Auto-generated method stub
this.shorty = compound.getBoolean("shorty");
}
@Override
protected void writeAdditional(CompoundNBT compound) {
// TODO Auto-generated method stub
}
@Override
public IPacket<?> createSpawnPacket() {
// TODO Auto-generated method stub
return NetworkHooks.getEntitySpawningPacket(this);
}
}
Here is what confuses me, when I spawn the entity using the summon command /summon entitytest:test_entity ~ ~ ~ {shorty:true} the following happens (inspected using breakpoints on eclipse):
Constructor is called.entityID = 4247
readAdditional is called. NBT contains information passed through command and shorty is set totrue. entityID = 4247
createSpawnPacket is called. shorty has valuetrue. entityID = 4247
Constructor is called again. entityID = 4248
Renderer is called with an entity with ID 4247,shorty is false.
Why is the constructor called twice and why is shorty set to false again?
Something weird also happens when I create an item that spawns the entity. The item is PlacerItem and it's class is:
package com.github.neutrinokillerino.entitytest.item;
import com.github.neutrinokillerino.entitytest.init.ModEntityTypes;
import net.minecraft.entity.SpawnReason;
import net.minecraft.item.Item;
import net.minecraft.item.ItemUseContext;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class PlacerItem extends Item {
public PlacerItem(Properties properties) {
super(properties);
}
public ActionResultType onItemUse(ItemUseContext context) {
BlockPos blockpos = context.getPos();
Direction direction = context.getFace();
BlockPos blockpos1 = blockpos.offset(direction);
World world = context.getWorld();
if (!world.isRemote()) {
CompoundNBT compound = new CompoundNBT();
compound.putBoolean("shorty", true);
ModEntityTypes.TEST_ENTITY.get().spawn(world, compound, null, null, blockpos1, SpawnReason.SPAWN_EGG, false, false);
}
return ActionResultType.SUCCESS;
}
}
When using the item, the following happens:
Constructor is called. entityID = 4254
createSpawnPacket is called.entityID = 4254
Constructor is called. entityID = 4255
Renderer is called. entityID = 4254
In this case, readAdditional is not called and the constructor is called two times.
I have also tried to create a bifunction as the constructor but then the calls get very messy.
I'd be grateful if anyone could clarify how Forge calls everything and how the spawn packet is handled.
Thanks.