Jump to content

Custom Mob that Picks up Blocks like Endermen [Solved]


SilasOtoko

Recommended Posts

I'm working on making my custom mob pick up and place blocks just like endermen. I thought that I had all the parts that I needed to make this work, but I am not seeing the mob carry the blocks around. I see random blocks disappear near my mob and later possibly get placed, but it's hard to tell because I don't see my mob pick them up or carry them around or place them. Anyone have an idea of what I may have wrong or am missing?

 

Entity:

 

public class EntityForestWalker extends EntityMob {

private int attackTimer;

    private int homeCheckTimer = 0;

    public static boolean[] carriableBlocks = new boolean[257];

 

public EntityForestWalker(World par1World){

super(par1World);

        this.setSize(1.4F, 2.9F);

        this.getNavigator().setAvoidsWater(true);

        this.tasks.addTask(1, new EntityAIAttackOnCollide(this, 1.0D, true));

        this.tasks.addTask(2, new EntityAIMoveTowardsTarget(this, 0.9D, 32.0F));

        this.tasks.addTask(4, new EntityAIMoveTowardsRestriction(this, 1.0D));

        this.tasks.addTask(6, new EntityAIWander(this, 0.6D));

        this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));

        this.tasks.addTask(8, new EntityAILookIdle(this));

        this.targetTasks.addTask(2, new EntityAIHurtByTarget(this, false));

        this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityLiving.class, 0, false, true, IMob.mobSelector));

}

 

    protected void entityInit()

    {

        super.entityInit();

            this.dataWatcher.addObject(16, new Byte((byte)0));

            this.dataWatcher.addObject(17, new Byte((byte)0));

    }

   

    /**

    * (abstract) Protected helper method to write subclass entity data to NBT.

    */

    public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)

    {

        super.writeEntityToNBT(par1NBTTagCompound);

        par1NBTTagCompound.setShort("carried", (short)this.getCarried());

        par1NBTTagCompound.setShort("carriedData", (short)this.getCarryingData());

    }

 

    /**

    * (abstract) Protected helper method to read subclass entity data from NBT.

    */

    public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)

    {

        super.readEntityFromNBT(par1NBTTagCompound);

        this.setCarried(par1NBTTagCompound.getShort("carried"));

        this.setCarryingData(par1NBTTagCompound.getShort("carriedData"));

    }

 

    /**

    * Returns true if the newer Entity AI code should be run

    */

    public boolean isAIEnabled()

    {

        return true;

    }

 

    /**

    * main AI tick function, replaces updateEntityActionState

    */

    protected void updateAITick()

    {

        super.updateAITick();

    }

 

    @Override

    protected void applyEntityAttributes()

    {

    super.applyEntityAttributes();

    this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setAttribute(100.0D);

    this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setAttribute(0.25D); //Recomended speed

    //this.getEntityAttribute(SharedMonsterAttributes.attackDamage).setAttribute(15D);

  // this.getEntityAttribute(SharedMonsterAttributes.followRange).setAttribute(20D);

    }

 

    /**

    * Decrements the entity's air supply when underwater

    */

    protected int decreaseAirSupply(int par1)

    {

        return par1;

    }

 

    protected void collideWithEntity(Entity par1Entity)

    {

        if (par1Entity instanceof IMob && !(par1Entity instanceof EntityForestWalker) && !(par1Entity instanceof EntityCreeper) && this.getRNG().nextInt(20) == 0)

        {

            this.setAttackTarget((EntityLiving)par1Entity);

        }

 

        super.collideWithEntity(par1Entity);

    }

 

    /**

    * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons

    * use this to react to sunlight and start to burn.

    */

    public void onLivingUpdate()

    {

       

 

        if (this.attackTimer > 0)

        {

            --this.attackTimer;

        }

 

        if (this.motionX * this.motionX + this.motionZ * this.motionZ > 2.500000277905201E-7D && this.rand.nextInt(5) == 0)

        {

            int i = MathHelper.floor_double(this.posX);

            int j = MathHelper.floor_double(this.posY - 0.20000000298023224D - (double)this.yOffset);

            int k = MathHelper.floor_double(this.posZ);

            int l = this.worldObj.getBlockId(i, j, k);

 

            if (l > 0)

            {

                this.worldObj.spawnParticle("tilecrack_" + l + "_" + this.worldObj.getBlockMetadata(i, j, k), this.posX + ((double)this.rand.nextFloat() - 0.5D) * (double)this.width, this.boundingBox.minY + 0.1D, this.posZ + ((double)this.rand.nextFloat() - 0.5D) * (double)this.width, 4.0D * ((double)this.rand.nextFloat() - 0.5D), 0.5D, ((double)this.rand.nextFloat() - 0.5D) * 4.0D);

            }

        }

        int i;

 

        if (!this.worldObj.isRemote && this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing"))

        {

            int j;

            int k;

            int l;

 

            if (this.getCarried() == 0)

            {

                if (this.rand.nextInt(20) == 0)

                {

                    i = MathHelper.floor_double(this.posX - 2.0D + this.rand.nextDouble() * 4.0D);

                    j = MathHelper.floor_double(this.posY + this.rand.nextDouble() * 3.0D);

                    k = MathHelper.floor_double(this.posZ - 2.0D + this.rand.nextDouble() * 4.0D);

                    l = this.worldObj.getBlockId(i, j, k);

 

                    if (carriableBlocks[l])

                    {

                        this.setCarried(this.worldObj.getBlockId(i, j, k));

                        this.setCarryingData(this.worldObj.getBlockMetadata(i, j, k));

                        this.worldObj.setBlock(i, j, k, 0);

                    }

                }

            }

            else if (this.rand.nextInt(2000) == 0)

            {

                i = MathHelper.floor_double(this.posX - 1.0D + this.rand.nextDouble() * 2.0D);

                j = MathHelper.floor_double(this.posY + this.rand.nextDouble() * 2.0D);

                k = MathHelper.floor_double(this.posZ - 1.0D + this.rand.nextDouble() * 2.0D);

                l = this.worldObj.getBlockId(i, j, k);

                int i1 = this.worldObj.getBlockId(i, j - 1, k);

 

                if (l == 0 && i1 > 0 && Block.blocksList[i1].renderAsNormalBlock())

                {

                    this.worldObj.setBlock(i, j, k, this.getCarried(), this.getCarryingData(), 3);

                    this.setCarried(0);

                }

            }

        }

        super.onLivingUpdate();

    }

 

    /**

    * Returns true if this entity can attack entities of the specified class.

    */

    @Override

    public boolean canAttackClass(Class par1Class)

    {

        return EntityForestWalker.class != par1Class && EntityCreeper.class != par1Class;

    }

 

   

 

    public boolean attackEntityAsMob(Entity par1Entity)

    {

        this.attackTimer = 10;

        this.worldObj.setEntityState(this, (byte)4);

        boolean flag = par1Entity.attackEntityFrom(DamageSource.causeMobDamage(this), (float)(7 + this.rand.nextInt(15)));

 

        if (flag)

        {

            par1Entity.motionY += 0.4000000059604645D;

        }

 

        this.playSound("mob.irongolem.throw", 1.0F, 1.0F);

        return flag;

    }

 

    @SideOnly(Side.CLIENT)

    public void handleHealthUpdate(byte par1)

    {

        if (par1 == 4)

        {

            this.attackTimer = 10;

            this.playSound("mob.irongolem.throw", 1.0F, 1.0F);

        }

        else

        {

            super.handleHealthUpdate(par1);

        }

    }

 

    @SideOnly(Side.CLIENT)

    public int getAttackTimer()

    {

        return this.attackTimer;

    }

 

    /**

    * Returns the sound this mob makes while it's alive.

    */

    protected String getLivingSound()

    {

        return "none";

    }

 

    /**

    * Returns the sound this mob makes when it is hurt.

    */

    protected String getHurtSound()

    {

        return "mob.irongolem.hit";

    }

 

    /**

    * Returns the sound this mob makes on death.

    */

    protected String getDeathSound()

    {

        return "mob.irongolem.death";

    }

 

    /**

    * Plays step sound at given x, y, z for the entity

    */

    protected void playStepSound(int par1, int par2, int par3, int par4)

    {

        this.playSound("mob.irongolem.walk", 1.0F, 1.0F);

    }

 

    /**

    * Drop 0-2 items of this living's type. @param par1 - Whether this entity has recently been hit by a player. @param

    * par2 - Level of Looting used to kill this mob.

    */

    protected void dropFewItems(boolean par1, int par2)

    {

        int j = this.rand.nextInt(3);

        int k;

 

        for (k = 0; k < j; ++k)

        {

            this.dropItem(TutorialMod.EarthRune.itemID, 2);

        }

 

        k = 3 + this.rand.nextInt(3);

 

        for (int l = 0; l < k; ++l)

        {

            this.dropItem(TutorialMod.SilverEssence.itemID, 2);

        }

    }

   

    /**

    * Set the id of the block an enderman carries

    */

    public void setCarried(int par1)

    {

        this.dataWatcher.updateObject(16, Byte.valueOf((byte)(par1 & 255)));

    }

 

    /**

    * Get the id of the block an enderman carries

    */

    public int getCarried()

    {

        return this.dataWatcher.getWatchableObjectByte(16);

    }

 

    /**

    * Set the metadata of the block an enderman carries

    */

    public void setCarryingData(int par1)

    {

        this.dataWatcher.updateObject(17, Byte.valueOf((byte)(par1 & 255)));

    }

 

    /**

    * Get the metadata of the block an enderman carries

    */

    public int getCarryingData()

    {

        return this.dataWatcher.getWatchableObjectByte(17);

    }

 

    /**

    * Called when the mob's health reaches 0.

    */

    public void onDeath(DamageSource par1DamageSource)

    {

        super.onDeath(par1DamageSource);

    }

 

    protected boolean canDespawn()

    {

        return false;

    }

 

    public int getMaxSpawnedInChunk()

    {

        return 1;

    }

 

public void initCreature() {

}

 

static

    {

        carriableBlocks[block.sapling.blockID] = true;

        //carriableBlocks[TutorialMod.RuneSapling.blockID] = true;

        //carriableBlocks[TutorialMod.GlowFlower.blockID] = true;

        carriableBlocks[block.plantYellow.blockID] = true;

        carriableBlocks[block.plantRed.blockID] = true;

        carriableBlocks[block.mushroomBrown.blockID] = true;

        carriableBlocks[block.mushroomRed.blockID] = true;

        carriableBlocks[block.cactus.blockID] = true;

        carriableBlocks[block.pumpkin.blockID] = true;

        carriableBlocks[block.melon.blockID] = true;

    }

}

 

 

