Tile Entities

Tile entities são blocos que são capazes de operações adicionais como fabricação autônoma (fornalhas e suporte de poções) ou provê efeitos (como um sinalizador ou um bloco de nota musical). Eles também contêm dados adicionais como um inventário ou texto (como baús, placas ou blocos de comando).

Identificando Tile Entites e seu Tipo

De novo, tudo começa com uma Location. A função Location#getTileEntity() retornará a tile entity correspondente ao bloco ou Optional.empty() se o bloco não é uma tile entity.

import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;

public boolean isTileEntity(Location<World> blockLoc) {
    return blockLoc.getTileEntity().isPresent();
}

The type of a tile entity can then be obtained by the TileEntity#getType() function which returns a TileEntityType. Which can then be compared similar to a BlockType. After performing this check the TileEntity variable can safely be cast to the according subtype.

import org.spongepowered.api.block.tileentity.Jukebox;
import org.spongepowered.api.block.tileentity.TileEntity;
import org.spongepowered.api.block.tileentity.TileEntityTypes;

public boolean isJukebox(TileEntity entity) {
    return entity.getType().equals(TileEntityTypes.JUKEBOX);
}

public void ejectDiscFromJukebox(TileEntity entity) {
    if (isJukebox(entity)) {
        Jukebox jukebox = (Jukebox) entity;
        jukebox.ejectRecord();
    }
}

After performing this cast, the methods provided by the particular interface can be accessed (in this example the Jukebox#ejectRecord() method). For detailed information about TileEntity subtypes and their respective methods refer to the org.spongepowered.api.block.tileentity package and its subpackages in the API.

Accessing and Modifying a Tile Entity’s Data

Similar to block states, the data stored in a tile entity is accessed using a DataManipulator. Since the kind of a data is fully described by the DataManipulator used, all data manipulation can be done with the TileEntity interface itself and does not require a cast.

The following example contains two methods to alter the data of a sign. The first method reads (if possible) the first line, the second attempts to set it and returns the boolean value indicating its success.

import org.spongepowered.api.data.manipulator.mutable.tileentity.SignData;
import org.spongepowered.api.text.Text;

import java.util.Optional;

public Optional<Text> getFirstLine(TileEntity entity) {
    Optional<SignData> data = entity.getOrCreate(SignData.class);
    if (data.isPresent()) {
        return Optional.of(data.get().lines().get(0));
    }
    return Optional.empty();
}

public boolean setFirstLine(TileEntity entity, Text line) {
    if (entity.supports(SignData.class)) {
        SignData sign = entity.getOrCreate(SignData.class).get();
        sign.set(sign.lines().set(0, line));
        entity.offer(sign);
        return true;
    }
    return false;
}

The main difference to working with a BlockState is that a tile entity is a mutable DataHolder as opposed to the immutable BlockState.

Acessar inventários

Quite a share of tile entities come with their own inventory, most notably chests and furnaces. That inventory cannot be accessed directly from the TileEntity interface. So a cast will be necessary. Since all tile entities containing an inventory extend the TileEntityCarrier interface it suffices to cast to that interface as shown below.

import org.spongepowered.api.block.tileentity.carrier.TileEntityCarrier;
import org.spongepowered.api.item.inventory.Inventory;

public void useInventory(TileEntity entity) {
    if (entity instanceof TileEntityCarrier) {
        TileEntityCarrier carrier = (TileEntityCarrier) entity;
        Inventory inventory = carrier.getInventory();
        [...]
    }
}

Refer to the inventory documentation regarding the manipulation of the inventory.