Jump to content

Recommended Posts

Posted

I haven't been able to find an answer to this question. I have a custom gui inventory that can store items, but should I be extending TileEntityLockableLoot or TileEntity? How does this necessarily affect using ItemStackHandler. Seen a few examples, and a lot of them vary. Still kind of confused on this. Thanks.

Posted

After a quick code browse, it looks like TileEntityLockableLoot supports not only inventory, but also a locking function and loot tables, ie. can be made to spawn naturally with loot already in it using said loot tables.

 

TileEntityLockable is similar, but without the loot tables.

 

If you don't care about locks or loot tables, you probably don't need either one, so a basic TileEntity should be fine, especially if you already have it working as intended (which it sounds like you do?)

Posted
6 minutes ago, Laike_Endaril said:

especially if you already have it working as intended (which it sounds like you do?)

Well, I have it working partially. The GUI and Container work fine. (It opens a menu when the block is activated, and I can store items in it.) But it won't save the items when I quit the world, because I really don't understand what should go in read and writeToNBT. The only reason I brought up TileEntityLockableLoot was because I thought that might have something to do with saving the data. I can't seem to find any examples either. Thanks.

Posted

Saving and loading to/from disk is all in the two NBT methods you mentioned afaik.  Don't think you're getting anywhere until you get those 2 methods straight.

Ofc I would just try copying the code from TileEntityChest, and altering it as necessary.

Actually, I would probably have just extended TileEntityChest if possible.

 

In any case, here is the code from TileEntityChest:
 

Spoiler

    public void readFromNBT(NBTTagCompound compound)
    {
        super.readFromNBT(compound);
        this.chestContents = NonNullList.<ItemStack>withSize(this.getSizeInventory(), ItemStack.EMPTY);

        if (!this.checkLootAndRead(compound))
        {
            ItemStackHelper.loadAllItems(compound, this.chestContents);
        }

        if (compound.hasKey("CustomName", 8))
        {
            this.customName = compound.getString("CustomName");
        }
    }

    public NBTTagCompound writeToNBT(NBTTagCompound compound)
    {
        super.writeToNBT(compound);

        if (!this.checkLootAndWrite(compound))
        {
            ItemStackHelper.saveAllItems(compound, this.chestContents);
        }

        if (this.hasCustomName())
        {
            compound.setString("CustomName", this.customName);
        }

        return compound;
    }

 

 

If your TE is registered correctly, those 2 methods should be called automatically, or at least that's what it looks like from browsing the AnvilChunkLoader class

Posted
52 minutes ago, Laike_Endaril said:

Actually, I would probably have just extended TileEntityChest if possible.

So I have an inventory for another TileEntity that extends TileEntityChest, and I also just used the GuiChest and ContainerChest, like you suggested, which is fine. But if I don't want it to act exactly like a chest, I should not extend TileEntityChest right? The !this.checkLootAndWrite method for example, is only accessible from TileEntityLockableLoot, which is what TileEntityChest extends. Is there another way to do it by just extending TileEntity?

Posted (edited)

You should be able to do it either way.  The nice thing about extending is that, for the most part, you can leave what you like as-is, and change what you don't like (with some exceptions).  For example, if you like how most of TileEntityChest works, but not how it handles a certain method, you can override just that method (if you have access to it).

 

That aside, you could *instead* extend a more basic class, such as TileEntity, and would have to write code yourself for anything you want but it doesn't have.  Going with that same logic, you could, in many cases, write a class completely from scratch without extending anything.

 

What it comes down to in most cases is finding the class which most closely reflects what you want to accomplish, extending or copying it, and then editing.

I can't give an authoritative answer on what's best in your case in the long run, but at a minimum you will need to extend TileEntity.  TileEntity or one of its subclasses, because the AnvilChunkLoader only calls the readFromNBT() and writeToNBT() methods for TileEntity instances (including any instance of an object which extends TileEntity).

I suppose if I were in your shoes, I would copy the entirety of the EntityTileChest class as-is, rename it, and edit as necessary.  The field used for storage in TileEntityChest is set to private access, so you won't have direct access to it if you extend TileEntityChest, which in turn means you probably won't be able to use TileEntityChest's built-in NBT methods as they are, but you can certainly use them for reference to see how they do things.

All in all, if the only feature you don't have working it disk save/load, then just keep what you have now, copy/paste TileEntityChest's two NBT methods in, and then edit them (you can copy it straight out of my previous post, in the spoiler).

 

Again, I haven't actually made a container myself, I'm just going off of what I see in the vanilla code and what I know about how MC handles data in general, so I can't really get any more detailed than this atm, though I'm sure someone else could (someone who has done it).  You could also try to find a mod on curseforge which adds a container and is open-source, and take a peek at their code for an example.

 

 

