--- 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` | La classe de l'entité | | constructor | `Function` | Fonction factory qui crée les instances | | codec | `DirectDecodeCodec` | 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`. ```java public class SimpleEntity extends Entity { public static final DirectDecodeCodec 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 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 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 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()); } ```