Jump to content

[SOLVED] TileEntity inventory lost on world save/load


Jay Avery

Recommended Posts

I'm creating a TileEntity which functions like a furnace. It now works in the game, and the inventory and cook time stay and keep working when the GUI is opened and closed. But when I save and exit the game while something is in the inventory, it's lost when the world is reloaded. From using printlns it looks like the inventory is being written to NBT correctly, but when the game is loaded a new TileEntity is created instead of loading it from NBT like it should.

 

How can I make sure the game loads the existing TileEntity instead of creating a new one each time the world is loaded? I can post my code if needed but there's a lot of it so I thought I'd ask for general suggestions first and see if there's anything obvious I might have missed.

 

Edit: Solved. I made a really silly error, I had just mixed up the names of my NBT tags so they weren't the same in the read and write methods.  :-[

Link to comment
Share on other sites

I'm creating a TileEntity which functions like a furnace. It now works in the game, and the inventory and cook time stay and keep working when the GUI is opened and closed. But when I save and exit the game while something is in the inventory, it's lost when the world is reloaded. From using printlns it looks like the inventory is being written to NBT correctly, but when the game is loaded a new TileEntity is created instead of loading it from NBT like it should.

 

How can I make sure the game loads the existing TileEntity instead of creating a new one each time the world is loaded? I can post my code if needed but there's a lot of it so I thought I'd ask for general suggestions first and see if there's anything obvious I might have missed.

Hmm maybe you missed the thingymabober in the whoseitwhatsit that caused the dohicky to become flabbergasted.

 

 

How are we supposed to know if you don't show what you have?

 

*Edit The more code there is the more possibilities it might be...

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

I'm creating a TileEntity which functions like a furnace. It now works in the game, and the inventory and cook time stay and keep working when the GUI is opened and closed. But when I save and exit the game while something is in the inventory, it's lost when the world is reloaded. From using printlns it looks like the inventory is being written to NBT correctly, but when the game is loaded a new TileEntity is created instead of loading it from NBT like it should.

 

How can I make sure the game loads the existing TileEntity instead of creating a new one each time the world is loaded? I can post my code if needed but there's a lot of it so I thought I'd ask for general suggestions first and see if there's anything obvious I might have missed.

Hmm maybe you missed the thingymabober in the whoseitwhatsit that caused the dohicky to become flabbergasted.

 

 

How are we supposed to know if you don't show what you have?

 

Like I said, I am happy to post my code but there are lots of files and I wondered if there might be a common or obvious solution without the hassle of reading through everything. At this point I'm going to have to post 5+ classes worth of code because I have no ideas about what is causing the problem.

 

My custom furnace is one of several types subclassed from an abstract class so that's where a lot of the action happens. The abstract class:

 

package com.jj.jjmod.tileentities.abstracts ;

import javax.annotation.Nullable ;
import com.jj.jjmod.crafting.ModCookingManager ;
import net.minecraft.block.state.IBlockState ;
import net.minecraft.entity.player.EntityPlayer ;
import net.minecraft.entity.player.InventoryPlayer ;
import net.minecraft.inventory.Container ;
import net.minecraft.inventory.IInventory ;
import net.minecraft.inventory.ItemStackHelper ;
import net.minecraft.item.ItemStack ;
import net.minecraft.nbt.NBTTagCompound ;
import net.minecraft.nbt.NBTTagList ;
import net.minecraft.tileentity.TileEntityLockable ;
import net.minecraft.util.ITickable ;
import net.minecraft.util.math.BlockPos ;
import net.minecraft.util.math.MathHelper ;
import net.minecraft.world.World ;

