Block-Zugriff

Grundlegende Informationen

Der Zugriff auf und die Identifikation von Blöcken findet meistens über ihre Location statt. Diese Position beschreibt eine bestimmte Koordinate innerhalb eines Extents. In den meisten Fällen wird World als Extent verwendet.

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

public Location<World> getBlockAt(String worldName, int posX, int posY, int posZ) {
    World world = Sponge.getServer().getWorld(worldName).get();
    Location<World> blockLoc = new Location<World>(world, posX, posY, posZ);
    return blockLoc;
}

Warnung

Man beachte, dass das obige Beispiel nicht prüft, ob die World existiert. getWorld(worldName).get() würde fehlschlagen, wenn keine Welt mit dem übergebenen Namen geladen wurde.

Mit diesem Location Objekt kann man weitere Informationen über den Block erhalten. Der folgende Code überprüft, ob der referenzierte Block irgendeine Art von Banner ist, indem er den Blocktyp prüft.

import org.spongepowered.api.block.BlockType;
import org.spongepowered.api.block.BlockTypes;

public boolean isBanner(Location<World> blockLoc) {
    BlockType type = blockLoc.getBlock().getType();
    return type.equals(BlockTypes.STANDING_BANNER)
            || type.equals(BlockTypes.WALL_BANNER);
}

Tipp

Die Funktion `` ==`` kann anstelle von equals() verwendet werden, da es nur eine :javadoc: Blocktyp Instanz für jeden Block gibt, es wird allerdings generell empfohlen equals() zu verwenden.

Block Daten Manipulatoren

Die Daten eines Blocks sind in einem DataManipulator enthalten, ähnlich zu anderen Teilen der API. Dieser Container enthält Informationen über die Komponenten unseres Blocks, sowie die Orientierung, die spezifischen Typen (Stein vs. Granit) und so weiter. Diese Werte zu überprüfen ist einfach, du musst bloß die Ausrichtung des Blocks (DirectionalData) überprüfen.

import org.spongepowered.api.data.key.Keys;
import org.spongepowered.api.data.manipulator.mutable.block.DirectionalData;

public boolean isFacingNorth(Location<World> blockLoc) {
    Optional<DirectionalData> optionalData = blockLoc.get(DirectionalData.class);
    if (!optionalData.isPresent()) {
        return false;
    }
    DirectionalData data = optionalData.get();
    if (data.get(Keys.DIRECTION).get().equals(Direction.NORTH)) {
        return true;
    }
    return false;
}

Zunächst müssen wir herausfinden, welches DataManipulator-Sub-Interface wir brauchen. Diejenigen, die für Blöcke sind, findet man in den org.spongepowered.api.data.manipulator.mutable und org.spongepowered.api.data.manipulator.mutable.block Paketen. Danach können wir diese Klasse an die get(DataManipulator) Methode von Location weitergeben, welche ein Optional zurückgeben wird. Als nächstes müssen wir überprüfen, ob unser DataManipulator für unseren Block tatsächlich existiert, indem wir schauen ob ifPresent() existiert. Falls ja, können wir es verwenden.

Du kannst mehr über DataManipulatoren in der Data Dokumentation erfahren.

Tipp

Sollte ein Block niemals aufhören einen spezifischen DataManipulator zu unterstützen, wie zum Beispiel bei DirectionalData und Stufen der Fall ist, dann ist es nicht nötig mit isPresent() zu prüfen, ob die Daten da sind. Entferne einfach das Optional um den DataManipulator und hole dir die existierenden Daten durch hinzufügen von .get() am Ende deines Ausdrucks. Bitte beachte, dass dies eine NullPointerException wirft, sollte der Block jemals aufhören, diesen DataManipulator zu unterstützen.

Block-Zustände

Ein BlockState (Zustand eines Blockes) enthält den BlockType, jegliche DataManipulatoren und Eigenschaften, die auf den Block angewendet wurden, sowie alle BlockTraits. Kurz gesagt speichert er alle unveränderlichen Werte für einen bestimmten Block. Ein möglicher Nutzen, den dies hat, ist das Holen von ImmutableDataManipulatoren, wie unten beschrieben ist:

import org.spongepowered.api.block.BlockState;
import org.spongepowered.api.data.manipulator.immutable.ImmutableWetData;

public void isWet(Location blockLoc) {
    BlockState sponge = blockLoc.getBlock();
    if (!sponge.getType().equals(BlockTypes.SPONGE)) {
        return false;
    }
    Optional<ImmutableWetData> wetness = sponge.get(ImmutableWetData.class);
    return wetness.isPresent();
}

Mehr Informationen über veränderbare und unveränderliche DataManipulatoren können in der Data Dokumentation gefunden werden.

Block Eigenschaften

