Remotely interacting with a block (opening chests in this case)

Discussion in 'Plugin Development' started by Zomis, Jan 10, 2012.

Thread Status:
Not open for further replies.
  1. Offline

    Zomis

    I am trying to develop a plugin which should be able to let a player open a chest from far away. Everything works except for the part where the chest is supposed to open...
    Opening chests nearby works fine, but opening chests from like 1000 blocks away or opening chests in another world does not work at all.
    The code to open the chest is:
    org.bukkit.Block targetBlock = ...;
    org.bukkit.entity.Player player = ...;
    Code:
    net.minecraft.server.World w = ((CraftWorld)targetBlock.getWorld()).getHandle();
     net.minecraft.server.EntityHuman eHuman = ((CraftPlayer)player).getHandle();
     boolean result = net.minecraft.server.Block.CHEST.interact(w, targetBlock.getX(), targetBlock.getY(), targetBlock.getZ(), eHuman);
    I know that the boolean result has the value true, I know that the targetBlock is a chest.
    I found the code from this post, and some others with a similar question: http://forums.bukkit.org/threads/how-to-press-a-button-from-a-plugin.26996/
    So how to make it possible to open a chest that is far away from the player?
     
  2. Offline

    Pandemoneus

    You might need to load the chunk the chest is in first.
     
  3. Offline

    Zomis

    I was going to say "Good thinking!" but loading the chunk did not help.

    org.bukkit.Chunk c = targetBlock.getChunk();
    c.load();
    ... (and then the code above)

    c.load() returns true, but it still doesn't work.

    Also, one thing I forgot to say is that sometimes (yes, sometimes! Not always, not never... have no idea how this "sometimes" works) when executing this code, the target chest is shown for a short time (less than 0.3 seconds) and then disappears.
     
  4. Offline

    jorisk322

    I'm not a dev, but that I do read Notch's blog, and he changed something a while ago, which made chests close if you moved too far away from them. You'd probably have to cancel this event (if it is an event, again, I'm not a dev).
     
  5. Offline

    Zomis

    That's an interesting thought. Unfortunately, I can't find the appropriate event type. And the InventoryListener class only seems to define onFurnaceBurn and onFurnaceSmelt

    I see that there is a constant defined as Event.Type.INVENTORY_CLOSE for this kind of event but that alone does not help.

    I have at least verified that it is because I am too far away from the chest, so the chest closes itself - just like when there's a Minecart with chest travelling on a rail and getting out of reach.

    Any ideas how to solve that problem?

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: May 23, 2016
  6. Offline

    jorisk322

    Maybe you could create a hidden chest somewhere near the player and copy the items to that chest. But it seems like something you'dd rather not do. Maybe you should take a look at the source of VirtualChest. That plugin creates a chest inventory screen, which doesn't immediately disappear.
     
  7. Offline

    Zomis

    I found out the exact source that is causing my problem, it is in TileEntityChest.java:
    Code:
        public boolean a(EntityHuman entityhuman) {
            if (this.world == null) return true; // CraftBukkit
            return this.world.getTileEntity(this.x, this.y, this.z) != this ? false : entityhuman.e((double) this.x + 0.5D, (double) this.y + 0.5D, (double) this.z + 0.5D) <= 64.0D;
        }
    
    So I created my own class:
    Code:
    package com.massivecraft.zplugin;
    
    import net.minecraft.server.EntityHuman;
    import net.minecraft.server.ItemStack;
    import net.minecraft.server.TileEntityChest;
    
    public class MyTileEntityChest extends TileEntityChest {
        public MyTileEntityChest() {}
        
        public void copyFrom(TileEntityChest tc) {
            for (int i = 0; i < 27; i++) {
                ItemStack itemstack = tc.getItem(i);
                setItem(i, itemstack);
            }
        }
        
        @Override
        public boolean a(EntityHuman entityHuman)
        {
            // This is the function that checks if the chest should remain open
            return true;
        }
    }
    
    And so far, so good. It works to access other chests over long ranges!
    The problem is that I get this error:
    Code:
    20:21:14 [SEVERE] java.lang.RuntimeException: class com.massivecraft.zplugin.MyTileEntityChest is missing a mapping! This is a bug!
    20:21:14 [SEVERE]       at net.minecraft.server.TileEntity.b(SourceFile:54)
    20:21:14 [SEVERE]       at net.minecraft.server.TileEntityChest.b(TileEntityChest.java:85)
    20:21:14 [SEVERE]       at net.minecraft.server.ChunkLoader.a(SourceFile:135)
    20:21:14 [SEVERE]       at net.minecraft.server.ChunkRegionLoader.a(SourceFile:84)
    20:21:14 [SEVERE]       at net.minecraft.server.ChunkProviderServer.saveChunk(ChunkProviderServer.java:152)
    20:21:14 [SEVERE]       at net.minecraft.server.ChunkProviderServer.saveChunks(ChunkProviderServer.java:201)
    20:21:14 [SEVERE]       at net.minecraft.server.World.save(World.java:269)
    20:21:14 [SEVERE]       at net.minecraft.server.World.doTick(World.java:1735)
    20:21:14 [SEVERE]       at net.minecraft.server.MinecraftServer.w(MinecraftServer.java:514)
    20:21:14 [SEVERE]       at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:425)
    20:21:14 [SEVERE]       at net.minecraft.server.ThreadServerApplication.run(SourceFile:457)
    And I don't know what to do about this. I can't find the source for TileEntity so I don't know why this exception is thrown, what mapping I am missing.
     
  8. Offline

    bergerkiller

    @Zomis look at SignLink in my signature, it replaced tile entities as well. All below the source code of 'VirtualEntitySign.java' on GitHub you'll find the code for 'b(NBTTagCompound)'

    Link

    You need to override and clone that function, ignoring the 'get type name from map' bit, which throws that error.

    Code:
    @Override
        public void b(NBTTagCompound nbttagcompound) {
         //Was complaining about ID <> class mapping issues
            nbttagcompound.setString("id", "Sign");
            nbttagcompound.setInt("x", this.x);
            nbttagcompound.setInt("y", this.y);
            nbttagcompound.setInt("z", this.z);
            nbttagcompound.setString("Text1", this.lines[0]);
            nbttagcompound.setString("Text2", this.lines[1]);
            nbttagcompound.setString("Text3", this.lines[2]);
            nbttagcompound.setString("Text4", this.lines[3]);
        }
     
  9. Offline

    Zomis

    Thanks! That will be good to know for future reference.

    I actually solved the problem I had, not by registering the class but by doing a whole other approach to the problem.

    I still extended the TileEntityChest, and my extended class keeps a private variable of the TileEntityChest class and calls the methods for that variable every time :) So instead of actually placing it on the map it is only used in memory. And it works fine!

    So you might see the first plugin from me after a few days or weeks...
     
Thread Status:
Not open for further replies.

Share This Page