public abstract class TEFurnaceAbstract extends TileEntityLockable
        implements ITickable , IInventory {

    public ItemStack[] stacks = new ItemStack[3] ;
    public int fuelLeft ;
    public int fuelEach ;
    public int cookSpent ;
    public int cookEach ;
    public ModCookingManager cookingManager ;

    public TEFurnaceAbstract( ModCookingManager cookingManager ,
            int cookEach ) {

        this.cookingManager = cookingManager ;
        this.cookEach = cookEach ;

    }

    // TODO
    // Inventory is not saved on world save/load
    // *-Move cookEach to constructor
    // cleanup

    @Override
    @Nullable
    public ItemStack getStackInSlot( int index ) {

        return this.stacks[index] ;

    }

    @Override
    @Nullable
    public ItemStack decrStackSize( int index , int count ) {

        return ItemStackHelper.getAndSplit( this.stacks , index , count ) ;

    }

    @Override
    @Nullable
    public ItemStack removeStackFromSlot( int index ) {

        return ItemStackHelper.getAndRemove( this.stacks , index ) ;

    }

    @Override
    public void setInventorySlotContents( int index ,
            @Nullable ItemStack stack ) {

        // Check if the same item
        boolean same = stack != null && stack
                .isItemEqual( this.stacks[index] ) && ItemStack
                        .areItemStackTagsEqual( stack , this.stacks[index] ) ;
        System.out.println( "setting stacks " + index + "to " + stack ) ;
        this.stacks[index] = stack ;
        System.out.println( "stacks " + index + " now " + this.stacks[index] ) ;

        // Make sure the stack is not illegal size
        if ( stack != null && stack.stackSize > this
                .getInventoryStackLimit() ) {

            stack.stackSize = this.getInventoryStackLimit() ;

        }

        // If a new item and in the cooking slot then update cook info
        if ( index == 0 && !same ) {

            System.out.println( "is new item and in cooking slot" ) ;

            this.cookSpent = 0 ;
            this.markDirty() ;

        }
    }

    public abstract int getFuelTime( ItemStack stack ) ;

    @Override
    public void readFromNBT( NBTTagCompound compound ) {

        System.out.println( "reading from nbt " + compound ) ;

        super.readFromNBT( compound ) ;

        // Get inventory stacks
        NBTTagList taglist = compound.getTagList( "stacks" , 10 ) ;
        this.stacks = new ItemStack[this.getSizeInventory()] ;

        System.out.println( "loading items list " + taglist ) ;

        for ( int i = 0 ; i < taglist.tagCount() ; ++i ) {
            NBTTagCompound tagcompound = taglist.getCompoundTagAt( i ) ;
            int j = tagcompound.getByte( "slot" ) ;

            if ( j >= 0 && j < this.stacks.length ) {
                this.stacks[j] =
                        ItemStack.loadItemStackFromNBT( tagcompound ) ;
            }
        }

        // Get other info
        this.fuelLeft = compound.getInteger( "fuelLeft" ) ;
        this.cookSpent = compound.getInteger( "cookSpent" ) ;
        this.cookEach = compound.getInteger( "cookEach" ) ;
        this.fuelEach = getFuelTime( this.stacks[1] ) ;

    }

    @Override
    public NBTTagCompound writeToNBT( NBTTagCompound compound ) {

        System.out.println( "writing to nbt" ) ;

        super.writeToNBT( compound ) ;

        // Send other info
        compound.setInteger( "fuelLeft" , this.fuelLeft ) ;
        compound.setInteger( "cookSpent" , this.cookSpent ) ;
        compound.setInteger( "cookEach" , this.cookEach ) ;

        // Send inventory stacks
        NBTTagList taglist = new NBTTagList() ;

        for ( int i = 0 ; i < this.stacks.length ; ++i ) {
            if ( this.stacks[i] != null ) {
                NBTTagCompound tagcompound = new NBTTagCompound() ;
                tagcompound.setByte( "slot" , (byte) i ) ;
                this.stacks[i].writeToNBT( tagcompound ) ;
                taglist.appendTag( tagcompound ) ;
            }
        }

        System.out.println( "setting items list " + taglist ) ;

        compound.setTag( "items" , taglist ) ;

        return compound ;
    }

    public boolean isBurning() {

        return this.fuelLeft > 0 ;

    }
    
    @Override
    public NBTTagCompound getUpdateTag() {
        
        System.out.println( "getting update tag" ) ;
        return this.writeToNBT( new NBTTagCompound() ) ;
    }

    @Override
    public void update() {

        // System.out.println( "slot 0 " + this.stacks[0] ) ;
        // System.out.println( "slot 1 " + this.stacks[1] ) ;
        // System.out.println( "slot 2 " + this.stacks[2] ) ;

        boolean isDirty = false ;

        // Reduce cook time
        if ( this.isBurning() ) {

            this.fuelLeft-- ;

        }

        // Do nothing if wrong side
        if ( this.worldObj.isRemote ) {

            return ;

        }

        // If ready to cook
        if ( this
                .canSmelt() && this.stacks[0] != null && this.stacks[1] != null ) {

            System.out.println( "ready to cook can smelt and stacks ready" ) ;
            System.out.println( "input stack " + this.stacks[0] ) ;
            System.out.println( "fuel stack " + this.stacks[1] ) ;

            // If already cooking
            if ( this.isBurning() ) {

                System.out.println( "is already cooking" ) ;

                this.cookSpent++ ;

                // If finished cooking
                if ( this.cookSpent == this.cookEach ) {

                    System.out.println( "finished cooking" ) ;

                    this.cookSpent = 0 ;
                    this.smeltItem() ;
                    isDirty = true ;

                }

                // If not already cooking
            } else {

                System.out.println( "not already cooking" ) ;

                // Start new cook
                this.fuelEach = getFuelTime( this.stacks[1] ) ;
                this.fuelLeft = this.fuelEach ;
                this.stacks[1].stackSize-- ;

                // If used last item
                if ( this.stacks[1].stackSize == 0 ) {

                    System.out.println( "used last item" ) ;

                    this.stacks[1] =
                            stacks[1].getItem().getContainerItem( stacks[1] ) ;

                }

                isDirty = true ;

            }
        }

        // If cooking from last fuel?
        if ( !this.isBurning() && this.cookSpent > 0 ) {

            this.cookSpent = MathHelper.clamp_int( this.cookSpent - 2 , 0 ,
                    this.cookEach ) ;

        }

        // If dirty
        if ( isDirty ) {

            this.markDirty() ;

        }
    }

    private boolean canSmelt() {

        // If no input
        if ( this.stacks[0] == null ) {

            return false ;

        }

        ItemStack result = cookingManager.getSmeltingResult( this.stacks[0] ) ;

        // Check recipe and space
        boolean hasRecipe = result != null ;
        boolean hasRoom =
                ( this.stacks[2] == null ) || ( hasRecipe && this.stacks[2]
                        .isItemEqual(
                                result ) && ( this.stacks[2].stackSize + result.stackSize < getInventoryStackLimit() ) ) ;

        return hasRecipe && hasRoom ;

    }

    public void smeltItem() {

        System.out.println( "smelt item" ) ;

        // If can't cook
        if ( !this.canSmelt() ) {

            System.out.println( "can't smelt" ) ;

            return ;

        }

        ItemStack result = cookingManager.getSmeltingResult( this.stacks[0] ) ;

        // If output empty
        if ( this.stacks[2] == null ) {

            System.out.println( "output empty " + this.stacks[2] ) ;

            this.stacks[2] = result.copy() ;

            // If output contains same as result
        } else if ( this.stacks[2].getItem() == result.getItem() ) {

            System.out.println( "output same as result " + this.stacks[2] ) ;

            this.stacks[2].stackSize += result.stackSize ;

        }

        this.stacks[0].stackSize-- ;

        if ( this.stacks[0].stackSize <= 0 ) {

            this.stacks[0] = null ;

        }
    }

    public boolean isItemFuel( ItemStack stack ) {

        return getFuelTime( stack ) > 0 ;

    }

    @Override
    public boolean isUseableByPlayer( EntityPlayer player ) {

        return true ;

    }

    @Override
    public abstract Container createContainer( InventoryPlayer playerInv ,
            EntityPlayer player ) ;

    public int getField( int id ) {

        switch ( id ) {
            case 0 :
                return this.fuelLeft ;
            case 1 :
                return this.fuelEach ;
            case 2 :
                return this.cookSpent ;
            case 3 :
                return this.cookEach ;
            default :
                return 0 ;
        }
    }

    public void setField( int id , int value ) {

        switch ( id ) {
            case 0 :
                this.fuelLeft = value ;
                break ;
            case 1 :
                this.fuelEach = value ;
                break ;
            case 2 :
                this.cookSpent = value ;
                break ;
            case 3 :
                this.cookEach = value ;
        }
    }

}

 

 

The subclass:

 

package com.jj.jjmod.tileentities ;

import com.jj.jjmod.crafting.CraftingManagers ;
import com.jj.jjmod.inventory.container.ContainerFurnaceCampfire ;
import com.jj.jjmod.tileentities.abstracts.TEFurnaceAbstract ;
import net.minecraft.entity.player.EntityPlayer ;
import net.minecraft.entity.player.InventoryPlayer ;
import net.minecraft.init.Items ;
import net.minecraft.inventory.Container ;
import net.minecraft.item.Item ;
import net.minecraft.item.ItemStack ;

