---
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());
}
```