Blöcke können verschiedene Eigenschaften haben. Eine Eigenschaft ist eine vordefinierter Wert, der definiert wie die Spiel Logik dieses speziellen Blocks funktioniert. Zum Beispiel, Blocks können eine festgelegte Resistenz gegen Explosionen haben, damit kannst du herausfinden, womit du es zu tun hast, ohne einzeln auf den tatsächlichen Typ des Blockes zu prüfen, mit dem du es zu tun haben könntest. Zum Beispiel, wenn du herausfinden möchtest, ob die Resistenz gegen Explosionen größer oder gleich eins ist, würdest du es so machen:

import org.spongepowered.api.data.property.DoubleProperty;
import org.spongepowered.api.data.property.block.BlastResistanceProperty;

public boolean blastResistanceGreaterThanOne(Location<World> blockLoc) {
    Optional<BlastResistanceProperty> optional =
        blockLoc.getProperty(BlastResistanceProperty.class);

    if(optional.isPresent()) {
        BlastResistanceProperty resistance = optional.get();
        DoubleProperty one = DoubleProperty.greaterThanOrEqual(1);
        return one.matches(resistance);
    }
    return false;
}

Auf diesen Weg erfährst du die Resistenz deines Blockes und vergleichst ihn mit einer neuen DoubleProperty, da BlastResistanceProperty von DoubleProperty abgeleitet ist. Diese Methode wird dann zurückgeben, ob die Resistenz deines Blockes gegen Explosionen größer ist, als die des Wertes, denn du in matches() platziert hast. Wenn wir stattdessen herausfinden möchten, ob es kleiner war als zwei würden wir stattdessen lessThan() verwenden.

Wenn wir zwei bereits existierende Eigenschaften miteinander vergleichen , wird der Operator unseres ersten Wertes, für den wir die Double Eigenschaft erstellt haben, genommen. Falls der Operator DELEGATE ist, was ein leerer Operator ist, dann wird der Operator des zweiten Wertes, dem innerhalb von matches(), verwendet. Der Vergleich wird falsch zurückgeben, wenn beide DELEGATE verwenden. Ein Beispiel bei dem zwei PoweredPropertys, die BooleanPropertys sind, miteinander verglichen werden, kann man hier drunter sehen:

import org.spongepowered.api.data.property.block.PoweredProperty;

public boolean areBlocksPowered(Location<World> blockLoc, Location<World> blockLoc2) {
    Optional<PoweredProperty> optional = blockLoc.getProperty(PoweredProperty.class);
    Optional<PoweredProperty> optional2 = blockLoc2.getProperty(PoweredProperty.class);

    if(optional.isPresent() && optional2.isPresent()) {
        PoweredProperty property1 = optional2.get();
        PoweredProperty property2 = optional2.get();
        BooleanProperty booleanProperty = BooleanProperty.of(property1);
        BooleanProperty booleanProperty2 = BooleanProperty.of(true);

        if(booleanProperty2.matches(property1)) {
            return booleanProperty.matches(property2);
        }
    }
    return false;
}

Die zweite if Überprüfung prüft, ob eine der Eigenschaften wahr ist, Wenn eine wahr ist und beide gleich sind, dann müssen beide wahr sein. Deshalb können wir uns die Überprüfung des zweiten Wertes sparen. Daher wissen wir nun, dass beide Blöcke durch Redstone aktiviert sind.

Eine List mit möglichen Eigenschaften von Blöcken kann im org.spongepowered.api.data.property.block Paket eingesehen werden.

Block Merkmale

Ein BlockTrait ist ein bestimmtes Merkmal der Teil des aktuellen Zustandes des Blockes ist. Je nachdem, um welchen Typ von Block es sich handelt, kann es sein, dass es BlockTraits gibt, bzw. nicht gibt. Beispielsweise hat ein Bed einen BooleanTrait namens BED_OCCUPIED. Da ein Boolean nur zwei Zustände annehmen kann, wahr und falsch, kann das BED_OCCUPIED Merkmal ebenfalls nur wahr und falsch annehmen. Diesen Wert zu überprüfen ist einfach, es reicht ein Aufruf der BlockState#getTraitValue(BlockTrait) Methode. Ein Beispiel hiervon mit einem Bett ist im folgenden gezeigt:

import org.spongepowered.api.block.trait.BooleanTraits;

public boolean isBedOccupied(Location<World> blockLoc) {
    if(blockLoc.getBlock().getType().equals(BlockTypes.BED)) {
        return blockLoc.getBlock().getTraitValue(BooleanTraits.BED_OCCUPIED).get();
    }
    return false;
}

Warnung

Wenn möglich, sollte ein DataManipulator anstelle von BlockTraits verwendet werden, da diese nur als Ausweichlösung für die Kompatibilität mit Mods gedacht ist.