public class TEFurnaceCampfire extends TEFurnaceAbstract {

    public TEFurnaceCampfire() {

        super( CraftingManagers.CAMPFIRE , 200 ) ;

    }

    @Override
    public Container createContainer( InventoryPlayer playerInv ,
            EntityPlayer player ) {

        return new ContainerFurnaceCampfire( playerInv , this ) ;

    }

    @Override
    public int getSizeInventory() {

        return this.stacks.length ;

    }

    @Override
    public int getInventoryStackLimit() {

        return 64 ;

    }

    // Required by interfaces
    @Override
    public void openInventory( EntityPlayer player ) {

    }

    @Override
    public void closeInventory( EntityPlayer player ) {

    }

    @Override
    public boolean isItemValidForSlot( int index , ItemStack stack ) {

        return true ;
        
    }

    @Override
    public int getFieldCount() {

        return 4 ;
        
    }

    @Override
    public void clear() {

        for ( int i = 0 ; i < this.stacks.length ; ++i ) {

            this.stacks[i] = null ;

        }
    }

    @Override
    public String getName() {

        return null ;
        
    }

    @Override
    public boolean hasCustomName() {

        return false ;
        
    }

    @Override
    public String getGuiID() {

        return null ;
        
    }

    @Override
    public int getFuelTime( ItemStack stack ) {
        
        System.out.println( "getting fuel time for " + stack ) ;
        
        if ( stack == null ) {
            
            return 0 ;
            
        }

        Item item = stack.getItem() ;
        
        if ( item == Items.COAL ) {
            
            System.out.println( "item is coal" ) ;
            
            return 100 ;
            
        }
        
        return 0 ;
        
    }
}

 

 

The same for the blocks, abstract class:

 

package com.jj.jjmod.blocks.abstracts ;

import javax.annotation.Nullable ;
import com.jj.jjmod.main.GuiHandler.GuiList ;
import com.jj.jjmod.main.Main ;
import com.jj.jjmod.tileentities.abstracts.TEFurnaceAbstract ;
import net.minecraft.block.BlockContainer ;
import net.minecraft.block.material.Material ;
import net.minecraft.block.state.IBlockState ;
import net.minecraft.creativetab.CreativeTabs ;
import net.minecraft.entity.player.EntityPlayer ;
import net.minecraft.init.Blocks ;
import net.minecraft.inventory.InventoryHelper ;
import net.minecraft.item.ItemStack ;
import net.minecraft.tileentity.TileEntity ;
import net.minecraft.util.EnumFacing ;
import net.minecraft.util.EnumHand ;
import net.minecraft.util.math.BlockPos ;
import net.minecraft.world.World ;

public abstract class BlockFurnaceAbstract extends BlockContainer {

    public GuiList GUI ;

    public BlockFurnaceAbstract( String name , Material material ,
            GuiList GUI ) {

        super( material ) ;
        this.setRegistryName( name ) ;
        this.setUnlocalizedName( name ) ;
        this.setCreativeTab( CreativeTabs.DECORATIONS ) ;
        this.GUI = GUI ;

    }

    @Override
    public boolean onBlockActivated( World world , BlockPos pos ,
            IBlockState state , EntityPlayer player , EnumHand hand ,
            @Nullable ItemStack item , EnumFacing side , float x , float y ,
            float z ) {

        if ( world.isRemote ) {

            return true ;

        }

        System.out.println( "on block activated pos " + pos ) ;

        player.openGui( Main.instance , this.GUI.ordinal() , world ,
                pos.getX() , pos.getY() , pos.getZ() ) ;

        return true ;

    }

    public void breakBlock( World worldIn , BlockPos pos , IBlockState state ) {

        TileEntity tileentity = worldIn.getTileEntity( pos ) ;

        if ( tileentity instanceof TEFurnaceAbstract ) {

            InventoryHelper.dropInventoryItems( worldIn , pos ,
                    (TEFurnaceAbstract) tileentity ) ;

        }

        super.breakBlock( worldIn , pos , state ) ;
    }

    // copy
    public static void setState( boolean active , World worldIn ,
            BlockPos pos ) {

        System.out.println( "set state" ) ;

        IBlockState iblockstate = worldIn.getBlockState( pos ) ;
        TileEntity tileentity = worldIn.getTileEntity( pos ) ;

        if ( tileentity != null ) {
            tileentity.validate() ;
            worldIn.setTileEntity( pos , tileentity ) ;
        }
    }

    @Override
    public abstract ItemStack getItem( World world , BlockPos pos ,
            IBlockState state ) ;

    /*
     * @Override public TileEntity createNewTileEntity( World world , int meta )
     * {
     * 
     * System.out.println( "creating new tileentity" ) ; return this.tileEntity
     * ;
     * 
     * }
     */

}

 

 

Subclass:

 

package com.jj.jjmod.blocks ;

import com.jj.jjmod.blocks.abstracts.BlockFurnaceAbstract ;
import com.jj.jjmod.main.GuiHandler.GuiList ;
import com.jj.jjmod.tileentities.TEFurnaceCampfire ;
import net.minecraft.block.material.Material ;
import net.minecraft.block.state.IBlockState ;
import net.minecraft.item.Item ;
import net.minecraft.item.ItemStack ;
import net.minecraft.tileentity.TileEntity ;
import net.minecraft.util.math.BlockPos ;
import net.minecraft.world.World ;

public class BlockFurnaceCampfire extends BlockFurnaceAbstract {
    
    public BlockFurnaceCampfire() {

        super( "furnaceCampfire" , Material.PLANTS , GuiList.CAMPFIRE ) ;

    }

    @Override
    public ItemStack getItem( World world , BlockPos pos , IBlockState state ) {

        return new ItemStack(
                Item.getItemFromBlock( ModBlocks.furnaceCampfire ) ) ;
    }

    @Override
    public TileEntity createNewTileEntity( World world , int meta ) {

        System.out.println( "creating new tileentity" ) ;
        return new TEFurnaceCampfire() ;

    }

}

 

 

The Containers if you need to see those - abstract class:

 

package com.jj.jjmod.inventory.container.abstracts ;