Model:

 

@SideOnly(Side.CLIENT)

public class ModelEnt extends ModelBase

{

public boolean isCarrying;

 

/** The head model for the iron golem. */

    public ModelRenderer ironGolemHead;

 

    /** The body model for the iron golem. */

    public ModelRenderer ironGolemBody;

 

    /** The right arm model for the iron golem. */

    public ModelRenderer ironGolemRightArm;

 

    /** The left arm model for the iron golem. */

    public ModelRenderer ironGolemLeftArm;

 

    /** The left leg model for the Iron Golem. */

    public ModelRenderer ironGolemLeftLeg;

 

    /** The right leg model for the Iron Golem. */

    public ModelRenderer ironGolemRightLeg;

 

    public ModelEnt()

    {

        this(0.0F);

    }

 

    public ModelEnt(float par1)

    {

        this(par1, -7.0F);

    }

 

    public ModelEnt(float par1, float par2)

    {

        short short1 = 128;

        short short2 = 128;

        this.ironGolemHead = (new ModelRenderer(this)).setTextureSize(short1, short2);

        this.ironGolemHead.setRotationPoint(0.0F, 0.0F + par2, -2.0F);

        this.ironGolemHead.setTextureOffset(0, 0).addBox(-4.0F, -12.0F, -5.5F, 8, 10, 8, par1);

        this.ironGolemHead.setTextureOffset(24, 0).addBox(-1.0F, -5.0F, -7.5F, 2, 4, 2, par1);

        this.ironGolemBody = (new ModelRenderer(this)).setTextureSize(short1, short2);

        this.ironGolemBody.setRotationPoint(0.0F, 0.0F + par2, 0.0F);

        this.ironGolemBody.setTextureOffset(0, 40).addBox(-9.0F, -2.0F, -6.0F, 18, 12, 11, par1);

        this.ironGolemBody.setTextureOffset(0, 70).addBox(-4.5F, 10.0F, -3.0F, 9, 5, 6, par1 + 0.5F);

        this.ironGolemRightArm = (new ModelRenderer(this)).setTextureSize(short1, short2);

        this.ironGolemRightArm.setRotationPoint(0.0F, -7.0F, 0.0F);

        this.ironGolemRightArm.setTextureOffset(60, 21).addBox(-13.0F, -2.5F, -3.0F, 4, 30, 6, par1);

        this.ironGolemLeftArm = (new ModelRenderer(this)).setTextureSize(short1, short2);

        this.ironGolemLeftArm.setRotationPoint(0.0F, -7.0F, 0.0F);

        this.ironGolemLeftArm.setTextureOffset(60, 58).addBox(9.0F, -2.5F, -3.0F, 4, 30, 6, par1);

        this.ironGolemLeftLeg = (new ModelRenderer(this, 0, 22)).setTextureSize(short1, short2);

        this.ironGolemLeftLeg.setRotationPoint(-4.0F, 18.0F + par2, 0.0F);

        this.ironGolemLeftLeg.setTextureOffset(37, 0).addBox(-3.5F, -3.0F, -3.0F, 6, 16, 5, par1);

        this.ironGolemRightLeg = (new ModelRenderer(this, 0, 22)).setTextureSize(short1, short2);

        this.ironGolemRightLeg.mirror = true;

        this.ironGolemRightLeg.setTextureOffset(60, 0).setRotationPoint(5.0F, 18.0F + par2, 0.0F);

        this.ironGolemRightLeg.addBox(-3.5F, -3.0F, -3.0F, 6, 16, 5, par1);

    }

 

