Files
2026-01-20 20:33:59 +01:00

21 KiB

title, type, weight
title type weight
Événements Bloc docs 3

Événements déclenchés par les interactions et modifications de blocs. Ces événements utilisent le pattern ECS (Entity Component System).

Événements de Destruction & Placement

BreakBlockEvent

{{< badge "Annulable" >}} {{< badge "ECS" >}}

Déclenché quand un bloc est en train d'être cassé.

Package : com.hypixel.hytale.server.core.event.events.ecs

{{< tabs items="Champs,Méthodes,Exemple" >}} {{< tab >}}

Champ Type Description
targetBlock Vector3i Position du bloc
blockType BlockType Type de bloc
itemInHand ItemStack Outil utilisé
{{< /tab >}}
{{< tab >}}
  • getTargetBlock() - Retourne la position du bloc
  • getBlockType() - Retourne le type de bloc
  • getItemInHand() - Retourne l'outil utilisé
  • isCancelled() - Vérifie si annulé
  • setCancelled(boolean) - Annule le cassage {{< /tab >}} {{< tab >}}
getEventRegistry().register(BreakBlockEvent.class, event -> {
    Vector3i position = event.getTargetBlock();
    BlockType blockType = event.getBlockType();
    ItemStack tool = event.getItemInHand();

    // Protéger certains blocs
    if (blockType.getId().equals("special_ore")) {
        event.setCancelled(true);
        return;
    }

    // Logger le cassage
    getLogger().at(Level.INFO).log("Bloc cassé à " + position + ": " + blockType.getId());
});

{{< /tab >}} {{< /tabs >}}


PlaceBlockEvent

{{< badge "Annulable" >}} {{< badge "ECS" >}}

Déclenché quand un bloc est placé.

Package : com.hypixel.hytale.server.core.event.events.ecs

{{< tabs items="Champs,Méthodes,Exemple" >}} {{< tab >}}

Champ Type Description
targetBlock Vector3i Position où le bloc sera placé
rotation RotationTuple Rotation/orientation du bloc
itemInHand ItemStack Item bloc placé
{{< /tab >}}
{{< tab >}}
  • getTargetBlock() - Retourne la position cible
  • setTargetBlock(Vector3i) - Change la position de placement
  • getRotation() - Retourne la rotation du bloc
  • setRotation(RotationTuple) - Change la rotation
  • getItemInHand() - Retourne l'item bloc
  • isCancelled() - Vérifie si annulé
  • setCancelled(boolean) - Annule le placement {{< /tab >}} {{< tab >}}
getEventRegistry().register(PlaceBlockEvent.class, event -> {
    Vector3i position = event.getTargetBlock();
    RotationTuple rotation = event.getRotation();
    ItemStack item = event.getItemInHand();

    // Vérifier les permissions de construction
    if (isProtectedArea(position)) {
        event.setCancelled(true);
        return;
    }

    // Forcer une certaine rotation
    event.setRotation(RotationTuple.of(Rotation.North, Rotation.None, Rotation.None));
});

{{< /tab >}} {{< /tabs >}}


DamageBlockEvent

{{< badge "Annulable" >}} {{< badge "ECS" >}}

Déclenché quand des dégâts sont appliqués à un bloc pendant le cassage (avant que le bloc ne soit complètement cassé).

Package : com.hypixel.hytale.server.core.event.events.ecs

{{< tabs items="Champs,Méthodes,Exemple" >}} {{< tab >}}

Champ Type Description
targetBlock Vector3i Position du bloc
blockType BlockType Type de bloc
itemInHand ItemStack Outil utilisé (peut être null)
currentDamage float Dégâts déjà appliqués au bloc
damage float Dégâts appliqués ce tick
{{< /tab >}}
{{< tab >}}
  • getTargetBlock() - Retourne la position du bloc
  • setTargetBlock(Vector3i) - Change le bloc cible
  • getBlockType() - Retourne le type de bloc
  • getItemInHand() - Retourne l'outil utilisé
  • getCurrentDamage() - Retourne les dégâts accumulés
  • getDamage() - Retourne les dégâts ce tick
  • setDamage(float) - Modifie le montant de dégâts
  • isCancelled() - Vérifie si annulé
  • setCancelled(boolean) - Annule les dégâts {{< /tab >}} {{< tab >}}
