This commit is contained in:
2026-01-20 20:33:59 +01:00
commit b16a40e431
583 changed files with 87339 additions and 0 deletions

View File

@@ -0,0 +1,266 @@
---
title: Faire Apparaître des Entités
type: docs
weight: 3
---
Créez et faites apparaître des entités dans le monde en enregistrant des classes d'entités et en utilisant l'API World.
## Enregistrer des Entités
Avant de faire apparaître des entités, enregistrez-les avec l'EntityRegistry dans la méthode `start()` de votre plugin :
```java
@Override
public void start() {
// Enregistrer l'entité avec clé, classe, constructeur et codec
getEntityRegistry().registerEntity(
"my_custom_entity",
CustomEntity.class,
world -> new CustomEntity(world),
CustomEntity.CODEC
);
}
```
### Paramètres d'Enregistrement
| Paramètre | Type | Description |
|-----------|------|-------------|
| key | `String` | Identifiant unique pour le type d'entité |
| clazz | `Class<T>` | La classe de l'entité |
| constructor | `Function<World, T>` | Fonction factory qui crée les instances |
| codec | `DirectDecodeCodec<T>` | Codec de sérialisation pour la persistance |
## Classes de Base d'Entité
Hytale fournit deux classes de base principales :
### Entity
Classe de base pour toutes les entités. Implémente `Component<EntityStore>`.
```java
public class SimpleEntity extends Entity {
public static final DirectDecodeCodec<SimpleEntity> CODEC =
Entity.CODEC.extend(SimpleEntity.class, SimpleEntity::new);
public SimpleEntity() {
super();
}
public SimpleEntity(World world) {
super(world);
}
}
```
### LivingEntity
Classe de base étendue pour les entités avec santé, inventaire et statistiques.
```java
public class CustomMob extends LivingEntity {
public static final DirectDecodeCodec<CustomMob> CODEC =
LivingEntity.CODEC.extend(CustomMob.class, CustomMob::new);
public CustomMob() {
super();
}
public CustomMob(World world) {
super(world);
}
@Override
protected Inventory createDefaultInventory() {
return new Inventory(36); // 36 emplacements
}
}
```
## Faire Apparaître des Entités
Utilisez l'API World pour faire apparaître des entités enregistrées :
```java
// Obtenir le monde
World world = player.getWorld();
// Créer l'instance de l'entité
CustomMob mob = new CustomMob(world);
// Définir la position et rotation de spawn
Vector3d position = new Vector3d(100, 64, 200);
Vector3f rotation = new Vector3f(0, 90, 0); // Face à l'est
// Faire apparaître l'entité (déprécié mais fonctionnel)
world.spawnEntity(mob, position, rotation);
```
### Méthode addEntity
Pour plus de contrôle sur les raisons de spawn, utilisez `addEntity` :
```java
// Options AddReason : SPAWN, LOAD, TRANSFER
world.addEntity(mob, position, rotation, AddReason.SPAWN);
```
{{< callout type="warning" >}}
**Avis de Dépréciation :** Les méthodes `spawnEntity` et `addEntity` sur World sont dépréciées. L'approche moderne utilise directement le système EntityStore basé sur les composants. Cependant, ces méthodes fonctionnent toujours et sont le moyen le plus simple de faire apparaître des entités.
{{< /callout >}}
## Cycle de Vie des Entités
### Chargement dans le Monde
Quand une entité est ajoutée à un monde :
```java
// Appelé automatiquement quand l'entité est ajoutée
entity.loadIntoWorld(world);
// L'entité reçoit un ID réseau
int networkId = entity.getNetworkId();
// Une référence est créée pour l'accès aux composants
Ref<EntityStore> ref = entity.getReference();
```
### Supprimer des Entités
```java
// Supprimer une entité du monde
boolean removed = entity.remove();
// Vérifier si l'entité a déjà été supprimée
if (entity.wasRemoved()) {
// L'entité n'est plus valide
}
```
## Événements d'Entité
### EntityRemoveEvent
Écouter la suppression d'entités :
```java
getEventRegistry().register(EntityRemoveEvent.class, event -> {
Entity entity = event.getEntity();
getLogger().at(Level.INFO).log("Entité supprimée: " + entity.getClass().getSimpleName());
});
```
### LivingEntityInventoryChangeEvent
Suivre les changements d'inventaire sur les entités vivantes :
```java
getEventRegistry().register(LivingEntityInventoryChangeEvent.class, event -> {
LivingEntity entity = event.getEntity();
// Gérer le changement d'inventaire
});
```
{{< callout type="info" >}}
**Pas d'Événement de Spawn :** Hytale n'a pas d'EntitySpawnEvent. Pour suivre les spawns, envisagez d'implémenter une logique personnalisée dans le constructeur de votre entité ou d'utiliser les callbacks d'ajout du système de composants.
{{< /callout >}}
## Exemple Complet
```java
public class MyPlugin extends JavaPlugin {
@Override
public void start() {
// Enregistrer l'entité personnalisée
getEntityRegistry().registerEntity(
"boss_monster",
BossMonster.class,
world -> new BossMonster(world),
BossMonster.CODEC
);
// Écouter les suppressions
getEventRegistry().register(EntityRemoveEvent.class, this::onEntityRemove);
}
private void onEntityRemove(EntityRemoveEvent event) {
if (event.getEntity() instanceof BossMonster) {
getLogger().at(Level.INFO).log("Le boss a été vaincu !");
}
}
public void spawnBoss(Player player) {
World world = player.getWorld();
// Créer le boss à la position du joueur
BossMonster boss = new BossMonster(world);
// Obtenir la position du joueur et ajouter un décalage
Vector3d spawnPos = player.getTransformComponent().getPosition();
spawnPos = new Vector3d(spawnPos.x + 5, spawnPos.y, spawnPos.z);
// Faire face au joueur
Vector3f rotation = new Vector3f(0, 180, 0);
// Spawner
world.spawnEntity(boss, spawnPos, rotation);
}
}
public class BossMonster extends LivingEntity {
public static final DirectDecodeCodec<BossMonster> CODEC =
LivingEntity.CODEC.extend(BossMonster.class, BossMonster::new);
public BossMonster() {
super();
}
public BossMonster(World world) {
super(world);
}
@Override
protected Inventory createDefaultInventory() {
return new Inventory(9); // Petit inventaire
}
@Override
public boolean isCollidable() {
return true;
}
}
```
## Thread Safety
{{< callout type="error" >}}
**Important :** Le spawn d'entités doit être fait sur le thread de tick du monde. Si vous appelez depuis un contexte asynchrone, utilisez l'exécuteur du monde :
{{< /callout >}}
```java
// Spawn sécurisé depuis un contexte asynchrone
world.execute(() -> {
world.spawnEntity(entity, position, rotation);
});
```
## Validation du Spawn
Le monde valide les positions de spawn :
```java
// Exigences de position :
// - X et Z doivent être dans +/- 33554432
// - Y doit être >= -32
// Les positions invalides lèvent IllegalArgumentException
try {
world.spawnEntity(entity, invalidPosition, rotation);
} catch (IllegalArgumentException e) {
getLogger().warning("Position de spawn invalide: " + e.getMessage());
}
```