import javax.annotation.Nullable ;
import com.jj.jjmod.blocks.abstracts.BlockFurnaceAbstract ;
import com.jj.jjmod.tileentities.abstracts.TEFurnaceAbstract ;
import net.minecraft.entity.player.EntityPlayer ;
import net.minecraft.entity.player.InventoryPlayer ;
import net.minecraft.inventory.Container ;
import net.minecraft.inventory.IContainerListener ;
import net.minecraft.inventory.IInventory ;
import net.minecraft.inventory.Slot ;
import net.minecraft.inventory.SlotFurnaceFuel ;
import net.minecraft.inventory.SlotFurnaceOutput ;
import net.minecraft.item.ItemStack ;
import net.minecraftforge.fml.relauncher.Side ;
import net.minecraftforge.fml.relauncher.SideOnly ;

public class ContainerFurnaceAbstract extends Container {

    public final IInventory tileFurnace ;
    public int fuelLeft ;
    public int fuelEach ;
    public int cookSpent ;
    public int cookEach ;

    public ContainerFurnaceAbstract( InventoryPlayer playerInv ,
            IInventory tileFurnace ) {

        this.tileFurnace = tileFurnace ;

        // Add furnace slots
        this.addSlotToContainer( new Slot( this.tileFurnace , 0 , 56 , 17 ) ) ;
        this.addSlotToContainer( new SlotFurnaceFuel(
                this.tileFurnace , 1 , 56 , 53 ) ) ;
        this.addSlotToContainer( new SlotFurnaceOutput( playerInv.player ,
                this.tileFurnace , 2 , 116 , 35 ) ) ;

        // Add inventory grid slots
        for ( int i = 0 ; i < 3 ; ++i ) {

            for ( int j = 0 ; j < 9 ; ++j ) {

                this.addSlotToContainer( new Slot( playerInv , j + i * 9 + 9 ,
                        8 + j * 18 , 84 + i * 18 ) ) ;

            }
        }

        // Add hotbar slots
        for ( int k = 0 ; k < 9 ; ++k ) {

            this.addSlotToContainer( new Slot(
                    playerInv , k , 8 + k * 18 , 142 ) ) ;
        }
    }

    @Override
    public void addListener( IContainerListener listener ) {

        super.addListener( listener ) ;
        listener.sendAllWindowProperties( this , this.tileFurnace ) ;

    }

    @Override
    public void detectAndSendChanges() {
        
        super.detectAndSendChanges() ;

        for ( int i = 0 ; i < this.listeners.size() ; ++i ) {
            IContainerListener icontainerlistener =
                    (IContainerListener) this.listeners.get( i ) ;

            if ( this.fuelLeft != this.tileFurnace.getField( 0 ) ) {
                icontainerlistener.sendProgressBarUpdate( this , 0 ,
                        this.tileFurnace.getField( 0 ) ) ;
            }

            if ( this.fuelEach != this.tileFurnace.getField( 1 ) ) {
                icontainerlistener.sendProgressBarUpdate( this , 1 ,
                        this.tileFurnace.getField( 1 ) ) ;
            }

            if ( this.cookSpent != this.tileFurnace.getField( 2 ) ) {
                icontainerlistener.sendProgressBarUpdate( this , 2 ,
                        this.tileFurnace.getField( 2 ) ) ;
            }

            if ( this.cookEach != this.tileFurnace.getField( 3 ) ) {
                icontainerlistener.sendProgressBarUpdate( this , 3 ,
                        this.tileFurnace.getField( 3 ) ) ;
            }
        }

        this.fuelLeft = this.tileFurnace.getField( 0 ) ;
        this.fuelEach = this.tileFurnace.getField( 1 ) ;
        this.cookSpent = this.tileFurnace.getField( 2 ) ;
        this.cookEach = this.tileFurnace.getField( 3 ) ;
    }

    @Override
    @SideOnly( Side.CLIENT )
    public void updateProgressBar( int id , int data ) {

        this.tileFurnace.setField( id , data ) ;

    }

    @Override
    public boolean canInteractWith( EntityPlayer player ) {        
        
        return this.tileFurnace.isUseableByPlayer( player ) ;

    }

    //TODO direct copy from vanilla furnace with minimal edits
    @Nullable
    public ItemStack transferStackInSlot( EntityPlayer playerIn , int index ) {

        System.out.println( "transfer stack in slot" ) ;
        
        ItemStack itemstack = null ;
        Slot slot = (Slot) this.inventorySlots.get( index ) ;

        if ( slot != null && slot.getHasStack() ) {
            
            System.out.println( "slot already has stack " ) ;
            ItemStack itemstack1 = slot.getStack() ;
            itemstack = itemstack1.copy() ;

            if ( index == 2 ) {
                
                System.out.println( "putting into index 2" ) ;
                
                if ( !this.mergeItemStack( itemstack1 , 3 , 39 , true ) ) {
                    return null ;
                }

                slot.onSlotChange( itemstack1 , itemstack ) ;
            } else if ( index != 1 && index != 0 ) {
                
                System.out.println( "putting into index not 1 or 0" ) ;
                
                if ( ( (TEFurnaceAbstract) tileFurnace ).cookingManager
                        .getSmeltingResult( itemstack1 ) != null ) {
                    if ( !this.mergeItemStack( itemstack1 , 0 , 1 , false ) ) {
                        return null ;
                    }
                } else if ( ( (TEFurnaceAbstract) tileFurnace ).isItemFuel( itemstack1 ) ) {
                    if ( !this.mergeItemStack( itemstack1 , 1 , 2 , false ) ) {
                        return null ;
                    }
                } else if ( index >= 3 && index < 30 ) {
                    if ( !this.mergeItemStack( itemstack1 , 30 , 39 ,
                            false ) ) {
                        return null ;
                    }
                } else if ( index >= 30 && index < 39 && !this
                        .mergeItemStack( itemstack1 , 3 , 30 , false ) ) {
                    return null ;
                }
            } else if ( !this.mergeItemStack( itemstack1 , 3 , 39 , false ) ) {
                return null ;
            }

            if ( itemstack1.stackSize == 0 ) {
                slot.putStack( (ItemStack) null ) ;
            } else {
                slot.onSlotChanged() ;
            }

            if ( itemstack1.stackSize == itemstack.stackSize ) {
                return null ;
            }

            slot.onPickupFromSlot( playerIn , itemstack1 ) ;
        }

        tileFurnace.markDirty() ;
        return itemstack ;
    }

}

 

 

Subclass:

 

package com.jj.jjmod.inventory.container ;

import com.jj.jjmod.inventory.container.abstracts.ContainerFurnaceAbstract ;
import com.jj.jjmod.tileentities.TEFurnaceCampfire ;
import net.minecraft.entity.player.InventoryPlayer ;
import net.minecraft.inventory.IInventory ;

