Spatial Queries

WorldGuard optimizes for two types of spatial queries:

  • Finding all regions containing a point
  • Finding regions overlapping another region

Spatial queries can be performed using an instance of a RegionManager, but they can also be performed through a special query cache. In either case, a returned ApplicableRegionSet object will be returned that contains a list of regions, as well as additional methods to perform Flag Calculation.

It’s also possible to, given a list of regions, to create your own ApplicableRegionSet. This is useful if you want to test the value of flags and you have already a list of regions to test with (and the regions do not even need to overlap).

Getting an ApplicableRegionSet

Through the Query Cache

The query cache stores the last query result for at most one or two seconds, which speeds up repeated lookups for the same a block, a common scenario during event handling. However, the query cache only supports the first type of query, point location. To utilize the cache, a new RegionQuery instance can be obtained from a RegionContainer:

RegionQuery query = container.createQuery();
ApplicableRegionSet set = query.getApplicableRegions(location);

Example: Getting regions at (10, 64, 100)

Location loc = new Location(world, 10, 64, 100);
RegionContainer container = getWorldGuard().getRegionContainer();
RegionQuery query = container.createQuery();
ApplicableRegionSet set = query.getApplicableRegions(loc);

One particular feature of the cache is that it will return virtual results if region protection is disabled or region data failed to load:

  • If region protection is disabled, an instance of PermissiveRegionSet will be returned, which will contain no regions and permit any action.
  • If region data failed to load, an instance of FailedLoadRegionSet will be returned, which will contain no regions, deny every action, and also implicitly provide values for some flags (such as deny-message to inform players of the error).

In either case, set.isVirtual() will return true if the result is virtual.

Through a RegionManager

Given an RegionManager, getApplicableRegions(Vector) can be used to perform a point location query (see From Bukkit Objects for converting from Bukkit locations).

Vector position = new Vector(20, 10, 4);
ApplicableRegionSet set = regions.getApplicableRegions(position);

Example: Getting regions at (10, 64, 100)

Location loc = new Location(world, 10, 64, 100);
RegionContainer container = getWorldGuard().getRegionContainer();
RegionManager regions = container.get(loc.getWorld());
// Check to make sure that "regions" is not null
ApplicableRegionSet set = regions.getApplicableRegions(BukkitUtil.toVector(loc));

If the goal is to find a list of regions that overlap another, use getApplicableRegions(ProtectedRegion) on the manager. Because shape and the region are currently the same objects (coupled together), you have to use a dummy ID:

Vector min = new Vector(0, 0, 0);
Vector max = new Vector(10, 10, 10);
ProtectedRegion test = new ProtectedCuboidRegion("dummy", min, max);
ApplicableRegionSet set = regions.getApplicableRegions(test);

Constructing Manually

RegionResultSet takes a List<ProtectedRegion> and an optional global region.

The provided regions do not need to overlap.

List<ProtectedRegion> regions = Lists.newArrayList();
regions.add(spawn);
regions.add(mall);
regions.add(pub);

ApplicableRegionSet set = new RegionResultSet(regions, null); // No global region

Warning

Your list of regions may be re-ordered in-place. After you have given a list of regions to the instance, it should no longer be used. In the future, RegionResultSet make take an ImmutableList instead (from Google’s Guava library).

Using a ApplicableRegionSet

If your interest is in getting the list of regions, ApplicableRegionSet implements Iterable<ProtectedRegion> so you can loop over it:

for (ProtectedRegion region : set) {
    // Do something with each region
}

Example: Getting a list of regions

Google’s Guava library has Lists.newArrayList(Iterable) to create an ArrayList from an Iterable.

List<ProtectedRegion> region = Lists.newArrayList(set);

If you are performing a spatial query to check protection or flags, see either Querying Protection or Flag Calculation.