Accessing Blocks

Basic Information

Blocks are most commonly identified and accessed by their Location. This location points to a certain coordinate within an World. In most cases an ServerWorld will be used as the World.

import org.spongepowered.api.Sponge;
import org.spongepowered.api.world.server.ServerLocation;
import org.spongepowered.api.world.server.ServerWorld;
import org.spongepowered.api.ResourceKey;

public ServerLocation getBlockAt(ResourceKey worldKey, int posX, int posY, int posZ) {
    ServerWorld world = Sponge.server().worldManager().world(worldKey).get();
    ServerLocation blockLocation = world.location(posX, posY, posZ);
    return blockLoc;
}

Aviso

Note that the above example does not check if the world exists. world(worldKey).get() will fail if there is no world of that name loaded.

With this ServerLocation object you can then obtain further information about the block. The following code checks if a referenced block is any kind of banner by checking the blocks type.

import org.spongepowered.api.block.BlockType;
import org.spongepowered.api.block.BlockTypes;
import org.spongepowered.api.tag.BlockTypeTag;
import org.spongepowered.api.world.server.ServerLocation;

public boolean isBanner(ServerLocation blockLoc) {
    Tag<BlockType> bannerTag = BlockTypeTags.BANNERS.get();
    BlockType blockType = blockLoc.blockType();
    return bannerTag.contains(blockType);
}

Dica

The function == could be used in place of equals() when it comes to comparing two BlockType’s as there are a fixed number of instances for every block, however it is generally recommended to use equals().

Block Data Manipulators

The data of a block is held as a DataManipulator, similar to other parts of the API. This is the container that holds information on components of our block such as the orientation, light level, and so on. Checking the values of these manipulators is easy, you just need to check the direction Key.

import org.spongepowered.api.util.Direction;
import org.spongepowered.api.data.Keys;

public boolean isFacingNorth(ServerLocation blockLoc) {
    Optional<Direction> optionalBlockDirection = blockLoc.get(Keys.DIRECTION).get();
    if(!optionalBlockDirection.isPresent()){
        return false;
    }
    Direction blockDirection = optionalBlockDirection.get();
    if(blockDirection.equals(Direction.NORTH)){
        return true;
    }
    return false;
}

First, we need to know which DataManipulator Key we need. We can then pass the get(Key) method of ServerLocation which will return an Optional. We then have to check if our DataManipulator actually exists for our block by checking ifPresent(). If it exists, then we can use it.

More on DataManipulators can be found in the data documentation.

Dica

If a block will never stop supporting a particular DataManipulator, such as DirectionalData with stairs, then there is no need to check for isPresent(). Just remove the optional around the DataManipulator’s value output and fetch the non-optional data by adding .get() to the end of the statement. Note, that this will cause a NoSuchElementException if a block ever stops supporting a particular DataManipulator.

Block States

A BlockState contains a BlockType, any DataManipulators and properties that are applied to the block, and any StatePropertys for a block. It stores all immutable values for a particular block. One use of this is getting an DataManipulator.Immutable, as shown below:

import org.spongepowered.api.block.BlockState;

public boolean isWet(ServerLocation blockLoc) {
    BlockState sponge = blockLoc.getBlock();
    if (!sponge.getType().equals(BlockTypes.SPONGE.get())) {
        return false;
    }
    Optional<Boolean> wetness = sponge.get(Keys.IS_WET);
    if (wetness.isPresent()){
        return wetness.get();
    }
    return false;
}

More information on mutable and immutable DataManipulators can be found in the data documentation.

Block State Properties

A block state property is a certain value on the current state of a block. A block may or may not contain properties depending on the type of block. For example, a bed has a BooleanStateProperty called BED_OCCUPIED. As a boolean can only have two values, true and false, the BED_OCCUPIED property can only be true or false. Checking this value is simple, just call the BlockState#stateProperty(StateProperty<T>) method. An example of this with a bed is shown below:

import org.spongepowered.api.state.BooleanStateProperties;

public boolean isBlueBedOccupied(ServerLocation blockLoc) {
    if(blockLoc.state().type().equals(BlockTypes.BLUE_BED.get())) {
        return blockLoc.state().stateProperty(BooleanStateProperties.BLUE_BED_OCCUPIED).get();
    }
    return false;
}

Aviso

If possible, it is recommended to use DataManipulators in place of StatePropertys where possible as they are only to be meant as a fallback for modded compatibility.