Jump to content

TileEntity that extends TileEntityLockableLoot


Siqhter

Recommended Posts

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.

Link to comment
Share on other sites

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?)

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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
Link to comment
Share on other sites

Best and simplest way: use an ItemStackHandler with the IItemHandler capability.

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/

Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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/

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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/

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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:?]

 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Wait guys, I still don't don't understand... I shall send my code -- Define the function to decrease hunger local function decreaseHunger(player)     local currentHunger = player.getHunger()          -- Check if hunger is not already zero     if currentHunger > 0 then         player.setHunger(currentHunger - 1)     end end -- Register event to decrease hunger over time script.registerEvent(EntityPlayer, function(player)     while true do         -- Decrease hunger every few seconds         decreaseHunger(player)         script.sleep(1000) -- Sleep for 1 second     end end)     Any help appriecated. It's been a while since I learnt Javascript or whatever Minecraft is made with... ... ... ... Nicknotname Hungerinpeaceful xx
    • good days  i get this error: java.lang.ClassCastException: class net.minecraft.client.player.LocalPlayer cannot be cast to class net.minecraftforge.common.extensions.IForgeServerPlayer (net.minecraft.client.player.LocalPlayer is in module minecraft@1.20.4 of loader 'TRANSFORMER' @3e8b3b79; net.minecraftforge.common.extensions.IForgeServerPlayer is in module forge@49.0.26 of loader 'TRANSFORMER' @3e8b3b79)     at mercmod.blocks.classes.panel_whit_entity_inside.use(panel_whit_entity_inside.java:576) ~[main/:?] {re:classloading}     at net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase.use(BlockBehaviour.java:826) ~[forge-1.20.4-49.0.26_mapped_official_1.20.4-recomp.jar:?] {re:classloading}     at net.minecraft.client.multiplayer.MultiPlayerGameMode.performUseItemOn(MultiPlayerGameMode.java:324) ~[forge-1.20.4-49.0.26_mapped_official_1.20.4-recomp.jar:?] {re:classloading,pl:runtimedistcleaner:A}     at net.minecraft.client.multiplayer.MultiPlayerGameMode.lambda$useItemOn$4(MultiPlayerGameMode.java:292) ~[forge-1.20.4-49.0.26_mapped_official_1.20.4-recomp.jar:?] {re:classloading,pl:runtimedistcleaner:A}     at net.minecraft.client.multiplayer.MultiPlayerGameMode.startPrediction(MultiPlayerGameMode.java:251) ~[forge-1.20.4-49.0.26_mapped_official_1.20.4-recomp.jar:?] {re:classloading,pl:runtimedistcleaner:A}     at net.minecraft.client.multiplayer.MultiPlayerGameMode.useItemOn(MultiPlayerGameMode.java:291) ~[forge-1.20.4-49.0.26_mapped_official_1.20.4-recomp.jar:?] {re:classloading,pl:runtimedistcleaner:A}     at net.minecraft.client.Minecraft.startUseItem(Minecraft.java:1799) ~[forge-1.20.4-49.0.26_mapped_official_1.20.4-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}     at net.minecraft.client.Minecraft.handleKeybinds(Minecraft.java:2083) ~[forge-1.20.4-49.0.26_mapped_official_1.20.4-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}     at net.minecraft.client.Minecraft.tick(Minecraft.java:1902) ~[forge-1.20.4-49.0.26_mapped_official_1.20.4-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}     at net.minecraft.client.Minecraft.runTick(Minecraft.java:1216) ~[forge-1.20.4-49.0.26_mapped_official_1.20.4-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}     at net.minecraft.client.Minecraft.run(Minecraft.java:801) ~[forge-1.20.4-49.0.26_mapped_official_1.20.4-recomp.jar:?] {re:classloading,pl:accesstransformer:B,pl:runtimedistcleaner:A}     at net.minecraft.client.main.Main.main(Main.java:234) ~[forge-1.20.4-49.0.26_mapped_official_1.20.4-recomp.jar:?] {re:classloading,pl:runtimedistcleaner:A} ------------------------------------------------------------------------------------------------------------------   context:  im updating the briefcase from mi mod an i need to make a gui whit this image that gonna be launched from a block and from a item soo im using kapenjoe tutorials  ---------------------------------------------------------------------------------------- The problem is that tutorial is for 1.20.1 and im using 1.20.4 and i really dont get how to call and open the gui from the block nor from the item i made this based on post i made short ago everything seems find but when right click the block to open the gui it crash the game  @Override public InteractionResult use(BlockState blkstate, Level warudo, BlockPos pos, Player pe, InteractionHand hand, BlockHitResult hitresult) {     if(warudo.isClientSide()){         BlockEntity blkentity = warudo.getBlockEntity(pos);         if(blkentity instanceof Panel_BlockEntity){             //   ↓↓↓  open the menu from the block              IForgeServerPlayer ifpe = (IForgeServerPlayer)pe; //<--- this is wrong  "class net.minecraft.client.player.LocalPlayer cannot be cast to class net.minecraftforge.common.extensions.IForgeServerPlayer"             ifpe.openMenu( (Panel_BlockEntity) blkentity, pos ); //<-- i need an example of how open a gui in 1.20.4         }     } return InteractionResult.sidedSuccess(warudo.isClientSide()); } Theres nothing highlighted in red in the code like everything where right an possible but dont works  ####################################################################################################### i need to see an example, just the piece of code for the use() method of the block whit the block entity for 1.20.4  and the same  but for the item     @Override     public @NotNull InteractionResultHolder<ItemStack> use(@NotNull Level warudo, @NotNull Player pe, @NotNull InteractionHand interactionHand)     {         if (!warudo.isClientSide())         {             ItemStack heldItem = pe.getItemInHand(interactionHand);                          if (heldItem.getCapability(ForgeCapabilities.ITEM_HANDLER).isPresent())             {                 //   ↓↓↓  open the menu from the item                 NetworkHooks.openScreen((ServerPlayer) pe, this);             }         }         return super.use(warudo, pe, interactionHand);     }   thanks for your attention           
    • It depends on the data you want to save, but generally speaking you should use some custom Player Capabilities, attach to the Player and use them to store/retrieve any kind of data you want. You can find how to make them work for 1.20.x in the documentation here: https://docs.minecraftforge.net/en/latest/datastorage/capabilities/
  • Topics

  • Who's Online (See full list)

    • There are no registered users currently online
×
×
  • Create New...

Important Information

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