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 blocgetBlockType()- Retourne le type de blocgetItemInHand()- 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 ciblesetTargetBlock(Vector3i)- Change la position de placementgetRotation()- Retourne la rotation du blocsetRotation(RotationTuple)- Change la rotationgetItemInHand()- Retourne l'item blocisCancelled()- 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 blocsetTargetBlock(Vector3i)- Change le bloc ciblegetBlockType()- Retourne le type de blocgetItemInHand()- Retourne l'outil utiliségetCurrentDamage()- Retourne les dégâts accumulésgetDamage()- Retourne les dégâts ce ticksetDamage(float)- Modifie le montant de dégâtsisCancelled()- 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'interactiongetContext()- Retourne le contexte d'interactiongetTargetBlock()- Retourne la position du blocgetBlockType()- Retourne le type de blocisCancelled()- 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'interactiongetContext()- Retourne le contexte d'interactiongetTargetBlock()- Retourne la position du blocgetBlockType()- 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'itemssetItemStack(ItemStack)- Change l'item lâchégetThrowSpeed()- Retourne la vitesse de lancersetThrowSpeed(float)- Change la vitesse de lancerisCancelled()- 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'inventairegetSlotId()- Retourne l'index du slotisCancelled()- 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'itemssetItemStack(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 craftgetQuantity()- Retourne la quantité craftéeisCancelled()- 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'inventairegetPreviousSlot()- Retourne l'index du slot précédentgetNewSlot()- Retourne l'index du nouveau slotsetNewSlot(byte)- Change le slot cibleisServerRequest()- Vérifie si initié par le serveurisClientRequest()- Vérifie si initié par le clientisCancelled()- 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 zoneisCancelled()- 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 jeusetGameMode(GameMode)- Change le mode de jeu cibleisCancelled()- 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.EARLYpour 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 >}}