    /**

    * Sets the models various rotation angles then renders the model.

    */

    public void render(Entity par1Entity, float par2, float par3, float par4, float par5, float par6, float par7)

    {

        this.setRotationAngles(par2, par3, par4, par5, par6, par7, par1Entity);

        this.ironGolemHead.render(par7);

        this.ironGolemBody.render(par7);

        this.ironGolemLeftLeg.render(par7);

        this.ironGolemRightLeg.render(par7);

        this.ironGolemRightArm.render(par7);

        this.ironGolemLeftArm.render(par7);

    }

 

    /**

    * Sets the model's various rotation angles. For bipeds, par1 and par2 are used for animating the movement of arms

    * and legs, where par1 represents the time(so that arms and legs swing back and forth) and par2 represents how

    * "far" arms and legs can swing at most.

    */

    public void setRotationAngles(float par1, float par2, float par3, float par4, float par5, float par6, Entity par7Entity)

    {

        this.ironGolemHead.rotateAngleY = par4 / (180F / (float)Math.PI);

        this.ironGolemHead.rotateAngleX = par5 / (180F / (float)Math.PI);

        this.ironGolemLeftLeg.rotateAngleX = -1.5F * this.func_78172_a(par1, 13.0F) * par2;

        this.ironGolemRightLeg.rotateAngleX = 1.5F * this.func_78172_a(par1, 13.0F) * par2;

        this.ironGolemLeftLeg.rotateAngleY = 0.0F;

        this.ironGolemRightLeg.rotateAngleY = 0.0F;

    }

 

    /**

    * Used for easily adding entity-dependent animations. The second and third float params here are the same second

    * and third as in the setRotationAngles method.

    */

    public void setLivingAnimations(EntityLivingBase par1EntityLivingBase, float par2, float par3, float par4)

    {

        EntityForestWalker entityforestwalker = (EntityForestWalker)par1EntityLivingBase;

        int i = entityforestwalker.getAttackTimer();

 

        if (i > 0)

        {

            this.ironGolemRightArm.rotateAngleX = -2.0F + 1.5F * this.func_78172_a((float)i - par4, 10.0F);

            this.ironGolemLeftArm.rotateAngleX = -2.0F + 1.5F * this.func_78172_a((float)i - par4, 10.0F);

        }

        else

        {

            if (this.isCarrying)

            {

            this.ironGolemRightArm.rotateAngleX = -0.5F;

                this.ironGolemLeftArm.rotateAngleX = -0.5F;

                this.ironGolemRightArm.rotateAngleZ = 0.05F;

                this.ironGolemLeftArm.rotateAngleZ = -0.05F;

            }

            else

            {

                this.ironGolemRightArm.rotateAngleX = (-0.2F + 1.5F * this.func_78172_a(par2, 13.0F)) * par3;

                this.ironGolemLeftArm.rotateAngleX = (-0.2F - 1.5F * this.func_78172_a(par2, 13.0F)) * par3;

            }

        }

    }

 

    private float func_78172_a(float par1, float par2)

    {

        return (Math.abs(par1 % par2 - par2 * 0.5F) - par2 * 0.25F) / (par2 * 0.25F);

    }

}

 

Link to comment
Share on other sites

Ughh...Everything works except now once in a while the game will crash when my mob is doing its block thing, not really sure at what point or what exactly causes the crash, but the error report says it's the OnLivingUpdate line of code involving the carryingBlocks.

 

Supposed culprit line 163:

 

if (carriableBlocks[l])

                    {

                        this.setCarried(this.worldObj.getBlockId(i, j, k));

                        this.setCarryingData(this.worldObj.getBlockMetadata(i, j, k));

                        this.worldObj.setBlock(i, j, k, 0);

                    }

 

 

Entity:

 

public class EntityForestWalker extends EntityMob {

private int attackTimer;

    private int homeCheckTimer = 0;

