Developer API/Areas

The Area Object

The Area object is the heart and core of the Flags API. Area is an interface that allows you to find flags, messages, trust lists, and more for each place in the world defined by your Area Plugin. The Area object also handles the wilderness (all location in the world NOT defined by the plugin) and the defaults (settings that apply to all defined areas that have no other settings).

Retrieving Areas

To obtain an area we can ask the FlagsAPI class to get one specific to the installed system, wilderness, or default. In the case of a system area, if none exists at the location a wilderness area will be returned instead allowing for a more automatic behavior.

Following the Subdivision Inheritance Path

The following method returns a plugin area at a specific location and if no area is found the wilderness area for the world. For systems that support the Subdividable interface, the subdivision will be returned if and only if the subdivisions inheritance is set to false, otherwise the parent will be returned. For prioritized systems (i.e. WorldGuard) all getArea methods return the highest priority area.

Example:

  Area myArea = FlagsAPI.getAreaAt(Location);

Ignoring the Subdivision Inheritance Path

If you wish to ignore inheritance, you may use the following method which will return the "lowest level" area at the location regardless of it's parent.

Example:

  Area myArea = FlagsAPI.getAbsoluteAreaAt(Location);

Wilderness and Default

You may also retrieve the wildereness area and default area directly.

Example:

  Area myArea = FlagsAPI.getWildernessAt(World);

  Area myArea = FlagsAPI.getDefaultArea(World);

Area Interfaces

Not all Area Plugins are created equal, to deal with this Area possesses several sub-interfaces allowing access to features for specific plugins. For example, Factoid, Grief Prevention, PreciousStones, Residence, and Flags all support Subdivisions of their areas. Factions, InfinitePlots, PlotMe, Regios, and WorldGuard do not.

So how do we know if the area we have supports this option? There are two ways. If you don't have an instance of Area handy, the AreaPlugin enumeration has some class snooping methods allowing you to determine this without instantiation. You can get the active AreaPlugin from FlagsAPI.

Example:

  boolean canSubdivide = FlagsAPI.getAreaPlugin().isSubdividable();

However, if you have an area object already, you may simply check the instance. This method is preferable because even though only one AreaPlugin may be active at a time, there is still the Wilderness area and the Default area to consider (neither of which are considered sub-dividable).

Example:

  boolean canSubdivide = myArea instanceof Subdividable;

Once you are certain that a cast would be valid you can proceed. Since Subdividable is a sub-interface (as opposed to a sub-class), you can access everything from Area after the cast.

Example:

  if(myArea instanceof Subdividable) {

    Subdividable mySubdividableArea = (Subdividable) myArea;

    if(mySubdividableArea.isSubdivision()) {

      System.out.print("This is a subdivision named "
               + mySubdividableArea.getName()
               + ". It's parent is named " 
               + mySubdividableArea.getParent().getName());
    }

  }

Subdividable is only one of several Interfaces for Area. For a complete list of interfaces and methods supported by them, please refer to the JavaDocs.

Area Comparison

There are three ways to compare two areas.

Comparison by ID

The default comparator simply returns the comparison of getId(). Where -1 is less than, 0 is equal, and 1 is greater than alphabetically (alpha-numeric alphabetization).

Example:

  int comparison = myArea.compareTo(myOtherArea);

Comparison by Name

The second method is to perform a comparison by given name. Like compareTo this returns -1, 0, and 1.

Example:

  int comparison = myArea.compareNameTo(myOtherArea);

Comparison by Relationship

The third comparison method is by relationship. This comparison works for any two instances of Area however if the Area is not Subdividable, it will always be EQUAL or UNRELATED.

RelationshipDescription
EQUALThe area is the same as the provided area.
PARENTThe area is a parent of the provided area.
CHILDThe area is a child (or subdivision) of the provided area.
SIBLINGThe area is a child of the provided areas parent area.
UNRELATEDThis area has no relationship to the provided area.

Be cautious not to mix the order of operations on this method. This is read as "This area is a <RELATIONSHIP> of the provided area." In the example below, read it as "if area1 is a CHILD of area2"

Example:

  if(area1.getRelationship(area2) == AreaRelationship.CHILD) {
    // area1 is a subdivision of area2
  }

Area Methods

When working with Flags, Bundles, or other aspects of the Area there are a common set of methods available through the Area class directly. Below are explanations of the more commonly used methods, consult the JavaDocs for a complete list.

