Skip to content

Regions: KelpRegion in general

PXAV edited this page Mar 20, 2021 · 1 revision

What are KelpRegions?

KelpRegions are different regions of blocks that can be of different shapes such as a cuboid or an ellipsoid.

They can be used to define certain areas of a world and protect them for example or control player movement inside those areas.

Creating a KelpRegion

To create a KelpRegion, you first have to know which shape you'd like to use. Currently, you can choose from:

(But it is also possible to write own implementations of a region if needed.)

Each of those implementations has its own static factory methods, which can be read in the corresponding wiki entry, but an example would be:

CuboidRegion region = CuboidRegion.create(KelpLocation, KelpLocation)

Basic information

As you can see in the code example above, a cuboid region needs two points to be created. Every KelpRegion has those points, which are called minPos and maxPos. They are opposite of each other and represent the cubic area around the region. So for a cuboid region like this, the minPos would be A and the maxPos would be D: An example of a rectangular cuboid region

Even an EllipsoidRegion has those corners. The ellipsoid itself is contained by the cuboid around it. Both positions minPos and maxPos are essential to calculate approximately which area or which chunks are covered by the corresponding region and calculating with those approximate cubic points is often more performance-friendly than calculating the exact shape of the region. You can retrieve those points at every time using:

  • KelpRegion#getMinPos()
  • KelpRegion#getMaxPos()

Furthermore, every region has a unique id, which is generated randomly every time you create a new region. This unique id can be used to identify a region independently from its other properties such as scale, radius, etc. This makes your operations safe against changes in scale or movements of a region.

Moving a region

A region can be moved in the world, which is called translation. Translation is usually done by a vector pointing in the direction you would like to move the region in. Here is an image demonstrating how moving with a vector works in 2d-space (for simplification):

Moving by a vector in 2d space

All points of the region are moved by the given vector resulting in a new region. You can also move by manually providing how many blocks a region should be moved on each axis. For every region, there are two methods:

KelpRegion#move(Vector)
KelpRegion#move(double deltaX, double deltaY, double deltaZ)

Depending on your implementation there might be even more move methods.

Transforming a region

You can change the scale of a region or expand/shrink it in a certain direction, etc. This is called transformation. Rotation is not yet supported as I am currently lacking the math skills to implement it. There are different default methods for transformation:

// expands the region in all directions (scales it up). 
// negative numbers will scale it down.
KelpRegion#expand(double amount);

// expands the region in a specific direction. 
// WEST will expand it on the negative x axis (towards west), etc.
KelpRegion#expand(KelpBlockFace face, double amount);
example: KelpRegion#expand(KelpBlockFace.WEST, double amount);

// manual expansion on the individual axis. 
// negativeX defines the expansion on the negative x axis (west), etc.
KelpRegion#expand(double negativeX, double positiveX, double negativeY, double positiveY, double negativeZ, double positiveZ);

This example shows how expansion might look like. Here the region has been expanded in the UP direction by 50%, which can be achieved using this code:

region.expand(KelpBlockFace.UP, double amount);

Expansion of a CuboidRegion

But depending on your implementation there might be further options to transform your region. In an ellipsoid region for example you can change the radius, which will result in a different shape:

EllipsoidRegion#setRadius(double radius);
EllipsoidRegion#setXRadius(double xRadius);
EllipsoidRegion#setYRadius(double yRadius);
EllipsoidRegion#setZRadius(double zRadius);

Region listeners

There are some region-related events you can listen for:

  • PlayerEnterRegionEvent triggered when a player enters a region
  • PlayerLeaveRegionEvent triggered when a player leaves a region

But as those events are quite performance heavy if you have lots of online players and lots of regions, they are disabled by default. You have to enable listeners for your region first for each region you want to listen for, which can be achieved with:

KelpRegion#enableListeners();

If you don't need them anymore, you can execute

KelpRegion#disableListeners();

To check if listeners are currently active for your region, do

if (region.listenersEnabled()) {...}

Some code examples

Set all blocks of a region to black wool.

CuboidRegion region = CuboidRegion.create(pos1, pos2);
region.getBlocks().forEach(block -> block.setMaterial(KelpMaterial.BLACK_WOOL));

Basic example of region protection. If a player tries to break a block inside the planet region, the event is canceled.

private EllipsoidRegion planet;

@EventHandler
public void onBlockBreak(BlockBreakEvent event) {
  KelpPlayer player = KelpPlayer.from(event.getPlayer());
  KelpBlock block = KelpBlock.from(event.getBlock());

  if (planet.contains(block)) {
    event.setCancelled(true);
    player.sendMessage("§cYou cannot break blocks on this planet.");
  }

}

This example has a region representing an area only accessible for VIP players. If a player without VIP rank tries to enter the region, they are pushed back and notified that they are not allowed to enter.

  private CuboidRegion premiumArea;
  
  public void createRegion() {
    ...
    
    premiumArea = CuboidRegion.create(pos1, pos2);
    premiumArea.enableListeners();
    
    ...
  }

  @EventHandler
  public void onRegionEnter(PlayerEnterRegionEvent event) {
    KelpPlayer player = event.getPlayer();
    KelpRegion region = event.getRegion();

    if (region.equals(premiumArea) && !player.hasPermission("server.vip")) {
      Vector pushBack = player.getLocation().getDirection().multiply(2);
      player.setVelocity(pushBack);
      player.sendMessage("§cYou cannot enter the VIP area with a normal player rank!");
    }

  }

Further reading

More information about general region methods can be found in the corresponding JavaDocs.

Clone this wiki locally