Jump to content

Recommended Posts

Posted

 

Alright, so I'll admit I'm a fairly new modder, but I know enough about coding to get the gist of everything. Let me be very clear- I know the basics of coding, and everything else is working fine just far, other than this problem that I just can't get my head around.

 

I can't get my custom mob to render its held item for the life of me. He is supposed to be holding a custom sword, but I can't figure out whatsoever why it won't render.

Here's the RenderClass for the mob in question:

package sonicrainbowdash.fallenstars.mobs.renders;

import net.minecraft.client.model.ModelBase;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.entity.RenderLiving;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.entity.layers.LayerHeldItem;
import net.minecraft.util.ResourceLocation;
import sonicrainbowdash.fallenstars.Reference;
import sonicrainbowdash.fallenstars.mobs.entities.EntityAnarcus;

public class RenderAnarcus extends RenderLiving<EntityAnarcus>
{
    public RenderAnarcus(RenderManager renderManager, ModelBase modelBase, float shadowSize)
    {
        super(renderManager, modelBase, shadowSize);
        this.addLayer(new LayerHeldItem(this));
    }

    private static final ResourceLocation ANARCUS_TEXTURE = new ResourceLocation(Reference.MOD_ID, "textures/entity/anarcus/anarcus_normal.png");

    @Override
    protected ResourceLocation getEntityTexture(EntityAnarcus entity)
    {
        return ANARCUS_TEXTURE;
    }

    protected void preRenderCallback(EntityAnarcus entitylivingbaseIn, float partialTickTime)
    {
        super.preRenderCallback(entitylivingbaseIn, partialTickTime);
        GlStateManager.scale(0.9365F, 0.9365F, 0.9365F);
    }
}

 

I've gone to check and review other mobs' Render Classes, and I've found the this.addLayer line of code for LayerHeldItem, but I still can't get it to work for the life of me.

 

Any help would be appreciated. I'm modding in 1.10.2, and can provide any additional information that's needed.

Posted
On 3/1/2017 at 0:27 AM, Animefan8888 said:

Where did you register the renderer?

If you mean the renderer for the mob, it's registered in the mob registry class, which the entirety of the registry is from the client proxy.

I also apologize for the late response.

Posted (edited)
On 3/3/2017 at 2:39 AM, diesieben07 said:

Please post that code and your entity class.

Here's the Mob Registry:

public class MobRegistry
{
    public static void register()
    {
        MobRegistry.registerRender();
        MobRegistry.registerEntity();
    }

    @SideOnly(Side.CLIENT)
    public static void registerRender()
    {
        RenderingRegistry.registerEntityRenderingHandler(EntityAnarcus.class, new RenderAnarcus(Minecraft.getMinecraft().getRenderManager(), new ModelAnarcus(), 0.5F));
    }

    public static void registerEntity()
    {
        EntityRegistry.registerModEntity(EntityAnarcus.class, "anarcus", 502, FallenStars.instance, 64, 1, true, 0x8458ad, 0x58ad58);
        EntityRegistry.addSpawn(EntityAnarcus.class, 1, 1, 1, EnumCreatureType.CREATURE, BiomeDictionary.getBiomesForType(BiomeDictionary.Type.PLAINS));
    }
}

Here's the Entity (which is mostly based off of the EntityPigZombie, minus a few things here and there):

public class EntityAnarcus extends EntityMob
{
    protected Block spawnableBlock = FallenStarsBlocks.astralgrass;
    private static final UUID ATTACK_SPEED_BOOST_MODIFIER_UUID = UUID.fromString("49455A49-7EC5-45BA-B886-3B90B23A1718");
    private final EntityAIBreakDoor breakDoor = new EntityAIBreakDoor(this);
    private boolean isBreakDoorsTaskSet;
    private static final AttributeModifier ATTACK_SPEED_BOOST_MODIFIER = (new AttributeModifier(ATTACK_SPEED_BOOST_MODIFIER_UUID, "Attacking speed boost", 0.05D, 0)).setSaved(false);
    /** The width of the entity */
    private float anarcusWidth = -1.0F;
    /** The height of the the entity. */
    private float anarcusHeight;
    /**
     * Above zero if this Anarcus is Angry.
     */
    private int angerLevel;
    /**
     * A random delay until this Anarcus next makes a sound.
     */
//    private int randomSoundDelay;
    private UUID angerTargetUUID;
 
    public EntityAnarcus(World worldIn)
    {
        super(worldIn);
        this.setSize(0.6F, 1.7775F);
        this.setHealth(this.getMaxHealth());
    }
 
