I'm currently updating my mod from 1.10 to 1.12 and could already fix most errors, but the last few percent of nasty ones remain. A lot of them are in the code of my tile entity, container and related classes.
In the following class, there are 2 problems I can't fix:
1) #pickup/setEntityItemStack: I have no idea, where I copied this code from, but this method is no longer there.
2) #readEntityFromNBT/loadItemStackFromNBT: I'm pretty sure there is a replacement for this, but I wasn't able to find this so far.
public class EntityArmadillo extends EntityAnimal implements IInventoryChangedListener
{
private ContainerHorseChest horseChest;
private static final UUID ARMOR_MODIFIER_UUID = UUID.fromString("556E1665-8B10-40C8-8F9D-CF9B1667F295");
private static final DataParameter<Integer> HORSE_ARMOR = EntityDataManager.<Integer>createKey(EntityHorse.class, DataSerializers.VARINT);
private String texturePrefix;
public static final int GUI_ID = 2;
public EntityArmadillo(World par1World)
{
super(par1World);
this.setSize(0.9F, 0.9F);
//this.getNavigator().setAvoidsWater(true);
this.tasks.addTask(0, new EntityAISwimming(this));
this.tasks.addTask(1, new EntityAIAttackMelee(this, 1.0D, true));
this.tasks.addTask(2, new EntityAIMate(this, 1.0D));
this.tasks.addTask(3, new EntityAITempt(this, 1.2D, ItemsBiodiversity.buckthornBerries, false));
this.tasks.addTask(4, new EntityAIFollowParent(this, 1.1D));
this.tasks.addTask(5, new EntityAIArmadilloCollect(this, 1.5D));
this.tasks.addTask(6, new EntityAIWander(this, 1.0D));
this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
this.tasks.addTask(8, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityAnt.class, true));
this.initHorseChest();
}
/**
* Returns true if the newer Entity AI code should be run
*/
public boolean isAIEnabled()
{
return true;
}
protected void dropFewItems(boolean par1, int par2)
{
int j = this.rand.nextInt(4) + this.rand.nextInt(1 + par2);
int k;
if(ConfigHandler.anteaterdropmeat){
for (k = 0; k < j; ++k)
{
this.dropItem(ItemsBiodiversity.exoticMeatRaw, 1);
}}
}
/**
* This function is used when two same-species animals in 'love mode' breed to generate the new baby animal.
*/
public EntityArmadillo spawnBabyAnimal(EntityAgeable par1EntityAgeable)
{
return new EntityArmadillo(this.world);
}
/**
* Checks if the parameter is an item which this animal can be fed to breed it (wheat, carrots or seeds depending on
* the animal type)
*/
public boolean isBreedingItem(ItemStack par1ItemStack)
{
return par1ItemStack != null && par1ItemStack.getItem() == ItemsBiodiversity.buckthornBerries;
}
public EntityAgeable createChild(EntityAgeable par1EntityAgeable)
{
return this.spawnBabyAnimal(par1EntityAgeable);
}
/**
* Called when the entity is attacked.
*/
public boolean attackEntityFrom(DamageSource par1DamageSource, float par2)
{
if (this.isEntityInvulnerable(par1DamageSource))
{
return false;
}
else
{
Entity entity = par1DamageSource.getEntity();
public boolean attackEntityAsMob(Entity par1Entity)
{
return par1Entity.attackEntityFrom(DamageSource.causeMobDamage(this), 2.5F);
}
/**
* 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()
{
super.onLivingUpdate();
this.checkCollideWithItem();
}
//Taming, Armor, Inventory
/**
* Returns number of slots depending horse type
*/
private int getChestSize()
{
return 19;
}
if (animalchest != null)
{
animalchest.removeInventoryChangeListener(this);
int i = Math.min(animalchest.getSizeInventory(), this.getHorseChest().getSizeInventory());
if (itemstack != null)
{
this.getHorseChest().setInventorySlotContents(j, itemstack.copy());
}
}
}
this.getHorseChest().addInventoryChangeListener(this);
this.updateHorseSlots();
this.itemHandler = new net.minecraftforge.items.wrapper.InvWrapper(this.getHorseChest());
}
/**
* Updates the items in the saddle and armor slots of the horse's inventory.
*/
private void updateHorseSlots()
{
if (!this.world.isRemote)
{
this.setHorseArmorStack(this.getHorseChest().getStackInSlot(0));
}
}
/**
* Set horse armor stack (for example: new ItemStack(Items.iron_horse_armor))
*/
public void setHorseArmorStack(ItemStack itemStackIn)
{
HorseArmorType horsearmortype = HorseArmorType.getByItemStack(itemStackIn);
//this.dataManager.set(HORSE_ARMOR, Integer.valueOf(horsearmortype.getOrdinal()));
//this.resetTexturePrefix();
if (!this.world.isRemote)
{
this.getEntityAttribute(SharedMonsterAttributes.ARMOR).removeModifier(ARMOR_MODIFIER_UUID);
int i = horsearmortype.getProtection();
if (i != 0)
{
this.getEntityAttribute(SharedMonsterAttributes.ARMOR).applyModifier((new AttributeModifier(ARMOR_MODIFIER_UUID, "Horse armor bonus", (double)i, 0)).setSaved(false));
}
}
}
/**
* Called by InventoryBasic.onInventoryChanged() on a array that is never filled.
*/
public void onInventoryChanged(InventoryBasic invBasic)
{
this.updateHorseSlots();
}
public void openGUI(EntityPlayer playerEntity)
{
if (!this.world.isRemote)
{
playerEntity.openGui(Biodiversity.instance, GUI_ID, playerEntity.getEntityWorld(), this.getEntityId(), 0, 0);
}
}
for (int i = 0; i < nbttaglist.tagCount(); ++i)
{
NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i);
int j = nbttagcompound.getByte("Slot") & 255;
public ContainerHorseChest getHorseChest() {
return horseChest;
}
public void setHorseChest(ContainerHorseChest horseChest) {
this.horseChest = horseChest;
}
@Override
public void onInventoryChanged(IInventory invBasic) {
this.updateHorseSlots();
}
}
Another thing being profoundly off are item stacks. Stacksize became private and there is no setter. Does this mean, I need to make a new stack every time I want to add an item? This is the problem of the following two classes, specifically in ArmadilloChest#addItem, TileEntityBeehive#canProduce and TileEntityBeehive#produceHoney
if (ItemStack.areItemsEqual(itemstack1, itemstack))
{
int j = Math.min(this.getInventoryStackLimit(), itemstack1.getMaxStackSize());
int k = Math.min(itemstack.stackSize, j - itemstack1.stackSize);
public int getProdTime()
{
return ConfigHandler.beehivespeed * 20;
}
/**
* Returns true if the furnace can smelt an item, i.e. has a source item, destination stack isn't full, etc.
*/
private boolean canProduce()
{
if (this.itemStackHandler.getStackInSlot(0) == null || this.itemStackHandler.getStackInSlot(0).getItem()!=ItemsBiodiversity.beeQueen)
{
return false;
}
else
{
if (this.itemStackHandler.getStackInSlot(1) == null) return true;
if (!(this.itemStackHandler.getStackInSlot(1).getItem() == ItemsBiodiversity.honey)) return false;
int result = this.itemStackHandler.getStackInSlot(1).stackSize + 1;
return result <= 64;
}
}
/**
* Turn one item from the furnace source stack into the appropriate smelted item in the furnace result stack
*/
public void produceHoney()
{
if (this.canProduce())
{
if (this.itemStackHandler.getStackInSlot(1) == null)
{
this.itemStackHandler.setStackInSlot(1, new ItemStack(ItemsBiodiversity.honey));
}
else if (this.itemStackHandler.getStackInSlot(1).getItem() == ItemsBiodiversity.honey)
{
this.itemStackHandler.getStackInSlot(1).stackSize += 1;
}
}
}
public int getField(int id)
{
switch (id)
{
case 0:
return this.prodTime;
case 1:
return this.totalProdTime;
default:
return 0;
}
}
public void setField(int id, int value)
{
switch (id)
{
case 0:
this.prodTime = value;
break;
case 1:
this.totalProdTime = value;
}
}
}
The last thing is #detectAndSendChanges/sendProgressBarUpdate in the following class.
private void addPlayerSlots(IInventory playerInventory) {
// Player Inventory, Slot 9-35, Slot IDs 9-35
for (int y = 0; y < 3; ++y) {
for (int x = 0; x < 9; ++x) {
this.addSlotToContainer(new Slot(playerInventory, x + y * 9 + 9, 8 + x * 18, 84 + y * 18));
}
}
// Player Inventory, Slot 0-8, Slot IDs 36-44
for (int x = 0; x < 9; ++x) {
this.addSlotToContainer(new Slot(playerInventory, x, 8 + x * 18, 142));
}
}
2) Will it work if I leave the old code untouched otherwise?
Two other random questions that concern entities:
How can I correctly place a mob spawner? The old code (vide infra) doesn't work anymore, but I found a similar looking method using a resource location. Can I use that and what resource location does it need?
Damage source work kinda differently now. How can I fix the attackEntityFrom below? Do I even need it, if my entity is just a random mob with standard attack?
[/p]
[p]/**
* Called when the entity is attacked.
*/
public boolean attackEntityFrom(DamageSource source, float amount)
{
if (super.attackEntityFrom(source, amount))
{
EntityLivingBase entitylivingbase = this.getAttackTarget();[/p]
[p]if (entitylivingbase == null && source.getEntity() instanceof EntityLivingBase)
{
entitylivingbase = (EntityLivingBase)source.getEntity();
}[/p]
[p]int i = MathHelper.floor(this.posX);
int j = MathHelper.floor(this.posY);
int k = MathHelper.floor(this.posZ);[/p]
[p]return true;
}
else
{
return false;
}
}[/p]
[p]
I think EnumHand didn't exist in 1.7.10. So instead of both instances of getHeldItem you need to use getCurrentEquippedItem (it was called if I remember correctly)
I got it to work. It was not the up/down. Somehow it did work if I made it print something in the log before checking all the blocks or when I did remove the check for the config option (although it was true, as I checked by printing it out).
Knowing this I placed the config check elsewhere which also works.
My tool is supposed to indicate chests in a certain range, when right-clicked on a wall or the soil. It did work before I added the horizontal version. Now ONLY the horizontal version works, vertical not as I checked with a chest I placed.
It is possible, I messed up with the facing, though I'm not sure. Any help is appreciated.
They do both need to be put inside a method, for the ClientProxy you usually have PreInit / Init /PostInit. For the ModEntities class call the method whatever you want and call it in PreInit of your main class.
That is certainly the problem from the first error,I don't know the second one, but try what I say, it is probably the same issue.
The function of the RenderFactory class is to instantiate the render class for your mob. If I understood it correctly this is necessary because of the order things are loaded.
This is an example:
package anagkai.biodiversity.entities.renderer;
import anagkai.biodiversity.entities.EntityArmadillo;
import anagkai.biodiversity.entities.models.ModelAnteater;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraftforge.fml.client.registry.IRenderFactory;
public class EntityArmadilloRF implements IRenderFactory<EntityArmadillo>{
@Override
public RenderArmadillo createRenderFor(RenderManager manager) {
return new RenderArmadillo(manager, new ModelAnteater(), 0.5F);
}
}
I'm doing 1.10. I think this should still in 1.11, but obviously I can't promise it.
This goes into ModMobs: It takes an entity class, an entity name (not display name!), the 0 is the id and needs to be different for any of your mobs, your modid. The last to args are the spawn egg colors.
RenderingRegistry.registerEntityRenderingHandler(EntityGargoyle.class, new EntityGargoyleRF());
This goes into the client proxy. It takes the entity class and the render factory class.
I need to work with item stacks with NBT and I have to questions.
1. Can I add itemstacks with NBT to creative tabs by overriding displayAllRelevantItems? It does work, but I was wondering if this might cause problems.
2. Is it true (I read this) that any itemstack with NBT on it must have a stack size of one? Or can I have a stack of three items for example with some integer as NBT and splitting the stack will create mutiple stacks with this NBT?
Normally swords have 3F plus the material value in damage. I want 3F or 5F depending on a certain boolean. In the code above I tried to make it 5F for testing purposes but that didn't work.
What I did worked in older versions and is basically copied from ItemSword. But somehow the weapon damage calculation is not changed. What am I missing?
0
I'm currently updating my mod from 1.10 to 1.12 and could already fix most errors, but the last few percent of nasty ones remain. A lot of them are in the code of my tile entity, container and related classes.
In the following class, there are 2 problems I can't fix:
1) #pickup/setEntityItemStack: I have no idea, where I copied this code from, but this method is no longer there.
2) #readEntityFromNBT/loadItemStackFromNBT: I'm pretty sure there is a replacement for this, but I wasn't able to find this so far.
package anagkai.biodiversity.entities;
import java.util.List;
import java.util.UUID;
import javax.annotation.Nullable;
import anagkai.biodiversity.Biodiversity;
import anagkai.biodiversity.ConfigHandler;
import anagkai.biodiversity.ai.EntityAIArmadilloCollect;
import anagkai.biodiversity.items.ItemsBiodiversity;
import anagkai.biodiversity.technical.armadillo.ArmadilloChest;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityAgeable;
import net.minecraft.entity.SharedMonsterAttributes;
import net.minecraft.entity.ai.EntityAIAttackMelee;
import net.minecraft.entity.ai.EntityAIFollowParent;
import net.minecraft.entity.ai.EntityAIHurtByTarget;
import net.minecraft.entity.ai.EntityAILookIdle;
import net.minecraft.entity.ai.EntityAIMate;
import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
import net.minecraft.entity.ai.EntityAISwimming;
import net.minecraft.entity.ai.EntityAITempt;
import net.minecraft.entity.ai.EntityAIWander;
import net.minecraft.entity.ai.EntityAIWatchClosest;
import net.minecraft.entity.ai.attributes.AttributeModifier;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.passive.EntityAnimal;
import net.minecraft.entity.passive.EntityHorse;
import net.minecraft.entity.passive.HorseArmorType;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.init.SoundEvents;
import net.minecraft.inventory.ContainerHorseChest;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.IInventoryChangedListener;
import net.minecraft.inventory.InventoryBasic;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.util.DamageSource;
import net.minecraft.util.EnumHand;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public class EntityArmadillo extends EntityAnimal implements IInventoryChangedListener
{
private ContainerHorseChest horseChest;
private static final UUID ARMOR_MODIFIER_UUID = UUID.fromString("556E1665-8B10-40C8-8F9D-CF9B1667F295");
private static final DataParameter<Integer> HORSE_ARMOR = EntityDataManager.<Integer>createKey(EntityHorse.class, DataSerializers.VARINT);
private String texturePrefix;
public static final int GUI_ID = 2;
public EntityArmadillo(World par1World)
{
super(par1World);
this.setSize(0.9F, 0.9F);
//this.getNavigator().setAvoidsWater(true);
this.tasks.addTask(0, new EntityAISwimming(this));
this.tasks.addTask(1, new EntityAIAttackMelee(this, 1.0D, true));
this.tasks.addTask(2, new EntityAIMate(this, 1.0D));
this.tasks.addTask(3, new EntityAITempt(this, 1.2D, ItemsBiodiversity.buckthornBerries, false));
this.tasks.addTask(4, new EntityAIFollowParent(this, 1.1D));
this.tasks.addTask(5, new EntityAIArmadilloCollect(this, 1.5D));
this.tasks.addTask(6, new EntityAIWander(this, 1.0D));
this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
this.tasks.addTask(8, new EntityAILookIdle(this));
this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, true));
this.targetTasks.addTask(2, new EntityAINearestAttackableTarget(this, EntityAnt.class, true));
this.initHorseChest();
}
/**
* Returns true if the newer Entity AI code should be run
*/
public boolean isAIEnabled()
{
return true;
}
protected void applyEntityAttributes()
{
super.applyEntityAttributes();
this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(20.0D);
this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.25D);
//this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(2.5D);
}
protected void updateAITasks()
{
super.updateAITasks();
}
protected void playStepSound(BlockPos pos, Block blockIn)
{
this.playSound(SoundEvents.ENTITY_PIG_STEP, 0.15F, 1.0F);
}
protected void dropFewItems(boolean par1, int par2)
{
int j = this.rand.nextInt(4) + this.rand.nextInt(1 + par2);
int k;
if(ConfigHandler.anteaterdropmeat){
for (k = 0; k < j; ++k)
{
this.dropItem(ItemsBiodiversity.exoticMeatRaw, 1);
}}
}
/**
* This function is used when two same-species animals in 'love mode' breed to generate the new baby animal.
*/
public EntityArmadillo spawnBabyAnimal(EntityAgeable par1EntityAgeable)
{
return new EntityArmadillo(this.world);
}
/**
* Checks if the parameter is an item which this animal can be fed to breed it (wheat, carrots or seeds depending on
* the animal type)
*/
public boolean isBreedingItem(ItemStack par1ItemStack)
{
return par1ItemStack != null && par1ItemStack.getItem() == ItemsBiodiversity.buckthornBerries;
}
public EntityAgeable createChild(EntityAgeable par1EntityAgeable)
{
return this.spawnBabyAnimal(par1EntityAgeable);
}
/**
* Called when the entity is attacked.
*/
public boolean attackEntityFrom(DamageSource par1DamageSource, float par2)
{
if (this.isEntityInvulnerable(par1DamageSource))
{
return false;
}
else
{
Entity entity = par1DamageSource.getEntity();
if (entity != null && !(entity instanceof EntityPlayer) && !(entity instanceof EntityArrow))
{
par2 = (par2 + 1.0F) / 2.0F;
}
return super.attackEntityFrom(par1DamageSource, par2);
}
}
public boolean attackEntityAsMob(Entity par1Entity)
{
return par1Entity.attackEntityFrom(DamageSource.causeMobDamage(this), 2.5F);
}
/**
* 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()
{
super.onLivingUpdate();
this.checkCollideWithItem();
}
//Taming, Armor, Inventory
/**
* Returns number of slots depending horse type
*/
private int getChestSize()
{
return 19;
}
private void initHorseChest()
{
ContainerHorseChest animalchest = this.getHorseChest();
this.setHorseChest(new ArmadilloChest("HorseChest", this.getChestSize()));
this.getHorseChest().setCustomName(this.getName());
if (animalchest != null)
{
animalchest.removeInventoryChangeListener(this);
int i = Math.min(animalchest.getSizeInventory(), this.getHorseChest().getSizeInventory());
for (int j = 0; j < i; ++j)
{
ItemStack itemstack = animalchest.getStackInSlot(j);
if (itemstack != null)
{
this.getHorseChest().setInventorySlotContents(j, itemstack.copy());
}
}
}
this.getHorseChest().addInventoryChangeListener(this);
this.updateHorseSlots();
this.itemHandler = new net.minecraftforge.items.wrapper.InvWrapper(this.getHorseChest());
}
/**
* Updates the items in the saddle and armor slots of the horse's inventory.
*/
private void updateHorseSlots()
{
if (!this.world.isRemote)
{
this.setHorseArmorStack(this.getHorseChest().getStackInSlot(0));
}
}
/**
* Set horse armor stack (for example: new ItemStack(Items.iron_horse_armor))
*/
public void setHorseArmorStack(ItemStack itemStackIn)
{
HorseArmorType horsearmortype = HorseArmorType.getByItemStack(itemStackIn);
//this.dataManager.set(HORSE_ARMOR, Integer.valueOf(horsearmortype.getOrdinal()));
//this.resetTexturePrefix();
if (!this.world.isRemote)
{
this.getEntityAttribute(SharedMonsterAttributes.ARMOR).removeModifier(ARMOR_MODIFIER_UUID);
int i = horsearmortype.getProtection();
if (i != 0)
{
this.getEntityAttribute(SharedMonsterAttributes.ARMOR).applyModifier((new AttributeModifier(ARMOR_MODIFIER_UUID, "Horse armor bonus", (double)i, 0)).setSaved(false));
}
}
}
/* private void resetTexturePrefix()
{
this.texturePrefix = null;
}*/
public void checkCollideWithItem(){
AxisAlignedBB axisalignedbb;
axisalignedbb = this.getEntityBoundingBox().expand(1.0D, 0.5D, 1.0D);
List<Entity> list = this.world.getEntitiesWithinAABBExcludingEntity(this, axisalignedbb);
for (int i = 0; i < list.size(); ++i)
{
Entity entity = (Entity)list.get(i);
if (!entity.isDead && entity instanceof EntityItem)
{
EntityItem itemstack = (EntityItem) entity;
this.pickup(itemstack);
}
}
}
public void pickup(EntityItem entity) {
if (!this.world.isRemote)
{
//if (this.delayBeforeCanPickup > 0) return;
ItemStack itemstack = entity.getItem();
//int i = itemstack.stackSize;
//int hook = net.minecraftforge.event.ForgeEventFactory.onItemPickup(this, entityIn, itemstack);
//if (hook < 0) return;
//if ((this.owner == null || lifespan - this.age <= 200 || this.owner.equals(entityIn.getName())) && (hook == 1 || i <= 0 || entityIn.inventory.addItemStackToInventory(itemstack)))
//{
ItemStack rest = this.horseChest.addItem(itemstack);
if(rest != itemstack){
//net.minecraftforge.fml.common.FMLCommonHandler.instance().firePlayerItemPickupEvent(entityIn, this);
if (!this.isSilent())
{
this.world.playSound((EntityPlayer)null, this.posX, this.posY, this.posZ, SoundEvents.ENTITY_ITEM_PICKUP, SoundCategory.PLAYERS, 0.2F, ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.7F + 1.0F) * 2.0F);
}
//entityIn.onItemPickup(this, i);
if (rest == null)
{
entity.setDead();
}else{
entity.setEntityItemStack(rest);
}
//entityIn.addStat(StatList.getObjectsPickedUpStats(itemstack.getItem()), i);
}
}
}
/**
* Called by InventoryBasic.onInventoryChanged() on a array that is never filled.
*/
public void onInventoryChanged(InventoryBasic invBasic)
{
this.updateHorseSlots();
}
public void openGUI(EntityPlayer playerEntity)
{
if (!this.world.isRemote)
{
playerEntity.openGui(Biodiversity.instance, GUI_ID, playerEntity.getEntityWorld(), this.getEntityId(), 0, 0);
}
}
public boolean processInteract(EntityPlayer player, EnumHand hand, @Nullable ItemStack stack)
{
if (stack != null && stack.getItem() == Items.SPAWN_EGG)
{
return super.processInteract(player, hand);
}
else if(this.isBreedingItem(stack)){
super.processInteract(player, hand);
}
//else if (!this.isTame())
//{
// return false;
//}
//else if (this.isTame())
//{
else{
this.openGUI(player);}
return true;
//}
//return super.processInteract(player, hand, stack);
}
/**
* Called when the mob's health reaches 0.
*/
public void onDeath(DamageSource cause)
{
super.onDeath(cause);
if (!this.world.isRemote)
{
this.dropItemsInChest(this, this.getHorseChest());
}
}
private void dropItemsInChest(Entity entityIn, ContainerHorseChest animalChestIn)
{
if (animalChestIn != null && !this.world.isRemote)
{
for (int i = 0; i < animalChestIn.getSizeInventory(); ++i)
{
ItemStack itemstack = animalChestIn.getStackInSlot(i);
if (itemstack != null)
{
this.entityDropItem(itemstack, 0.0F);
}
}
}
}
/**
* (abstract) Protected helper method to write subclass entity data to NBT.
*/
public void writeEntityToNBT(NBTTagCompound compound)
{
super.writeEntityToNBT(compound);
//compound.setBoolean("Tame", this.isTame());
//if (this.getOwnerUniqueId() != null)
//{
// compound.setString("OwnerUUID", this.getOwnerUniqueId().toString());
//}
NBTTagList nbttaglist = new NBTTagList();
for (int i = 1; i < this.getHorseChest().getSizeInventory(); ++i)
{
ItemStack itemstack = this.getHorseChest().getStackInSlot(i);
if (itemstack != null)
{
NBTTagCompound nbttagcompound = new NBTTagCompound();
nbttagcompound.setByte("Slot", (byte)i);
itemstack.writeToNBT(nbttagcompound);
nbttaglist.appendTag(nbttagcompound);
}
}
compound.setTag("Items", nbttaglist);
if (this.getHorseChest().getStackInSlot(0) != null)
{
compound.setTag("ArmorItem", this.getHorseChest().getStackInSlot(0).writeToNBT(new NBTTagCompound()));
}
}
/**
* (abstract) Protected helper method to read subclass entity data from NBT.
*/
public void readEntityFromNBT(NBTTagCompound compound)
{
super.readEntityFromNBT(compound);
/*this.setHorseTamed(compound.getBoolean("Tame"));
String s;
if (compound.hasKey("OwnerUUID", 8))
{
s = compound.getString("OwnerUUID");
}
else
{
String s1 = compound.getString("Owner");
s = PreYggdrasilConverter.convertMobOwnerIfNeeded(this.getServer(), s1);
}
if (!s.isEmpty())
{
this.setOwnerUniqueId(UUID.fromString(s));
}*/
NBTTagList nbttaglist = compound.getTagList("Items", 10);
this.initHorseChest();
for (int i = 0; i < nbttaglist.tagCount(); ++i)
{
NBTTagCompound nbttagcompound = nbttaglist.getCompoundTagAt(i);
int j = nbttagcompound.getByte("Slot") & 255;
if (j >= 1 && j < this.getHorseChest().getSizeInventory())
{
this.getHorseChest().setInventorySlotContents(j, ItemStack.loadItemStackFromNBT(nbttagcompound));
}
}
if (compound.hasKey("ArmorItem", 10))
{
ItemStack itemstack = ItemStack.loadItemStackFromNBT(compound.getCompoundTag("ArmorItem"));
if (itemstack != null && HorseArmorType.isHorseArmor(itemstack.getItem()))
{
this.getHorseChest().setInventorySlotContents(0, itemstack);
}
}
this.updateHorseSlots();
}
public boolean replaceItemInInventory(int inventorySlot, @Nullable ItemStack itemStackIn)
{
if (inventorySlot == 499)
{
if (itemStackIn == null)
{
this.initHorseChest();
return true;
}
if (itemStackIn != null && itemStackIn.getItem() == Item.getItemFromBlock(Blocks.CHEST))
{
this.initHorseChest();
return true;
}
}
int i = inventorySlot - 400;
if (i >= 0 && i < 1 && i < this.getHorseChest().getSizeInventory())
{
if (i != 0 || (itemStackIn == null || HorseArmorType.isHorseArmor(itemStackIn.getItem())))
{
this.getHorseChest().setInventorySlotContents(i, itemStackIn);
this.updateHorseSlots();
return true;
}
else
{
return false;
}
}
else
{
int j = inventorySlot - 500 + 1;
if (j >= 1 && j < this.getHorseChest().getSizeInventory())
{
this.getHorseChest().setInventorySlotContents(j, itemStackIn);
return true;
}
else
{
return false;
}
}
}
private net.minecraftforge.items.IItemHandler itemHandler = null; // Initialized by initHorseChest above.
@SuppressWarnings("unchecked")
@Override
public <T> T getCapability(net.minecraftforge.common.capabilities.Capability<T> capability, net.minecraft.util.EnumFacing facing)
{
if (capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) return (T) itemHandler;
return super.getCapability(capability, facing);
}
@Override
public boolean hasCapability(net.minecraftforge.common.capabilities.Capability<?> capability, net.minecraft.util.EnumFacing facing)
{
return capability == net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY || super.hasCapability(capability, facing);
}
public ContainerHorseChest getHorseChest() {
return horseChest;
}
public void setHorseChest(ContainerHorseChest horseChest) {
this.horseChest = horseChest;
}
@Override
public void onInventoryChanged(IInventory invBasic) {
this.updateHorseSlots();
}
}
Another thing being profoundly off are item stacks. Stacksize became private and there is no setter. Does this mean, I need to make a new stack every time I want to add an item? This is the problem of the following two classes, specifically in ArmadilloChest#addItem, TileEntityBeehive#canProduce and TileEntityBeehive#produceHoney
package anagkai.biodiversity.technical.armadillo;
import javax.annotation.Nullable;
import anagkai.biodiversity.items.ItemsBiodiversity;
import net.minecraft.inventory.ContainerHorseChest;
import net.minecraft.item.ItemStack;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
public class ArmadilloChest extends ContainerHorseChest{
public ArmadilloChest(String inventoryName, int slotCount)
{
super(inventoryName, slotCount);
}
@SideOnly(Side.CLIENT)
public ArmadilloChest(ITextComponent invTitle, int slotCount)
{
super(invTitle, slotCount);
}
@Override
@Nullable
public ItemStack addItem(ItemStack stack)
{
ItemStack itemstack = stack.copy();
//if(itemstack.getItem() == ItemsBiodiversity.armadilloHelmet && this.getStackInSlot(0) == null){
// this.setInventorySlotContents(0, itemstack);
// return null;
//}else{
for (int i = 1; i < this.getSizeInventory(); ++i)
{
ItemStack itemstack1 = this.getStackInSlot(i);
if (itemstack1 == null)
{
this.setInventorySlotContents(i, itemstack);
this.markDirty();
return null;
}
if (ItemStack.areItemsEqual(itemstack1, itemstack))
{
int j = Math.min(this.getInventoryStackLimit(), itemstack1.getMaxStackSize());
int k = Math.min(itemstack.stackSize, j - itemstack1.stackSize);
if (k > 0)
{
itemstack1.stackSize += k;
itemstack.stackSize -= k;
if (itemstack.stackSize <= 0)
{
this.markDirty();
return null;
}
}
}
}
//}
if (itemstack.stackSize != stack.stackSize)
{
this.markDirty();
}
return itemstack;
}
}
package anagkai.biodiversity.technical.beehive;
import java.util.List;
import javax.annotation.Nullable;
import anagkai.biodiversity.Biodiversity;
import anagkai.biodiversity.ConfigHandler;
import anagkai.biodiversity.items.ItemsBiodiversity;
import net.minecraft.block.BlockFurnace;
import net.minecraft.client.resources.I18n;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.FurnaceRecipes;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ITickable;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.ItemStackHandler;
public class TileEntityBeehive extends TileEntity implements ITickable{
public static final int SIZE = 2;
private int prodTime;
private int totalProdTime = ConfigHandler.beehivespeed * 20;
public ItemStackHandler itemStackHandler = new ItemStackHandler(SIZE) {
@Override
protected void onContentsChanged(int slot) {
TileEntityBeehive.this.markDirty();
}
};
@Override
public void readFromNBT(NBTTagCompound compound) {
super.readFromNBT(compound);
if (compound.hasKey("items")) {
itemStackHandler.deserializeNBT((NBTTagCompound) compound.getTag("items"));
}
this.prodTime = compound.getInteger("ProdTime");
this.totalProdTime = compound.getInteger("ProdTimeTotal");
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound compound) {
super.writeToNBT(compound);
compound.setTag("items", itemStackHandler.serializeNBT());
compound.setInteger("ProdTime", this.prodTime);
compound.setInteger("ProdTimeTotal", this.totalProdTime);
return compound;
}
public boolean canInteractWith(EntityPlayer playerIn) {
return !isInvalid() && playerIn.getDistanceSq(pos.add(0.5D, 0.5D, 0.5D)) <= 64D;
}
@Override
public boolean hasCapability(Capability<?> capability, EnumFacing facing) {
if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
return true;
}
return super.hasCapability(capability, facing);
}
@Override
public <T> T getCapability(Capability<T> capability, EnumFacing facing) {
if (capability == CapabilityItemHandler.ITEM_HANDLER_CAPABILITY) {
return (T) itemStackHandler;
}
return super.getCapability(capability, facing);
}
/**
* Like the old updateEntity(), except more generic.
*/
@Override
public void update()
{
//System.out.println("update");
boolean flag1 = false;
if (!this.world.isRemote)
{
if (this.canProduce())
{
//System.out.println(String.valueOf(prodTime));
++this.prodTime;
if (this.prodTime == this.totalProdTime)
{
this.prodTime = 0;
this.totalProdTime = this.getProdTime();
this.produceHoney();
flag1 = true;
}
}
else
{
this.prodTime = 0;
}
}
else if (this.prodTime > 0)
{
this.prodTime = MathHelper.clamp(this.prodTime - 2, 0, this.totalProdTime);
}
if (flag1)
{
this.markDirty();
}
}
public int getProdTime()
{
return ConfigHandler.beehivespeed * 20;
}
/**
* Returns true if the furnace can smelt an item, i.e. has a source item, destination stack isn't full, etc.
*/
private boolean canProduce()
{
if (this.itemStackHandler.getStackInSlot(0) == null || this.itemStackHandler.getStackInSlot(0).getItem()!=ItemsBiodiversity.beeQueen)
{
return false;
}
else
{
if (this.itemStackHandler.getStackInSlot(1) == null) return true;
if (!(this.itemStackHandler.getStackInSlot(1).getItem() == ItemsBiodiversity.honey)) return false;
int result = this.itemStackHandler.getStackInSlot(1).stackSize + 1;
return result <= 64;
}
}
/**
* Turn one item from the furnace source stack into the appropriate smelted item in the furnace result stack
*/
public void produceHoney()
{
if (this.canProduce())
{
if (this.itemStackHandler.getStackInSlot(1) == null)
{
this.itemStackHandler.setStackInSlot(1, new ItemStack(ItemsBiodiversity.honey));
}
else if (this.itemStackHandler.getStackInSlot(1).getItem() == ItemsBiodiversity.honey)
{
this.itemStackHandler.getStackInSlot(1).stackSize += 1;
}
}
}
public int getField(int id)
{
switch (id)
{
case 0:
return this.prodTime;
case 1:
return this.totalProdTime;
default:
return 0;
}
}
public void setField(int id, int value)
{
switch (id)
{
case 0:
this.prodTime = value;
break;
case 1:
this.totalProdTime = value;
}
}
}
The last thing is #detectAndSendChanges/sendProgressBarUpdate in the following class.
package anagkai.biodiversity.technical.beehive;
import javax.annotation.Nullable;
import anagkai.biodiversity.technical.SlotOutput;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.inventory.IContainerListener;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.SlotItemHandler;
public class ContainerBeehive extends Container {
private TileEntityBeehive te;
private int prodTimeTime;
private int totalProdTime;
public ContainerBeehive(IInventory playerInventory, TileEntityBeehive te) {
this.te = te;
addOwnSlots();
addPlayerSlots(playerInventory);
}
private void addPlayerSlots(IInventory playerInventory) {
// Player Inventory, Slot 9-35, Slot IDs 9-35
for (int y = 0; y < 3; ++y) {
for (int x = 0; x < 9; ++x) {
this.addSlotToContainer(new Slot(playerInventory, x + y * 9 + 9, 8 + x * 18, 84 + y * 18));
}
}
// Player Inventory, Slot 0-8, Slot IDs 36-44
for (int x = 0; x < 9; ++x) {
this.addSlotToContainer(new Slot(playerInventory, x, 8 + x * 18, 142));
}
}
private void addOwnSlots() {
IItemHandler itemHandler = this.te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
addSlotToContainer(new SlotBee(itemHandler, 0, 13, 35));
addSlotToContainer(new SlotOutput(itemHandler, 1, 116, 35));
}
@Nullable
@Override
public ItemStack transferStackInSlot(EntityPlayer playerIn, int index) {
ItemStack itemstack = null;
Slot slot = this.inventorySlots.get(index);
if (slot != null && slot.getHasStack()) {
ItemStack itemstack1 = slot.getStack();
itemstack = itemstack1.copy();
if (index < TileEntityBeehive.SIZE) {
if (!this.mergeItemStack(itemstack1, TileEntityBeehive.SIZE, this.inventorySlots.size(), true)) {
return null;
}
} else if (!this.mergeItemStack(itemstack1, 0, TileEntityBeehive.SIZE, false)) {
return null;
}
if (itemstack1.isEmpty()) {
slot.putStack(null);
} else {
slot.onSlotChanged();
}
}
return itemstack;
}
@Override
public boolean canInteractWith(EntityPlayer playerIn) {
return te.canInteractWith(playerIn);
}
/**
* Looks for changes made in the container, sends them to every listener.
*/
public void detectAndSendChanges()
{
super.detectAndSendChanges();
for (int i = 0; i < this.listeners.size(); ++i)
{
IContainerListener icontainerlistener = (IContainerListener)this.listeners.get(i);
if (this.prodTimeTime != this.te.getField(0))
{
icontainerlistener.sendProgressBarUpdate(this, 0, this.te.getField(0));
}
if (this.totalProdTime != this.te.getField(1))
{
icontainerlistener.sendProgressBarUpdate(this, 1, this.te.getField(1));
}
}
this.prodTimeTime = this.te.getField(0);
this.totalProdTime = this.te.getField(1);
}
public void addListener(IContainerListener listener)
{
super.addListener(listener);
//listener.sendAllWindowProperties(this, this.te);
}
@SideOnly(Side.CLIENT)
public void updateProgressBar(int id, int data)
{
this.te.setField(id, data);
}
}
I'm interested in any ideas on how to fix the problems discribed. Thanks in advance!
0
So the entity registering code for 1.10 doesn't work any more. Eclipse tells me I could add a ResourceLocation.
Old Code:
I have two questions:
1) What kind of ResourceLocation do I need?
2) Will it work if I leave the old code untouched otherwise?
Two other random questions that concern entities:
How can I correctly place a mob spawner? The old code (vide infra) doesn't work anymore, but I found a similar looking method using a resource location. Can I use that and what resource location does it need?
Damage source work kinda differently now. How can I fix the attackEntityFrom below? Do I even need it, if my entity is just a random mob with standard attack?
Any help is appreciated. Thanks in advance.
0
I would like to create a block that can pick up items. Similar to a hopper but with slightly increased range.
I did something similar with entities picking up items.
There I used getEntityBoundingBox().expand() inside a function called by onLivingUpdate() to get any items nearby.
What I'd like to know is:
1. Can I do something similar as using the entity bounding box?
2. Where would I check for nearby items? Obviously a block doesn't have onLivingUpdate().
0
This mod is now available for 1.10 under the name of Biodiversity Mod.
0
I recently got into AI programming and did entities that will destroy crops or pick up items.
The problem with the latter is the entities will "freeze" if they can't get to the stack that's been chosen as target for the ai task.
Is there any easy way to check if an entity can reach something?
If so I could just check it in the shouldMoveTo function.
0
I think EnumHand didn't exist in 1.7.10. So instead of both instances of getHeldItem you need to use getCurrentEquippedItem (it was called if I remember correctly)
0
I got it to work. It was not the up/down. Somehow it did work if I made it print something in the log before checking all the blocks or when I did remove the check for the config option (although it was true, as I checked by printing it out).
Knowing this I placed the config check elsewhere which also works.
0
My tool is supposed to indicate chests in a certain range, when right-clicked on a wall or the soil. It did work before I added the horizontal version. Now ONLY the horizontal version works, vertical not as I checked with a chest I placed.
It is possible, I messed up with the facing, though I'm not sure. Any help is appreciated.
Concerned Code: Item Class
0
They do both need to be put inside a method, for the ClientProxy you usually have PreInit / Init /PostInit. For the ModEntities class call the method whatever you want and call it in PreInit of your main class.
That is certainly the problem from the first error,I don't know the second one, but try what I say, it is probably the same issue.
The function of the RenderFactory class is to instantiate the render class for your mob. If I understood it correctly this is necessary because of the order things are loaded.
This is an example:
I'm doing 1.10. I think this should still in 1.11, but obviously I can't promise it.
0
This goes into ModMobs: It takes an entity class, an entity name (not display name!), the 0 is the id and needs to be different for any of your mobs, your modid. The last to args are the spawn egg colors.
This goes into the client proxy. It takes the entity class and the render factory class.
0
I need to work with item stacks with NBT and I have to questions.
1. Can I add itemstacks with NBT to creative tabs by overriding displayAllRelevantItems? It does work, but I was wondering if this might cause problems.
2. Is it true (I read this) that any itemstack with NBT on it must have a stack size of one? Or can I have a stack of three items for example with some integer as NBT and splitting the stack will create mutiple stacks with this NBT?
0
That explains why the code from ItemSword doesn't work as is.
This works, although it needs to be getAttributeUnlocalizedName and not getName, at least in the version I'm using.
0
It extends ItemSword. What didn't work is that the 3 and the 5 have the same damage. And that corresponds to what I expected for the 3.
No, it won't changed. It is set in the constructor and only used to determine whether the damage should be material plus 3 or plus 5.
0
Normally swords have 3F plus the material value in damage. I want 3F or 5F depending on a certain boolean. In the code above I tried to make it 5F for testing purposes but that didn't work.
0
Weapon class
What I did worked in older versions and is basically copied from ItemSword. But somehow the weapon damage calculation is not changed. What am I missing?