Flag State & Flag Inheritance

Flag inheritance should not be confused with Subdivision inheritance as these are two entirely different principles. Flag inheritance is the path that a flag state, message, trust list, etc. can be retrieved if it has not been explicitly set in an area.

Imagine an area where the flag state has never been set by a player. The state of the flag for that area is considered null, but your event handler will probably need true or false. Flag inheritance allows you to automatically fall back to the default area set for the world. If the world default flag state has not been set either, the state falls back to the flag's default state, which is provided by the plugin creating the flag.

Flag Inheritance Path: Area Flag State -> World Default Flag State -> Flag Default

To get the flag state from an area while following the inheritance path, use the getState() method in the Area class. You will need to provide the Flag object as each flag has it's own state.

Example:

  boolean state = myArea.getState(myFlag);

If you want to know exactly what the flag state is, including it's null unset state, you can get the absolute state. Note the return type is the nullable object Boolean instead of the primitive type boolean.

Example:

  Boolean state = myArea.getAbsoluteState(myFlag);

Finally, you can directly alter the state of the flag for the area. For this method, and all "set" methods, it is recommended you provide a CommandSender when the state change is the result of a player action. The command sender is not used by the set methods directly, but passed along to the Events. If the state change is the result of an algorithm in your plugin, the CommandSender may be null. You may also erase the flag state by providing null, allowing it to fall back into it's inheritance path. This can be canceled by an event, so it will return if it was successful.

Example:

  boolean success = myArea.setState(myFlag, true, myCommandSender);

Messages

Messages follow the same Flag inheritance path as the flag state does and has normal, absolute, and set methods. However, messages have the ability to be parsed for color codes and wildcard indicators in the get methods. The default method parses everything except the {Player} wildcard, because it doesn't know the player name.

Example:

  String areaMessage = myArea.getMessage(myFlag);

However, you can also tell Flags what player name should replace the wildcard.

Example:

  String areaMessage = myArea.getMessage(myFlag, myPlayer.getName());

You also can get the message without any string replacement at all.

Example:

  String areaMessage = myArea.getRawMessage(myFlag);

Permissions

There are 3 types of permissions for setting flags (and bundles) in an area. These permissions determine if the player can set flags in their own areas, administrator areas, or anyone's area. Convenience methods are provided to check all of them for you.

  boolean flagPermitted = myArea.hasFlagPermissions(myPlayer);
  boolean bundlePermitted = myArea.hasBundlePermissions(myPlayer);

Trust Lists

Trust lists come in two forms. Permission Trust Lists and Player Trust lists. Each are accessed in the same way, with only their data types differing. Permission Trust uses the Bukkit Permission object and Player Trust uses the Bukkit OfflinePlayer object.

Before delving into the specific methods, there is a convenience method that will check all possible trusts for a specified player. This method returns true if the player:

  1. Has been assigned the bypass permission for the flag.
  2. Is the owner of the area.
  3. Is on the player trust list for the flag and area.
  4. If the area is not Wilderness and the player is on the world default player trust list.
  5. Has a permission on the permission trust list for the flag and area.
  6. If the area is not Wilderness and the player has a permission on the world default permission trust list.

Example:

  boolean  trusted = myArea.hasTrust(myFlag, myPlayer);

For setting a new player to a trust list of either type we use the overloaded method setTrust(). Since these are event cancellable, they will return the success of the operation. As before, CommandSender is used for the purposes of the event and should be provided if possible.

Example:

  boolean success = 
        myArea.setTrust(myFlag, myOfflinePlayer, myCommandSender);

  boolean success = 
        myArea.setTrust(myFlag, myPermission, myCommandSender);

Unlike flags and messages, null cannot be accepted due to the overload so there is also an explicit overloaded method for removing trust.

Example:

  boolean success = 
        myArea.removeTrust(myFlag, myOfflinePlayer, myCommandSender);

  boolean success = 
        myArea.removeTrust(myFlag, myPermission, myCommandSender).

Retrieving the full list of trusts involves two separate methods. This method also follows the flag inheritance path and returns a combined list of trusted players from the world's default area and the specified area. There are Absolute methods available to circumvent this behavior, which return only the specified area's trust list.

Example:

  Collection<OfflinePlayer> myPlayerTrustList =
        myArea.getPlayerTrustList(myFlag);

  Collection<Permission> myPermTrustList = 
        myArea.getPermissionTrustList(myFlag);