Modifier les Blocs

Changer le Type de Blocs

Changer le Type d’un Bloc est aussi simple que d’appeler la méthode Location#setBlockType(BlockType, Cause) avec le nouveau BlockType. Comme avec la plupart des modifications de blocs, nous devons fournir une cause pour le changement de bloc. Dans la plupart des cas, cela peut se faire dans la classe principale de votre plugin. Le code suivant transforme le bloc à la Location donnée en éponge :

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

C’est aussi simple que cela. Si vous voulez juste “supprimer” un bloc (Qui se fait en le remplaçant par de l’air), vous devez juste utiliser la méthode Location#removeBlock(Cause) qui est fournie par Location.

Modifier les États des Blocs

Comme dans l’exemple ci-dessus, la classe Location fournit une méthode Location#setBlock(BlockState, Cause) acceptant un nouveau BlockState. Pour pouvoir l’utiliser, vous devez en premier lieu avoir un BlockState que vous pouvez modifier. Vous pouvez faire la même chose en obtenant l’état actuel du bloc avec la méthode Location#getBlock() ou en utilisant un état de BlockType par défaut. Ce dernier est démontré ci-dessous. L’état par défaut d’un bloc d’éponge est récupéré et ensuite modifié pour créer directement un bloc d’éponge mouillée :

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

Puisqu’un BlockState est un ImmutableDataHolder, vous pouvez utiliser les méthodes fournies with() et without() qui vont toutes les deux renvoyer un nouveau BlockState modifié ou Optional.empty() si le ImmutableDataManipulator donné n’est pas applicable au type de bloc représenté par le BlockState.

La méthode with() accepte un ImmutableDataManipulator et va essayer de créer un nouveau BlockState avec l’ensemble de données fourni, en écrasant les valeurs existantes. L’exemple suivant va changer n’importe quel bloc de terre en podzol.

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

Notez que DirtData est une copie mutable des données contenues dans le BlockState. Elles sont changées et ensuite utilisées pour créer un nouveau BlockState qui va remplacer le bloc originel.

La méthode without() accepte une classe référence et va créer un nouveau BlockState sans les données représentées par la classe donnée. Si le nouveau BlockState n’est pas valide sans ces données, une valeur par défaut sera utilisée. Donc si la donnée DirtData d’un bloc de terre est supprimée, elle sera automatiquement remplacée par la valeur DirtTypes#DIRT, la valeur par défaut. L’exemple suivant va sécher le bloc à la Location donnée, si possible.

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

Puisque le manipulateur de données WetData représente des données booléennes, en le supprimant nous définissons l’humidité du bloc (s’il en possède) à false. La vérification dryState.isPresent() échouera lorsqu’elle sera faite sur des blocs ne pouvant pas être humides puisque dryState sera Optional.empty() dans ce cas.

Copier les Blocs

Si vous souhaitez copier toutes les données d’un bloc, la classe BlockSnapshot sera votre meilleure amie. Même si elle ne prend pas en compte toutes les données, elle sauvegarde un BlockType, son BlockState et, si nécessaire, toutes les données supplémentaires des Tile Entities (Pour les inventaires de coffres par exemple). Comme les choses sont bien faites, la classe Location fournit la méthode Location#createSnapshot() pour créer une copie du bloc à ce point dans le temps. Cela rend la copie d’un bloc d’un emplacement à un autre très 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());
}