getEventRegistry().register(DamageBlockEvent.class, event -> {
    Vector3i position = event.getTargetBlock();
    BlockType blockType = event.getBlockType();

    // Rendre certains blocs indestructibles
    if (blockType.getId().equals("bedrock")) {
        event.setCancelled(true);
        return;
    }

    // Réduire les dégâts sur les blocs renforcés
    if (blockType.getId().startsWith("hardened_")) {
        event.setDamage(event.getDamage() * 0.5f);
    }

    // Logger la progression du minage
    float progress = event.getCurrentDamage() / 100f;
    getLogger().at(Level.INFO).log("Bloc " + blockType.getId() + " à " + progress + "% de dégâts");
});

{{< /tab >}} {{< /tabs >}}


Événements d'Interaction

UseBlockEvent

Classe de base pour les événements d'utilisation de bloc. A des variantes Pre et Post.

Package : com.hypixel.hytale.server.core.event.events.ecs

UseBlockEvent.Pre

{{< badge "Annulable" >}}

Déclenché avant qu'une action d'utilisation de bloc ne se produise (clic droit sur bloc).

{{< tabs items="Champs,Méthodes,Exemple" >}} {{< tab >}}

Champ Type Description
interactionType InteractionType Type d'interaction
context InteractionContext Contexte d'interaction
targetBlock Vector3i Position du bloc
blockType BlockType Le type de bloc
{{< /tab >}}
{{< tab >}}
  • getInteractionType() - Retourne le type d'interaction
  • getContext() - Retourne le contexte d'interaction
  • getTargetBlock() - Retourne la position du bloc
  • getBlockType() - Retourne le type de bloc
  • isCancelled() - Vérifie si annulé
  • setCancelled(boolean) - Annule l'action d'utilisation {{< /tab >}} {{< tab >}}
getEventRegistry().register(UseBlockEvent.Pre.class, event -> {
    Vector3i position = event.getTargetBlock();
    BlockType blockType = event.getBlockType();
    InteractionContext context = event.getContext();

    // Empêcher l'ouverture de conteneurs verrouillés
    if (isLocked(position)) {
        event.setCancelled(true);
    }
});

{{< /tab >}} {{< /tabs >}}


UseBlockEvent.Post

Déclenché après qu'une action d'utilisation de bloc s'est terminée avec succès.

{{< tabs items="Champs,Méthodes,Exemple" >}} {{< tab >}}

Champ Type Description
interactionType InteractionType Type d'interaction
context InteractionContext Contexte d'interaction
targetBlock Vector3i Position du bloc
blockType BlockType Le type de bloc
{{< /tab >}}
{{< tab >}}
  • getInteractionType() - Retourne le type d'interaction
  • getContext() - Retourne le contexte d'interaction
  • getTargetBlock() - Retourne la position du bloc
  • getBlockType() - Retourne le type de bloc {{< /tab >}} {{< tab >}}
getEventRegistry().register(UseBlockEvent.Post.class, event -> {
    Vector3i position = event.getTargetBlock();
    BlockType blockType = event.getBlockType();

    // Suivre les interactions pour les quêtes
    if (isQuestBlock(blockType)) {
        completeQuestObjective("interact_with_" + blockType.getId());
    }
});

{{< /tab >}} {{< /tabs >}}


Événements d'Items

DropItemEvent

{{< badge "Annulable" >}} {{< badge "ECS" >}}

Déclenché quand un item est lâché. A deux variantes : Drop et PlayerRequest.

Package : com.hypixel.hytale.server.core.event.events.ecs

DropItemEvent.Drop

L'événement de drop réel avec les détails de l'item.

{{< tabs items="Champs,Méthodes,Exemple" >}} {{< tab >}}

Champ Type Description
itemStack ItemStack Item lâché
throwSpeed float Vitesse du lancer
{{< /tab >}}
{{< tab >}}
  • getItemStack() - Retourne le stack d'items
  • setItemStack(ItemStack) - Change l'item lâché
  • getThrowSpeed() - Retourne la vitesse de lancer
  • setThrowSpeed(float) - Change la vitesse de lancer
  • isCancelled() - Vérifie si annulé
  • setCancelled(boolean) - Annule le drop {{< /tab >}} {{< tab >}}
getEventRegistry().register(DropItemEvent.Drop.class, event -> {
    ItemStack item = event.getItemStack();

    // Empêcher de lâcher certains items
    if (item.getId().equals("quest_item")) {
        event.setCancelled(true);
        return;
    }

    // Modifier la vitesse de lancer
    event.setThrowSpeed(event.getThrowSpeed() * 1.5f);
});

