Blöcke verändern

Den Typ eines Blocks ändern

Den Typ eines Blocks zu ändern ist so einfach wie das Aufrufen der Location#setBlockType(BlockType)-Methode zusammen mit dem neuen BlockType. Der folgende Code verwandelt den Block an der angegebenen Location (Position) in einen Schwamm:

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

public void setToSponge(Location<World> blockLoc) {
    blockLoc.setBlockType(BlockTypes.SPONGE);
}

So einfach ist das. Wenn du nur den Block entfernen möchtest (was du machen könntest, indem du ihn mit Luft ersetzt), dann solltest du einfach die Methode Location#removeBlock() benutzen, die Location bereitstellt.

Einen Block-Status verändern

Ähnlich zum Beispiel oben, bietet die Location``Klasse eine Methode :javadoc:`Location#setBlock(BlockState)` die einen :javadoc:`BlockState` verwendet. Um diese Methode verwenden zu können, musst du zuerst einen ``BlockState holen, den du verändern kannst. Dies kannst du, indem du den aktuellen Status des Blockes mit Location#getBlock() abfragst oder dir Standardzustand eines BlockTypen holst. Hier wird zuerst der Ursprungszustand es Schwammes abgefragt und dann verändert, um damit einen nassen Schwamm Block zu erstellen:

import org.spongepowered.api.Sponge;
import org.spongepowered.api.block.BlockState;
import org.spongepowered.api.data.manipulator.mutable.WetData;

public void setToWetSponge(Location<World> blockLoc) {
    BlockState state = BlockTypes.SPONGE.getDefaultState();
    WetData wetness = Sponge.getDataManager().
        getManipulatorBuilder(WetData.class).get().create();
    wetness.set(wetness.wet().set(true));
    BlockState newState = state.with(wetness.asImmutable()).get();
    blockLoc.setBlock(newState);
}

Da ein BlockState ein :javadoc:`ImmutableDataHolder`` ist, kannst du die bereitgestellten Methoden with() und without() verwenden, die beide einen neuen geänderten BlockState zurückgeben oder Optional. empty(), wenn der angegebene :javadoc:`ImmutableDataManipulator`` nicht auf die Art des Blocks anwendbar ist, der durch den BlockState repräsentiert wird.

Die Methode with() akzeptiert einen ImmutableDataManipulator und wird versuchen einen neuen BlockState zu erstellen, bei dem die Daten gesetzt wurden, bzw. alte Daten überschrieben wurden. Das folgende Beispiel verändert jegliche Art von Dreckblöcken zu Podsol.

import org.spongepowered.api.data.key.Keys;
import
    org.spongepowered.api.data.manipulator.immutable.block.ImmutableDirtData;
import org.spongepowered.api.data.manipulator.mutable.block.DirtData;
import org.spongepowered.api.data.type.DirtTypes;

public void dirtToPodzol(Location<World> blockLoc) {
    BlockState state = blockLoc.getBlock();
    Optional<ImmutableDirtData> dirtDataOpt =
        state.get(ImmutableDirtData.class);

    if (dirtDataOpt.isPresent()) {
        DirtData dirtData = dirtDataOpt.get().asMutable();
        dirtData.set(Keys.DIRT_TYPE, DirtTypes.PODZOL);
        BlockState dirtState = state.with(dirtData.asImmutable()).get();
        blockLoc.setBlock(dirtState);
    }
}

Bitte beachte, dass DirtData eine veränderbare Kopie der Daten im BlockState enthält. Diese werden verändert, bevor sie wieder eine unveränderliche Variante umgewandelt werden und zum Erstellen des neuen BlockStates verwendet werden. Dieser ersetzt dann den vorherigen Block.

Die Methode without() akzeptiert eine Referenz auf die Klasse, dessen Daten aus dem neu zu erstellendem BlockState` entfernt werden sollen. Wenn der Block ohne diese Daten nicht gültig wäre, wird der Standardwert verwendet. Wenn du also die DirtData eines Erd-Blocks entfernst, dann wird diese auf den DirtTypes#DIRT zurückfallen, da dies der Standardwert ist. Das nachfolgende Beispiel versucht den Block an der angegebenen Stelle zu trocknen, falls möglich.

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

public void dry(Location<World> blockLoc) {
    BlockState wetState = blockLoc.getBlock();
    Optional<BlockState> dryState = wetState.without(ImmutableWetData.class);
    if (dryState.isPresent()) {
        blockLoc.setBlock(dryState.get());
    }
}

Da der WetData DataManipulator Daten vom Typ Boolean repräsentiert, setzen wir durch das Entfernen die Nässe des Blocks (wenn er eine hat) auf false. Die Prüfung dryState.isPresent() schlägt bei Blöcken, die nicht nass sein können, fehl, da dryState in diesem Fall Optional.empty() ist.

Kopieren von Blöcken

Wenn du alle Eigenschaften eines Blockzustandes kopieren möchtest, dann ist die BlockSnapshot Klasse dein bester Freund. Während es nicht alle Daten bereitstellt, speichert es doch den BlockType, seinem BlockState und falls nötig auch die dazugehörigen Daten des Tile Entities (beispielsweise den Inhalt einer Kiste). Praktischer Weise enthält die Location Klasse die Location#createSnapshot() Methode, die zum Erstellen eines Schnappschusses zum aktuellen Zeitpunkt verwendet werden kann. Dies macht das Kopieren von Blöcken von einem Ort zu einem anderen sehr einfach:

import org.spongepowered.api.block.BlockSnapshot;

public void copyBlock(Location<World> from, Location<World> to) {
    BlockSnapshot snapshot = from.createSnapshot();
    to.setBlock(snapshot.getState());
}