我添加了一个投掷物,可以投掷出去且有效果,但是不显示材质。


版本信息
你使用的系统:Windows 10,64位系统
你是用的JDK:1.8.0_162 ,64位
你使用的IDE:IntelliJ IDEA
你使用的IDE版本:2019.3.2.0
Forge版本: forge-31.1.0
Minecraft版本:1.15.2

出错图

错误情况简述
我之前按照教程,尝试添加了一个投掷物的实体,并且确定弄好了材质,但是我在游戏中测试的时候,发现该物品可以进行投掷,并且会产生效果,但是投掷出去变成实体后,却看不到材质了,我也不知道应该如何解决。(说明:原版投掷物可正常显示材质)

相关代码
实体主文件:GasolineCan.java

package com.specialitem.specialitem.entity.GasolineCan;

import com.specialitem.specialitem.items.ModItems;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.monster.BlazeEntity;
import net.minecraft.entity.projectile.ProjectileItemEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.particles.IParticleData;
import net.minecraft.particles.ItemParticleData;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.util.DamageSource;
import net.minecraft.util.math.EntityRayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.Explosion;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

public class ThrownGasolineCan extends ProjectileItemEntity {

    public ThrownGasolineCan(World worldIn, LivingEntity throwerIn) {
        super(GasolineCanHelper.THROWN_GASOLINE_CAN, throwerIn, worldIn);
    }

    public ThrownGasolineCan(World world) {
        super(GasolineCanHelper.THROWN_GASOLINE_CAN, world);
    }

    public Item func_213885_i() {
        return ModItems.gasolineCan;
    }

    @Override
    public void tick() {
        if (this.world.isRemote  && this.isAlive()) {
            for(int i = 0; i < 2; ++i) {
                this.world.addParticle(ParticleTypes.FLAME,
                        this.func_226282_d_(0.5D),
                        this.func_226279_cv_() - 0.25D,
                        this.func_226287_g_(0.5D),
                        (this.rand.nextDouble() - 0.5D) * 2.0D,
                        -this.rand.nextDouble(),
                        (this.rand.nextDouble() - 0.5D) * 2.0D);
            }

        }
        super.tick();
    }

    @OnlyIn(Dist.CLIENT)
    private IParticleData func_213887_n() {
        ItemStack itemstack = this.func_213882_k();
        return itemstack.isEmpty() ? ParticleTypes.FLAME : new ItemParticleData(ParticleTypes.ITEM, itemstack);
    }

    @OnlyIn(Dist.CLIENT)
    public void handleStatusUpdate(byte id) {
        if (id == 3) {
            IParticleData iparticledata = this.func_213887_n();

            for(int i = 0; i < 8; ++i) {
                this.world.addParticle(iparticledata, this.func_226277_ct_(), this.func_226278_cu_(), this.func_226281_cx_(), 0.0D, 0.0D, 0.0D);
            }
        }

    }

    protected void onImpact(RayTraceResult result) {
        if (result.getType() == RayTraceResult.Type.ENTITY) {
            Entity entity = ((EntityRayTraceResult)result).getEntity();
            int i = entity instanceof BlazeEntity ? 3 : 0;
            entity.attackEntityFrom(DamageSource.netherBedExplosion(), (float)i);
            entity.world.createExplosion(null,DamageSource.netherBedExplosion(),
                    entity.getPosition().getX(),entity.getPosition().getY(),entity.getPosition().getZ(),
                    3.0F,true, Explosion.Mode.NONE);
        }

        if (!this.world.isRemote) {
            world.createExplosion(null,DamageSource.netherBedExplosion(),
                    getPosition().getX(),getPosition().getY(),getPosition().getZ(),
                    3.0F,true, Explosion.Mode.NONE);
            this.world.setEntityState(this, (byte)3);
            this.remove();
        }

    }

}

实体渲染文件:GasolineCanRenderer.java

package com.specialitem.specialitem.entity.GasolineCan;

import com.specialitem.specialitem.SpecialItem;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererManager;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