public class ContainerFurnaceCampfire extends ContainerFurnaceAbstract {

    public ContainerFurnaceCampfire( InventoryPlayer playerInv , IInventory te ) {
       
        super( playerInv , te ) ;

    }

}

(I know this isn't a necessary subclass yet but I have plans to add more customisations so that's why)

 

 

I also have the TileEntities registered in init in my common proxy, the blocks registered in preinit, and a GUI handler to set up the containers. I can post all of that if you really want but I'll stop here for now.

Link to comment
Share on other sites

I'm creating a TileEntity which functions like a furnace. It now works in the game, and the inventory and cook time stay and keep working when the GUI is opened and closed. But when I save and exit the game while something is in the inventory, it's lost when the world is reloaded. From using printlns it looks like the inventory is being written to NBT correctly, but when the game is loaded a new TileEntity is created instead of loading it from NBT like it should.

 

How can I make sure the game loads the existing TileEntity instead of creating a new one each time the world is loaded? I can post my code if needed but there's a lot of it so I thought I'd ask for general suggestions first and see if there's anything obvious I might have missed.

Hmm maybe you missed the thingymabober in the whoseitwhatsit that caused the dohicky to become flabbergasted.

 

 

How are we supposed to know if you don't show what you have?

 

Like I said, I am happy to post my code but there are lots of files and I wondered if there might be a common or obvious solution without the hassle of reading through everything. At this point I'm going to have to post 5+ classes worth of code because I have no ideas about what is causing the problem.

 

My custom furnace is one of several types subclassed from an abstract class so that's where a lot of the action happens. The abstract class:

 

package com.jj.jjmod.tileentities.abstracts ;

import javax.annotation.Nullable ;
import com.jj.jjmod.crafting.ModCookingManager ;
import net.minecraft.block.state.IBlockState ;
import net.minecraft.entity.player.EntityPlayer ;
import net.minecraft.entity.player.InventoryPlayer ;
import net.minecraft.inventory.Container ;
import net.minecraft.inventory.IInventory ;
import net.minecraft.inventory.ItemStackHelper ;
import net.minecraft.item.ItemStack ;
import net.minecraft.nbt.NBTTagCompound ;
import net.minecraft.nbt.NBTTagList ;
import net.minecraft.tileentity.TileEntityLockable ;
import net.minecraft.util.ITickable ;
import net.minecraft.util.math.BlockPos ;
import net.minecraft.util.math.MathHelper ;
import net.minecraft.world.World ;

