Modificación de Bloques

Cambiar un Tipo de Bloque

Cambiar el Tipo de un Bloque es tan simple como llamar al método Location#setBlockType(BlockType, Cause) con el nuevo BlockType. Al igual que con las modificaciones de bloque, necesitamos suministrar una causa para el cambio de bloque. En la mayoría de los casos, esto puede ser su clase de complemento principal. El siguiente código convierte el bloque en la :javadoc:`Ubicación` dada en una sponge:

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

Es tan simple como eso. Si solo quiere “eliminar” un bloque (que se hace al reemplazarlo con aire), puede utilizar el método Location#removeBlock(Cause) proporcionado por la Ubicación.

Alteración de Estados de Bloque

Similar al ejemplo anterior, la clase Ubicación proporciona un método Location#setBlock(BlockState, Cause) aceptando un nuevo BlockState. Para hacer uso de esto, primero debe adquirir un BlockState que pueda modificar. Puede hacerlo obteniendo el estado actual del bloque a través del método Location#getBlock() o utilizando un estado predeterminado de BlockType. Lo último es demostrado a continuación. El estado por defecto para un bloque Sponge es recuperado y luego modificado para crear directamente un bloque wet sponge:

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

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

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

Ya que el manipulador de datos WetData representa los datos boolean, al removerlo establecemos la humedad del bloque (si tiene alguna) como falso. La verificación de dryState.isPresent() fallará en los estados de bloque que no pueden ser mojados ya que dryState será Optional.empty() en este caso.

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