Accéder aux Blocs

Informations basiques

Les blocs sont dans la majeure partie du temps identifiables et accessibles par leur Location (position). Cette position nous indique des coordonnées et un Extent (zone). Dans la plupart des cas un World (monde) sera utilisé comme zone.

import org.spongepowered.api.Sponge;
import org.spongepowered.api.world.Location;
import org.spongepowered.api.world.World;

public Location<World> getBlockAt(String worldName, int posX, int posY, int posZ) {
    World world = Sponge.getServer().getWorld(worldName).get();
    Location<World> blockLoc = new Location<World>(world, posX, posY, posZ);
    return blockLoc;
}

Avertissement

Notez que l’exemple ci-dessous ne vérifie pas si le monde existe. La méthode getWorld(worldName).get() va échouer si aucun monde portant ce nom n’est chargé.

Avec cet objet Location vous pouvez obtenir des informations plus complètes à propos du bloc. Le code suivant vérifie si un bloc référencé est une bannière en regardant le type de bloc.

import org.spongepowered.api.block.BlockType;
import org.spongepowered.api.block.BlockTypes;

public boolean isBanner(Location<World> blockLoc) {
    BlockType type = blockLoc.getBlock().getType();
    return type.equals(BlockTypes.STANDING_BANNER)
            || type.equals(BlockTypes.WALL_BANNER);
}

Astuce

La fonction == pourrait être utilisée à la place de equals() comme il n’y a qu’une seule instance de BlockType pour chaque bloc, mais il est recommandé d’utiliser equals().

Manipulateurs de Données de Blocs

Les données d’un bloc sont contenues dans le DataManipulator, comme pour les autres parties de l’API. Ceci contient des informations liées au bloc, comme son orientation, son type (pierre / granite), et ainsi de suite. Vérifier les valeurs de ces manipulateurs est facile, vous devez juste vérifier la direction du bloc DirectionalData.

import org.spongepowered.api.data.key.Keys;
import org.spongepowered.api.data.manipulator.mutable.block.DirectionalData;

public boolean isFacingNorth(Location<World> blockLoc) {
    Optional<DirectionalData> optionalData = blockLoc.get(DirectionalData.class);
    if (!optionalData.isPresent()) {
        return false;
    }
    DirectionalData data = optionalData.get();
    if (data.get(Keys.DIRECTION).get().equals(Direction.NORTH)) {
        return true;
    }
    return false;
}

Tout d’abord, nous devons savoir de quelle sous-interface de DataManipulator nous avons besoin. Celles qui s’appliquent aux blocs se trouvent dans les packages org.spongepowered.api.data.manipulator.mutable et org.spongepowered.api.data.manipulator.mutable.block. Ensuite, nous pouvons juste passer cette classe à la méthode get(DataManipulator) de Location qui va retourner un Optional. Nous devons ensuite vérifier si notre DataManipulator existe actuellement pour notre bloc en vérifiant ifPresent(). Si il existe, nous pouvons alors l’utiliser.

Plus d’infos sur les DataManipulators peuvent être trouvées dans la documentation des données.

Astuce

Si un bloc ne s’arrêtera jamais de supporter un DataManipulator particulier, comme le DirectionalData avec les escaliers, il n’y a alors pas besoin de vérifier le isPresent(). Supprimez juste l’optional autour du DataManipulator et récupérer les données non-optionnelles en ajoutant .get() à la fin de l’instruction. Notez que cela entraînera une NullPointerException si un bloc s’arrête de supporter un DataManipulator particulier.

États des Blocs

Un BlockState contient un BlockType, n’importe quels DataManipulators et des propriétés qui sont appliquées au bloc, et n’importe quels BlockTraits pour un bloc. Il stocke toutes les valeurs immuables pour un bloc particulier. Une utilisation de ceci est de récupérer un ImmutableDataManipulator, comme montré ci-dessous :

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

public void isWet(Location blockLoc) {
    BlockState sponge = blockLoc.getBlock();
    if (!sponge.getType().equals(BlockTypes.SPONGE)) {
        return false;
    }
    Optional<ImmutableWetData> wetness = sponge.get(ImmutableWetData.class);
    return wetness.isPresent();
}

Plus d’informations sur les DataManipulators mutables et immuables peuvent être trouvées dans la documentation des données.

