Init
This commit is contained in:
721
content/core-concepts/events/event-reference/block-events.fr.md
Normal file
721
content/core-concepts/events/event-reference/block-events.fr.md
Normal file
@@ -0,0 +1,721 @@
|
||||
---
|
||||
title: Événements Bloc
|
||||
type: docs
|
||||
weight: 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 >}}
|
||||
```java
|
||||
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 >}}
|
||||
```java
|
||||
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 >}}
|
||||
```java
|
||||
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 >}}
|
||||
```java
|
||||
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 >}}
|
||||
```java
|
||||
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 >}}
|
||||
```java
|
||||
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 >}}
|
||||
```java
|
||||
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 >}}
|
||||
```java
|
||||
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 >}}
|
||||
```java
|
||||
// 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 >}}
|
||||
```java
|
||||
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 >}}
|
||||
```java
|
||||
// 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 >}}
|
||||
```java
|
||||
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
|
||||
|
||||
```java
|
||||
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
|
||||
|
||||
```java
|
||||
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
|
||||
|
||||
```java
|
||||
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
|
||||
|
||||
```java
|
||||
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 >}}
|
||||
Reference in New Issue
Block a user