Get chunk coordinates from block coordinates

Discussion in 'Plugin Development' started by DDoS, Nov 27, 2011.

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

    DDoS

    Here's my problem: I have a cuboid region, which may cover more then one chunk, and in a multitude of different configurations. When the region is in use, chunks may not offload if they are part of the region. The region is defined by two vectors, a min and a max, and a world. The corner positions of the max and min vector are not defined, they may be any opposite corners of the regions, but the coordinates of both vectors are known.

    What I'm thinking to do is to get the chunk coordinates of the x and z coords for both vectors, then add or subtract 1 to those (depending their position), in order to make a new region that encases all the chunks in the region, based on chunk coordinates.

    When a chunk offloads, I use this region to check if the chunk is part of the normal region. If the x coord of the chunk is between the max and min x coord of the region (same for the z), then the chunk is part of the region, and the event is cancelled.

    My main problem is translating the block coords to chunk coords, and determining wether I have to subtract or add 1 to the coords to make the new chunk region.

    Any help would be greatly appreciated.
     
  2. Offline

    bleachisback

    world.getChunkAt(location);
     
  3. Offline

    DDoS

    This won't do. I don't have a precise location, and since chunks can be in the middle of the region, or on the sides, I can't use the corners (else not all chunks are covered). I'd have to iterate through the blocks in the regions (every 16 blocks) and compare the chunks I get to the one offloading. Certainly doesn't sound like a very efficient process.
     
  4. For consistent use, you should store vectors not for any opposite corners, but for the ones with the lowest and highest coordinates respectively.
    You can easily do that by comparing the x/y/z coordinates of the vecotrs on their own, and storing the smaller ones and the bigger ones.

    Now you have the lower and the higher corner, measured in blocks. To convert them to chunks, all you need to do is shift them by 4 bits (IIRC). You don't need to ever add or subtract 1 to anything.

    Assuming you have lowX, lowZ, highX and highZ as integers containing the above mentioned values, you can do that:
    Code:
    int lowChunkX = lowX >> 4;
    int lowChunkZ = lowZ >> 4;
    int highChunkX = highX >> 4;
    int highChunkZ = highZ >> 4;
    Now even though the highChunk begins at lower coordinates that the actual high corner block, the latter is still inside the chunk.

    An alternative and probably easier way would be to just call bukkit's API methods (getChunk()) - provided you have / can obtain a Block instance of your corner).


    Note: I don't claim that all that was 100% correct, it was all written by the top of my head ;)
     
  5. Offline

    DDoS

    The region i'm using comes from WorldEdit (I use it's API), so I'm not sure it the vectors have the lowest and highest coords, I'll got take a look at the source code. If this is true, then your right, I was making my life too complicated. I can get the blocks at opposite corners, get the chunks, and then get the chunk coordinates, and use those to create the new chunk region.

    Thanks for the help.
     
  6. The WorldEdit API provides methods to get the correct vectors (I've used them myself for RoutePlanner).
    They are called getMinimumPoint() and getMaximumPoint(), declared in the interface Region, implemented in CuboidRegion. Note that they do the math as well as creating a new vector on each call, so make sure you aren't calling them more often than necessary :)
     
  7. Offline

    bleachisback

    wait wait wait

    You said that you wanted to get the chunk coordinates of a block.

    so just doing
    Code:
    Chunk chunk=world.getChunkAt(block.getLocation());
    int x=chunk.getX();
    int z=chunk.getZ();
    
    Doesn't work?
     
  8. Offline

    DDoS

    I guess I'll just implement my own Region class, partly based on the WorldEdit one.


    Sorry, I got confused (you didn't provide me with much info). You were right, I should've used that.
     
  9. Offline

    Raphfrk

    If you don't create the regions very often but have to make many checks, then there isn't much lost by doing a comparison to see which coords are max/min.

    This class takes 2 Vectors and creates a Region object. You can then test is a chunk is contained inside the region using the contains method.

    Code:
    public class Region {
        private final int xChunkMin, xChunkMax, zChunkMin, zChunkMax;
    
        public Region (Vector v1, Vector v2) {
            int x1 = vector1.getBlockX();
            int z1 = vector1.getBlockZ();
            int x2 = vector2.getBlockX();
            int z2 = vector2.getBlockZ();
    
            if (x2 > x1) {
                xChunkMax = x2 >> 4;
                xChunkMin = x1 >> 4;
            } else {
                xChunkMax = x1 >> 4;
                xChunkMin = x2 >> 4;
            }
    
            if (z2 > z1) {
                zChunkMax = z2 >> 4;
                zChunkMin = z1 >> 4;
            } else {
                zChunkMax = z1 >> 4;
                zChunkMin = z2 >> 4;
            }
        }
    
        public boolean contains(int cx, int cz) {
            return cx >= xChunkMin && cx <= xChunkMax && cz >= zChunkMin && cz <= zChunkMax;
       }
        public boolean contains(Chunk chunk) {
            return contains(chunk.getX(), chunk.getZ());
        }
    }
    
     
  10. Offline

    DDoS


    Thanks for the reply, I've already setup a method for my normal region class:

    PHP:
    public boolean containsChunk(Chunk chunk) {

            if (!
    chunk.getWorld().equals(world)) {
                return 
    false;
            }
            
    int minChunkX min.getBlockX() >> 4;
            
    int minChunkZ min.getBlockZ() >> 4;
            
    int maxChunkX max.getBlockX() >> 4;
            
    int maxChunkZ max.getBlockZ() >> 4;

            return (
    chunk.getX() >= minChunkX && chunk.getX() <= maxChunkX
                    
    && chunk.getZ() >= minChunkZ && chunk.getZ() <= maxChunkZ);

        }
    I've yet to test it, but do you think it's ok?
     
  11. Offline

    Raphfrk

    Yeah, seems fine.
     
Thread Status:
Not open for further replies.

Share This Page