    public static boolean[] carriableBlocks = new boolean[257];

 

public EntityForestWalker(World par1World){

super(par1World);

        this.setSize(1.4F, 2.9F);

        this.getNavigator().setAvoidsWater(true);

        this.tasks.addTask(1, new EntityAIAttackOnCollide(this, 1.0D, true));

        this.tasks.addTask(2, new EntityAIMoveTowardsTarget(this, 0.9D, 32.0F));

        this.tasks.addTask(4, new EntityAIMoveTowardsRestriction(this, 1.0D));

        this.tasks.addTask(6, new EntityAIWander(this, 0.6D));

        this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));

        this.tasks.addTask(8, new EntityAILookIdle(this));

        this.targetTasks.addTask(2, new EntityAIHurtByTarget(this, false));

        this.targetTasks.addTask(3, new EntityAINearestAttackableTarget(this, EntityLiving.class, 0, false, true, IMob.mobSelector));

}

 

    protected void entityInit()

    {

        super.entityInit();

            this.dataWatcher.addObject(19, new Byte((byte)0));

            this.dataWatcher.addObject(20, new Byte((byte)0));

    }

   

    /**

    * (abstract) Protected helper method to write subclass entity data to NBT.

    */

    public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)

    {

        super.writeEntityToNBT(par1NBTTagCompound);

        par1NBTTagCompound.setShort("carried", (short)this.getCarried());

        par1NBTTagCompound.setShort("carriedData", (short)this.getCarryingData());

    }

 

    /**

    * (abstract) Protected helper method to read subclass entity data from NBT.

    */

    public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)

    {

        super.readEntityFromNBT(par1NBTTagCompound);

        this.setCarried(par1NBTTagCompound.getShort("carried"));

        this.setCarryingData(par1NBTTagCompound.getShort("carriedData"));

    }

 

    /**

    * Returns true if the newer Entity AI code should be run

    */

    public boolean isAIEnabled()

    {

        return true;

    }

 

    /**

    * main AI tick function, replaces updateEntityActionState

    */

    protected void updateAITick()

    {

        super.updateAITick();

    }

 

    @Override

    protected void applyEntityAttributes()

    {

    super.applyEntityAttributes();

    this.getEntityAttribute(SharedMonsterAttributes.maxHealth).setAttribute(100.0D);

    this.getEntityAttribute(SharedMonsterAttributes.movementSpeed).setAttribute(0.25D); //Recomended speed

    //this.getEntityAttribute(SharedMonsterAttributes.attackDamage).setAttribute(15D);

  // this.getEntityAttribute(SharedMonsterAttributes.followRange).setAttribute(20D);

    }

 

    /**

    * Decrements the entity's air supply when underwater

    */

    protected int decreaseAirSupply(int par1)

    {

        return par1;

    }

 

    protected void collideWithEntity(Entity par1Entity)

    {

        if (par1Entity instanceof IMob && !(par1Entity instanceof EntityForestWalker) && !(par1Entity instanceof EntityCreeper) && this.getRNG().nextInt(20) == 0)

        {

            this.setAttackTarget((EntityLiving)par1Entity);

        }

 

        super.collideWithEntity(par1Entity);

    }

 

    /**

    * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons

    * use this to react to sunlight and start to burn.

    */

    public void onLivingUpdate()

    {

       

 

        if (this.attackTimer > 0)

        {

            --this.attackTimer;

        }

 

        if (this.motionX * this.motionX + this.motionZ * this.motionZ > 2.500000277905201E-7D && this.rand.nextInt(5) == 0)

        {

            int i = MathHelper.floor_double(this.posX);

            int j = MathHelper.floor_double(this.posY - 0.20000000298023224D - (double)this.yOffset);

            int k = MathHelper.floor_double(this.posZ);

            int l = this.worldObj.getBlockId(i, j, k);

 

            if (l > 0)

            {

                this.worldObj.spawnParticle("tilecrack_" + l + "_" + this.worldObj.getBlockMetadata(i, j, k), this.posX + ((double)this.rand.nextFloat() - 0.5D) * (double)this.width, this.boundingBox.minY + 0.1D, this.posZ + ((double)this.rand.nextFloat() - 0.5D) * (double)this.width, 4.0D * ((double)this.rand.nextFloat() - 0.5D), 0.5D, ((double)this.rand.nextFloat() - 0.5D) * 4.0D);

            }

        }

        int i;

 

        if (!this.worldObj.isRemote && this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing"))

        {

            int j;

            int k;

            int l;

 

            if (this.getCarried() == 0)

            {

                if (this.rand.nextInt(20) == 0)

                {

                    i = MathHelper.floor_double(this.posX - 2.0D + this.rand.nextDouble() * 4.0D);

                    j = MathHelper.floor_double(this.posY + this.rand.nextDouble() * 3.0D);

                    k = MathHelper.floor_double(this.posZ - 2.0D + this.rand.nextDouble() * 4.0D);

                    l = this.worldObj.getBlockId(i, j, k);

 

                    if (carriableBlocks[l])

                    {

                        this.setCarried(this.worldObj.getBlockId(i, j, k));

                        this.setCarryingData(this.worldObj.getBlockMetadata(i, j, k));

                        this.worldObj.setBlock(i, j, k, 0);

                    }

                }

            }

            else if (this.rand.nextInt(2000) == 0)

            {

                i = MathHelper.floor_double(this.posX - 1.0D + this.rand.nextDouble() * 2.0D);

                j = MathHelper.floor_double(this.posY + this.rand.nextDouble() * 2.0D);

                k = MathHelper.floor_double(this.posZ - 1.0D + this.rand.nextDouble() * 2.0D);

                l = this.worldObj.getBlockId(i, j, k);

                int i1 = this.worldObj.getBlockId(i, j - 1, k);

 

                if (l == 0 && i1 > 0 && Block.blocksList[i1].renderAsNormalBlock())

                {

                    this.worldObj.setBlock(i, j, k, this.getCarried(), this.getCarryingData(), 3);

                    this.setCarried(0);

                }

            }

        }

        super.onLivingUpdate();

    }

 

    /**

    * Returns true if this entity can attack entities of the specified class.

    */

    @Override

    public boolean canAttackClass(Class par1Class)

    {

        return EntityForestWalker.class != par1Class && EntityCreeper.class != par1Class;

    }

 

   

 

    public boolean attackEntityAsMob(Entity par1Entity)

    {

        this.attackTimer = 10;

        this.worldObj.setEntityState(this, (byte)4);

        boolean flag = par1Entity.attackEntityFrom(DamageSource.causeMobDamage(this), (float)(7 + this.rand.nextInt(15)));

 

        if (flag)

        {

            par1Entity.motionY += 0.4000000059604645D;

        }

 

        this.playSound("mob.irongolem.throw", 1.0F, 1.0F);

        return flag;

    }

 

    @SideOnly(Side.CLIENT)

    public void handleHealthUpdate(byte par1)

    {

        if (par1 == 4)

        {

            this.attackTimer = 10;

            this.playSound("mob.irongolem.throw", 1.0F, 1.0F);

        }

        else

        {

            super.handleHealthUpdate(par1);

        }

    }

 

    @SideOnly(Side.CLIENT)

    public int getAttackTimer()

    {

        return this.attackTimer;

    }

 

    /**

    * Returns the sound this mob makes while it's alive.

    */

    protected String getLivingSound()

    {

        return "none";

    }

 

    /**

    * Returns the sound this mob makes when it is hurt.

    */

    protected String getHurtSound()

    {

        return "mob.irongolem.hit";

    }

 

    /**

    * Returns the sound this mob makes on death.

    */

    protected String getDeathSound()

    {

        return "mob.irongolem.death";

    }

 

    /**

    * Plays step sound at given x, y, z for the entity

    */

    protected void playStepSound(int par1, int par2, int par3, int par4)

    {

        this.playSound("mob.irongolem.walk", 1.0F, 1.0F);

    }

 

    /**

    * Drop 0-2 items of this living's type. @param par1 - Whether this entity has recently been hit by a player. @param

    * par2 - Level of Looting used to kill this mob.

    */

    protected void dropFewItems(boolean par1, int par2)

    {

        int j = this.rand.nextInt(3);

        int k;

 

        for (k = 0; k < j; ++k)

        {

            this.dropItem(TutorialMod.EarthRune.itemID, 2);

        }

 

        k = 3 + this.rand.nextInt(3);

 

        for (int l = 0; l < k; ++l)

        {

            this.dropItem(TutorialMod.SilverEssence.itemID, 2);

        }

    }

   

    /**

    * Set the id of the block an enderman carries

    */

    public void setCarried(int par1)

    {

        this.dataWatcher.updateObject(19, Byte.valueOf((byte)(par1 & 255)));

    }

 

    /**

    * Get the id of the block an enderman carries

    */

    public int getCarried()

    {

        return this.dataWatcher.getWatchableObjectByte(19);

    }

 

    /**

    * Set the metadata of the block an enderman carries

    */

    public void setCarryingData(int par1)

    {

        this.dataWatcher.updateObject(20, Byte.valueOf((byte)(par1 & 255)));

    }

 

    /**

    * Get the metadata of the block an enderman carries

    */

    public int getCarryingData()

    {

        return this.dataWatcher.getWatchableObjectByte(20);

    }

 

    /**

    * Called when the mob's health reaches 0.

    */

    public void onDeath(DamageSource par1DamageSource)

    {

        super.onDeath(par1DamageSource);

    }

 

    protected boolean canDespawn()

    {

        return false;

    }

 

    public int getMaxSpawnedInChunk()

    {

        return 1;

    }

 

public void initCreature() {

}

 

static

    {

        carriableBlocks[block.sapling.blockID] = true;

        //carriableBlocks[TutorialMod.RuneSapling.blockID] = true;

      // carriableBlocks[TutorialMod.GlowFlower.blockID] = true;

        carriableBlocks[block.plantYellow.blockID] = true;

        carriableBlocks[block.plantRed.blockID] = true;

        carriableBlocks[block.mushroomBrown.blockID] = true;

        carriableBlocks[block.mushroomRed.blockID] = true;

        carriableBlocks[block.cactus.blockID] = true;

        carriableBlocks[block.pumpkin.blockID] = true;

        carriableBlocks[block.melon.blockID] = true;

    }

}

 

 

 