@OnlyIn(Dist.CLIENT)
public class GasolineCanRenderer extends EntityRenderer<ThrownGasolineCan> {
    private static final ResourceLocation TEXTURES = new ResourceLocation(SpecialItem.MODID,"textures/entity/thrown_gasoline_can.png");

    public GasolineCanRenderer(EntityRendererManager renderManager) {
        super(renderManager);
    }

    @Override
    public ResourceLocation getEntityTexture(ThrownGasolineCan entity) {
        return TEXTURES;
    }
}

RegistryHandler.java里的相关的注册信息:

        Event.getRegistry().register(EntityType.Builder.create((entityEntityType, world) -> new ThrownGasolineCan(world), EntityClassification.MISC)
                .size(0.5F, 0.5F)
                .build("thrown_gasoline_can")
                .setRegistryName(SpecialItem.MODID, "thrown_gasoline_can"));

随便一个原版投掷物的代码(这个是雪球的代码):

package net.minecraft.entity.projectile;

import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.monster.BlazeEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.particles.IParticleData;
import net.minecraft.particles.ItemParticleData;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.util.DamageSource;
import net.minecraft.util.math.EntityRayTraceResult;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;

public class SnowballEntity extends ProjectileItemEntity {
   public SnowballEntity(EntityType<? extends SnowballEntity> p_i50159_1_, World p_i50159_2_) {
      super(p_i50159_1_, p_i50159_2_);
   }

   public SnowballEntity(World worldIn, LivingEntity throwerIn) {
      super(EntityType.SNOWBALL, throwerIn, worldIn);
   }

   public SnowballEntity(World worldIn, double x, double y, double z) {
      super(EntityType.SNOWBALL, x, y, z, worldIn);
   }

   protected Item func_213885_i() {
      return Items.SNOWBALL;
   }

   @OnlyIn(Dist.CLIENT)
   private IParticleData func_213887_n() {
      ItemStack itemstack = this.func_213882_k();
      return (IParticleData)(itemstack.isEmpty() ? ParticleTypes.ITEM_SNOWBALL : new ItemParticleData(ParticleTypes.ITEM, itemstack));
   }

   /**
    * Handler for {@link World#setEntityState}
    */
   @OnlyIn(Dist.CLIENT)
   public void handleStatusUpdate(byte id) {
      if (id == 3) {
         IParticleData iparticledata = this.func_213887_n();

         for(int i = 0; i < 8; ++i) {
            this.world.addParticle(iparticledata, this.func_226277_ct_(), this.func_226278_cu_(), this.func_226281_cx_(), 0.0D, 0.0D, 0.0D);
         }
      }

   }

   /**
    * Called when this EntityThrowable hits a block or entity.
    */
   protected void onImpact(RayTraceResult result) {
      if (result.getType() == RayTraceResult.Type.ENTITY) {
         Entity entity = ((EntityRayTraceResult)result).getEntity();
         int i = entity instanceof BlazeEntity ? 3 : 0;
         entity.attackEntityFrom(DamageSource.causeThrownDamage(this, this.getThrower()), (float)i);
      }

      if (!this.world.isRemote) {
         this.world.setEntityState(this, (byte)3);
         this.remove();
      }

   }
}

FledgeXu


你的模型文件呢?



物品实体好像是不需要模型文件的。。



不是立体的实体好像不需要模型文件。


FledgeXu


没有显示材质就两种情况:

  1. 没有渲染模型
  2. 你只在服务端创建了实体,在客户端没有创建实体.


可以解释一下第二点吗?


FledgeXu


我看你在客户端试图调用addParticle生成火焰粒子效果,但是实际上你的图里面没有这个粒子效果.
你应该考虑一下你的实体有没有在客户端创建.
自己在Tick下断点调试一下,看见有没有在客户端执行,如果没有说明你的实体就没有在客户端创建.
https://neutrino.v2mcdev.com/introducation/vanilla.html


FledgeXu


