Entity пропадает после перезагрузки мира

Версия Minecraft
1.12+
Всем привет! Да, я знаю, что есть уже такой вопрос, да, я читал, нет, не помогло.
Суть такова: создал экземпляр EntityHanging, расширил, как писали, через IEntityAdditionalSpawnData. После перезагрузки мира сущность всё равно исчезает...

Ссылка на похожий вопрос: Сущность не сохраняется при перезаходе.

Немного кода:

Сама сущность:
Код:
package rcdev.rcroads.entities;

import io.netty.buffer.ByteBuf;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityHanging;
import net.minecraft.init.SoundEvents;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.*;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.registry.IEntityAdditionalSpawnData;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

import javax.annotation.Nullable;

public class Test extends EntityHanging implements IEntityAdditionalSpawnData {


    public Test(World worldIn)
    {
        super(worldIn);
    }

    public Test(World worldIn, BlockPos pos, EnumFacing facing)
    {
        super(worldIn, pos);
        this.updateFacingWithBoundingBox(facing);
    }

    @Override
    public void writeEntityToNBT(NBTTagCompound compound)
    {
        super.writeEntityToNBT(compound);
    }

    @Override
    public void readEntityFromNBT(NBTTagCompound compound)
    {
        super.readEntityFromNBT(compound);
    }

    public int getWidthPixels()
    {
        return 16;
    }

    public int getHeightPixels()
    {
        return 16;
    }

    @Override
    public boolean attackEntityFrom(DamageSource source, float amount)
    {
        if(this.getEntityWorld().isRemote) this.setDead();
        return true;
    }

    @Override
    public void onBroken(@Nullable Entity brokenEntity)
    {
        return;
    }

    public void playPlaceSound()
    {
        this.playSound(SoundEvents.ENTITY_PAINTING_PLACE, 1.0F, 1.0F);
    }

    public void setLocationAndAngles(double x, double y, double z, float yaw, float pitch)
    {
        this.setPosition(x, y, z);
    }

    @SideOnly(Side.CLIENT)
    public void setPositionAndRotationDirect(double x, double y, double z, float yaw, float pitch, int posRotationIncrements, boolean teleport)
    {
        BlockPos blockpos = this.hangingPosition.add(x - this.posX, y - this.posY, z - this.posZ);
        this.setPosition((double)blockpos.getX(), (double)blockpos.getY(), (double)blockpos.getZ());
    }

    @Override
    public void onUpdate() {
        if (this.facingDirection != null)
        {
            double d0 = (double)this.hangingPosition.getX() + 0.5D;
            double d1 = (double)this.hangingPosition.getY() + 0.5D;
            double d2 = (double)this.hangingPosition.getZ() + 0.5D;
            double d4 = this.offs(this.getWidthPixels());
            double d5 = this.offs(this.getHeightPixels());
            d0 = d0 - (double)this.facingDirection.getFrontOffsetX() * 0.46875D;
            d2 = d2 - (double)this.facingDirection.getFrontOffsetZ() * 0.46875D;
            d1 = d1 + d5;
            EnumFacing enumfacing = this.facingDirection.rotateYCCW();
            d0 = d0 + d4 * (double)enumfacing.getFrontOffsetX();
            d2 = d2 + d4 * (double)enumfacing.getFrontOffsetZ();
            double d6 = (double)this.getWidthPixels();
            double d7 = (double)this.getHeightPixels();
            double d8 = (double)this.getWidthPixels();
            if (this.facingDirection.getAxis() == EnumFacing.Axis.Z)
            {
                if (this.getHorizontalFacing() == EnumFacing.SOUTH) { d2 = d2 - 0.42D; }
                else { d2 = d2 + 0.42D; }
                d8 = 2.0D;
            }
            else
            {
                if (this.getHorizontalFacing() == EnumFacing.EAST) { d0 = d0 - 0.42D; }
                else { d0 = d0 + 0.42D; }
                d6 = 2.0D;
            }
            this.posX = d0;
            this.posY = d1;
            this.posZ = d2;
            d6 = d6 / 32.0D;
            d7 = d7 / 32.0D;
            d8 = d8 / 32.0D;
            this.setEntityBoundingBox(new AxisAlignedBB(d0 - d6, d1 - d7, d2 - d8, d0 + d6, d1 + d7, d2 + d8));
        }
    }

    private double offs(int val)
    {
        return val % 32 == 0 ? 0.5D : 0.0D;
    }

    @Override
    public void writeSpawnData(ByteBuf buffer) {
        PacketBuffer pack = new PacketBuffer(buffer);
        pack.writeBlockPos(getHangingPosition());
        pack.writeEnumValue(this.getHorizontalFacing());
    }

    @Override
    public void readSpawnData(ByteBuf buffer) {
        PacketBuffer pack = new PacketBuffer(buffer);
        hangingPosition = pack.readBlockPos();
        updateFacingWithBoundingBox(pack.readEnumValue(EnumFacing.class));
    }
}
Предмет:
Код:
package rcdev.rcroads.items;

import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.EntityHanging;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import rcdev.rcroads.entities.Test;

public class ITest extends Item
{
    private final Class <? extends EntityHanging> hangingEntityClass;

    public ITest(String name, Class <? extends EntityHanging > entityClass)
    {
        this.hangingEntityClass = entityClass;
        this.setCreativeTab(CreativeTabs.BUILDING_BLOCKS);
        this.setRegistryName(name);
        this.setUnlocalizedName(name);
    }

    public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ)
    {
        ItemStack itemstack = player.getHeldItem(hand);
        BlockPos blockpos = pos.offset(facing);

        if (facing != EnumFacing.DOWN && facing != EnumFacing.UP)
        {
            EntityHanging entityhanging = new Test(worldIn, blockpos, facing);
            if(worldIn.isRemote) {
                worldIn.spawnEntity(entityhanging);
                entityhanging.playPlaceSound();
            }
            itemstack.shrink(1);
            return EnumActionResult.SUCCESS;
        }
        else
        {
            return EnumActionResult.FAIL;
        }
    }
}

Заранее спасибо за уделённое внимание! Жду предложений решения вопроса :)
 
Решение
Возможно проблема в том, что ты спавнишь сущность в клиентском мире?
World.isRemote == true для клиентского мира, false для серверного.
Java:
if(worldIn.isRemote) {
    worldIn.spawnEntity(entityhanging);
    entityhanging.playPlaceSound();
}
Да, это так, попробовал убрать условие, сущность сохранилась. Но теперь она себя странно ведёт, спавнится дважды и одна из них сдвигается на один блок через пару секунд. Есть идеи, как исправить?
При условии if(!worldIn.isRemote) спавнится один раз, но всё равно сдвигается и, если сломать, после перезахода снова появляется..
 
154
17
96
Остается она скорее всего потому, что у тебя в методе attackEntityFrom(DamageSource source, float amount) стоит та же проверка.
Лучше тебе вообще его не переопределять, а ту логику, которая должна быть после разрушения сущности, реализовать в методе onBroken(Entity brokenEntity)
 
Отлично, с созданием/ломанием всё исправил, но осталось странное поведение. Я спавню сущность, по идее она должна висеть как картинка или рамка, а она так секунды 2-3 повисит, а потом съезжает на блок. Иногда начинает дёргаться. Когда на клиенте спавнил такой проблемы не было, есть идеи?
 
Сверху