public abstract class TEFurnaceAbstract extends TileEntityLockable
        implements ITickable , IInventory {

    public ItemStack[] stacks = new ItemStack[3] ;
    public int fuelLeft ;
    public int fuelEach ;
    public int cookSpent ;
    public int cookEach ;
    public ModCookingManager cookingManager ;

    public TEFurnaceAbstract( ModCookingManager cookingManager ,
            int cookEach ) {

        this.cookingManager = cookingManager ;
        this.cookEach = cookEach ;

    }

    // TODO
    // Inventory is not saved on world save/load
    // *-Move cookEach to constructor
    // cleanup

    @Override
    @Nullable
    public ItemStack getStackInSlot( int index ) {

        return this.stacks[index] ;

    }

    @Override
    @Nullable
    public ItemStack decrStackSize( int index , int count ) {

        return ItemStackHelper.getAndSplit( this.stacks , index , count ) ;

    }

    @Override
    @Nullable
    public ItemStack removeStackFromSlot( int index ) {

        return ItemStackHelper.getAndRemove( this.stacks , index ) ;

    }

    @Override
    public void setInventorySlotContents( int index ,
            @Nullable ItemStack stack ) {

        // Check if the same item
        boolean same = stack != null && stack
                .isItemEqual( this.stacks[index] ) && ItemStack
                        .areItemStackTagsEqual( stack , this.stacks[index] ) ;
        System.out.println( "setting stacks " + index + "to " + stack ) ;
        this.stacks[index] = stack ;
        System.out.println( "stacks " + index + " now " + this.stacks[index] ) ;

        // Make sure the stack is not illegal size
        if ( stack != null && stack.stackSize > this
                .getInventoryStackLimit() ) {

            stack.stackSize = this.getInventoryStackLimit() ;

        }

        // If a new item and in the cooking slot then update cook info
        if ( index == 0 && !same ) {

            System.out.println( "is new item and in cooking slot" ) ;

            this.cookSpent = 0 ;
            this.markDirty() ;

        }
    }

    public abstract int getFuelTime( ItemStack stack ) ;

    @Override
    public void readFromNBT( NBTTagCompound compound ) {

        System.out.println( "reading from nbt " + compound ) ;

        super.readFromNBT( compound ) ;

        // Get inventory stacks
        NBTTagList taglist = compound.getTagList( "stacks" , 10 ) ;
        this.stacks = new ItemStack[this.getSizeInventory()] ;

        System.out.println( "loading items list " + taglist ) ;

        for ( int i = 0 ; i < taglist.tagCount() ; ++i ) {
            NBTTagCompound tagcompound = taglist.getCompoundTagAt( i ) ;
            int j = tagcompound.getByte( "slot" ) ;

            if ( j >= 0 && j < this.stacks.length ) {
                this.stacks[j] =
                        ItemStack.loadItemStackFromNBT( tagcompound ) ;
            }
        }

        // Get other info
        this.fuelLeft = compound.getInteger( "fuelLeft" ) ;
        this.cookSpent = compound.getInteger( "cookSpent" ) ;
        this.cookEach = compound.getInteger( "cookEach" ) ;
        this.fuelEach = getFuelTime( this.stacks[1] ) ;

    }

    @Override
    public NBTTagCompound writeToNBT( NBTTagCompound compound ) {

        System.out.println( "writing to nbt" ) ;

        super.writeToNBT( compound ) ;

        // Send other info
        compound.setInteger( "fuelLeft" , this.fuelLeft ) ;
        compound.setInteger( "cookSpent" , this.cookSpent ) ;
        compound.setInteger( "cookEach" , this.cookEach ) ;

        // Send inventory stacks
        NBTTagList taglist = new NBTTagList() ;

        for ( int i = 0 ; i < this.stacks.length ; ++i ) {
            if ( this.stacks[i] != null ) {
                NBTTagCompound tagcompound = new NBTTagCompound() ;
                tagcompound.setByte( "slot" , (byte) i ) ;
                this.stacks[i].writeToNBT( tagcompound ) ;
                taglist.appendTag( tagcompound ) ;
            }
        }

        System.out.println( "setting items list " + taglist ) ;

        compound.setTag( "items" , taglist ) ;

        return compound ;
    }

    public boolean isBurning() {

        return this.fuelLeft > 0 ;

    }
    
    @Override
    public NBTTagCompound getUpdateTag() {
        
        System.out.println( "getting update tag" ) ;
        return this.writeToNBT( new NBTTagCompound() ) ;
    }

    @Override
    public void update() {

        // System.out.println( "slot 0 " + this.stacks[0] ) ;
        // System.out.println( "slot 1 " + this.stacks[1] ) ;
        // System.out.println( "slot 2 " + this.stacks[2] ) ;

        boolean isDirty = false ;

        // Reduce cook time
        if ( this.isBurning() ) {

            this.fuelLeft-- ;

        }

        // Do nothing if wrong side
        if ( this.worldObj.isRemote ) {

            return ;

        }

        // If ready to cook
        if ( this
                .canSmelt() && this.stacks[0] != null && this.stacks[1] != null ) {

            System.out.println( "ready to cook can smelt and stacks ready" ) ;
            System.out.println( "input stack " + this.stacks[0] ) ;
            System.out.println( "fuel stack " + this.stacks[1] ) ;

            // If already cooking
            if ( this.isBurning() ) {

                System.out.println( "is already cooking" ) ;

                this.cookSpent++ ;

                // If finished cooking
                if ( this.cookSpent == this.cookEach ) {

                    System.out.println( "finished cooking" ) ;

                    this.cookSpent = 0 ;
                    this.smeltItem() ;
                    isDirty = true ;

                }

                // If not already cooking
            } else {

                System.out.println( "not already cooking" ) ;

                // Start new cook
                this.fuelEach = getFuelTime( this.stacks[1] ) ;
                this.fuelLeft = this.fuelEach ;
                this.stacks[1].stackSize-- ;

                // If used last item
                if ( this.stacks[1].stackSize == 0 ) {

                    System.out.println( "used last item" ) ;

                    this.stacks[1] =
                            stacks[1].getItem().getContainerItem( stacks[1] ) ;

                }

                isDirty = true ;

            }
        }

        // If cooking from last fuel?
        if ( !this.isBurning() && this.cookSpent > 0 ) {

            this.cookSpent = MathHelper.clamp_int( this.cookSpent - 2 , 0 ,
                    this.cookEach ) ;

        }

        // If dirty
        if ( isDirty ) {

            this.markDirty() ;

        }
    }

    private boolean canSmelt() {

        // If no input
        if ( this.stacks[0] == null ) {

            return false ;

        }

        ItemStack result = cookingManager.getSmeltingResult( this.stacks[0] ) ;

        // Check recipe and space
        boolean hasRecipe = result != null ;
        boolean hasRoom =
                ( this.stacks[2] == null ) || ( hasRecipe && this.stacks[2]
                        .isItemEqual(
                                result ) && ( this.stacks[2].stackSize + result.stackSize < getInventoryStackLimit() ) ) ;

        return hasRecipe && hasRoom ;

    }

    public void smeltItem() {

        System.out.println( "smelt item" ) ;

        // If can't cook
        if ( !this.canSmelt() ) {

            System.out.println( "can't smelt" ) ;

            return ;

        }

        ItemStack result = cookingManager.getSmeltingResult( this.stacks[0] ) ;

        // If output empty
        if ( this.stacks[2] == null ) {

            System.out.println( "output empty " + this.stacks[2] ) ;

            this.stacks[2] = result.copy() ;

            // If output contains same as result
        } else if ( this.stacks[2].getItem() == result.getItem() ) {

            System.out.println( "output same as result " + this.stacks[2] ) ;

            this.stacks[2].stackSize += result.stackSize ;

        }

        this.stacks[0].stackSize-- ;

        if ( this.stacks[0].stackSize <= 0 ) {

            this.stacks[0] = null ;

        }
    }

    public boolean isItemFuel( ItemStack stack ) {

        return getFuelTime( stack ) > 0 ;

    }

    @Override
    public boolean isUseableByPlayer( EntityPlayer player ) {

        return true ;

    }

    @Override
    public abstract Container createContainer( InventoryPlayer playerInv ,
            EntityPlayer player ) ;

    public int getField( int id ) {

        switch ( id ) {
            case 0 :
                return this.fuelLeft ;
            case 1 :
                return this.fuelEach ;
            case 2 :
                return this.cookSpent ;
            case 3 :
                return this.cookEach ;
            default :
                return 0 ;
        }
    }

    public void setField( int id , int value ) {

        switch ( id ) {
            case 0 :
                this.fuelLeft = value ;
                break ;
            case 1 :
                this.fuelEach = value ;
                break ;
            case 2 :
                this.cookSpent = value ;
                break ;
            case 3 :
                this.cookEach = value ;
        }
    }

}

 

 

The subclass:

 

package com.jj.jjmod.tileentities ;

import com.jj.jjmod.crafting.CraftingManagers ;
import com.jj.jjmod.inventory.container.ContainerFurnaceCampfire ;
import com.jj.jjmod.tileentities.abstracts.TEFurnaceAbstract ;
import net.minecraft.entity.player.EntityPlayer ;
import net.minecraft.entity.player.InventoryPlayer ;
import net.minecraft.init.Items ;
import net.minecraft.inventory.Container ;
import net.minecraft.item.Item ;
import net.minecraft.item.ItemStack ;

public class TEFurnaceCampfire extends TEFurnaceAbstract {

    public TEFurnaceCampfire() {

        super( CraftingManagers.CAMPFIRE , 200 ) ;

    }

    @Override
    public Container createContainer( InventoryPlayer playerInv ,
            EntityPlayer player ) {

        return new ContainerFurnaceCampfire( playerInv , this ) ;

    }

    @Override
    public int getSizeInventory() {

        return this.stacks.length ;

    }

    @Override
    public int getInventoryStackLimit() {

        return 64 ;

    }

    // Required by interfaces
    @Override
    public void openInventory( EntityPlayer player ) {

    }

    @Override
    public void closeInventory( EntityPlayer player ) {

    }

    @Override
    public boolean isItemValidForSlot( int index , ItemStack stack ) {

        return true ;
        
    }

    @Override
    public int getFieldCount() {

        return 4 ;
        
    }

    @Override
    public void clear() {

        for ( int i = 0 ; i < this.stacks.length ; ++i ) {

            this.stacks[i] = null ;

        }
    }