Error Report:

 

---- Minecraft Crash Report ----

// There are four lights!

 

Time: 1/5/14 5:02 AM

Description: Ticking entity

 

java.lang.ArrayIndexOutOfBoundsException: 2403

at josiah.FirstMod.EntityForestWalker.func_70636_d(EntityForestWalker.java:163)

at net.minecraft.entity.EntityLivingBase.func_70071_h_(EntityLivingBase.java:1826)

at net.minecraft.entity.EntityLiving.func_70071_h_(EntityLiving.java:257)

at net.minecraft.entity.monster.EntityMob.func_70071_h_(SourceFile:29)

at net.minecraft.world.World.func_72866_a(World.java:2350)

at net.minecraft.world.WorldServer.func_72866_a(WorldServer.java:719)

at net.minecraft.world.World.func_72870_g(World.java:2311)

at net.minecraft.world.World.func_72939_s(World.java:2157)

at net.minecraft.world.WorldServer.func_72939_s(WorldServer.java:550)

at net.minecraft.server.MinecraftServer.func_71190_q(MinecraftServer.java:668)

at net.minecraft.server.MinecraftServer.func_71217_p(MinecraftServer.java:587)

at net.minecraft.server.integrated.IntegratedServer.func_71217_p(IntegratedServer.java:175)

at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:484)

at net.minecraft.server.ThreadMinecraftServer.run(SourceFile:583)

 

 

A detailed walkthrough of the error, its code path and all known details is as follows:

---------------------------------------------------------------------------------------

 

-- Head --

Stacktrace:

at josiah.FirstMod.EntityForestWalker.func_70636_d(EntityForestWalker.java:163)

at net.minecraft.entity.EntityLivingBase.func_70071_h_(EntityLivingBase.java:1826)

at net.minecraft.entity.EntityLiving.func_70071_h_(EntityLiving.java:257)

at net.minecraft.entity.monster.EntityMob.func_70071_h_(SourceFile:29)

at net.minecraft.world.World.func_72866_a(World.java:2350)

at net.minecraft.world.WorldServer.func_72866_a(WorldServer.java:719)

at net.minecraft.world.World.func_72870_g(World.java:2311)

 

-- Entity being ticked --

Details:

Entity Type: Ent (josiah.FirstMod.EntityForestWalker)

Entity ID: 156

Entity Name: entity.Ent.name

Entity's Exact location: -220.70, 11.00, 245.70

Entity's Block location: World: (-221,11,245), Chunk: (at 3,0,5 in -14,15; contains blocks -224,0,240 to -209,255,255), Region: (-1,0; contains chunks -32,0 to -1,31, blocks -512,0,0 to -1,255,511)

Entity's Momentum: 0.00, -0.08, 0.00

Stacktrace:

at net.minecraft.world.World.func_72939_s(World.java:2157)

at net.minecraft.world.WorldServer.func_72939_s(WorldServer.java:550)

 

-- Affected level --

Details:

Level name: Thaumcraft