{{< /tab >}} {{< /tabs >}}


DropItemEvent.PlayerRequest

Déclenché quand un joueur demande à lâcher un item (avant le drop réel).

{{< tabs items="Champs,Méthodes,Exemple" >}} {{< tab >}}

Champ Type Description
inventorySectionId int ID de la section d'inventaire
slotId short Slot depuis lequel on drop
{{< /tab >}}
{{< tab >}}
  • getInventorySectionId() - Retourne la section d'inventaire
  • getSlotId() - Retourne l'index du slot
  • isCancelled() - Vérifie si annulé
  • setCancelled(boolean) - Annule la requête {{< /tab >}} {{< tab >}}
getEventRegistry().register(DropItemEvent.PlayerRequest.class, event -> {
    int sectionId = event.getInventorySectionId();
    short slot = event.getSlotId();

    // Empêcher de drop depuis certains slots
    if (sectionId == Inventory.HOTBAR && slot == 0) {
        event.setCancelled(true);  // Ne peut pas drop le premier slot hotbar
    }
});

{{< /tab >}} {{< /tabs >}}


InteractivelyPickupItemEvent

{{< badge "Annulable" >}} {{< badge "ECS" >}}

Déclenché quand un joueur ramasse un item de manière interactive (ramassage manuel, pas auto-pickup).

Package : com.hypixel.hytale.server.core.event.events.ecs

{{< tabs items="Champs,Méthodes,Exemple" >}} {{< tab >}}

Champ Type Description
itemStack ItemStack L'item ramassé
{{< /tab >}}
{{< tab >}}
  • getItemStack() - Retourne le stack d'items
  • setItemStack(ItemStack) - Change l'item ramassé
  • isCancelled() - Vérifie si annulé
  • setCancelled(boolean) - Annule le ramassage {{< /tab >}} {{< tab >}}
getEventRegistry().register(InteractivelyPickupItemEvent.class, event -> {
    ItemStack item = event.getItemStack();

    // Empêcher de ramasser des items de quête qui n'appartiennent pas au joueur
    if (item.getId().startsWith("quest_") && !canPickupQuestItem(player, item)) {
        event.setCancelled(true);
        return;
    }

    // Transformer les items au ramassage
    if (item.getId().equals("raw_ore")) {
        event.setItemStack(item.withCount(item.getCount() * 2));
    }
});

{{< /tab >}} {{< /tabs >}}


Événements de Craft

CraftRecipeEvent

{{< badge "Annulable" >}} {{< badge "ECS" >}}

Déclenché quand une recette de craft est exécutée. A des variantes Pre et Post.

Package : com.hypixel.hytale.server.core.event.events.ecs

{{< tabs items="Champs,Méthodes,Exemple" >}} {{< tab >}}

Champ Type Description
craftedRecipe CraftingRecipe La recette craftée
quantity int Nombre d'items craftés
{{< /tab >}}
{{< tab >}}
  • getCraftedRecipe() - Retourne la recette de craft
  • getQuantity() - Retourne la quantité craftée
  • isCancelled() - Vérifie si annulé (Pre uniquement)
  • setCancelled(boolean) - Annule le craft (Pre uniquement) {{< /tab >}} {{< tab >}}
// Vérification pré-craft
getEventRegistry().register(CraftRecipeEvent.Pre.class, event -> {
    CraftingRecipe recipe = event.getCraftedRecipe();
    int quantity = event.getQuantity();

    // Bloquer certaines recettes
    if (isRestrictedRecipe(recipe)) {
        event.setCancelled(true);
    }
});

// Suivi post-craft
getEventRegistry().register(CraftRecipeEvent.Post.class, event -> {
    CraftingRecipe recipe = event.getCraftedRecipe();
    int quantity = event.getQuantity();

    // Suivre les statistiques de craft
    incrementCraftCount(recipe.getId(), quantity);
});

{{< /tab >}} {{< /tabs >}}


Autres Événements

SwitchActiveSlotEvent

{{< badge "Annulable" >}} {{< badge "ECS" >}}

Déclenché quand un joueur change son slot actif de hotbar.

Package : com.hypixel.hytale.server.core.event.events.ecs

{{< tabs items="Champs,Méthodes,Exemple" >}} {{< tab >}}