    @Override
    public String getName() {

        return null ;
        
    }

    @Override
    public boolean hasCustomName() {

        return false ;
        
    }

    @Override
    public String getGuiID() {

        return null ;
        
    }

    @Override
    public int getFuelTime( ItemStack stack ) {
        
        System.out.println( "getting fuel time for " + stack ) ;
        
        if ( stack == null ) {
            
            return 0 ;
            
        }

        Item item = stack.getItem() ;
        
        if ( item == Items.COAL ) {
            
            System.out.println( "item is coal" ) ;
            
            return 100 ;
            
        }
        
        return 0 ;
        
    }
}

 

 

The same for the blocks, abstract class:

 

package com.jj.jjmod.blocks.abstracts ;

import javax.annotation.Nullable ;
import com.jj.jjmod.main.GuiHandler.GuiList ;
import com.jj.jjmod.main.Main ;
import com.jj.jjmod.tileentities.abstracts.TEFurnaceAbstract ;
import net.minecraft.block.BlockContainer ;
import net.minecraft.block.material.Material ;
import net.minecraft.block.state.IBlockState ;
import net.minecraft.creativetab.CreativeTabs ;
import net.minecraft.entity.player.EntityPlayer ;
import net.minecraft.init.Blocks ;
import net.minecraft.inventory.InventoryHelper ;
import net.minecraft.item.ItemStack ;
import net.minecraft.tileentity.TileEntity ;
import net.minecraft.util.EnumFacing ;
import net.minecraft.util.EnumHand ;
import net.minecraft.util.math.BlockPos ;
import net.minecraft.world.World ;

public abstract class BlockFurnaceAbstract extends BlockContainer {

    public GuiList GUI ;

    public BlockFurnaceAbstract( String name , Material material ,
            GuiList GUI ) {

        super( material ) ;
        this.setRegistryName( name ) ;
        this.setUnlocalizedName( name ) ;
        this.setCreativeTab( CreativeTabs.DECORATIONS ) ;
        this.GUI = GUI ;

    }

    @Override
    public boolean onBlockActivated( World world , BlockPos pos ,
            IBlockState state , EntityPlayer player , EnumHand hand ,
            @Nullable ItemStack item , EnumFacing side , float x , float y ,
            float z ) {

        if ( world.isRemote ) {

            return true ;

        }

        System.out.println( "on block activated pos " + pos ) ;

        player.openGui( Main.instance , this.GUI.ordinal() , world ,
                pos.getX() , pos.getY() , pos.getZ() ) ;

        return true ;

    }

    public void breakBlock( World worldIn , BlockPos pos , IBlockState state ) {

        TileEntity tileentity = worldIn.getTileEntity( pos ) ;

        if ( tileentity instanceof TEFurnaceAbstract ) {

            InventoryHelper.dropInventoryItems( worldIn , pos ,
                    (TEFurnaceAbstract) tileentity ) ;

        }

        super.breakBlock( worldIn , pos , state ) ;
    }

    // copy
    public static void setState( boolean active , World worldIn ,
            BlockPos pos ) {

        System.out.println( "set state" ) ;

        IBlockState iblockstate = worldIn.getBlockState( pos ) ;
        TileEntity tileentity = worldIn.getTileEntity( pos ) ;

        if ( tileentity != null ) {
            tileentity.validate() ;
            worldIn.setTileEntity( pos , tileentity ) ;
        }
    }

    @Override
    public abstract ItemStack getItem( World world , BlockPos pos ,
            IBlockState state ) ;

    /*
     * @Override public TileEntity createNewTileEntity( World world , int meta )
     * {
     * 
     * System.out.println( "creating new tileentity" ) ; return this.tileEntity
     * ;
     * 
     * }
     */

}

 

 

Subclass:

 

package com.jj.jjmod.blocks ;

import com.jj.jjmod.blocks.abstracts.BlockFurnaceAbstract ;
import com.jj.jjmod.main.GuiHandler.GuiList ;
import com.jj.jjmod.tileentities.TEFurnaceCampfire ;
import net.minecraft.block.material.Material ;
import net.minecraft.block.state.IBlockState ;
import net.minecraft.item.Item ;
import net.minecraft.item.ItemStack ;
import net.minecraft.tileentity.TileEntity ;
import net.minecraft.util.math.BlockPos ;
import net.minecraft.world.World ;

public class BlockFurnaceCampfire extends BlockFurnaceAbstract {
    
    public BlockFurnaceCampfire() {

        super( "furnaceCampfire" , Material.PLANTS , GuiList.CAMPFIRE ) ;

    }

    @Override
    public ItemStack getItem( World world , BlockPos pos , IBlockState state ) {

        return new ItemStack(
                Item.getItemFromBlock( ModBlocks.furnaceCampfire ) ) ;
    }

    @Override
    public TileEntity createNewTileEntity( World world , int meta ) {

        System.out.println( "creating new tileentity" ) ;
        return new TEFurnaceCampfire() ;

    }

}

 

 

The Containers if you need to see those - abstract class:

 

package com.jj.jjmod.inventory.container.abstracts ;

import javax.annotation.Nullable ;
import com.jj.jjmod.blocks.abstracts.BlockFurnaceAbstract ;
import com.jj.jjmod.tileentities.abstracts.TEFurnaceAbstract ;
import net.minecraft.entity.player.EntityPlayer ;
import net.minecraft.entity.player.InventoryPlayer ;
import net.minecraft.inventory.Container ;
import net.minecraft.inventory.IContainerListener ;
import net.minecraft.inventory.IInventory ;
import net.minecraft.inventory.Slot ;
import net.minecraft.inventory.SlotFurnaceFuel ;
import net.minecraft.inventory.SlotFurnaceOutput ;
import net.minecraft.item.ItemStack ;
import net.minecraftforge.fml.relauncher.Side ;
import net.minecraftforge.fml.relauncher.SideOnly ;

public class ContainerFurnaceAbstract extends Container {

    public final IInventory tileFurnace ;
    public int fuelLeft ;
    public int fuelEach ;
    public int cookSpent ;
    public int cookEach ;