    protected void initEntityAI()
    {
        this.tasks.addTask(0, new EntityAISwimming(this));
        this.tasks.addTask(2, new EntityAIAttackMelee(this, 1.0F, true));
        this.tasks.addTask(5, new EntityAIMoveTowardsRestriction(this, 1.0D));
        this.tasks.addTask(7, new EntityAIWander(this, 1.0D));
        this.tasks.addTask(8, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
        this.tasks.addTask(8, new EntityAILookIdle(this));
        this.applyEntityAI();
    }
 
    public void setRevengeTarget(@Nullable EntityLivingBase livingBase)
    {
        super.setRevengeTarget(livingBase);
 
        if (livingBase != null)
        {
            this.angerTargetUUID = livingBase.getUniqueID();
        }
    }
 
    protected void applyEntityAI()
    {
        this.targetTasks.addTask(1, new EntityAnarcus.AIHurtByAggressor(this));
        this.targetTasks.addTask(2, new EntityAnarcus.AITargetAggressor(this));
        this.tasks.addTask(6, new EntityAIMoveThroughVillage(this, 1.0D, false));
        this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true, new Class[] {EntityAnarcus.class}));
        this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityVillager.class, false));
    }
 
    protected void applyEntityAttributes()
    {
        super.applyEntityAttributes();
        this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(500.0D);
        this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.3D);
        this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(10.0D);
        this.getEntityAttribute(SharedMonsterAttributes.ARMOR).setBaseValue(40.0D);
        this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(500.0D);
    }
 
    protected void entityInit()
    {
        super.entityInit();
    }
 
    public boolean isBreakDoorsTaskSet()
    {
        return this.isBreakDoorsTaskSet;
    }
 
    /**
     * Sets or removes EntityAIBreakDoor task
     */
    public void setBreakDoorsAItask(boolean enabled)
    {
        if (this.isBreakDoorsTaskSet != enabled)
        {
            this.isBreakDoorsTaskSet = enabled;
            ((PathNavigateGround)this.getNavigator()).setBreakDoors(enabled);
 
            if (enabled)
            {
                this.tasks.addTask(1, this.breakDoor);
            }
            else
            {
                this.tasks.removeTask(this.breakDoor);
            }
        }
    }
 
    /**
     * Get the experience points the entity currently has.
     */
    protected int getExperiencePoints(EntityPlayer player)
    {
        return super.getExperiencePoints(player);
    }
 
    public EnumCreatureAttribute getCreatureAttribute()
    {
        return EnumCreatureAttribute.UNDEFINED;
    }
 
    /**
     * Called to update the entity's position/logic.
     */
    public void onUpdate()
    {
        super.onUpdate();
    }
 
    protected void updateAITasks()
    {
        IAttributeInstance iattributeinstance = this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED);
 
        if (this.isAngry())
        {
            if (!iattributeinstance.hasModifier(ATTACK_SPEED_BOOST_MODIFIER))
            {
                iattributeinstance.applyModifier(ATTACK_SPEED_BOOST_MODIFIER);
            }
 
            --this.angerLevel;
        } else if (iattributeinstance.hasModifier(ATTACK_SPEED_BOOST_MODIFIER))
        {
            iattributeinstance.removeModifier(ATTACK_SPEED_BOOST_MODIFIER);
        }
 
