Tile Entities

Tile-Entities sind Blöcke, die fähig sind weitere Operationen wie automatisches Craften (Öfen und Braustände) auszuführen oder Effekte (Leuchtfeuer oder Notenblock) zu generieren. Sie enthalten außerdem weitere Daten wie ein Inventar oder Text (Truhen, Schilder oder Command-Blöcke).

Tile-Entities und ihren Typ erkennen

Wieder beginnt alles mit einer Location. Die Funktion Location#getTileEntity() gibt entweder das zum Block gehörende Tile-Entity oder Optional.empty() zurück, falls der Block kein Tile-Entity ist.

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

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

Der Typ eines Tile-Entitys kann durch die Funktion TileEntity#getType() herausgefunden werden, die ein TileEntityType-Objekt zurückgibt. Dieses kann dann, ähnlich wie ein BlockType, verglichen werden. Nachdem dieser Test durchgeführt wurde, kann die TileEntity-Variable sicher zum Typ einer Unterklasse konvertiert werden.

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

Nachdem diese Typumwandlung stattgefunden hat, kann auf die Methoden des entsprechenden Interfaces zugegriffen werden (in diesem Beispiel die Methode Jukebox#ejectRecord()). Detaillierte Informationen über die TileEntity-Unterklassen und ihre entsprechenden Methoden befinden sich im org.spongepowered.api.block.tileentity-Package und seinen untergeordneten Packages in der API-Dokumentation.

Zugreifen und Ändern der Daten eines Tile-Entitys

Ähnlich den Block-States wird mittels eines DataManipulator auf die Daten eines Tile-Entitys zugegriffen. Da die Art der Daten vollständig durch den benutzten DataManipulator beschrieben sind, können alle Änderungen mit dem TileEntity-Interface selbst durchgeführt werden und eine Typumwandlung ist nicht nötig.

Das folgende Beispiel zeigt zwei Methoden, um die Daten eines Schildes zu ändern. Die erste Methode liest (wenn möglich) die erste Zeile. Die Zweite versucht sie zu ändern und gibt einen booleschen Wert zurück, welcher angibt, ob die Operation erfolgreich war.

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;
}

Der hauptsächliche Unterschied bei dem Arbeiten mit einem BlockState und einem Tile-Entity ist, dass Letztere im Gegensatz zum unveränderlichen BlockState ein veränderbarer DataHolder ist.

Auf Inventare zugreifen

Ein großer Teil der Tile-Entities haben ihr eigenes Inventar, am offensichtlichsten sind Truhen und Öfen. Das Inventar kann nicht direkt vom TileEntity aus zugegriffen werden. Daher ist vorher ein Cast notwendig. Da alle Tile Entities, die ein Inventar haben, von TileEntityCarrier abgeleitet sind, reicht es aus auf dieses Interface zu casten, wie unten beschrieben.

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

Wende dich an die Inventar Dokumentation bezüglich der Manipulation des Inventars.