Propriétés de Blocs

Les blocs peuvent contenir certaines propriétés. Une propriété est une valeur prédéterminée qui définit la logique de jeu de ce bloc particulier. Par exemple, les blocs peuvent contenir des valeurs de résistance aux explosions prédéterminées qui peuvent être utilisées pour déterminer avec quoi vous travailler, sans vérifier le type de bloc que ça pourrait être un par un. Par exemple, si nous voulions récupérer la résistance aux explosions d’un bloc et vérifier si elle est plus grande ou égale à un, ça serait fait comme ceci :

import org.spongepowered.api.data.property.DoubleProperty;
import org.spongepowered.api.data.property.block.BlastResistanceProperty;

public boolean blastResistanceGreaterThanOne(Location<World> blockLoc) {
    Optional<BlastResistanceProperty> optional =
        blockLoc.getProperty(BlastResistanceProperty.class);

    if(optional.isPresent()) {
        BlastResistanceProperty resistance = optional.get();
        DoubleProperty one = DoubleProperty.greaterThanOrEqual(1);
        return one.matches(resistance);
    }
    return false;
}

Ceci récupére la résistance aux explosions de notre bloc et la compare à un nouveau DoubleProperty, puisque BlastResistanceProperty hérite de DoubleProperty. La méthode va donc retourner si la résistance aux explosions de notre bloc est plus grande que un, la valeur du matches(). Si nous voulions voir si elle était plus petite que deux, nous le remplacerions par lessThan().

Si nous étions en train de comparer deux propriétés déjà existantes, ça prendrait l”Operator de notre première valeur, celle pour laquelle nous créons une propriété double. Si l”Operator est DELEGATE, qui est l’opérateur « aucun », alors il prendra l”Operator de la seconde valeur, celle du matches(). La comparaison retournera false si les deux sont DELEGATE. Un exemple de comparaison de deux PoweredPropertys, et d’une BooleanProperty peut être trouvé ci-dessous :

import org.spongepowered.api.data.property.block.PoweredProperty;

public boolean areBlocksPowered(Location<World> blockLoc, Location<World> blockLoc2) {
    Optional<PoweredProperty> optional = blockLoc.getProperty(PoweredProperty.class);
    Optional<PoweredProperty> optional2 = blockLoc2.getProperty(PoweredProperty.class);

    if(optional.isPresent() && optional2.isPresent()) {
        PoweredProperty property1 = optional2.get();
        PoweredProperty property2 = optional2.get();
        BooleanProperty booleanProperty = BooleanProperty.of(property1);
        BooleanProperty booleanProperty2 = BooleanProperty.of(true);

        if(booleanProperty2.matches(property1)) {
            return booleanProperty.matches(property2);
        }
    }
    return false;
}

Le second if vérifie si une des propriétés est vraie. Si c’est vrai et que les deux sont égales, alors les deux valeurs doivent être vraies. Par conséquent, éliminant le besoin de vérifier la seconde valeur. Maintenant nous savons que les deux blocs sont alimentés.

Une liste des propriétés de blocs possibles peut être trouvée dans le package org.spongepowered.api.data.property.block.

Caractéristiques de Blocs

Une caractéristique de bloc est une certaine valeur sur l’état actuel d’un bloc. Un bloc peut ou peut ne pas contenir des caractéristiques selon le type de bloc. Par exemple, un lit possède un BooleanTrait appelé BED_OCCUPIED. Comme un booléen peut seulement avoir deux valeurs, vrai et faux, la caractéristique BED_OCCUPIED peut seulement être vraie ou fausse. Vérifier cette valeur est simple, appelez juste la méthode BlockState#getTraitValue(BlockTrait). Un exemple avec un lit est illustré ci-dessous :

import org.spongepowered.api.block.trait.BooleanTraits;

public boolean isBedOccupied(Location<World> blockLoc) {
    if(blockLoc.getBlock().getType().equals(BlockTypes.BED)) {
        return blockLoc.getBlock().getTraitValue(BooleanTraits.BED_OCCUPIED).get();
    }
    return false;
}

Avertissement

Si possible, il est recommandé d’utiliser les DataManipulators à la place des BlockTraits lorsque c’est possible car ils sont seulement conçus comme un secours pour la compatibilité avec les mods.