So I have code for a macerator that is supposed to save what is in the inventory and then read what was saved. Unfortunately when I leave the world and come back the inventory has been deleted.
Source for the tile entity
public class TileEntityMacerator extends TileEntity implements ISidedInventory{
private String localizedName;
private static final int[] slots_top = new int[]{0};
private static final int[] slots_bottom = new int[]{2, 1};
private static final int[] slots_sides = new int[]{1};
private ItemStack[] slots = new ItemStack[3];
/**Furnace Speed*/
public int maceratingSpeed = 70;
/**How long this furnace will continue to burn.*/
public int power;
public int maxPower = 10000;
/**How much time left before item cooked.*/
public int cookTime;
public int getSizeInventory()
{
return this.slots.length;
}
if (this.slots[0] == null)
{
return false;
}
else
{
ItemStack itemstack = FurnaceRecipes.smelting().getSmeltingResult(this.slots[0]);
if (itemstack == null) return false;
if (!this.isOre(this.slots[0])) return false;
if (this.slots[2] == null) return true;
if (!this.slots[2].isItemEqual(itemstack)) return false;
int result = slots[2].stackSize + itemstack.stackSize * 2;
return result <= getInventoryStackLimit() && result <= this.slots[2].getMaxStackSize(); //Forge BugFix: Make it respect stack sizes properly.
}
}
public void macerateItem()
{
if (this.canMacerate())
{
ItemStack itemstack = FurnaceRecipes.smelting().getSmeltingResult(this.slots[0]);
if (this.slots[2] == null)
{
this.slots[2] = itemstack.copy();
this.slots[2].stackSize*=2;
}
else if (this.slots[2].getItem() == itemstack.getItem())
{
this.slots[2].stackSize += itemstack.stackSize*2; // Forge BugFix: Results may have multiple items
}
--this.slots[0].stackSize;
if (this.slots[0].stackSize <= 0)
{
this.slots[0] = null;
}
}
}
/**Gets the time in tick in which the item burns.*/
public static int getPower(ItemStack itemstack)
{
if (itemstack == null)
{
return 0;
}
else
{
Item item = itemstack.getItem();
if (item == Items.redstone) return 5;
if (item == Item.getItemFromBlock(Blocks.redstone_block)) return 45;
return 0;
}
}
public boolean isMacerating()
{
return this.cookTime > 0;
}
this.slots is an array, but in your load method you forgot the '[i]' and assign it directly to an ItemStack; should be 'this.slots[i] = ...' Check the save method, too.
this.slots is an array, but in your load method you forgot the '' and assign it directly to an ItemStack; should be 'this.slots = ...' Check the save method, too.
No it seems that the code somehow decided to delete that when I copied it in. In the code it is this.slots.
No it seems that the code somehow decided to delete that when I copied it in. In the code it is this.slots.
It just doesn't want to copy right.
Gotta love the forum editor - happens to me all the time when I put in code, especially with arrays. Use pastebin or a similar service for accurate and true-to-formatting code.
Your NBT read and write methods look like they are fine. When getting the tag list, you can use 'Constants.NBT.TAG_COMPOUND' instead of '10' - no difference except nicer to use constants vs. magic numbers.
At this point you need to do some debugging:
- Print to the console in both your read and write methods, making sure to note if the world is remote (client) or not (server); they should only print on the server
- If you don't see anything print, double-check that you registered your TileEntity:
- If they print but there is nothing in the inventory slots, check that your Gui / Container is setup correctly; GUIs are client-side only and rely on the container to synchronize to the server. If that step is messed up, you'll get items that look like they are in the furnace (because you can see them on the client), but they're not really there on the server.
Your NBT read and write methods look like they are fine. When getting the tag list, you can use 'Constants.NBT.TAG_COMPOUND' instead of '10' - no difference except nicer to use constants vs. magic numbers.
At this point you need to do some debugging:
- Print to the console in both your read and write methods, making sure to note if the world is remote (client) or not (server); they should only print on the server
- If you don't see anything print, double-check that you registered your TileEntity:
- If they print but there is nothing in the inventory slots, check that your Gui / Container is setup correctly; GUIs are client-side only and rely on the container to synchronize to the server. If that step is messed up, you'll get items that look like they are in the furnace (because you can see them on the client), but they're not really there on the server.
Good luck!
Dang the stupid things I do when I'm tired. Didn't register the TileEntity. Lol
Dang the stupid things I do when I'm tired. Didn't register the TileEntity. Lol
But
I do have another problem. The Macerator keeps the fuel it has and
displays it on every Macerator that is placed in the world.
'static' is not your friend, and it can sneak up on you - Blocks and Items are all effectively static in Minecraft, because there is only a single instance of each one; thus, any class fields you make inside of your Block or Item classes are tied to that single instance.
Something like:
public class YourBlock extends Block {
private int fuel;
}
'fuel' will be exactly the same for every single block placed in the world. You need to store any mutable fields inside of the TileEntity (for blocks) or ItemStack NBT tag (for Items).
For TileEntities, be sure not to use the 'static' keyword on your class fields.
'static' is not your friend, and it can sneak up on you - Blocks and Items are all effectively static in Minecraft, because there is only a single instance of each one; thus, any class fields you make inside of your Block or Item classes are tied to that single instance.
Something like:
public class YourBlock extends Block {
private int fuel;
}
'fuel' will be exactly the same for every single block placed in the world. You need to store any mutable fields inside of the TileEntity (for blocks) or ItemStack NBT tag (for Items).
For TileEntities, be sure not to use the 'static' keyword on your class fields.
So I have code for a macerator that is supposed to save what is in the inventory and then read what was saved. Unfortunately when I leave the world and come back the inventory has been deleted.
Source for the tile entity
public class TileEntityMacerator extends TileEntity implements ISidedInventory{
private String localizedName;
private static final int[] slots_top = new int[]{0};
private static final int[] slots_bottom = new int[]{2, 1};
private static final int[] slots_sides = new int[]{1};
private ItemStack[] slots = new ItemStack[3];
/**Furnace Speed*/
public int maceratingSpeed = 70;
/**How long this furnace will continue to burn.*/
public int power;
public int maxPower = 10000;
/**How much time left before item cooked.*/
public int cookTime;
public int getSizeInventory()
{
return this.slots.length;
}
public String getInventoryName()
{
return this.hasCustomInventoryName() ? this.localizedName : "Macerator";
}
public boolean hasCustomInventoryName()
{
return this.localizedName != null && this.localizedName.length() > 0;
}
public void setGuiDisplayName(String displayName) {
this.localizedName = displayName;
}
@Override
public ItemStack getStackInSlot(int i) {
return this.slots;
}
@Override
public ItemStack decrStackSize(int i, int j) {
if (this.slots != null)
{
ItemStack itemstack;
if (this.slots.stackSize <= j)
{
itemstack = this.slots;
this.slots = null;
return itemstack;
}
else
{
itemstack = this.slots.splitStack(j);
if (this.slots.stackSize == 0)
{
this.slots = null;
}
return itemstack;
}
}
else
{
return null;
}
}
@Override
public ItemStack getStackInSlotOnClosing(int i) {
if (this.slots != null)
{
ItemStack itemstack = this.slots;
this.slots = null;
return itemstack;
}
else
{
return null;
}
}
@Override
public void setInventorySlotContents(int i, ItemStack itemstack) {
this.slots = itemstack;
if (itemstack != null && itemstack.stackSize > this.getInventoryStackLimit())
{
itemstack.stackSize = this.getInventoryStackLimit();
}
}
@Override
public int getInventoryStackLimit() {
return 64;
}
@Override
public void readFromNBT(NBTTagCompound nbt)
{
super.readFromNBT(nbt);
NBTTagList list = nbt.getTagList("items", 10);
this.slots = new ItemStack[this.getSizeInventory()];
for(int i = 0; i < list.tagCount(); i++)
{
NBTTagCompound compound = (NBTTagCompound) list.getCompoundTagAt(i);
byte b = compound.getByte("Slot");
if(b >= 0 && b < this.slots.length)
{
this.slots = ItemStack.loadItemStackFromNBT(compound);
}
}
this.power = nbt.getShort("Power");
this.cookTime = nbt.getShort("CookTime");
this.maxPower = getPower(this.slots[1]);
if(nbt.hasKey("MaceratorCont"))
{
this.localizedName = nbt.getString("MaceratorCont");
}
}
@Override
public void writeToNBT(NBTTagCompound nbt)
{
super.writeToNBT(nbt);
nbt.setShort("Power", (short)this.power);
nbt.setShort("CookTime", (short)this.cookTime);
nbt.setShort("MaxPower", (short)this.maxPower);
NBTTagList list = new NBTTagList();
for(int i = 0; i < this.slots.length; i++)
{
if(this.slots != null)
{
NBTTagCompound compound = new NBTTagCompound();
compound.setByte("Slot", (byte) i );
this.slots.writeToNBT(compound);
list.appendTag(compound);
}
}
nbt.setTag("items", list);
if(this.hasCustomInventoryName())
{
nbt.setString("MaceratorCont", this.localizedName);
}
}
@Override
public boolean isUseableByPlayer(EntityPlayer entityplayer) {
return this.worldObj.getTileEntity(this.xCoord, this.yCoord, this.zCoord) != this ? false : entityplayer.getDistanceSq((double)this.xCoord + 0.5D, (double)this.yCoord + 0.5D, (double)this.zCoord + 0.5D) <= 64.0D;
}
@Override
public void openInventory() {}
@Override
public void closeInventory() {}
public boolean hasPower()
{
return this.power > 0;
}
@Override
public void updateEntity()
{
boolean flag = this.power > 0;
boolean flag1 = false;
if (this.hasPower() && this.isMacerating())
{
this.power--;
}
if (!this.worldObj.isRemote)
{
if (this.hasItemPower(this.slots[1]) && this.power <= (this.maxPower - this.getPower(this.slots[1])))
{
this.power += getPower(this.slots[1]);
flag1 = true;
if(this.slots[1] != null)
{
this.slots[1].stackSize--;
if(this.slots[1].stackSize == 0)
{
this.slots[1] = this.slots[1].getItem().getContainerItem(this.slots[1]);
}
}
}
if(this.hasPower() && this.canMacerate())
{
this.cookTime++;
if(this.cookTime == this.maceratingSpeed)
{
this.cookTime = 0;
this.macerateItem();
flag1 = true;
}
}
else
{
this.cookTime = 0;
}
if(flag != this.hasPower())
{
flag1 = true;
Macerator.updateMaceratorBlockState(this.hasPower(), this.worldObj, this.xCoord, this.yCoord, this.zCoord);
}
}
if (flag1)
{
this.markDirty();
}
}
private boolean isOre(ItemStack itemStack) {
//TODO
return true;
}
private boolean canMacerate()
{
if (this.slots[0] == null)
{
return false;
}
else
{
ItemStack itemstack = FurnaceRecipes.smelting().getSmeltingResult(this.slots[0]);
if (itemstack == null) return false;
if (!this.isOre(this.slots[0])) return false;
if (this.slots[2] == null) return true;
if (!this.slots[2].isItemEqual(itemstack)) return false;
int result = slots[2].stackSize + itemstack.stackSize * 2;
return result <= getInventoryStackLimit() && result <= this.slots[2].getMaxStackSize(); //Forge BugFix: Make it respect stack sizes properly.
}
}
public void macerateItem()
{
if (this.canMacerate())
{
ItemStack itemstack = FurnaceRecipes.smelting().getSmeltingResult(this.slots[0]);
if (this.slots[2] == null)
{
this.slots[2] = itemstack.copy();
this.slots[2].stackSize*=2;
}
else if (this.slots[2].getItem() == itemstack.getItem())
{
this.slots[2].stackSize += itemstack.stackSize*2; // Forge BugFix: Results may have multiple items
}
--this.slots[0].stackSize;
if (this.slots[0].stackSize <= 0)
{
this.slots[0] = null;
}
}
}
/**Gets the time in tick in which the item burns.*/
public static int getPower(ItemStack itemstack)
{
if (itemstack == null)
{
return 0;
}
else
{
Item item = itemstack.getItem();
if (item == Items.redstone) return 5;
if (item == Item.getItemFromBlock(Blocks.redstone_block)) return 45;
return 0;
}
}
public boolean isMacerating()
{
return this.cookTime > 0;
}
public static boolean hasItemPower(ItemStack itemstack)
{
return getPower(itemstack) > 0;
}
@Override
public boolean isItemValidForSlot(int i, ItemStack itemstack) {
return i == 2 ? false : (i == 1 ? hasItemPower(itemstack) : true);
}
@Override
public int[] getAccessibleSlotsFromSide(int var1) {
return var1 == 0 ? slots_bottom : (var1 == 1 ? slots_top : slots_sides);
}
@Override
public boolean canInsertItem(int i, ItemStack itemstack,
int j) {
return this.isItemValidForSlot(i, itemstack);
}
@Override
public boolean canExtractItem(int i, ItemStack itemstack,
int j) {
return j != 0 || i != 1 || itemstack.getItem() == Items.bucket;
}
@SideOnly(Side.CLIENT)
public int getPowerRemainingScaled(int i) {
if(this.maxPower == 0)
{
this.maxPower = this.maceratingSpeed;
}
return this.power * i / this.maxPower;
}
@SideOnly(Side.CLIENT)
public int getMacerationProgressScaled(int i)
{
return this.cookTime * i / this.maceratingSpeed;
}
Everything so far works perfectly except that.
this.slots is an array, but in your load method you forgot the '[i]' and assign it directly to an ItemStack; should be 'this.slots[i] = ...' Check the save method, too.
No it seems that the code somehow decided to delete that when I copied it in. In the code it is this.slots.
It just doesn't want to copy right.
Gotta love the forum editor - happens to me all the time when I put in code, especially with arrays. Use pastebin or a similar service for accurate and true-to-formatting code.
Ok I made a paste on pastebin.
Paste
Your NBT read and write methods look like they are fine. When getting the tag list, you can use 'Constants.NBT.TAG_COMPOUND' instead of '10' - no difference except nicer to use constants vs. magic numbers.
At this point you need to do some debugging:
- Print to the console in both your read and write methods, making sure to note if the world is remote (client) or not (server); they should only print on the server
- If you don't see anything print, double-check that you registered your TileEntity:
- If they print but there is nothing in the inventory slots, check that your Gui / Container is setup correctly; GUIs are client-side only and rely on the container to synchronize to the server. If that step is messed up, you'll get items that look like they are in the furnace (because you can see them on the client), but they're not really there on the server.
Good luck!
Dang the stupid things I do when I'm tired. Didn't register the TileEntity. Lol
'static' is not your friend, and it can sneak up on you - Blocks and Items are all effectively static in Minecraft, because there is only a single instance of each one; thus, any class fields you make inside of your Block or Item classes are tied to that single instance.
Something like:
'fuel' will be exactly the same for every single block placed in the world. You need to store any mutable fields inside of the TileEntity (for blocks) or ItemStack NBT tag (for Items).
For TileEntities, be sure not to use the 'static' keyword on your class fields.
Thank you for helping me. It works perfectly now.