Minecraft Forge 1.7.10 自定义实体未在客户端生成?

Minecraft Forge 1.7.10 Custom Entity Not Spawning On The Client?

在我的 Minecraft Forge mod 1.7.10 中。我知道这个版本可以说是老新闻了,但它是我最喜欢的版本,我 mod 的所有 体验都是这个版本。

我正在创建自定义 TNT 块。问题是 prime 版本没有渲染。点燃后,TNT 消失,不久后发生爆炸。如果 TNT 被放置在空中,爆炸就会在下面,就像它应该是由于引爆的 TNT 掉落一样。问题是它没有渲染。当我使用fn+f3+b显示hitboxes时,没有显示hitboxes.

问题是在 服务器 上生成的实体不会复制到 客户端 。我知道这个是因为:

BlockTNT class(其中大部分源自原始代码,但已设计为在实例化时采用相应的自定义引物 TNT 实体 class,问题不在于在这里是因为实例化默认 EntityTNTPrimed 而不是提供的 primed class 确实可以正确呈现,但我将其包括在内是因为此代码有助于证明问题的根源):

class BlockTNT extends net.minecraft.block.BlockTNT {
    private final Class primed;
    public BlockTNT(final Class primed) {
        this.primed = primed;
        stepSound = net.minecraft.block.Block.soundTypeGrass;
    }
    protected EntityTNTPrimed getPrimed(final World world, final int x, final int y, final int z, final EntityLivingBase igniter) {
        try {
            return (EntityTNTPrimed)primed.getDeclaredConstructor(World.class, double.class, double.class, double.class, EntityLivingBase.class).newInstance(world, (double)((float)x+0.5F), (double)((float)y+0.5F), (double)((float)z+0.5F), igniter);
        } catch (Exception exception) {
            return null;
        }
    }
    @Override public void onBlockDestroyedByExplosion(final World world, final int x, final int y, final int z, final Explosion explosion) {
        if(world.isRemote)
            return;
        final EntityTNTPrimed tnt = getPrimed(world, x, y, z, explosion.getExplosivePlacedBy());
        tnt.fuse = world.rand.nextInt(tnt.fuse>>2)+(tnt.fuse>>3);
        world.spawnEntityInWorld(tnt);
    }
    @Override public void func_150114_a(final World world, final int x, final int y, final int z, final int meta, final EntityLivingBase igniter) {
        if(world.isRemote || (meta&1) == 0)
            return;
        final EntityTNTPrimed tnt = getPrimed(world, x, y, z, igniter);
        world.spawnEntityInWorld(tnt);
        world.playSoundAtEntity(tnt, "game.tnt.primed", 1.0F, 1.0F);
    }
}

在主要 mod class 中,我注册了实体:

@Instance public static ExampleMod instance;
@SidedProxy(clientSide="com.examplemod.ClientProxy", serverSide="com.examplemod.CommonProxy") public static com.examplemod.CommonProxy proxy;
private static void registerTnt(final Class primed, String name, final int id) {
    proxy.registerTntRenderer(primed, registerBlock(new BlockTNT(primed), name.toLowerCase()+"_tnt"));
    EntityRegistry.registerGlobalEntityID(primed, name = "PrimedTnt"+name, EntityRegistry.findGlobalUniqueEntityId());
    EntityRegistry.registerModEntity(primed, name, id, instance, 160, 10, true);
}
@EventHandler public void init(FMLInitializationEvent event) {
    registerTnt(com.examplemod.TNTPrimedCharged.class, "Charged", 0);
    // ...
}

然后我们在客户端代理中注册渲染器(再次测试并有效):

@Override public void registerTntRenderer(final Class primed, final Block block) {
    RenderingRegistry.registerEntityRenderingHandler(primed, new com.examplemod.RenderTNTPrimed(block));
}

这里是自定义实体的 class:

public abstract class TNTPrimed extends net.minecraft.entity.item.EntityTNTPrimed {
    public TNTPrimed(final World world, final double x, final double y, final double z, final EntityLivingBase igniter) {
        super(world, x, y, z, igniter);
    }
    public TNTPrimed(final World world) {
        super(world);
    }
    @Override public void onUpdate() {
        prevPosX = posX;
        prevPosY = posY;
        prevPosZ = posZ;
        moveEntity(motionX, motionY -= 0.04D, motionZ);
        motionX *= 0.98D;
        motionY *= 0.98D;
        motionZ *= 0.98D;
        if(onGround) {
            motionX *= 0.7D;
            motionZ *= 0.7D;
            motionY *= -0.5D;
        }
        if(fuse-- <= 0) {
            setDead();
            if(!worldObj.isRemote)
                explode();
        } else
            worldObj.spawnParticle("smoke", posX, posY+0.5D, posZ, 0.0D, 0.0D, 0.0D);
    }
    protected abstract void explode();
}
public class TNTPrimedCharged extends com.examplemod.TNTPrimed {
    public TNTPrimedCharged(final World world, final double x, final double y, final double z, final EntityLivingBase igniter) {
        super(world, x, y, z, igniter);
    }
    public TNTPrimedCharged(final World world) {
        super(world);
    }
    @Override protected void explode() {
        worldObj.newExplosion(this, posX, posY, posZ, 8, false, true);
    }
}

虽然我可以断然声明自定义实体渲染器class 不是罪魁祸首,但我提供它以供参考:

class RenderTNTPrimed extends net.minecraft.client.renderer.entity.RenderTNTPrimed {
    private final RenderBlocks renderer = new RenderBlocks();
    private final Block block;
    public RenderTNTPrimed(final Block block) {
        super();
        this.block = block;
    }
    @Override public void doRender(final EntityTNTPrimed entity, final double x, final double y, final double z, final float yaw, final float tick) {
        GL11.glPushMatrix();
        GL11.glTranslatef((float)x, (float)y, (float)z);
        float var0 = entity.fuse-tick+1.0F;
        if (var0 < 10.0F) {
            final float scale = (float)Math.pow(Math.max(Math.min(1-var0/10, 1.0F), 0.0F), 4.0F)*0.3F+1.0F;
            GL11.glScalef(scale, scale, scale);
        }
        bindEntityTexture(entity);
        renderer.renderBlockAsItem(block, 0, entity.getBrightness(tick));
        if (((entity.fuse/5)&1) == 0) {
            GL11.glDisable(GL11.GL_TEXTURE_2D);
            GL11.glDisable(GL11.GL_LIGHTING);
            GL11.glEnable(GL11.GL_BLEND);
            GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_DST_ALPHA);
            GL11.glColor4f(1.0F, 1.0F, 1.0F, (1.0F-var0/100.0F)*0.8F);
            renderer.renderBlockAsItem(block, 0, 1.0F);
            GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
            GL11.glDisable(GL11.GL_BLEND);
            GL11.glEnable(GL11.GL_LIGHTING);
            GL11.glEnable(GL11.GL_TEXTURE_2D);
        }
        GL11.glPopMatrix();
    }
}

所以当服务器在我的 自定义实体 上调用 world.spawnEntityInWorld() 时,为什么它无法在 客户端 上生成它作为出色地?我该如何解决这个问题,因为 TNT 在被点燃时就消失了是不受欢迎的,我不知道还能尝试什么。我怎样才能让自定义的 TNT 出现在 客户端?

对其他类似的 mod 进行逆向工程(特别是 TNT 太多 mod),他们的 TNT 启动实体在使用 /summon 时成功渲染,并且他们会检查客户端在他们的 TNT 区块 classes 中。经过调查,我不知道他们做了什么不同的事情会导致他们的实体呈现而不是我的。

我花了几个小时研究这个问题,但没有结果,并且鉴于在这次编辑中这个问题是谷歌基本搜索词的第二个命中,如 'Minecraft Forge 1.7.10 Entity Not Rendering' 和第三个对于'Minecraft Forge 1.7.10 Entity Invisible,',很可能进一步的研究是徒劳的。

问题很简单,当我的 mod 添加的实体 在服务器线程上生成时,它并没有在客户端线程上生成,即使它应该是。我该如何解决?我什么都试过了。

原来问题实际上不是实体没有在客户端生成。问题是 fuse 属性 在客户端上被设置为 0,即使它在服务器上被设置为 80。因此,客户端 TNT 立即 setDead() 自身。实施 cpw.mods.fml.common.registry.IEntityAdditionalSpawnData 然后将保险丝 属性 设置为 readSpawnData 中的正确值似乎已经解决了问题。