    public ContainerFurnaceAbstract( InventoryPlayer playerInv ,
            IInventory tileFurnace ) {

        this.tileFurnace = tileFurnace ;

        // Add furnace slots
        this.addSlotToContainer( new Slot( this.tileFurnace , 0 , 56 , 17 ) ) ;
        this.addSlotToContainer( new SlotFurnaceFuel(
                this.tileFurnace , 1 , 56 , 53 ) ) ;
        this.addSlotToContainer( new SlotFurnaceOutput( playerInv.player ,
                this.tileFurnace , 2 , 116 , 35 ) ) ;

        // Add inventory grid slots
        for ( int i = 0 ; i < 3 ; ++i ) {

            for ( int j = 0 ; j < 9 ; ++j ) {

                this.addSlotToContainer( new Slot( playerInv , j + i * 9 + 9 ,
                        8 + j * 18 , 84 + i * 18 ) ) ;

            }
        }

        // Add hotbar slots
        for ( int k = 0 ; k < 9 ; ++k ) {

            this.addSlotToContainer( new Slot(
                    playerInv , k , 8 + k * 18 , 142 ) ) ;
        }
    }

    @Override
    public void addListener( IContainerListener listener ) {

        super.addListener( listener ) ;
        listener.sendAllWindowProperties( this , this.tileFurnace ) ;

    }

    @Override
    public void detectAndSendChanges() {
        
        super.detectAndSendChanges() ;

        for ( int i = 0 ; i < this.listeners.size() ; ++i ) {
            IContainerListener icontainerlistener =
                    (IContainerListener) this.listeners.get( i ) ;

            if ( this.fuelLeft != this.tileFurnace.getField( 0 ) ) {
                icontainerlistener.sendProgressBarUpdate( this , 0 ,
                        this.tileFurnace.getField( 0 ) ) ;
            }

            if ( this.fuelEach != this.tileFurnace.getField( 1 ) ) {
                icontainerlistener.sendProgressBarUpdate( this , 1 ,
                        this.tileFurnace.getField( 1 ) ) ;
            }

            if ( this.cookSpent != this.tileFurnace.getField( 2 ) ) {
                icontainerlistener.sendProgressBarUpdate( this , 2 ,
                        this.tileFurnace.getField( 2 ) ) ;
            }

            if ( this.cookEach != this.tileFurnace.getField( 3 ) ) {
                icontainerlistener.sendProgressBarUpdate( this , 3 ,
                        this.tileFurnace.getField( 3 ) ) ;
            }
        }

        this.fuelLeft = this.tileFurnace.getField( 0 ) ;
        this.fuelEach = this.tileFurnace.getField( 1 ) ;
        this.cookSpent = this.tileFurnace.getField( 2 ) ;
        this.cookEach = this.tileFurnace.getField( 3 ) ;
    }

    @Override
    @SideOnly( Side.CLIENT )
    public void updateProgressBar( int id , int data ) {

        this.tileFurnace.setField( id , data ) ;

    }

    @Override
    public boolean canInteractWith( EntityPlayer player ) {        
        
        return this.tileFurnace.isUseableByPlayer( player ) ;

    }

    //TODO direct copy from vanilla furnace with minimal edits
    @Nullable
    public ItemStack transferStackInSlot( EntityPlayer playerIn , int index ) {

        System.out.println( "transfer stack in slot" ) ;
        
        ItemStack itemstack = null ;
        Slot slot = (Slot) this.inventorySlots.get( index ) ;

        if ( slot != null && slot.getHasStack() ) {
            
            System.out.println( "slot already has stack " ) ;
            ItemStack itemstack1 = slot.getStack() ;
            itemstack = itemstack1.copy() ;

            if ( index == 2 ) {
                
                System.out.println( "putting into index 2" ) ;
                
                if ( !this.mergeItemStack( itemstack1 , 3 , 39 , true ) ) {
                    return null ;
                }

                slot.onSlotChange( itemstack1 , itemstack ) ;
            } else if ( index != 1 && index != 0 ) {
                
                System.out.println( "putting into index not 1 or 0" ) ;
                
                if ( ( (TEFurnaceAbstract) tileFurnace ).cookingManager
                        .getSmeltingResult( itemstack1 ) != null ) {
                    if ( !this.mergeItemStack( itemstack1 , 0 , 1 , false ) ) {
                        return null ;
                    }
                } else if ( ( (TEFurnaceAbstract) tileFurnace ).isItemFuel( itemstack1 ) ) {
                    if ( !this.mergeItemStack( itemstack1 , 1 , 2 , false ) ) {
                        return null ;
                    }
                } else if ( index >= 3 && index < 30 ) {
                    if ( !this.mergeItemStack( itemstack1 , 30 , 39 ,
                            false ) ) {
                        return null ;
                    }
                } else if ( index >= 30 && index < 39 && !this
                        .mergeItemStack( itemstack1 , 3 , 30 , false ) ) {
                    return null ;
                }
            } else if ( !this.mergeItemStack( itemstack1 , 3 , 39 , false ) ) {
                return null ;
            }

            if ( itemstack1.stackSize == 0 ) {
                slot.putStack( (ItemStack) null ) ;
            } else {
                slot.onSlotChanged() ;
            }

            if ( itemstack1.stackSize == itemstack.stackSize ) {
                return null ;
            }

            slot.onPickupFromSlot( playerIn , itemstack1 ) ;
        }

        tileFurnace.markDirty() ;
        return itemstack ;
    }

}

 

 

Subclass:

 

package com.jj.jjmod.inventory.container ;

import com.jj.jjmod.inventory.container.abstracts.ContainerFurnaceAbstract ;
import com.jj.jjmod.tileentities.TEFurnaceCampfire ;
import net.minecraft.entity.player.InventoryPlayer ;
import net.minecraft.inventory.IInventory ;

public class ContainerFurnaceCampfire extends ContainerFurnaceAbstract {

    public ContainerFurnaceCampfire( InventoryPlayer playerInv , IInventory te ) {
       
        super( playerInv , te ) ;

    }

}

(I know this isn't a necessary subclass yet but I have plans to add more customisations so that's why)

 

 

I also have the TileEntities registered in init in my common proxy, the blocks registered in preinit, and a GUI handler to set up the containers. I can post all of that if you really want but I'll stop here for now.

You write your ItemStacks to the tag items and then try to read them from stacks. That was not obvious, also I see you override getUpdateTag(...) but not its partner.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

You write your ItemStacks to the tag items and then try to read them from stacks. That was not obvious, also I see you override getUpdateTag(...) but not its partner.

 

Oh my goodness, that is such an embarrassing mistake to make and not notice. Thank you for pointing it out.  :-[ The inventory is now correctly saving and loading with the world.

 

(The getUpdateTag(...) was just an experiment from another post I found about a similar problem so I added it without fully understanding, but luckily it turns out it's not needed at all anyway).

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.

Announcements



×
×
  • Create New...

Important Information

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