Area selection?

Discussion in 'Plugin Development' started by iffa, Jun 18, 2011.

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

    iffa

    I know this probably has been discussed 500 times, but how do I "make" my own "region" selection thing? StyxSpace would really love to have that for areas you can breathe in.
     
  2. Offline

    garbagemule

    You could do the same kind of selection as WorldEdit. Give the user a "wand" of sorts, and let them choose the two corners of a rectangular box by left- and right-clicking. With a region selected, allow commands to store the region in a file of sorts (yml would be easy, but a simple text-file could work too). Always keep the Collection of regions in memory while the plugin is enabled, however, so you don't take a massive performance hit from file I/O.

    To make everything a little easier to work with, you might find it useful to define a couple of classes. In these examples, I use protected variables, which isn't good practice, but is faster than getters (and still not as visible as public). The reason is that performance in this case is very high priority, especially if your users define many regions that need to be checked.

    Code:
    public class StyxPoint
    {
        protected World world;
        protected int x, y, z;
    
        public StyxPoint(int x, int y, int z, World world)
        {
            this.world = world;
            this.x = x;
            this.y = y;
            this.z = z;
        }
    }
    
    public class StyxRegion
    {
        protected StyxPoint p1, p2;
    
        // Precondition: p1.world and p2.world must be equal
        public StyxRegion(StyxPoint p1, StyxPoint p2)
        {
            this.p1 = p1;
            this.p2 = p2;
            fixPoints();
        }
    
        // Preconditions: p1.x <= p2.x, p1.y <= p2.y, p1.z <= p2.z
        public boolean inRegion(Location l)
        {
            if (!l.getWorld().equals(p1.world))
                return false;
            return ((l.getX() >= p1.x && l.getX() <= p2.x) &&
                    (l.getZ() >= p1.z && l.getZ() <= p2.z) &&
                    (l.getY() >= p1.y && l.getY() <= p2.y));
        }
    
        private void fixPoints()
        {
            int tmp;
            if (p1.x > p2.x)
            {
                tmp = p1.x;
                p1.x = p2.x;
                p2.x = tmp;
            }
    
            // Same for y and z
            ...
        }
    }
    Notice the preconditions. If you make sure to check before creating a new StyxRegion that the two points are in the same World, you can avoid broken checks. Furthermore, if you uphold the invariant that p1 is always the "lowest" point, and p2 is the "highest" point (fixPoints() will do that for you), you only have to make the six comparisons in inRegion, after verifying that the World of the location you are checking for is actually the same World as the points of the StyxRegion. Otherwise, you'd need to make twice as many comparisons.

    When defining the regions, just make sure to only create a StyxRegion if both points have the same world. Then, keep a Collection of StyxRegions and loop through all of them until you either reach the end of the line, or a region match is found. Another thing you could do is keep a Collection of StyxRegions for every world on the server, and only loop through the StyxRegions for the world in question. With this, you could leave out the World-field, and only do comparisons with the coordinates.

    I hope I understood the question, and I hope you can use this ;D
     
  3. Offline

    iffa

    Yes... I forgot to mention I could've loved the part that actually makes it an area, oh well. Tired me.
     
Thread Status:
Not open for further replies.

Share This Page