All players: 1 total; [EntityPlayerMP['SilasOtoko'/324, l='Thaumcraft', x=-153.46, y=69.00, z=216.16]]

Chunk stats: ServerChunkCache: 653 Drop: 0

Level seed: 4165729980649466483

Level generator: ID 00 - default, ver 1. Features enabled: true

Level generator options:

Level spawn location: World: (-256,64,256), Chunk: (at 0,4,0 in -16,16; contains blocks -256,0,256 to -241,255,271), Region: (-1,0; contains chunks -32,0 to -1,31, blocks -512,0,0 to -1,255,511)

Level time: 362311 game time, 410041 day time

Level dimension: 0

Level storage version: 0x04ABD - Anvil

Level weather: Rain time: 131583 (now: false), thunder time: 4360 (now: true)

Level game mode: Game mode: survival (ID 0). Hardcore: false. Cheats: false

Stacktrace:

at net.minecraft.server.MinecraftServer.func_71190_q(MinecraftServer.java:668)

at net.minecraft.server.MinecraftServer.func_71217_p(MinecraftServer.java:587)

at net.minecraft.server.integrated.IntegratedServer.func_71217_p(IntegratedServer.java:175)

at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:484)

at net.minecraft.server.ThreadMinecraftServer.run(SourceFile:583)

 

-- System Details --

Details:

Minecraft Version: 1.6.4

Operating System: Windows 7 (amd64) version 6.1

Java Version: 1.7.0_25, Oracle Corporation

Java VM Version: Java HotSpot 64-Bit Server VM (mixed mode), Oracle Corporation

Memory: 247619016 bytes (236 MB) / 587202560 bytes (560 MB) up to 954466304 bytes (910 MB)

JVM Flags: 2 total; -XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe_minecraft.exe.heapdump -Xmx1G

AABB Pool Size: 3810 (213360 bytes; 0 MB) allocated, 1029 (57624 bytes; 0 MB) used

Suspicious classes: FML and Forge are installed

IntCache: cache: 0, tcache: 0, allocated: 1, tallocated: 63

FML: MCP v8.11 FML v6.4.49.965 Minecraft Forge 9.11.1.965 Optifine OptiFine_1.6.4_HD_C6 9 mods loaded, 9 mods active

mcp{8.09} [Minecraft Coder Pack] (minecraft.jar) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available

FML{6.4.49.965} [Forge Mod Loader] (minecraftforge-9.11.1.965.jar) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available

Forge{9.11.1.965} [Minecraft Forge] (minecraftforge-9.11.1.965.jar) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available

TooManyItems{1.6.4} [TooManyItems] (minecraft.jar) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available

DamageIndicatorsMod{2.9.1.6} [Damage Indicators] (1.6.4 DamageIndicatorsv2.9.1.6.zip) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available

