Modificación de Bloques

Changing a Block’s Type

Changing the Type of a Block is as simple as calling the Location#setBlockType(BlockType) method with the new BlockType. The following code turns the block at the given Location into a sponge:

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

Es tan simple como eso. Si solo quieres “eliminar” un bloque (lo cual es hecho reemplazándolo con aire), puedes usar el método Location#removeBlock() proporcionado por Location.

Alteración de Estados de Bloque

Similar al ejemplo anterior, la clase Location proporciona un método Location#setBlock(BlockState) aceptando un nuevo BlockState. Para usarlo, primero debes adquirir un BlockState que puedas modificar. Puedes hacerlo obteniendo el estado actual del bloque mediante el método Location#getBlock() o utilizando el estado predeterminado de BlockType. El último se demuestra abajo. El estado predeterminado para un bloque de Sponge se recupera y luego se modifica para crear directamente un bloque de sponge húmedo:

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

Ya que un BlockState es un ImmutableDataHolder, puede utilizar los métodos proporcionados with() y without(), ambos devolverán un nuevo BlockState alterado o Optional.empty() si el ImmutableDataManipulator dado no es aplicable para el tipo de bloque representado por el BlockState.

El método with() acepta un ImmutableDataManipulator y tratará de crear un nuevo BlockState con el conjunto de datos dados, sobrescribiendo valores existentes. El siguiente ejemplo cambiará cualquier bloque de tierra por 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);
    }
}

Tenga en cuenta que el DirtData es una copia mutable de los datos guardados en el BlockState. Se cambia y luego se vuelve a convertir en una inmutable y se utiliza para crear un nuevo BlockState que después sustituye al bloque original.

El método without() acepta un referencia de clase y creará un nuevo BlockState sin los datos representados por la clase dada. Si el estado de bloque no será válido sin esos datos, un valor por defecto será utilizado. Así que si la DirtData de un estado de bloque de tierra es removido, se recurrirá a DirtTypes#DIRT, el valor predeterminado. El siguiente ejemplo secará al bloque en una Ubicación dada, si es posible.

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

Since the WetData data manipulator represents boolean data, by removing it we set the wetness of the block (if it has any) to false. The dryState.isPresent() check will fail on block states that cannot be wet since dryState will be Optional.empty() in that case.

Copia de Bloques

Si quiere copiar todo en unos datos de bloque, la clase BlockSnapshot es su mejor amiga. Mientras no expone todos los datos, almacena un BlockType, su BlockState y si es necesario, todos los Datos de Tipo Entidad de Bloque adicionales (por ejemplo inventarios de arca). Convenientemente, la clase Ubicación proporciona un método Location#createSnapshot() para crear una foto del bloque en el momento exacto. Eso hace que copiar el bloque de una ubicación a otra sea muy simple:

import org.spongepowered.api.block.BlockSnapshot;

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