//        if (this.randomSoundDelay > 0 && --this.randomSoundDelay == 0)
//        {
//            this.playSound(SoundEvents.ENTITY_ZOMBIE_PIG_ANGRY, this.getSoundVolume() * 2.0F, ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F) * 1.8F);
//        }
 
        if (this.angerLevel > 0 && this.angerTargetUUID != null && this.getAITarget() == null)
        {
            EntityPlayer entityplayer = this.worldObj.getPlayerEntityByUUID(this.angerTargetUUID);
            this.setRevengeTarget(entityplayer);
            this.attackingPlayer = entityplayer;
            this.recentlyHit = this.getRevengeTimer();
        }
 
        super.updateAITasks();
    }
 
    /**
     * Checks if the entity's current position is a valid location to spawn this entity.
     */
    public boolean getCanSpawnHere()
    {
        int i = MathHelper.floor_double(this.posX);
        int j = MathHelper.floor_double(this.getEntityBoundingBox().minY);
        int k = MathHelper.floor_double(this.posZ);
        BlockPos blockpos = new BlockPos(i, j, k);
        return this.worldObj.getBlockState(blockpos.down()).getBlock() == this.spawnableBlock && this.worldObj.getLight(blockpos) > 1 && super.getCanSpawnHere();
    }
 
    /**
     * Checks that the entity is not colliding with any blocks / liquids
     */
    public boolean isNotColliding()
    {
        return this.worldObj.checkNoEntityCollision(this.getEntityBoundingBox(), this) && this.worldObj.getCollisionBoxes(this, this.getEntityBoundingBox()).isEmpty() && !this.worldObj.containsAnyLiquid(this.getEntityBoundingBox());
    }
 
    /**
     * (abstract) Protected helper method to write subclass entity data to NBT.
     */
    public void writeEntityToNBT(NBTTagCompound compound)
    {
        super.writeEntityToNBT(compound);
        compound.setBoolean("CanBreakDoors", this.isBreakDoorsTaskSet());
        compound.setShort("Anger", (short) this.angerLevel);
 
        if (this.angerTargetUUID != null)
        {
            compound.setString("HurtBy", this.angerTargetUUID.toString());
        } else
        {
            compound.setString("HurtBy", "");
        }
    }
 
    public float getEyeHeight()
    {
        float f = 1.6F;
 
        return f;
    }
 
    /**
     * (abstract) Protected helper method to read subclass entity data from NBT.
     */
    public void readEntityFromNBT(NBTTagCompound compound)
    {
        super.readEntityFromNBT(compound);
        this.angerLevel = compound.getShort("Anger");
        String s = compound.getString("HurtBy");
 
        if (!s.isEmpty())
        {
            this.angerTargetUUID = UUID.fromString(s);
            EntityPlayer entityplayer = this.worldObj.getPlayerEntityByUUID(this.angerTargetUUID);
            this.setRevengeTarget(entityplayer);
 
            if (entityplayer != null)
            {
                this.attackingPlayer = entityplayer;
                this.recentlyHit = this.getRevengeTimer();
            }
        }
    }
 
    /**
     * Called when the entity is attacked.
     */
    public boolean attackEntityFrom(DamageSource source, float amount)
    {
        if (this.isEntityInvulnerable(source))
        {
            return false;
        } else
        {
            Entity entity = source.getEntity();
 
            if (entity instanceof EntityPlayer)
            {
                this.becomeAngryAt(entity);
            }
 
            return super.attackEntityFrom(source, amount);
        }
    }
 
    /**
     * Causes this PigZombie to become angry at the supplied Entity (which will be a player).
     */
    private void becomeAngryAt(Entity p_70835_1_)
    {
        this.angerLevel = 400 + this.rand.nextInt(400);
//        this.randomSoundDelay = this.rand.nextInt(40);
 
        if (p_70835_1_ instanceof EntityLivingBase)
        {
            this.setRevengeTarget((EntityLivingBase) p_70835_1_);
        }
    }
 
    public boolean isAngry()
    {
        return this.angerLevel > 0;
    }
 
//    protected SoundEvent getAmbientSound()
//    {
//        return SoundEvents.ENTITY_ZOMBIE_PIG_AMBIENT;
//    }
//
//    protected SoundEvent getHurtSound()
//    {
//        return SoundEvents.ENTITY_ZOMBIE_PIG_HURT;
//    }
//
//    protected SoundEvent getDeathSound()
//    {
//        return SoundEvents.ENTITY_ZOMBIE_PIG_DEATH;
//    }
 
    @Nullable
    protected ResourceLocation getLootTable()
    {
        return LootTableRegistry.ANARCUS;
    }
 
    public boolean processInteract(EntityPlayer player, EnumHand hand, @Nullable ItemStack stack)
    {
        return false;
    }
 
    /**
     * Gives armor or weapon for entity based on given DifficultyInstance
     */
    protected void setEquipmentBasedOnDifficulty(DifficultyInstance difficulty)
    {
        this.setItemStackToSlot(EntityEquipmentSlot.OFFHAND, new ItemStack(FallenStarsItems.darksword));
    }
 
    /**
     * Called only once on an entity when first time spawned, via egg, mob spawner, natural spawning etc, but not called
     * when entity is reloaded from nbt. Mainly used for initializing attributes and inventory
     */
    @Nullable
    public IEntityLivingData onInitialSpawn(DifficultyInstance difficulty, @Nullable IEntityLivingData livingdata)
    {
        livingdata = super.onInitialSpawn(difficulty, livingdata);
        float f = difficulty.getClampedAdditionalDifficulty();
        this.setCanPickUpLoot(this.rand.nextFloat() < 0.55F * f);
 
        this.setBreakDoorsAItask(this.rand.nextFloat() < f * 0.1F);
 
        this.getEntityAttribute(SharedMonsterAttributes.KNOCKBACK_RESISTANCE).applyModifier(new AttributeModifier("Random spawn bonus", this.rand.nextDouble() * 0.05000000074505806D, 0));
        double d0 = this.rand.nextDouble() * 1.5D * (double)f;
 
        if (d0 > 1.0D)
        {
            this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).applyModifier(new AttributeModifier("Random zombie-spawn bonus", d0, 2));
        }
 
        if (this.rand.nextFloat() < f * 0.05F)
        {
            this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).applyModifier(new AttributeModifier("Leader zombie bonus", this.rand.nextDouble() * 3.0D + 1.0D, 2));
            this.setBreakDoorsAItask(true);
        }
 
        return livingdata;
    }
 
    protected boolean canDespawn()
    {
        return true;
    }
 
    /**
     * Sets the width and height of the entity.
     */
    protected final void setSize(float width, float height)
    {
        boolean flag = this.anarcusWidth > 0.0F && this.anarcusHeight > 0.0F;
        this.anarcusWidth = width;
        this.anarcusHeight = height;
 
        if (!flag)
        {
            this.multiplySize(1.0F);
        }
    }
 
    /**
     * Multiplies the height and width by the provided float.
     */
    protected final void multiplySize(float size)
    {
        super.setSize(this.anarcusWidth * size, this.anarcusHeight * size);
    }
 
    /**
     * Returns the Y Offset of this entity.
     */
    public double getYOffset()
    {
        return this.isChild() ? 0.0D : -0.35D;
    }
 
    /**
     * Called when the mob's health reaches 0.
     */
    public void onDeath(DamageSource cause)
    {
        super.onDeath(cause);
    }
 
    static class AIHurtByAggressor extends EntityAIHurtByTarget
    {
        public AIHurtByAggressor(EntityAnarcus p_i45828_1_)
        {
            super(p_i45828_1_, true, new Class[0]);
        }
 
        protected void setEntityAttackTarget(EntityCreature creatureIn, EntityLivingBase entityLivingBaseIn)
        {
            super.setEntityAttackTarget(creatureIn, entityLivingBaseIn);
 
            if (creatureIn instanceof EntityAnarcus)
            {
                ((EntityAnarcus) creatureIn).becomeAngryAt(entityLivingBaseIn);
            }
        }
    }
 
    static class AITargetAggressor extends EntityAINearestAttackableTarget<EntityPlayer>
    {
        public AITargetAggressor(EntityAnarcus p_i45829_1_)
        {
            super(p_i45829_1_, EntityPlayer.class, true);
        }
 
        /**
         * Returns whether the EntityAIBase should begin execution.
         */
        public boolean shouldExecute()
        {
            return ((EntityAnarcus) this.taskOwner).isAngry() && super.shouldExecute();
        }
    }
}

