Tile Entities

Tile entities - это блоки способные к дополнительным операциям, такие как автономный крафт (печки и варочные стойки) или обеспечивающие эффекты (маяк или нотный блок). Так же они могут хранить дополнительную информацию, как инвентарь или текст (сундуки, таблички или командные блоки)

Идентификация Tile Entities и их типа

Снова, все начинается с Location. Location#getTileEntity() - это функция возвращающая tile entity соответствующая блоку, или ``Optional.empty()`, если блок не является tile entity.

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

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

Тип клетки может быть получен функцией TileEntity#getType(), которая возвращает TileEntityType. Которые затем можно сравнивать по аналогии с BlockType. После выполнения этой проверки переменная TileEntity может быть безопасно записана в соответствии с подтипом.

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.

Accessing Inventories

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();
        [...]
    }
}

Смотрите документацию оборудования для того, чтобы использовать его.