Jump to content
Search In
  • More options...
Find results that contain...
Find results in...

[SOLVED] [1.7.10] Sticking Tile Entities Where They Don't Belong


Recommended Posts

I have two spots in my mod where its useful to me to add in Tile Entities after the fact. I can do both in different ways if I really need to, but this is the ideal way of doing things in either case. At first, I tried using world.setTileEntity(x,y,z,TileEntity), but that didn't actually do anything. So I stuck a way of creating and checking for tile entities into a PlayerInteractEvent handler and proceeded to start trying stuff. After digging into things a little bit, I determined that in the chunk function it checks if the block at that location is actually supposed to have a tile entity, and if it doesn't then the tile entity won't be added. So I rewrote it without that check. Now, according to my check, which is calling world.getTileEntity, it gets set, but OPIS doesn't see it and it disappears if I reload the world. I'm pretty sure my function does all the same stuff as the original, only without the check, so I'm not really sure what the problem is. Anyone know, or know a better way of adding Tile Entities after the fact where they might not belong? Btw, for one of the usecases I'm dealing with vanilla blocks and blocks from other mods, so I can't modify the block code.

Relevant code:

 

PlayerEventHandler to create and check for Tile Entities (Location is basically just a container for coordinates):

@SubscribeEvent
public void interactHandler(PlayerInteractEvent event) {
	if (event.entityPlayer.getHeldItem() == null) return;
	if (event.action != PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) return;
	ItemStack stack = event.entityPlayer.getHeldItem();
	try {
		if (stack.getItem() == Items.baked_potato) {
			TileEntity te = TileDataOnly.class.newInstance();
			LogHelper.info("Tile entity is invalid? " + te.isInvalid());
			WorldHelper.setTileAnywhere(te, new Location(event.x, event.y, event.z, event.world));
		}
	} catch (IllegalAccessException e) {
		LogHelper.info(e);
	} catch (InstantiationException e) {
		LogHelper.info(e);
	}
	LogHelper.info(event.world.getBlock(event.x, event.y, event.z) + ": " + event.world.getBlockMetadata(event.x, event.y, event.z));
	LogHelper.info(event.world.getTileEntity(event.x, event.y, event.z));
}

 

setTileAnywhere, my replacement for world.setTileEntity (This is in groovy, but besides the lack of semicolons its basically java):

static def setTileAnywhere(TileEntity te, Location l) {

        if(te == null || te.isInvalid()) return

        //calls the normal setTileEntity to do... something, I'm not really sure what
        //but it accesses private fields in world and should fail before it gets to what
        //the rest of it does so this is just easier
        l.setTile(te)

        //adds the tileEntity into the world
        //this until the end is basically copied and pasted from
        Chunk chunk = l.world().getChunkFromBlockCoords(l.x(), l.z())
        if (chunk != null) {
            //this is basically copied and pasted from func_150812_a in Chunk, except without the check
            //for if the block should have a tile entity
            ChunkPosition chunkposition = new ChunkPosition(l.x() & 15, l.y(), l.z() & 15)
            te.setWorldObj(l.world())
            te.xCoord = l.x()
            te.yCoord = l.y()
            te.zCoord = l.z()

            if (chunk.chunkTileEntityMap.containsKey(chunkposition))
            {
                ((TileEntity)chunk.chunkTileEntityMap.get(chunkposition)).invalidate()
            }

            te.validate();
            chunk.chunkTileEntityMap.put(chunkposition, te)
        }

        //notifies the world of the changes
        l.world().func_147453_f(l.x(), l.y(), l.z(), l.getBlock())
    }

 

Link to post
Share on other sites

I think the "proper" way to do it would be to create custom blocks that extend each of the vanilla blocks you want to add tile entities to, and when you want to add a tile entity you actually replace the block with your own (which would provide tile entity).

 

The one possible problem with this approach is that a lot of the Minecraft code compares with exact instances rather than using instanceof against the class. So when you extend a class, some code may not recognize your block. I think it is a shame that Minecraft was coded that way, because modding would be a lot more powerful if you could extend vanilla classes and expect them to be treated as equivalent to the superclass where relevant.

 

What are you trying to achieve exactly? If you just want to store some data associated with a position in the world, there may be other ways of achieving that.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to post
Share on other sites

Alright, so apparently what was happening is when the chunks were reloaded, it called that same function in Chunk I had to rewrite earlier. I was able to fix things by handling ChunkDataEvent.Load and loading it using my rewritten version. It still isn't showing in OPIS, which is hopefully not indicative of some larger problem and is just an idiosyncrasy of however OPIS tracks tile entities. Actually, as I write this, I'm thinking maybe its just because the particular tile entity I was testing with has canUpdate return false, and maybe OPIS doesn't track those. Anyway, it seems to be solved.

Link to post
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.

Guest
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.



×
×
  • Create New...

Important Information

By using this site, you agree to our Privacy Policy.