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 DataManipulator
en 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 DataManipulator
en 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 DataManipulator
en 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 BlockTrait
s 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 BlockTrait
s verwendet werden, da diese nur als Ausweichlösung für die Kompatibilität mit Mods gedacht ist.