Champ Type Description
inventorySectionId int ID de la section d'inventaire
previousSlot int Le slot avant le changement
newSlot byte Le slot cible
serverRequest boolean Si le serveur a initié le changement
{{< /tab >}}
{{< tab >}}
  • getInventorySectionId() - Retourne la section d'inventaire
  • getPreviousSlot() - Retourne l'index du slot précédent
  • getNewSlot() - Retourne l'index du nouveau slot
  • setNewSlot(byte) - Change le slot cible
  • isServerRequest() - Vérifie si initié par le serveur
  • isClientRequest() - Vérifie si initié par le client
  • isCancelled() - Vérifie si annulé
  • setCancelled(boolean) - Annule le changement de slot {{< /tab >}} {{< tab >}}
getEventRegistry().register(SwitchActiveSlotEvent.class, event -> {
    int fromSlot = event.getPreviousSlot();
    int toSlot = event.getNewSlot();

    // Empêcher le changement pendant un cooldown
    if (isOnCooldown(player)) {
        event.setCancelled(true);
        return;
    }

    // Suivre l'usage des slots pour analytics
    if (event.isClientRequest()) {
        trackSlotSwitch(player, fromSlot, toSlot);
    }
});

{{< /tab >}} {{< /tabs >}}


DiscoverZoneEvent

{{< badge "ECS" >}}

Déclenché quand un joueur découvre une nouvelle zone. A une variante Display qui est annulable.

Package : com.hypixel.hytale.server.core.event.events.ecs

{{< tabs items="Champs,Méthodes,Exemple" >}} {{< tab >}}

Champ Type Description
discoveryInfo ZoneDiscoveryInfo Informations sur la zone découverte
{{< /tab >}}
{{< tab >}}
  • getDiscoveryInfo() - Retourne les infos de découverte de zone
  • isCancelled() - Vérifie si annulé (Display uniquement)
  • setCancelled(boolean) - Annule l'affichage (Display uniquement) {{< /tab >}} {{< tab >}}
// Annuler l'affichage de notification de découverte de zone
getEventRegistry().register(DiscoverZoneEvent.Display.class, event -> {
    WorldMapTracker.ZoneDiscoveryInfo info = event.getDiscoveryInfo();

    // Cacher certaines zones de l'UI de découverte
    if (isHiddenZone(info)) {
        event.setCancelled(true);
        return;
    }

    // Logger la découverte pour les succès
    recordZoneDiscovery(player, info);
});

{{< /tab >}} {{< /tabs >}}


ChangeGameModeEvent

{{< badge "Annulable" >}} {{< badge "ECS" >}}

Déclenché quand le mode de jeu d'une entité change.

Package : com.hypixel.hytale.server.core.event.events.ecs

{{< tabs items="Champs,Méthodes,Exemple" >}} {{< tab >}}

Champ Type Description
gameMode GameMode Le nouveau mode de jeu
{{< /tab >}}
{{< tab >}}
  • getGameMode() - Retourne le nouveau mode de jeu
  • setGameMode(GameMode) - Change le mode de jeu cible
  • isCancelled() - Vérifie si annulé
  • setCancelled(boolean) - Annule le changement de mode {{< /tab >}} {{< tab >}}
getEventRegistry().register(ChangeGameModeEvent.class, event -> {
    GameMode newMode = event.getGameMode();

    // Empêcher le mode créatif dans certains mondes
    if (newMode == GameMode.CREATIVE && isRestrictedWorld(player.getWorld())) {
        event.setCancelled(true);
        player.sendMessage(Message.raw("Mode créatif non autorisé ici !"));
        return;
    }

    // Forcer le mode aventure
    if (shouldForceAdventure(player)) {
        event.setGameMode(GameMode.ADVENTURE);
    }

    getLogger().at(Level.INFO).log(player.getDisplayName() + " changé en " + newMode);
});

{{< /tab >}} {{< /tabs >}}


Exemples Pratiques

Plugin Logger de Blocs

public class BlockLoggerPlugin extends JavaPlugin {

    @Override
    public void start() {
        getEventRegistry().register(PlaceBlockEvent.class, event -> {
            logAction("PLACE", event.getTargetBlock(), event.getItemInHand());
        });

        getEventRegistry().register(BreakBlockEvent.class, event -> {
            logAction("BREAK", event.getTargetBlock(), event.getBlockType());
        });
    }

