Blöcke verändern

Einen Block-Typ ändern

Das Ändern des Blocktypes ist so einfach, wie der Aufruf von Location#setBlockType(BlockType, Cause) mit dem neuen BlockType. Ähnlich wie bei den meisten Veränderungen von Blöcken, müssen wie den Grund (Cause) für die Änderung des Blockes angeben. In den meisten Fällen reicht es hier, die Haupt-Plugin Klasse anzugeben. Der folgende Code verwandelt den Block an der angegebenen Stelle (Location) in einen Schwamm:

import org.spongepowered.api.block.BlockTypes;
import org.spongepowered.api.event.cause.Cause;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;

public void setToSponge(Location<World> blockLoc, Object myPluginInstance) {
    blockLoc.setBlockType(BlockTypes.SPONGE, Cause.source(myPluginInstance).build());
}

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(Cause) benutzen, die Location bereitstellt.

Einen Block-Status verändern

Ähnlich zum Beispiel oben, bietet die Location``Klasse eine Methode :javadoc:`Location#setBlock(BlockState, Cause)` 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, Object myPluginInstance) {
    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, Cause.source(myPluginInstance).build());
}

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, Object myPluginInstance) {
    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, Cause.source(myPluginInstance).build());
    }
}

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, Object myPluginInstance) {
    BlockState wetState = blockLoc.getBlock();
    Optional<BlockState> dryState = wetState.without(ImmutableWetData.class);
    if (dryState.isPresent()) {
        blockLoc.setBlock(dryState.get(), Cause.source(myPluginInstance).build());
    }
}

Da der WetData Daten Manipulator Boolean Daten repräsentiert, wird durch dessen entfernen dessen die Feuchtigkeit des Blocks (falls vorhanden) auf falsch gesetzt. Die Überprüfung des dryState.isPresent()` wird bei Blöcken, die nicht nass sein können, fehlschlagen, da der dryState in dem Fall Optional.empty() sein wird.

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, Object myPluginInstance) {
    BlockSnapshot snapshot = from.createSnapshot();
    to.setBlock(snapshot.getState(), Cause.source(myPluginInstance).build());
}