Edit: Forgot to answer your last question about !this.checkLootAndWrite.

 

First, just to be clear, the method itself is checkLootAndWrite().  The exclamation mark is negation, which means if !checkLootAndWrite() is true, then checkLootAndWrite() is false.  And the "this." part just means that we're calling it from "this instance", which in most cases is redundant, but can sometimes prevent confusion and errors involving fields/methods with the same name from other classes/instances.

 

And yes, you could extend TileEntity and write that method from scratch...*OR* you could extend TileEntityChest and overwrite that method, which would replace its functionality.  In this *particular* case the result would be the same, because that *particular* method is only called from TileEntityChest and its subclasses (not from any of its superclasses, and not from any other external classes).  In intelliJ, you can see where a method is called from (or just in general, what connects to what) by middle clicking it or by setting the typing cursor on it and pressing ctrl+B
 

But yeah, maybe someone else can give you a more specific answer, or check out some repository code of an open-source mod with a working container

Edited by Laike_Endaril
  • Like 1
Posted

Yep, and like I said if you're on intelliJ, use that middle click to poke around at things.  It's extremely useful.

I haven't used eclipse in a long while but I imagine it has a similar feature.  Not sure what the shortcut for it would be though.

Posted
19 minutes ago, Laike_Endaril said:

use that middle click to poke around at things

I wouldn't be even half way where I am (which is obviously still learning a lot of the basics) if it wasn't for being able to view the source code. :)

Posted
5 hours ago, larsgerrits said:

Best and simplest way: use an ItemStackHandler with the IItemHandler

Yes, I've been looking at capabilities ever since I was told not to use IInventory. However, I'm unclear as to what they really do. I removed the two methods (getCapability and hasCapability) and the gui interface still works. I do use an ItemStackHandler instead of the NonNullList, which is what I think you're talking about?

Posted

Your should be extending the base TileEntity, and you only need an ItemStackHandler for the inventory.

 

Override hasCapability and getCapability to allow other blocks to interact with your inventory.

Don't PM me with questions. They will be ignored! Make a thread on the appropriate board for support.

 

1.12 -> 1.13 primer by williewillus.

 

1.7.10 and older versions of Minecraft are no longer supported due to it's age! Update to the latest version for support.

 

http://www.howoldisminecraft1710.today/

Posted
5 hours ago, larsgerrits said:

and you only need an ItemStackHandler for the inventory.

Ah, that's why. I wasn't sure if I knew why it was working.

 

5 hours ago, larsgerrits said:

Override hasCapability and getCapability to allow other blocks to interact with your inventory.

I didn't realize what overriding these two methods did altogether, now that works as intended. I'm still not able to save the items to the inventory, however.

Posted

You have to save it to NBT.

 

Overwrite the writeToNBT method and save the NBTTagCompound resulting from the ItemStackHandler's serializeNBT method.

 

Overwrite the readToNBT method and load the data by getting the NBTTagCompound from the NBTTagCompound parameter and passing it into ItemStackHandler's deserializeNBT method.

  • Like 1

Don't PM me with questions. They will be ignored! Make a thread on the appropriate board for support.

 

1.12 -> 1.13 primer by williewillus.

 

1.7.10 and older versions of Minecraft are no longer supported due to it's age! Update to the latest version for support.

 

http://www.howoldisminecraft1710.today/

Posted

Thank you, it is saving now, but I'm a bit confused about this null error:

Spoiler

A TileEntity has thrown an exception during loading, its state cannot be restored. Report this to the mod author
java.lang.NullPointerException: null

The error in the console does not cause the game to crash. It directs me to the readFromNBT method, so here they are. Could it be that the tileentity is trying to save empty inventory space?

Spoiler

@Override
public NBTTagCompound writeToNBT(NBTTagCompound compound)
{
    super.writeToNBT(compound);
    compound.setTag("Items", inventory.serializeNBT());

    return compound;
}

@Override
public void readFromNBT(NBTTagCompound compound)
{
    super.readFromNBT(compound);
    inventory.deserializeNBT((NBTTagCompound) compound.getTag("Items"));
}

"inventory" is my ItemStackHandler.

Posted

Ok, it didn't change anything. The error I'm getting seems to be directing to readFromNBT, so could it be something different?

Spoiler

java.lang.NullPointerException: null
    at net.minecraftforge.items.ItemStackHandler.deserializeNBT(ItemStackHandler.java:196) ~[ItemStackHandler.class:?]

 

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.