--- title: Blocs type: docs weight: 3 --- La manipulation des blocs est une partie centrale de la modification du monde dans les plugins Hytale. La classe `World` fournit l'accès aux blocs via l'interface `IChunkAccessorSync`, tandis que `WorldChunk` implémente l'interface complète `BlockAccessor` pour le placement avec rotation. {{< callout type="warning" >}} **Important :** `World` n'implémente PAS `BlockAccessor` directement. Pour `placeBlock()` avec rotation, vous devez d'abord obtenir le chunk avec `world.getChunk()`. {{< /callout >}} ## Obtenir des Blocs ```java import com.hypixel.hytale.server.core.universe.Universe; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; import com.hypixel.hytale.math.vector.Vector3i; World world = Universe.get().getWorld("default"); // Obtenir l'ID du bloc (index int) à une position int blockId = world.getBlock(x, y, z); int blockId = world.getBlock(new Vector3i(x, y, z)); // Obtenir le BlockType à une position BlockType blockType = world.getBlockType(x, y, z); BlockType blockType = world.getBlockType(new Vector3i(x, y, z)); // Vérifier si le bloc est vide if (blockType == BlockType.EMPTY) { // Air ou espace vide } ``` ## Définir des Blocs La méthode `setBlock` prend une **clé de type bloc String**, pas un objet BlockType ou un int ID : ```java import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; World world = player.getWorld(); // Définir un bloc par clé de type (ID string) world.setBlock(x, y, z, "stone"); world.setBlock(x, y, z, "oak_planks", 0); // avec settings // Utiliser BlockType - obtenir d'abord la chaîne ID BlockType stone = BlockType.getAssetMap().getAsset("stone"); if (stone != null) { world.setBlock(x, y, z, stone.getId()); // Utiliser getId() pour obtenir la clé string } // Index d'ID de bloc (pour usage interne) int stoneIndex = BlockType.getAssetMap().getIndex("stone"); // Note : setBlock prend String, pas int - utilisez la clé directement ``` ## Placement de Blocs avec Rotation {{< callout type="info" >}} **placeBlock() est sur WorldChunk, pas World !** Vous devez d'abord obtenir le chunk pour placer des blocs avec rotation. {{< /callout >}} ```java import com.hypixel.hytale.server.core.universe.world.chunk.WorldChunk; import com.hypixel.hytale.server.core.asset.type.blocktype.config.Rotation; import com.hypixel.hytale.server.core.asset.type.blocktype.config.RotationTuple; import com.hypixel.hytale.math.util.ChunkUtil; // Obtenir le chunk contenant cette position de bloc WorldChunk chunk = world.getChunk(ChunkUtil.indexChunkFromBlock(x, z)); if (chunk != null) { // Placer un bloc avec rotation // Valeurs de Rotation : None, Ninety, OneEighty, TwoSeventy chunk.placeBlock(x, y, z, "oak_log", Rotation.Ninety, // yaw (90 degrés) Rotation.None, // pitch Rotation.None // roll ); // Placer avec tuple de rotation et options chunk.placeBlock(x, y, z, "oak_log", RotationTuple.of(Rotation.Ninety, Rotation.None, Rotation.None), 0, // settings true // validatePlacement ); } ``` ### Valeurs de Rotation L'enum `Rotation` a ces valeurs (PAS les directions cardinales) : | Rotation | Degrés | |----------|--------| | `Rotation.None` | 0° | | `Rotation.Ninety` | 90° | | `Rotation.OneEighty` | 180° | | `Rotation.TwoSeventy` | 270° | ## Casser des Blocs ```java // Casser un bloc à une position (nécessite le paramètre settings) world.breakBlock(x, y, z, 0); // 0 = settings par défaut ``` ## Assets BlockType Les assets BlockType définissent les propriétés des blocs : ```java import com.hypixel.hytale.server.core.asset.type.blocktype.config.BlockType; import com.hypixel.hytale.protocol.BlockMaterial; // Obtenir le type de bloc par ID BlockType blockType = BlockType.getAssetMap().getAsset("stone"); if (blockType != null) { // Obtenir la chaîne ID du bloc String blockId = blockType.getId(); // Obtenir le matériau BlockMaterial material = blockType.getMaterial(); } // Obtenir l'index d'ID du bloc (pour usage interne) int blockIndex = BlockType.getAssetMap().getIndex("stone"); // Obtenir le bloc depuis l'index BlockType fromIndex = BlockType.getAssetMap().getAsset(blockIndex); ``` ## Événements de Blocs ### BreakBlockEvent Déclenché quand un bloc est cassé : ```java import com.hypixel.hytale.server.core.event.events.ecs.BreakBlockEvent; import com.hypixel.hytale.math.vector.Vector3i; import java.util.logging.Level; getEventRegistry().register(BreakBlockEvent.class, event -> { // Obtenir les infos de destruction Vector3i position = event.getTargetBlock(); BlockType blockType = event.getBlockType(); getLogger().at(Level.INFO).log("Bloc cassé à " + position); // Annuler si protégé event.setCancelled(true); }); ``` ### PlaceBlockEvent Déclenché quand un bloc est placé : ```java import com.hypixel.hytale.server.core.event.events.ecs.PlaceBlockEvent; import com.hypixel.hytale.server.core.asset.type.blocktype.config.RotationTuple; getEventRegistry().register(PlaceBlockEvent.class, event -> { // Obtenir les infos de placement Vector3i position = event.getTargetBlock(); RotationTuple rotation = event.getRotation(); getLogger().at(Level.INFO).log("Bloc placé à " + position); // Annuler si non autorisé event.setCancelled(true); }); ``` ### DamageBlockEvent Déclenché quand un bloc est endommagé (avant d'être cassé) : ```java import com.hypixel.hytale.server.core.event.events.ecs.DamageBlockEvent; getEventRegistry().register(DamageBlockEvent.class, event -> { Vector3i position = event.getTargetBlock(); BlockType blockType = event.getBlockType(); // Annuler pour empêcher les dégâts event.setCancelled(true); }); ``` ## État d'Interaction de Bloc Les blocs peuvent avoir des états d'interaction (comme portes ouvertes/fermées) : ```java BlockType currentBlock = world.getBlockType(x, y, z); if (currentBlock != null) { // Définir le bloc à un état différent world.setBlockInteractionState( new Vector3i(x, y, z), currentBlock, "open" // nom de l'état ); } ``` ## Travailler avec les Blocs ### Vérifier une Zone pour un Type de Bloc ```java public boolean containsBlockType(World world, Vector3i min, Vector3i max, String blockTypeKey) { // Note : Vector3i utilise getX(), getY(), getZ() - PAS x(), y(), z() for (int x = min.getX(); x <= max.getX(); x++) { for (int y = min.getY(); y <= max.getY(); y++) { for (int z = min.getZ(); z <= max.getZ(); z++) { BlockType block = world.getBlockType(x, y, z); if (block != null && block.getId().equals(blockTypeKey)) { return true; } } } } return false; } ``` ### Remplir une Zone ```java public void fillArea(World world, Vector3i min, Vector3i max, String blockTypeKey) { for (int x = min.getX(); x <= max.getX(); x++) { for (int y = min.getY(); y <= max.getY(); y++) { for (int z = min.getZ(); z <= max.getZ(); z++) { world.setBlock(x, y, z, blockTypeKey); } } } } ``` ### Remplacer des Blocs ```java public void replaceBlocks(World world, Vector3i min, Vector3i max, String fromBlock, String toBlock) { for (int x = min.getX(); x <= max.getX(); x++) { for (int y = min.getY(); y <= max.getY(); y++) { for (int z = min.getZ(); z <= max.getZ(); z++) { BlockType current = world.getBlockType(x, y, z); if (current != null && current.getId().equals(fromBlock)) { world.setBlock(x, y, z, toBlock); } } } } } ``` ## Positions de Blocs ```java import com.hypixel.hytale.math.vector.Vector3i; // Vector3i pour les positions de blocs entières Vector3i blockPos = new Vector3i(100, 64, 200); // Obtenir les coordonnées individuelles - utiliser getX(), getY(), getZ() int x = blockPos.getX(); int y = blockPos.getY(); int z = blockPos.getZ(); // Positions adjacentes Vector3i above = new Vector3i(x, y + 1, z); Vector3i below = new Vector3i(x, y - 1, z); Vector3i north = new Vector3i(x, y, z - 1); Vector3i south = new Vector3i(x, y, z + 1); Vector3i east = new Vector3i(x + 1, y, z); Vector3i west = new Vector3i(x - 1, y, z); ``` ## Bonnes Pratiques {{< callout type="info" >}} **Conseils pour la Manipulation de Blocs :** - Les opérations sur les blocs doivent s'exécuter sur le thread de tick du monde - Utilisez `getBlockType()` pour vérifier les types, `getBlock()` pour les IDs bruts - Vérifiez `BlockType.EMPTY` pour les blocs air/vides - Les événements étendent `CancellableEcsEvent` - utilisez `setCancelled(true)` pour empêcher - Considérez les limites de chunks lors du traitement de grandes zones - Pour `placeBlock()` avec rotation, obtenez d'abord le chunk {{< /callout >}} ```java // Modification sécurisée de bloc depuis un contexte asynchrone world.execute(() -> { world.setBlock(x, y, z, "stone"); }); ``` ## Référence API ### Méthodes World (IChunkAccessorSync) | Méthode | Retour | Description | |--------|--------|-------------| | `getBlock(int, int, int)` | `int` | Obtenir l'ID du bloc à la position | | `getBlock(Vector3i)` | `int` | Obtenir l'ID du bloc à la position | | `getBlockType(int, int, int)` | `BlockType?` | Obtenir le BlockType à la position | | `getBlockType(Vector3i)` | `BlockType?` | Obtenir le BlockType à la position | | `setBlock(x, y, z, String)` | `void` | Définir bloc par clé de type | | `setBlock(x, y, z, String, int)` | `void` | Définir bloc avec settings | | `breakBlock(x, y, z, int)` | `boolean` | Casser bloc avec settings | | `setBlockInteractionState(...)` | `void` | Définir état du bloc | ### Méthodes WorldChunk (BlockAccessor) | Méthode | Retour | Description | |--------|--------|-------------| | `placeBlock(x, y, z, String, Rotation, Rotation, Rotation)` | `boolean` | Placer avec rotation | | `placeBlock(x, y, z, String, RotationTuple, int, boolean)` | `boolean` | Placer avec options | | `testPlaceBlock(...)` | `boolean` | Tester si placement valide |