    private void logAction(String action, Vector3i pos, Object data) {
        getLogger().at(Level.INFO).log(String.format("%s: %d,%d,%d - %s",
            action, pos.x(), pos.y(), pos.z(), data));
    }
}

Système de Protection de Région

public class RegionPlugin extends JavaPlugin {

    private final Set<Region> regions = new HashSet<>();

    @Override
    public void start() {
        // Protéger contre le cassage
        getEventRegistry().register(EventPriority.EARLY, BreakBlockEvent.class, event -> {
            if (isInProtectedRegion(event.getTargetBlock())) {
                event.setCancelled(true);
            }
        });

        // Protéger contre le placement
        getEventRegistry().register(EventPriority.EARLY, PlaceBlockEvent.class, event -> {
            if (isInProtectedRegion(event.getTargetBlock())) {
                event.setCancelled(true);
            }
        });

        // Protéger contre l'utilisation
        getEventRegistry().register(EventPriority.EARLY, UseBlockEvent.Pre.class, event -> {
            if (isInProtectedRegion(event.getTargetBlock())) {
                event.setCancelled(true);
            }
        });
    }

    private boolean isInProtectedRegion(Vector3i pos) {
        return regions.stream().anyMatch(r -> r.contains(pos));
    }
}

Système de Minerais Custom

public class CustomOrePlugin extends JavaPlugin {

    private final Random random = new Random();

    @Override
    public void start() {
        getEventRegistry().register(BreakBlockEvent.class, event -> {
            BlockType blockType = event.getBlockType();

            if (isCustomOre(blockType)) {
                // Appliquer le multiplicateur fortune
                ItemStack tool = event.getItemInHand();
                int fortuneLevel = getFortuneLevel(tool);
                int dropMultiplier = 1 + random.nextInt(fortuneLevel + 1);

                // Programmer les drops custom
                Vector3i pos = event.getTargetBlock();
                scheduleOreDrops(pos, blockType, dropMultiplier);
            }
        });
    }

    private boolean isCustomOre(BlockType blockType) {
        return blockType.getId().startsWith("custom_ore_");
    }
}

Système Anti-Grief

public class AntiGriefPlugin extends JavaPlugin {

    private final Map<Vector3i, BlockAction> recentActions = new HashMap<>();

    @Override
    public void start() {
        // Suivre les cassages de blocs pour rollback
        getEventRegistry().register(BreakBlockEvent.class, event -> {
            Vector3i pos = event.getTargetBlock();
            BlockType blockType = event.getBlockType();

            recentActions.put(pos, new BlockAction(
                ActionType.BREAK,
                blockType,
                System.currentTimeMillis()
            ));
        });

        // Suivre les placements de blocs pour rollback
        getEventRegistry().register(PlaceBlockEvent.class, event -> {
            Vector3i pos = event.getTargetBlock();

            recentActions.put(pos, new BlockAction(
                ActionType.PLACE,
                null,
                System.currentTimeMillis()
            ));
        });
    }

    public void rollback(World world, int seconds) {
        long cutoff = System.currentTimeMillis() - (seconds * 1000L);

        recentActions.entrySet().stream()
            .filter(e -> e.getValue().timestamp() >= cutoff)
            .forEach(e -> {
                Vector3i pos = e.getKey();
                BlockAction action = e.getValue();

                if (action.type() == ActionType.PLACE) {
                    // Supprimer les blocs placés
                    world.breakBlock(pos.x(), pos.y(), pos.z());
                } else if (action.blockType() != null) {
                    // Restaurer les blocs cassés
                    world.setBlock(pos.x(), pos.y(), pos.z(), action.blockType());
                }
            });

        recentActions.clear();
    }

    record BlockAction(ActionType type, BlockType blockType, long timestamp) {}
    enum ActionType { BREAK, PLACE }
}

Bonnes Pratiques

{{< callout type="info" >}} Directives pour les Événements de Bloc :

  • Utiliser EventPriority.EARLY pour les systèmes de protection
  • Les événements ECS fournissent un contrôle détaillé sur les opérations de bloc
  • Toujours valider les positions avant de modifier les blocs
  • Considérer l'état de chargement des chunks pour les blocs distants
  • Nettoyer les données de suivi quand elles ne sont plus nécessaires {{< /callout >}}

{{< callout type="warning" >}} Note de Performance : Les événements de bloc peuvent se déclencher très fréquemment. Évitez les opérations coûteuses dans les handlers et mettez en cache les résultats si possible. {{< /callout >}}