Jump to content

TileEntities that are not in World - Can I do this better?


Draco18s

Recommended Posts

So a block I had in 1.7 worked really quite well with utilizing the ISidedInventory interface.

 

The basic premise was that the block would store phantom items, specifically blocks with inventories (when trying to insert to a particular set of slots, I'd check to see if the Item was a block, and if that block implemented IInventory).  Then when any other item was attempted to be put into the primary inventory slots, it was checked to see if it was possible to insert that item into the stored block from a given side (top, bottom, side).  If the item was allowed to be inserted, then my block would allow the insertion to its own inventory.

 

Because of the way the ISidedIventory interface allowed access to inventory slots, it was exceedingly rare for a block to throw a Null Pointer Exception trying to test-insert items (I never once saw it happen, but I wrapped the sole method of failure in a try...catch anyway, just in case).

 

However, now that Capabilities are a thing, that's grown a little more...tenuous.

hasCapability

doesn't pass a blockstate and it would not be unreasonable for a block to differentiate slot validity based on blockstate (for example, my own millstone, which allows insertion on the edge blocks of a 3x3 square, and extraction from the center).  Depending on how any given author decides to implement their has/getCapability methods, they may not handle their TE having a null worldObj.

 

So this code (that I have now) is not fail proof (and one of three or four possible failure points, instead the original one):

 

ItemBlock ib = (ItemBlock)stack.getItem();
IBlockState state = ib.block.getStateFromMeta(ib.getMetadata(stack));
if(ib.block.hasTileEntity(state)) {
TileEntity te = ib.block.createTileEntity(null, state);
return te.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
}

 

Is there anything I can do to reduce the chance of error? Or do I need to just accept it, and wrap all three/four spots in a try...catch?

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

There are various ways you can pass a

World

object. For example, you can use

setWorldObj

on the

TileEntity

to set the world.

 

You can get a

World

object from

Minecraft#theWorld

(GUI), or your own

TileEntity

's worldObj. You can also pass in the

World

reference to

Block#createTileEntity

and

TileEntity#hasCapability

to reduce the chance on NPEs.

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

There are various ways you can pass a

World

object. For example, you can use

setWorldObj

on the

TileEntity

to set the world.

 

You can get a

World

object from

Minecraft#theWorld

(GUI), or your own

TileEntity

's worldObj. You can also pass in the

World

reference to

Block#createTileEntity

and

TileEntity#hasCapability

to reduce the chance on NPEs.

 

That doesn't actually solve the problem, because if the TE uses that world, it's BlockPos is still 0,0,0 and it itself doesn't exist there, so it will fail to retrieve its own blockstate.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

There are various ways you can pass a

World

object. For example, you can use

setWorldObj

on the

TileEntity

to set the world.

 

You can get a

World

object from

Minecraft#theWorld

(GUI), or your own

TileEntity

's worldObj. You can also pass in the

World

reference to

Block#createTileEntity

and

TileEntity#hasCapability

to reduce the chance on NPEs.

You could call get placed blockstate or getStateFromMeta. If I understood it correctly you have an ItemStack of a Block you shouold be able to get the block from the Item in the stack, then get the blockstate from those methods.

 

That doesn't actually solve the problem, because if the TE uses that world, it's BlockPos is still 0,0,0 and it itself doesn't exist there, so it will fail to retrieve its own blockstate.

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 could call get placed blockstate or getStateFromMeta. If I understood it correctly you have an ItemStack of a Block you shouold be able to get the block from the Item in the stack, then get the blockstate from those methods.

 

Oh *I* can get the blockstate from an item stack. That's not the problem.

The problem is I want to instantiate the tile entity associated with that state and invoke getCapbability.

 

I have no control over what someone else's getCapbability does...such as doing

worldObj.getBlockState(this.getPos())

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

You could call get placed blockstate or getStateFromMeta. If I understood it correctly you have an ItemStack of a Block you shouold be able to get the block from the Item in the stack, then get the blockstate from those methods.

 

Oh *I* can get the blockstate from an item stack. That's not the problem.

The problem is I want to instantiate the tile entity associated with that state and invoke getCapbability.

 

I have no control over what someone else's getCapbability does...such as doing

worldObj.getBlockState(this.getPos())

Instantiate the TileEntity with Block#createTileEntity(IBlockState) using the method I said above. Which will give you the TileEntity for that specfic BlockState. Correct?

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

Yes.  Which I am.

 

That is also not the problem.  The problem is not the TE creation but invoking getCapability as I've said three times now.

 

getCapability DOES NOT PASS A STATE

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

I have an idea, but first I'd like to check that I understand what you're trying to do.

 

You have a block with an inventory. If blocks that have TEs are inserted into that inventory, their TEs are instantiated. If any other item/block is inserted, the inventories of the contained TEs are tested to see if they will accept the item/block, and it is inserted into one of the inventories that will take it.

In 1.9+ there are problems with this approach. Some TEs behave differently depending on the attached blockstate. To get their blockstate they need the World it is in. Since your block never actually places them they have a null World, causing a crash when the TEs try to check their blockstates, as most authors don't expect a null World.

 

Is the above correct?

Link to comment
Share on other sites

Is the above correct?

 

Yes, that is correct.

(player's guide to using it: http://reasonable-realism.wikia.com/wiki/Filtering_Hopper )

 

I could pass a non-null world, but it wouldn't make a difference as the TE's author would (reasonably) assume that the block-at-the-TE's-position was its own block.  I know my own code says "hold on, this isn't me" and allows full access to all slots, same as if a null side was passed (to handle cases like blocks being set to air before the block has a chance to drop all the TE's contents--because that was a problem at one point) but that may not be universally true (as I think aforementioned issue was fixed).

 

The other reason my millstone block does that is that it needs to do that before requesting properties from the blockstate, as to not cause an InvalidPropertyException (or whatever it actually throws when you try to get/set a property that doesn't exist).

 

I suppose that I could use two different TEs for my millstone block (one for the edges that accepts items and one for the center that processes and allows extraction) but I originally coded it to just be the same TE and use the Sided interface nature of things to make the distinction.

 

But again, the point is, "if I managed to do this in this way, someone else might do it too."  And it wasn't until I was coding my filter block that I realized that my getCapability method was insufficiently built to handle possible problems (took me three attempts to properly make sure that what I was doing would work).

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Link to comment
Share on other sites

I think the best option is to actually place the Blocks and their TEs in a World. This way the TEs should have everything they could expect to have. The easiest way to do this is to create an inaccessible void world dimension that all filtering hoppers place their phantom blocks in. For performance and resource reasons, each filtering hopper should load and unload the chunk it uses in the dimension as it is loaded and unloaded. You could probably get away with a World that only has a single Chunk if you wanted to, a single Chunk could serve 10,000+ filtering hoppers in the manner I have described.

Link to comment
Share on other sites

That...sounds excessive.

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

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.