BiomesOPlenty{1.1.2} [biomes O' Plenty] (BiomesOPlenty-universal-1.6.4-1.1.2.51.jar) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available

Runes{v1.3} [Runes] (Runes1.3.zip) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available

Thaumcraft{4.0.4c} [Thaumcraft] (Thaumcraft4.0.4c.zip) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available

mod_ZanMinimap{0.9.4} [Zan's Minimap] (ZansMinimap1.6.4.zip) Unloaded->Constructed->Pre-initialized->Initialized->Post-initialized->Available->Available->Available->Available

Profiler Position: N/A (disabled)

Vec3 Pool Size: 1563 (87528 bytes; 0 MB) allocated, 142 (7952 bytes; 0 MB) used

Player Count: 1 / 8; [EntityPlayerMP['SilasOtoko'/324, l='Thaumcraft', x=-153.46, y=69.00, z=216.16]]

Type: Integrated Server (map_client.txt)

Is Modded: Definitely; Client brand changed to 'fml,forge'

 

Link to comment
Share on other sites

I'm getting the same error myself while working through a tutorial where I'm essentially just copying the EntityEnderman class.  The issue is with the EntityEnderman::carriableBlocks array, which stores an array of boolean true/false values determining whether or not the block with the id of the array's index can be picked up by an Enderman.  Here's the rub: it's initialized to a [256] size array, which is sufficient for vanilla Minecraft's block IDs, but not for all of the custom block IDs we introduce and then spam around our chunks.  Our Enderman or custom mobs sufficiently similar to them try to pick up one of our custom blocks, the index at the block ID is out of the [256] bounds of the EntityEnderman::carriableBlock array, and you're done.

 

I'm about to write a wrapper function for GameRegistry::registerBlock() that tries to resize a carriableBlock property on every entity to at least the associated block ID, but I don't want to start hacking EntityEnderman even at runtime if I can avoid it.  Anyone have a better solution for me?  One that's compliant with the MCF API would be nice...

Link to comment
Share on other sites

This is what I came up with. 

 

Watching the logs, you can see that something (Forge?) updates the EntityEnderman::carriableBlocks field to a boolean[4096], but that happens at runtime somewhere and doesn't account for any custom entities that may be copying the original EntityEnderman.java file from Forge.  This code COULD be shorter if your blocks subclassed a subclass of Block that ALWAYS had an isCarriable boolean field and you only used the EnderSafe class to register a subclass of Entity GUARANTEED to have a boolean[] carriableBlocks field, but I wanted the methods to serve as replacements for GameRegistry.registerBlock(Block block,String name), EntityRegistry.registerGlobalEntityID(Class<? extends Entity> entity,String name,int id), and EntityList.entityEggs.put(Object id,Object eggInfo) without imposing tighter coupling against the parameters.

 

 

package mcmods.tutorial;

import java.lang.reflect.Field;
import java.util.Vector;

import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityEggInfo;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.monster.EntityEnderman;
import cpw.mods.fml.common.registry.EntityRegistry;
import cpw.mods.fml.common.registry.GameRegistry;

public class EnderSafe 
{

private static Vector<Class<? extends Entity>> entities = new Vector<Class<? extends Entity>>();
private static int maxId = 256;

public static void registerBlock(Block block,String name)
{System.out.println("XXXXXXX: Registering Block: "+block.getLocalizedName());
	if (entities.size() == 0)
	{System.out.println("XXXXXXX: Adding Enderman to list");
		entities.add(EntityEnderman.class);
	}
	System.out.println("XXXXXXX: Registering block with Forge");
	GameRegistry.registerBlock(block,name);
	System.out.println("XXXXXXX: Checking maxId ("+maxId+") < "+block.getLocalizedName()+"["+block.blockID+"]");
	if (maxId < block.blockID)
	{System.out.println("("+maxId+" < ["+block.blockID+"], updating");
		maxId = block.blockID;
	}

	boolean isCarriable = false;
	try {System.out.println("XXXXXXX: Trying to get isCarriable");
		isCarriable = block.getClass().getField("isCarriable").getBoolean(null);
		System.out.println("XXXXXXX: isCarriable successfully retrieved: "+block.getClass().getName()+".isCarriable = "+isCarriable);
	} catch (Exception e) {
		System.out.println("XXXXXXX: Failed to get isCarriable");
		e.printStackTrace();
	}

	System.out.println("XXXXXXX: Looping EnderSafe.entities["+entities.size()+"]");
	for (Class<? extends Entity> entity : entities)
	{System.out.println("XXXXXXX: Registering blocks for entity: "+entity.getName());
		boolean[] carriableBlocks = null;
		try {System.out.println("XXXXXXX: Trying to get carriableBlocks");
			carriableBlocks = (boolean[]) entity.getField("carriableBlocks").get(null);
			System.out.println("XXXXXXX: Successfully retrieved carriableBlocks: "+entity.getName()+".carriableBlocks = boolean["+carriableBlocks.length+"]");
		} catch (Exception e) {
			e.printStackTrace();
		}

		if (carriableBlocks != null)
		{System.out.println("XXXXXXX: "+entity.getName()+".carriableBlocks exists, checking ["+carriableBlocks.length+"] < <"+block.blockID+">");
			if (carriableBlocks.length < block.blockID)
			{System.out.println("XXXXXXX: Extending Array for: "+entity.getName());
				boolean[] temp = carriableBlocks.clone();
				carriableBlocks = new boolean[block.blockID];
				System.arraycopy(temp,0,carriableBlocks,0,temp.length);
				try {
					entity.getField("carriableBlocks").set(null, carriableBlocks);
				} catch (Exception e) {
					e.printStackTrace();
				}
				carriableBlocks[block.blockID] = isCarriable;
			}
		}
	}
}

public static void registerEntity(Class<? extends Entity> entity,String name,int bkEggColor,int fgEggColor)
{System.out.println("XXXXXXX: Registering entity: "+entity.getName());
	int id = EntityRegistry.findGlobalUniqueEntityId();
	EntityRegistry.registerGlobalEntityID(entity, name, id);
	EntityList.entityEggs.put(Integer.valueOf(id), new EntityEggInfo(id,bkEggColor,fgEggColor));
	System.out.println("XXXXXXX: Entity registered with Forge.  Registering with EnderSafe");
	entities.add(entity);
	boolean[] carriableBlocks = null;
	try {System.out.println("XXXXXXX: Trying to get "+entity.getName()+".carriableBlocks");
		carriableBlocks = (boolean[]) entity.getField("carriableBlocks").get(null);
		System.out.println("XXXXXXX: Successfully retrieved "+entity.getName()+".carriableBlocks["+carriableBlocks.length+"]");
	} catch (Exception e) {
		System.out.println("XXXXXXX: Failed to retrive "+entity.getName()+".carriableBlocks.  Entity not compatible with EnderSafe");
		e.printStackTrace();
	}

	System.out.println("XXXXXXX: Checking to see if "+maxId+" > 256 && "+maxId+" > ["+carriableBlocks.length+"]");
	if (maxId > 256 && maxId > carriableBlocks.length)
	{System.out.println("XXXXXXX: Resizing array for "+entity.getName());
		boolean[] temp = carriableBlocks.clone();
		carriableBlocks = new boolean[maxId];
		System.arraycopy(temp, 0, carriableBlocks, 0, temp.length);
		try {
			entity.getField("carriableBlocks").set(null, carriableBlocks);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

public static void registerEntity(Class<? extends Entity> entity,String name)
{
	registerEntity(entity,name,0,0);
}

}

 

 

I'm not sure how much I LIKE this as a solution, but I didn't find anything else internal to Forge or Minecraft, so I hope it helps anyone else who is having this problem, even if it's only helping them to find a better solution.

 

Frankly, since Forge handles the array for EntityEnderman, you COULD just write all of your Entities to have a carriableBlocks array big enough to start with, but that's just TOO simple, right?

 

public static boolean[] carriableBlocks = new boolean[A_REALLY_BIG_NUMBER];

 

Good luck.

Link to comment
Share on other sites

Increasing the array to allow for custom blocks is nice and all, but what would you suggest if I am getting an error with the Entity carrying Vanilla blocks only?

 

I'm pretty sure this is an issue with a custom block.  Check your error:

 

java.lang.ArrayIndexOutOfBoundsException: 2403
   at josiah.FirstMod.EntityForestWalker.func_70636_d(EntityForestWalker.java:163)

 

That 2403 is the block ID of the block your Forest Walker is trying to pick up, and it's outside the bounds of your 257 bit boolean array.  I don't know if the blocks are yours or from some other mod you have loaded, but your class needs to adapt to it.  Forge updates the EntityEnderman array to 4096, which I seem to remember seeing as an upper bound in a tutorial.  Unless the parameter is stored somewhere as a 12 bit value instead of 32, the only reason for that constraint is the expanded size of EntityEnderman.carriableBlocks, so perhaps that is some kind of standard that you can rely upon for whatever other mods you may have and an array size of 4096 may be a better solution (WAY simpler too!) without more control over custom block IDs.

 

I don't get why you don't extend EntityEnderman.

 

That is certainly an option that would help to simplify the code, but at the expense of its flexibility.  I did suggest when I posted it that an entity guaranteed to have a carriableBlocks field would allow that and extending a class that has such a field (like EntityEnderman) would be one way of making that guarantee.  Just a design decision on my part to reflect instead, your mileage may vary.

Link to comment
Share on other sites

  • 2 weeks later...

I see now that I am extending EntityMob not EntityIronGolem so I probably could have just extended EntityEnderman. But fortunately I don't need to because your advice about the boolean range worked! I changed it to 4096 and so far the game has not crashed like it used to. I didn't take your advice at first because I wasn't having my Entity pick up an custom blocks, but it has fixed it all the same. Thanks citizenslave!

Link to comment
Share on other sites

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.



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • The Advanced Solar Panels and the IC2 build are not matching - try different builds of these mods until you find a working combination
    • Minecraft 1.12.2 Forge 14.23.5.2860   Description: There was a severe problem during mod loading that has caused the game to fail net.minecraftforge.fml.common.LoaderExceptionModCrash: Caught exception from Advanced Solar Panels (advanced_solar_panels) Caused by: java.lang.NoClassDefFoundError: ic2/core/block/IInventorySlotHolder at java.lang.Class.getDeclaredConstructors0(Native Method) at java.lang.Class.privateGetDeclaredConstructors(Class.java:2671) at java.lang.Class.getConstructor0(Class.java:3075) at java.lang.Class.newInstance(Class.java:412) at com.chocohead.advsolar.tiles.TEs.buildDummies(TEs.java:124) at com.chocohead.advsolar.AdvancedSolarPanels.init(AdvancedSolarPanels.java:125) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at net.minecraftforge.fml.common.FMLModContainer.handleModStateEvent(FMLModContainer.java:637) at sun.reflect.GeneratedMethodAccessor3.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at com.google.common.eventbus.Subscriber.invokeSubscriberMethod(Subscriber.java:91) at com.google.common.eventbus.Subscriber$SynchronizedSubscriber.invokeSubscriberMethod(Subscriber.java:150) at com.google.common.eventbus.Subscriber$1.run(Subscriber.java:76) at com.google.common.util.concurrent.MoreExecutors$DirectExecutor.execute(MoreExecutors.java:399) at com.google.common.eventbus.Subscriber.dispatchEvent(Subscriber.java:71) at com.google.common.eventbus.Dispatcher$PerThreadQueuedDispatcher.dispatch(Dispatcher.java:116) at com.google.common.eventbus.EventBus.post(EventBus.java:217) at net.minecraftforge.fml.common.LoadController.sendEventToModContainer(LoadController.java:219) at net.minecraftforge.fml.common.LoadController.propogateStateMessage(LoadController.java:197) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at com.google.common.eventbus.Subscriber.invokeSubscriberMethod(Subscriber.java:91) at com.google.common.eventbus.Subscriber$SynchronizedSubscriber.invokeSubscriberMethod(Subscriber.java:150) at com.google.common.eventbus.Subscriber$1.run(Subscriber.java:76) at com.google.common.util.concurrent.MoreExecutors$DirectExecutor.execute(MoreExecutors.java:399) at com.google.common.eventbus.Subscriber.dispatchEvent(Subscriber.java:71) at com.google.common.eventbus.Dispatcher$PerThreadQueuedDispatcher.dispatch(Dispatcher.java:116) at com.google.common.eventbus.EventBus.post(EventBus.java:217) at net.minecraftforge.fml.common.LoadController.distributeStateMessage(LoadController.java:136) at net.minecraftforge.fml.common.Loader.initializeMods(Loader.java:749) at net.minecraftforge.fml.client.FMLClientHandler.finishMinecraftLoading(FMLClientHandler.java:336) at net.minecraft.client.Minecraft.func_71384_a(Minecraft.java:535) at net.minecraft.client.Minecraft.func_99999_d(Minecraft.java:378) at net.minecraft.client.main.Main.main(SourceFile:123) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at net.minecraft.launchwrapper.Launch.launch(Launch.java:135) at net.minecraft.launchwrapper.Launch.main(Launch.java:28) Caused by: java.lang.ClassNotFoundException: ic2.core.block.IInventorySlotHolder at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:191) at java.lang.ClassLoader.loadClass(ClassLoader.java:424) at java.lang.ClassLoader.loadClass(ClassLoader.java:357) ... 46 more Caused by: java.lang.NullPointerException
    • You can try other builds of Quark/Zeta
    • Hello all, I recently tried to upgrade my Minecraft mod to version 1.21.3, and I seem to have a problem with the `RenderSystem#setShaderColor` method. Here is how the screen is usually supposed to look like: Here is how it looks at present: To further explain, the note labels atop of the note buttons are colored cyan (here) using `RenderSystem#setShaderColor`. The note buttons and labels get their colors from their native texture - white. This means that even though I set the coloring to apply to the label (top), it is applied to the button (bottom). What I conclude is happening then, in essence, is that this method (at least for my case) does not color the blit after - but rather the blit before..?  This also blocks me from later resetting the shader, as I need to set it back to white before the blitting is done, and not when it's done. So like... what? I've tested this further with other components that require this method, and this preceding-like behavior seems to be pretty consistent for them too.   I should mention that all the snippets I am about to show have all worked in past versions. In my class `ClientUtil`, the following methods are defined: public static void setShaderColor(final Color color, final float alpha) { RenderSystem.setShaderColor( color.getRed() / 255f, color.getGreen() / 255f, color.getBlue() / 255f, alpha ); } public static void setShaderColor(final Color color) { setShaderColor(color, 1); } public static void resetShaderColor() { setShaderColor(Color.WHITE); } //... public static RenderType guiRT(final ResourceLocation loc) { return RenderType.guiTextured(loc); } And here is the snippet from `NoteButtonRenderer#renderNote` using it: // "Note" here refers to those symbols in the middle of a note button protected void renderNote(final GuiGraphics gui, final InstrumentThemeLoader themeLoader) { final int noteWidth = noteButton.getWidth()/2, noteHeight = noteButton.getHeight()/2; ClientUtil.setShaderColor((noteButton.isPlaying() && !foreignPlaying) ? themeLoader.notePressed() : themeLoader.noteReleased() ); gui.blit(ClientUtil::guiRT, noteTextureProvider.get(), noteButton.getX() + noteWidth/2, noteButton.getY() + noteHeight/2, 0, 0, noteWidth, noteHeight, noteWidth, noteButton.getHeight()/2 ); ClientUtil.resetShaderColor(); } You may find the full source here. The odd thing is that Minecraft does seem to use this method the regular way I showed, for instance `SkyRenderer#renderSkyDisc` (not sure if I'l allowed to paste it). Could it be that I'm doing something wrong that leads to this issue..? I'm really stumped on this one.  I couldn't really find any change logs or documentation for this rendering API (even in this Fabric blog post), so I'm sorry if this seems obvious or anything.  Either way, any help would be appreciated.
  • Topics

×
×
  • Create New...

Important Information

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