And I was unsure whether you wanted the entity itself or the render for said entity, so here's the latter just in case. This is where I made the attempt to show the held item, like how I've seen for RenderPigZombie or RenderSkeleton for LayerHeldItem.

public class RenderAnarcus extends RenderLiving<EntityAnarcus>
{
    public RenderAnarcus(RenderManager renderManager, ModelBase modelBase, float shadowSize)
    {
        super(renderManager, modelBase, shadowSize);
        this.addLayer(new LayerHeldItem(this));
    }

    private static final ResourceLocation ANARCUS_TEXTURE = new ResourceLocation(Reference.MOD_ID, "textures/entity/anarcus/anarcus_normal.png");

    @Override
    protected ResourceLocation getEntityTexture(EntityAnarcus entity)
    {
        return ANARCUS_TEXTURE;
    }

    protected void preRenderCallback(EntityAnarcus entitylivingbaseIn, float partialTickTime)
    {
        super.preRenderCallback(entitylivingbaseIn, partialTickTime);
        GlStateManager.scale(0.9365F, 0.9365F, 0.9365F);
    }
}

 

Edited by WrilyCoyoteGabe
Posted (edited)
3 hours ago, diesieben07 said:

The version of registerEntityRenderingHandler you are using is deprecated. Stop using it.

Alright, I'm trying to use the non-deprecated version of it, but I can't quite seem to figure it out entirely. How would one go about implementing this version instead? I apologize if I sound a bit inexperienced, I've just never used this version of it until now.

 

**EDIT** So I think I figured out how to use the non-deprecated version of the Handler, but I'm not sure if I did it correctly.

Considering my mob now looks like this, I get the strange feeling I might have done something wrong, because that really isn't what he looked like before.

Here's the new code, and it'd be appreciated if you could help me spot the issue.

RenderingRegistry.registerEntityRenderingHandler(EntityAnarcus.class, new IRenderFactory<EntityAnarcus>()
        {
            @Override
            public Render<? super EntityAnarcus> createRenderFor(RenderManager manager)
            {
                return new RenderAnarcus(manager, new ModelAnarcus(), 0.5F);
            }
        });

 

Edited by WrilyCoyoteGabe
Posted (edited)
On 3/5/2017 at 0:05 PM, diesieben07 said:

That code is correct, are you calling it in preInit?

 

Thank you- that was in fact the problem! The model is now rendering just fine with the non-deprecated version. However, I am still having the issue of the item that the mob is holding not rendering in the mob's hand. Can you see where that issue may be being caused?

 

I used the LayerHeldItem as mentioned before, but I'm unsure as to what else would be missing.

Edited by WrilyCoyoteGabe

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.