Finding chests within an area

Discussion in 'Plugin Development' started by xTrollxDudex, Jun 19, 2013.

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

    xTrollxDudex

    Bone008 asked me to post this to benefit the community :D

    A while back, he described a way to find chests in a world by using chunk.getTileEntities, or whatever somethin to do with TileEntities. It was not very explanatory and lacked comments to describe how to use the code.
    I also wanted to know how to use the code to find chests in a specified area.

    So, Bone008, or whoever else who can help, can you provide an example for me with explanations? Thanks.

    PS it would be nice if you could also tell me:
    1-having a specified block BEHAVE like a chest
    2-using the found chests to fill all the chests in the area <---- This one first if possible
    3-explanation for multiple arenas at the same time? This one is seriously confusing for me. Hopefully after knowing these I can release my ChestGames plugin!
     
  2. Offline

    chasechocolate

    Create a List<Block>, then loop through the chunks in a world, loop through the tile entities in each chunk (chunk.getTileEntities(), which will return a list of BlockStates), check if state instanceof Chest, and then add state.getBlock() to your list.

    1. You are going to have to listen for PlayerInteractEvent and check if a player right clicked a block. From there, you can create a HashMap<Block, Inventory> so blocks can have their own specific inventories. If the map contains the clicked block, then use player.openInventory(map.get(block)), otherwise, use map.put(block, Bukkit.createInventory(null, 27, "Inventory Title")) and open it as I said before.

    2. http://forums.bukkit.org/threads/how-to-make-random-loot-chests-appear.140755/ - just apply that to every chest inside your list.

    3. "site:bukkit.org multiple arenas" - put that into Google.
     
    CubieX likes this.
  3. Offline

    xTrollxDudex

    What about the are part? I already have he 2 corner points.
    Anyway, ignoring the area part,

    Would this work for finding location of chests?
    Code:java
    1.  
    2.  
    3. //onCommand method
    4. if(label.equals("findchests")) {
    5. for (Blockstate state: chunk.getTileEntities) {
    6. if (state instanceof Chest) {
    7. //config crap here with state.getLocation()?
    8. }
    9. }
    10.  


    1. Like this?
    Code:java
    1.  
    2.  
    3. class Filler implements Listener {
    4.  
    5. HashMap<Block, Inventory> map = new HashMap<Block, Inventory>();
    6. Inventory inv = Bukkit.createInventory(null, 27, "Here, take these :)"));
    7.  
    8. @EventHandler(priority = EventPriority.HIGH)
    9. public void onBoxOpen(PlayerInteractEvent event) {
    10. if (event.getAction() == Action.RIGHT_CLICK_BLOCK) {
    11. if (event.getBlock().getType() == Material.DIAMOND_ORE) {
    12. map.put(event.getBlock, inv);
    13. inv.getInventory.addItem(Material.APPLE);
    14. event.getPlayer().openInventory(map.get(event.getBlock));
    15. }
    16. }
    17. }
    18.  


    2. Given
    Code:java
    1.  
    2. Random r = new Random();
    3. int randomInt = r.nextInt(200);
    4. int itemsInChest = r.nextInt(9);
    5. int itemLimit = r.nextInt(5);
    6. //assuming this is in PlayerInteractEvent:
    7. Chest chest = (Chest) event.getLocation.getState();
    8. ItemStack stack = new ItemStack(randomInt, itemLimit);
    9.  
    10. //would this work?
    11. for (int chestItems; chestItems <= itemsInChest; chestItems) {
    12. chest.getInventory().addItem(stack)
    13.  


    3. Ty for that.

    PS you are totally awesome. Like for you! I cannot show my appreciation enough.
     
  4. Offline

    chasechocolate

    xTrollxDudex to get the location, use state.getBlock().getLocation(). I'll show you the inventory one tomorrow, not on my computer ATM.
     
  5. Offline

    xTrollxDudex

    I knew that
    Im on my ipod atm xD
     
  6. About the chest finding:
    1. Find the chunks where your region is in. These are multiple ones and most likely Also partially Occupied.
    2. Loop over the chunks
    3. Loop over the tile entities in the current chunk
    4. check if its a chest and check if the location is actually contained in your region
    5. now you have a matched chest and you can do stuff with it

    Ill write some example code once I get home. But try to understand the concept above first.

    Okay, here's some example code:

    Code:
    // 1. Find the chunks. Assuming you have the blocks "min" and "max":
    Chunk chunkMin = min.getChunk();
    Chunk chunkMax = max.getChunk();
     
    // 2. you loop over the 2-dimensional group of chunks, "cx" is the x coordinate of the current chunk, "cz" the z coordinate
    for(int cx = chunkMin.getX(); cx < chunkMax.getX(); cx++) {
        for(int cz = chunkMin.getZ(); cz < chunkMax.getZ(); cz++) {
            // get the chunk you are currently looking at
            Chunk currentChunk = world.getChunkAt(cx, cz);
           
            // now do the rest of the code with TileEntities (see below)
    }
    
    For the current chunk, "currentChunk.getTileEntities()" returns the tileentities (including chests) of the chunk. So now you can do:
    Code:
    for(BlockState tileEntity : chunk.getTileEntities()) {
        if(tileEntity instanceof Chest) {
            // now check if it's contained in min/max
            // that is the case if tileEntity.x > min.x and < max.x (do the same for y and z, if everything matches, it's contained)
     
            // now you can cast "tileEntity" to a Chest and do stuff with its inventory; that's up to you
        }
    }
    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 2, 2016
  7. Offline

    xTrollxDudex

    Wow. Thats a lotta info. Anyway, this would work right?

    Code:java
    1.  
    2. //onPlayerInteract, if player.getItemInHand = Somematerial, save event.getBlock().getClickedBlock().getLocation() min an max
    3. Chunk cMin = min.getChunk();
    4. Chunk cMax = max.getChunk();
    5.  
    6. for(int cx = cMin.getX(); cx < cMax.getX(); cx++) {
    7. for(int cz = cMin.getZ(); cz < cMax.getZ(); cz++) {
    8. for(int cy = cMin.getY(); cy < cMax.getY(); cy++){
    9. Chunk currentChunk = world.getChunkAt(cx, cz);
    10. //why is this needed^ it serves no apparent purpose?
    11.  
    12. for(BlockState te : chunk.getTileEntites()){
    13. if(te instanceof Chest){
    14. if(min.x<te.x<max.x && min.y<te.y<max.y && min.z<te.z<max.z){
    15. //Is min.x a type? Shouldnt they be min.getX() or te.getY() or something?
    16. Chest chest = (Chest) te.getBlock().getLocation();
    17. chest.blahblahblahblahblah......
    18. }
    19. }
    20. }
    21. }
    22. }
    23. }
    24.  
     
  8. Pretty close. Keep in mind chunks are only spread out horizontally. You don't need a 3rd for-loop for "cy"!

    The line with "currentChunk" is needed for the innermost for-loop (where chunk.getTileEntities() needs to be currentChunk.getTileEntities(), I thought that would be clear).

    And no, "min.x" doesn't exist like that, that was supposed to be pseudo-code demonstrating the concept. And Java doesn't allow the mathematical "a<b<c" notation. Just try it yourself, you'll figure out something that will compile ...
     
  9. Offline

    xTrollxDudex

  10. Yes, because a chunk defines the entire 16x16 region from bottom to top. Getting tile entities in that region returns all tile entities with the containing x and z coordinates, disregarding their y coordinate.
     
Thread Status:
Not open for further replies.

Share This Page