而且你都创建EntityRenderer并没有渲染模型,那你相当于什么东西都没有渲染.


FledgeXu


而且你好像也没有写渲染绑定的代码,总之问题非常多.你还是先把基础的实体先弄清楚再说吧.
https://neutrino.v2mcdev.com/entity/scratchentity.html



应该不是模型的问题,对比了一下代码,材质是直接利用物品本身的材质,我翻看了一下原版的实体模型的目录,也没有有关于投掷物的模型,只有立体类实体的模型。估计是在客户端没有创建实体。此外,我添加生物的时候,生物是立体的实体,能够正常显示材质。


FledgeXu


确实,那你为什么要自定义Render呢?原版的鸡蛋雪球什么的直接用的是SpriteRenderer啊。
你可以看一下原版的EntityRendererManager这个类,原版的所有实体的Render都在这里注册。



我看了一下原版的EntityRendererManager.class这个类,发现里面的字段是private的,是不是要用AT来把它们修改成public啊?不然没办法用SpriteRenderer。

   private void func_229097_a_(net.minecraft.client.renderer.ItemRenderer p_229097_1_, IReloadableResourceManager p_229097_2_) {
      this.func_229087_a_(EntityType.AREA_EFFECT_CLOUD, new AreaEffectCloudRenderer(this));
      this.func_229087_a_(EntityType.ARMOR_STAND, new ArmorStandRenderer(this));
      this.func_229087_a_(EntityType.ARROW, new TippedArrowRenderer(this));
      this.func_229087_a_(EntityType.BAT, new BatRenderer(this));
      .....以下省略......
}

FledgeXu


public static void onClientSetUpEvent(FMLClientSetupEvent event) {
RenderingRegistry.registerEntityRenderingHandler(EntityTypeRegistry.flyingSwordEntity.get(), 
    (EntityRendererManager manager) -> {
        return new FlyingSwordRender(manager);
});
}

我的意思是,这里不是调用RenderingRegistry.registerEntityRenderingHandler注册嘛,你把EntityTypeRegistry.flyingSwordEntity.get()换成你自己的实体,把FlyingSwordRender换成SpriteRenderer



我照着你的方法改了,但是还是存在问题:


FledgeXu


我看了一下SpriteRenderer有两个构造参数,第一个参数就你填的没错,第二个参数我觉得你可以试试Minecraft.getInstance().getItemRenderer()
根据你写的,你写的实体也也是错的,应该是GasolinCanHelper.THROWN_GAOSOLINE_CAN.get()吧。
最后,以后代码不要发图片,请直接贴上来。



是这样子写的吗?

RenderingRegistry.registerEntityRenderingHandler(GasolineCanHelper.THROWN_GASOLINE_CAN.getClass(),(EntityRendererManager manager) -> new Minecraft.getInstance().getItemRenderer());

但如果这样子写的话,getInstance()部分会显示红色,并且会提示:
Cannot resolve symbol'getInstance()'
而且,在我输入Minecraft().之后,并没有显示getInstance()的选项:
Snipaste_2020-07-14_20-50-45
然而我去翻看Minecraft.java的时候,发现了如下的代码:

   public static Minecraft getInstance() {
      return instance;
   }

说明是可以用的。

还没完,输入Minecraft()后,括号里面还要填写"gameConfig",然而这个"gameConfig"又要牵涉到一大堆的东西。。。

public Minecraft(GameConfiguration gameConfig) {
.....省略一大堆代码.....
}

所以,我是不是有什么地方搞错了?


FledgeXu


……Minecraft类你new它干嘛,getInstance写的很清楚了啊,这是个静态方法。
请先好好学编程吧,不要通过写mod来学编程。


kabuki_


另外在创建实体类并注册时,有几个刷新率的参数(记得专业名词叫Tracking?)会影响到实体是否会显示,即使没有材质的抛射物也会显示一个相应大小的白色六方体


FledgeXu


我不知道你在说什么……


system


该主题在最后一个回复创建后7天后自动关闭。不再允许新的回复。