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,86 @@
---
title: NPC System
type: docs
weight: 10
---
The NPC (Non-Player Character) system provides a complete framework for creating intelligent game characters with autonomous behavior, decision-making, and navigation capabilities.
**Package:** `com.hypixel.hytale.server.npc`
{{< cards >}}
{{< card link="npc-basics" title="NPC Basics" subtitle="Creating and configuring NPCs" >}}
{{< card link="npc-components" title="NPC Components" subtitle="Core components and data" >}}
{{< card link="npc-ai" title="NPC AI" subtitle="Blackboard, decisions, and sensors" >}}
{{< card link="npc-movement" title="NPC Movement" subtitle="Navigation and pathfinding" >}}
{{< card link="npc-commands" title="NPC Commands" subtitle="Admin and debug commands" >}}
{{< /cards >}}
## Architecture Overview
The NPC system is built on several interconnected subsystems:
```
NPCEntity
├── Blackboard (shared state/memory)
├── Role (behavioral template)
│ ├── Instructions (high-level goals)
│ ├── Sensors (perception)
│ └── Actions (behaviors)
├── DecisionMaker (AI logic)
│ ├── Evaluators (condition checking)
│ └── Options (action selection)
└── Movement
├── MotionController (movement execution)
├── PathFollower (path tracking)
└── NavigationGraph (A* pathfinding)
```
## Quick Example
```java
// Register NPC-related event
getEventRegistry().register(NPCSpawnEvent.class, event -> {
NPCEntity npc = event.getNPC();
// Access blackboard for state
Blackboard blackboard = npc.getBlackboard();
// Get current role
Role role = npc.getRole();
// Check if NPC has target
if (blackboard.hasTarget()) {
Entity target = blackboard.getTarget();
}
});
```
## Key Classes
| Class | Description |
|-------|-------------|
| `NPCEntity` | Base class for all NPCs |
| `NPCPlugin` | Plugin entry point for NPC system |
| `Blackboard` | Shared state container for NPC data |
| `Role` | Defines NPC behavior template |
| `DecisionMaker` | AI decision logic |
| `MotionController` | Movement execution |
| `PathFollower` | Path tracking and following |
## Subpackages
| Package | Files | Description |
|---------|-------|-------------|
| `corecomponents/` | 327 | Core ECS components for NPCs |
| `asset/` | 152 | NPC asset configuration |
| `util/` | 50 | Utility classes |
| `blackboard/` | 30 | State management |
| `movement/` | 27 | Movement behaviors |
| `systems/` | 25 | ECS systems |
| `commands/` | 23 | Admin commands |
| `decisionmaker/` | 22 | AI decision logic |
| `sensorinfo/` | 20 | Perception system |
| `role/` | 17 | Role definitions |
| `instructions/` | 14 | High-level behaviors |
| `navigation/` | 12 | Pathfinding |

View File

@@ -0,0 +1,86 @@
---
title: Système NPC
type: docs
weight: 10
---
Le système NPC (Non-Player Character) fournit un framework complet pour créer des personnages de jeu intelligents avec un comportement autonome, une prise de décision et des capacités de navigation.
**Package:** `com.hypixel.hytale.server.npc`
{{< cards >}}
{{< card link="npc-basics" title="Bases NPC" subtitle="Création et configuration des NPCs" >}}
{{< card link="npc-components" title="Composants NPC" subtitle="Composants de base et données" >}}
{{< card link="npc-ai" title="IA NPC" subtitle="Blackboard, décisions et capteurs" >}}
{{< card link="npc-movement" title="Mouvement NPC" subtitle="Navigation et pathfinding" >}}
{{< card link="npc-commands" title="Commandes NPC" subtitle="Commandes admin et debug" >}}
{{< /cards >}}
## Vue d'Ensemble de l'Architecture
Le système NPC est construit sur plusieurs sous-systèmes interconnectés :
```
NPCEntity
├── Blackboard (état/mémoire partagé)
├── Role (template comportemental)
│ ├── Instructions (objectifs haut niveau)
│ ├── Sensors (perception)
│ └── Actions (comportements)
├── DecisionMaker (logique IA)
│ ├── Evaluators (vérification conditions)
│ └── Options (sélection actions)
└── Movement
├── MotionController (exécution mouvement)
├── PathFollower (suivi de chemin)
└── NavigationGraph (pathfinding A*)
```
## Exemple Rapide
```java
// Enregistrer un événement lié aux NPCs
getEventRegistry().register(NPCSpawnEvent.class, event -> {
NPCEntity npc = event.getNPC();
// Accéder au blackboard pour l'état
Blackboard blackboard = npc.getBlackboard();
// Obtenir le rôle actuel
Role role = npc.getRole();
// Vérifier si le NPC a une cible
if (blackboard.hasTarget()) {
Entity target = blackboard.getTarget();
}
});
```
## Classes Principales
| Classe | Description |
|--------|-------------|
| `NPCEntity` | Classe de base pour tous les NPCs |
| `NPCPlugin` | Point d'entrée plugin pour le système NPC |
| `Blackboard` | Conteneur d'état partagé pour les données NPC |
| `Role` | Définit le template de comportement NPC |
| `DecisionMaker` | Logique de décision IA |
| `MotionController` | Exécution des mouvements |
| `PathFollower` | Suivi et parcours de chemin |
## Sous-packages
| Package | Fichiers | Description |
|---------|----------|-------------|
| `corecomponents/` | 327 | Composants ECS de base pour NPCs |
| `asset/` | 152 | Configuration des assets NPC |
| `util/` | 50 | Classes utilitaires |
| `blackboard/` | 30 | Gestion d'état |
| `movement/` | 27 | Comportements de mouvement |
| `systems/` | 25 | Systèmes ECS |
| `commands/` | 23 | Commandes admin |
| `decisionmaker/` | 22 | Logique de décision IA |
| `sensorinfo/` | 20 | Système de perception |
| `role/` | 17 | Définitions de rôles |
| `instructions/` | 14 | Comportements haut niveau |
| `navigation/` | 12 | Pathfinding |

View File

@@ -0,0 +1,373 @@
---
title: NPC AI
type: docs
weight: 3
---
The NPC AI system provides intelligent decision-making through blackboards, decision makers, sensors, and instructions.
**Packages:**
- `com.hypixel.hytale.server.npc.blackboard`
- `com.hypixel.hytale.server.npc.decisionmaker`
- `com.hypixel.hytale.server.npc.sensorinfo`
- `com.hypixel.hytale.server.npc.instructions`
## Blackboard System
The Blackboard is a shared memory space where NPC components communicate through key-value pairs.
### Blackboard Class
```java
public class Blackboard {
private Map<BlackboardKey<?>, Object> data;
// Store value
public <T> void set(BlackboardKey<T> key, T value);
// Retrieve value
public <T> T get(BlackboardKey<T> key);
public <T> T getOrDefault(BlackboardKey<T> key, T defaultValue);
// Check existence
public boolean has(BlackboardKey<?> key);
// Remove value
public void remove(BlackboardKey<?> key);
// Clear all
public void clear();
}
```
### BlackboardKey
Type-safe keys for blackboard access:
```java
// Predefined keys
public class BlackboardKeys {
public static final BlackboardKey<Entity> TARGET =
new BlackboardKey<>("target", Entity.class);
public static final BlackboardKey<Vector3d> HOME_POSITION =
new BlackboardKey<>("home_position", Vector3d.class);
public static final BlackboardKey<Float> ALERT_LEVEL =
new BlackboardKey<>("alert_level", Float.class);
public static final BlackboardKey<Boolean> IN_COMBAT =
new BlackboardKey<>("in_combat", Boolean.class);
}
// Custom keys
BlackboardKey<String> CUSTOM_KEY = new BlackboardKey<>("custom_data", String.class);
```
### Using the Blackboard
```java
NPCEntity npc = // get NPC
Blackboard bb = npc.getBlackboard();
// Set target
bb.set(BlackboardKeys.TARGET, targetEntity);
// Get home position
Vector3d home = bb.getOrDefault(BlackboardKeys.HOME_POSITION, npc.getPosition());
// Check combat status
if (bb.getOrDefault(BlackboardKeys.IN_COMBAT, false)) {
// Handle combat
}
```
## Decision Maker System
The Decision Maker evaluates options and selects the best action for the NPC to take.
### DecisionMaker Interface
```java
public interface DecisionMaker {
// Evaluate and select best option
Option evaluate(NPCEntity npc, Blackboard blackboard);
// Get all available options
List<Option> getOptions();
// Add option
void addOption(Option option);
}
```
### Option Class
Options represent possible actions:
```java
public class Option {
private String id;
private Evaluator evaluator;
private Action action;
private float basePriority;
// Calculate score based on context
public float evaluate(NPCEntity npc, Blackboard blackboard);
// Execute the action
public void execute(NPCEntity npc, Blackboard blackboard);
}
```
### Evaluator Interface
Evaluators calculate option scores:
```java
public interface Evaluator {
// Return score from 0.0 to 1.0
float evaluate(NPCEntity npc, Blackboard blackboard);
}
// Built-in evaluators
public class Evaluators {
// Returns 1.0 if target exists
public static final Evaluator HAS_TARGET = (npc, bb) ->
bb.has(BlackboardKeys.TARGET) ? 1.0f : 0.0f;
// Returns health percentage
public static final Evaluator HEALTH_PERCENT = (npc, bb) ->
npc.getHealth() / npc.getMaxHealth();
// Returns 1.0 if at home
public static final Evaluator AT_HOME = (npc, bb) -> {
Vector3d home = bb.get(BlackboardKeys.HOME_POSITION);
return npc.getPosition().distance(home) < 5.0 ? 1.0f : 0.0f;
};
}
```
### Creating a Decision Maker
```java
DecisionMaker dm = new StandardDecisionMaker();
// Add attack option
dm.addOption(new Option(
"attack",
Evaluators.HAS_TARGET,
new AttackAction(),
10.0f // High priority
));
// Add flee option
dm.addOption(new Option(
"flee",
(npc, bb) -> npc.getHealth() < 20 ? 1.0f : 0.0f,
new FleeAction(),
15.0f // Higher priority when triggered
));
// Add wander option
dm.addOption(new Option(
"wander",
(npc, bb) -> 0.3f, // Low constant score
new WanderAction(),
1.0f // Low priority fallback
));
npc.setDecisionMaker(dm);
```
## Sensor System
Sensors gather information about the world and update the blackboard.
### Sensor Interface
```java
public interface Sensor {
// Process sensor input
void sense(NPCEntity npc, Blackboard blackboard, float deltaTime);
// Get sensor type
String getSensorType();
}
```
### SensorInfo Classes
Sensor information containers:
```java
// Visual detection info
public class VisualSensorInfo {
private List<Entity> visibleEntities;
private float detectionRange;
private float fieldOfView;
public List<Entity> getVisibleEntities();
public boolean canSee(Entity entity);
}
// Audio detection info
public class AudioSensorInfo {
private List<SoundEvent> heardSounds;
private float hearingRange;
public List<SoundEvent> getHeardSounds();
public Vector3d getLoudestSoundPosition();
}
// Threat detection info
public class ThreatSensorInfo {
private List<Entity> threats;
private Entity primaryThreat;
private float threatLevel;
}
```
### Built-in Sensors
```java
// Visual sensor - detects visible entities
public class VisualSensor implements Sensor {
private float range = 20.0f;
private float fov = 120.0f; // degrees
@Override
public void sense(NPCEntity npc, Blackboard bb, float dt) {
List<Entity> visible = findVisibleEntities(npc);
bb.set(BlackboardKeys.VISIBLE_ENTITIES, visible);
}
}
// Proximity sensor - detects nearby entities
public class ProximitySensor implements Sensor {
private float range = 5.0f;
@Override
public void sense(NPCEntity npc, Blackboard bb, float dt) {
List<Entity> nearby = findNearbyEntities(npc, range);
bb.set(BlackboardKeys.NEARBY_ENTITIES, nearby);
}
}
// Damage sensor - reacts to damage taken
public class DamageSensor implements Sensor {
@Override
public void sense(NPCEntity npc, Blackboard bb, float dt) {
if (npc.wasRecentlyDamaged()) {
bb.set(BlackboardKeys.LAST_ATTACKER, npc.getLastAttacker());
bb.set(BlackboardKeys.ALERT_LEVEL, 1.0f);
}
}
}
```
## Instruction System
Instructions define high-level behavioral goals.
### Instruction Interface
```java
public interface Instruction {
// Check if instruction should activate
boolean shouldActivate(NPCEntity npc, Blackboard blackboard);
// Execute instruction logic
void execute(NPCEntity npc, Blackboard blackboard, float deltaTime);
// Check if instruction is complete
boolean isComplete(NPCEntity npc, Blackboard blackboard);
// Get priority
float getPriority();
}
```
### Built-in Instructions
```java
// Wander instruction
public class WanderInstruction implements Instruction {
private float wanderRadius;
private float minWaitTime;
private float maxWaitTime;
@Override
public boolean shouldActivate(NPCEntity npc, Blackboard bb) {
return !bb.has(BlackboardKeys.TARGET);
}
}
// Guard instruction
public class GuardInstruction implements Instruction {
private Vector3d guardPosition;
private float guardRadius;
@Override
public void execute(NPCEntity npc, Blackboard bb, float dt) {
if (npc.getPosition().distance(guardPosition) > guardRadius) {
bb.set(BlackboardKeys.MOVE_TARGET, guardPosition);
}
}
}
// Follow instruction
public class FollowInstruction implements Instruction {
private Entity followTarget;
private float followDistance;
}
// Patrol instruction
public class PatrolInstruction implements Instruction {
private List<Vector3d> patrolPoints;
private int currentPoint;
}
```
## Combining AI Systems
```java
public void setupNPCAI(NPCEntity npc) {
// Configure blackboard
Blackboard bb = npc.getBlackboard();
bb.set(BlackboardKeys.HOME_POSITION, npc.getPosition());
bb.set(BlackboardKeys.AGGRO_RANGE, 15.0f);
// Add sensors
npc.addSensor(new VisualSensor(20.0f, 120.0f));
npc.addSensor(new ProximitySensor(5.0f));
npc.addSensor(new DamageSensor());
// Configure decision maker
DecisionMaker dm = new StandardDecisionMaker();
dm.addOption(new Option("attack", hasHostileTarget, attackAction, 10.0f));
dm.addOption(new Option("flee", lowHealth, fleeAction, 15.0f));
dm.addOption(new Option("patrol", isGuard, patrolAction, 5.0f));
dm.addOption(new Option("idle", always, idleAction, 1.0f));
npc.setDecisionMaker(dm);
// Add instructions
npc.addInstruction(new GuardInstruction(guardPost, 10.0f));
npc.addInstruction(new ReactToThreatInstruction());
}
```
## Best Practices
{{< callout type="info" >}}
**AI Guidelines:**
- Use the Blackboard for all inter-component communication
- Keep Evaluators simple and fast - they run frequently
- Use appropriate sensor ranges to balance awareness vs performance
- Design Instructions to be interruptible
- Test AI behavior with various scenarios
{{< /callout >}}
{{< callout type="warning" >}}
**Performance:** Large numbers of NPCs with complex AI can impact performance. Consider:
- Reducing sensor update frequency for distant NPCs
- Using LOD (Level of Detail) for AI complexity
- Limiting pathfinding requests
{{< /callout >}}

View File

@@ -0,0 +1,373 @@
---
title: IA NPC
type: docs
weight: 3
---
Le système d'IA NPC fournit une prise de décision intelligente via les blackboards, decision makers, capteurs et instructions.
**Packages:**
- `com.hypixel.hytale.server.npc.blackboard`
- `com.hypixel.hytale.server.npc.decisionmaker`
- `com.hypixel.hytale.server.npc.sensorinfo`
- `com.hypixel.hytale.server.npc.instructions`
## Système Blackboard
Le Blackboard est un espace mémoire partagé où les composants NPC communiquent via des paires clé-valeur.
### Classe Blackboard
```java
public class Blackboard {
private Map<BlackboardKey<?>, Object> data;
// Stocker une valeur
public <T> void set(BlackboardKey<T> key, T value);
// Récupérer une valeur
public <T> T get(BlackboardKey<T> key);
public <T> T getOrDefault(BlackboardKey<T> key, T defaultValue);
// Vérifier l'existence
public boolean has(BlackboardKey<?> key);
// Supprimer une valeur
public void remove(BlackboardKey<?> key);
// Tout effacer
public void clear();
}
```
### BlackboardKey
Clés typées pour l'accès au blackboard :
```java
// Clés prédéfinies
public class BlackboardKeys {
public static final BlackboardKey<Entity> TARGET =
new BlackboardKey<>("target", Entity.class);
public static final BlackboardKey<Vector3d> HOME_POSITION =
new BlackboardKey<>("home_position", Vector3d.class);
public static final BlackboardKey<Float> ALERT_LEVEL =
new BlackboardKey<>("alert_level", Float.class);
public static final BlackboardKey<Boolean> IN_COMBAT =
new BlackboardKey<>("in_combat", Boolean.class);
}
// Clés personnalisées
BlackboardKey<String> CUSTOM_KEY = new BlackboardKey<>("custom_data", String.class);
```
### Utiliser le Blackboard
```java
NPCEntity npc = // obtenir le NPC
Blackboard bb = npc.getBlackboard();
// Définir la cible
bb.set(BlackboardKeys.TARGET, targetEntity);
// Obtenir la position d'origine
Vector3d home = bb.getOrDefault(BlackboardKeys.HOME_POSITION, npc.getPosition());
// Vérifier le statut de combat
if (bb.getOrDefault(BlackboardKeys.IN_COMBAT, false)) {
// Gérer le combat
}
```
## Système Decision Maker
Le Decision Maker évalue les options et sélectionne la meilleure action pour le NPC.
### Interface DecisionMaker
```java
public interface DecisionMaker {
// Évaluer et sélectionner la meilleure option
Option evaluate(NPCEntity npc, Blackboard blackboard);
// Obtenir toutes les options disponibles
List<Option> getOptions();
// Ajouter une option
void addOption(Option option);
}
```
### Classe Option
Les options représentent les actions possibles :
```java
public class Option {
private String id;
private Evaluator evaluator;
private Action action;
private float basePriority;
// Calculer le score selon le contexte
public float evaluate(NPCEntity npc, Blackboard blackboard);
// Exécuter l'action
public void execute(NPCEntity npc, Blackboard blackboard);
}
```
### Interface Evaluator
Les évaluateurs calculent les scores des options :
```java
public interface Evaluator {
// Retourne un score de 0.0 à 1.0
float evaluate(NPCEntity npc, Blackboard blackboard);
}
// Évaluateurs intégrés
public class Evaluators {
// Retourne 1.0 si une cible existe
public static final Evaluator HAS_TARGET = (npc, bb) ->
bb.has(BlackboardKeys.TARGET) ? 1.0f : 0.0f;
// Retourne le pourcentage de vie
public static final Evaluator HEALTH_PERCENT = (npc, bb) ->
npc.getHealth() / npc.getMaxHealth();
// Retourne 1.0 si à la maison
public static final Evaluator AT_HOME = (npc, bb) -> {
Vector3d home = bb.get(BlackboardKeys.HOME_POSITION);
return npc.getPosition().distance(home) < 5.0 ? 1.0f : 0.0f;
};
}
```
### Créer un Decision Maker
```java
DecisionMaker dm = new StandardDecisionMaker();
// Ajouter option d'attaque
dm.addOption(new Option(
"attack",
Evaluators.HAS_TARGET,
new AttackAction(),
10.0f // Haute priorité
));
// Ajouter option de fuite
dm.addOption(new Option(
"flee",
(npc, bb) -> npc.getHealth() < 20 ? 1.0f : 0.0f,
new FleeAction(),
15.0f // Priorité plus haute quand déclenché
));
// Ajouter option d'errance
dm.addOption(new Option(
"wander",
(npc, bb) -> 0.3f, // Score constant bas
new WanderAction(),
1.0f // Basse priorité par défaut
));
npc.setDecisionMaker(dm);
```
## Système de Capteurs
Les capteurs collectent des informations sur le monde et mettent à jour le blackboard.
### Interface Sensor
```java
public interface Sensor {
// Traiter l'entrée du capteur
void sense(NPCEntity npc, Blackboard blackboard, float deltaTime);
// Obtenir le type de capteur
String getSensorType();
}
```
### Classes SensorInfo
Conteneurs d'informations de capteurs :
```java
// Info de détection visuelle
public class VisualSensorInfo {
private List<Entity> visibleEntities;
private float detectionRange;
private float fieldOfView;
public List<Entity> getVisibleEntities();
public boolean canSee(Entity entity);
}
// Info de détection audio
public class AudioSensorInfo {
private List<SoundEvent> heardSounds;
private float hearingRange;
public List<SoundEvent> getHeardSounds();
public Vector3d getLoudestSoundPosition();
}
// Info de détection de menace
public class ThreatSensorInfo {
private List<Entity> threats;
private Entity primaryThreat;
private float threatLevel;
}
```
### Capteurs Intégrés
```java
// Capteur visuel - détecte les entités visibles
public class VisualSensor implements Sensor {
private float range = 20.0f;
private float fov = 120.0f; // degrés
@Override
public void sense(NPCEntity npc, Blackboard bb, float dt) {
List<Entity> visible = findVisibleEntities(npc);
bb.set(BlackboardKeys.VISIBLE_ENTITIES, visible);
}
}
// Capteur de proximité - détecte les entités proches
public class ProximitySensor implements Sensor {
private float range = 5.0f;
@Override
public void sense(NPCEntity npc, Blackboard bb, float dt) {
List<Entity> nearby = findNearbyEntities(npc, range);
bb.set(BlackboardKeys.NEARBY_ENTITIES, nearby);
}
}
// Capteur de dégâts - réagit aux dégâts subis
public class DamageSensor implements Sensor {
@Override
public void sense(NPCEntity npc, Blackboard bb, float dt) {
if (npc.wasRecentlyDamaged()) {
bb.set(BlackboardKeys.LAST_ATTACKER, npc.getLastAttacker());
bb.set(BlackboardKeys.ALERT_LEVEL, 1.0f);
}
}
}
```
## Système d'Instructions
Les instructions définissent des objectifs comportementaux de haut niveau.
### Interface Instruction
```java
public interface Instruction {
// Vérifier si l'instruction doit s'activer
boolean shouldActivate(NPCEntity npc, Blackboard blackboard);
// Exécuter la logique de l'instruction
void execute(NPCEntity npc, Blackboard blackboard, float deltaTime);
// Vérifier si l'instruction est complète
boolean isComplete(NPCEntity npc, Blackboard blackboard);
// Obtenir la priorité
float getPriority();
}
```
### Instructions Intégrées
```java
// Instruction d'errance
public class WanderInstruction implements Instruction {
private float wanderRadius;
private float minWaitTime;
private float maxWaitTime;
@Override
public boolean shouldActivate(NPCEntity npc, Blackboard bb) {
return !bb.has(BlackboardKeys.TARGET);
}
}
// Instruction de garde
public class GuardInstruction implements Instruction {
private Vector3d guardPosition;
private float guardRadius;
@Override
public void execute(NPCEntity npc, Blackboard bb, float dt) {
if (npc.getPosition().distance(guardPosition) > guardRadius) {
bb.set(BlackboardKeys.MOVE_TARGET, guardPosition);
}
}
}
// Instruction de suivi
public class FollowInstruction implements Instruction {
private Entity followTarget;
private float followDistance;
}
// Instruction de patrouille
public class PatrolInstruction implements Instruction {
private List<Vector3d> patrolPoints;
private int currentPoint;
}
```
## Combiner les Systèmes d'IA
```java
public void setupNPCAI(NPCEntity npc) {
// Configurer le blackboard
Blackboard bb = npc.getBlackboard();
bb.set(BlackboardKeys.HOME_POSITION, npc.getPosition());
bb.set(BlackboardKeys.AGGRO_RANGE, 15.0f);
// Ajouter les capteurs
npc.addSensor(new VisualSensor(20.0f, 120.0f));
npc.addSensor(new ProximitySensor(5.0f));
npc.addSensor(new DamageSensor());
// Configurer le decision maker
DecisionMaker dm = new StandardDecisionMaker();
dm.addOption(new Option("attack", hasHostileTarget, attackAction, 10.0f));
dm.addOption(new Option("flee", lowHealth, fleeAction, 15.0f));
dm.addOption(new Option("patrol", isGuard, patrolAction, 5.0f));
dm.addOption(new Option("idle", always, idleAction, 1.0f));
npc.setDecisionMaker(dm);
// Ajouter les instructions
npc.addInstruction(new GuardInstruction(guardPost, 10.0f));
npc.addInstruction(new ReactToThreatInstruction());
}
```
## Bonnes Pratiques
{{< callout type="info" >}}
**Directives IA :**
- Utilisez le Blackboard pour toute communication inter-composants
- Gardez les Évaluateurs simples et rapides - ils s'exécutent fréquemment
- Utilisez des portées de capteurs appropriées pour équilibrer conscience vs performance
- Concevez les Instructions pour être interruptibles
- Testez le comportement IA avec différents scénarios
{{< /callout >}}
{{< callout type="warning" >}}
**Performance :** Un grand nombre de NPCs avec une IA complexe peut impacter les performances. Considérez :
- Réduire la fréquence de mise à jour des capteurs pour les NPCs distants
- Utiliser le LOD (Level of Detail) pour la complexité IA
- Limiter les requêtes de pathfinding
{{< /callout >}}

View File

@@ -0,0 +1,217 @@
---
title: NPC Basics
type: docs
weight: 1
---
This guide covers the fundamentals of creating and configuring NPCs in Hytale.
**Package:** `com.hypixel.hytale.server.npc`
## NPCEntity Class
`NPCEntity` is the base class for all non-player characters. It extends the entity hierarchy and provides NPC-specific functionality.
```java
public class NPCEntity extends LivingEntity {
// Core NPC functionality
private Blackboard blackboard;
private Role role;
private DecisionMaker decisionMaker;
private MotionController motionController;
}
```
### Creating an NPC
NPCs are typically created through the asset system or spawned programmatically:
```java
// Spawn NPC from asset
NPCEntity npc = world.spawnNPC("villager", position);
// Configure NPC after spawn
npc.setRole(customRole);
npc.getBlackboard().setHomePosition(position);
```
## NPC Assets
NPC definitions are configured through YAML asset files:
```yaml
# npc/villager.yaml
Type: NPC
Id: villager
DisplayName: "Villager"
Model: models/characters/villager
Role: roles/villager_role
Stats:
Health: 100
Speed: 3.0
Components:
- Type: NPCBrain
- Type: Interactable
- Type: DialogueCapable
```
### Asset Structure
| Property | Type | Description |
|----------|------|-------------|
| `Type` | String | Must be "NPC" |
| `Id` | String | Unique identifier |
| `DisplayName` | String | Display name |
| `Model` | String | Model asset reference |
| `Role` | String | Default role reference |
| `Stats` | Object | Base statistics |
| `Components` | Array | Component configurations |
## NPC Roles
Roles define the behavioral template for an NPC. They specify what instructions, sensors, and actions the NPC can use.
```yaml
# roles/villager_role.yaml
Type: Role
Id: villager_role
Instructions:
- Wander
- ReactToThreats
- Interact
Sensors:
- Type: VisualSensor
Range: 15.0
- Type: AudioSensor
Range: 10.0
Actions:
- Walk
- Run
- Talk
- Trade
```
### Role Components
```java
public class Role {
private List<Instruction> instructions;
private List<Sensor> sensors;
private List<Action> availableActions;
// Get active instruction
public Instruction getCurrentInstruction();
// Check if action is available
public boolean hasAction(String actionId);
}
```
## NPC Systems
The NPC module registers several ECS systems for processing NPC behavior:
| System | Description |
|--------|-------------|
| `NPCBrainSystem` | Processes AI decisions |
| `NPCMovementSystem` | Handles movement updates |
| `NPCSensorSystem` | Processes sensor inputs |
| `NPCAnimationSystem` | Updates animations |
| `NPCInteractionSystem` | Handles interactions |
### System Registration
```java
public class NPCPlugin extends JavaPlugin {
@Override
public void start() {
// Systems are auto-registered by NPCPlugin
// Custom systems can be added:
getEntityStoreRegistry().registerSystem(
new CustomNPCSystem()
);
}
}
```
## NPC Utilities
The `util/` package provides helper classes:
### NPCUtils
```java
// Find nearest NPC
NPCEntity nearest = NPCUtils.findNearest(position, world, 50.0);
// Get all NPCs in area
List<NPCEntity> npcsInArea = NPCUtils.getNPCsInRadius(
position, world, 25.0
);
// Check line of sight
boolean canSee = NPCUtils.hasLineOfSight(npc, target);
```
### NPCSpawner
```java
// Spawn with configuration
NPCEntity npc = NPCSpawner.spawn(
world,
"villager",
position,
config -> {
config.setRole("merchant");
config.setFaction("town");
}
);
```
## Common Patterns
### Setting Up an NPC Shop
```java
NPCEntity merchant = world.spawnNPC("merchant", shopPosition);
merchant.getBlackboard().set("shop_inventory", inventory);
merchant.getBlackboard().set("is_merchant", true);
merchant.setRole(merchantRole);
```
### Creating a Guard NPC
```java
NPCEntity guard = world.spawnNPC("guard", guardPosition);
Blackboard bb = guard.getBlackboard();
bb.setPatrolPath(patrolWaypoints);
bb.setHostileToFactions(List.of("bandits", "monsters"));
guard.setRole(guardRole);
```
### NPC with Custom Behavior
```java
NPCEntity custom = world.spawnNPC("custom_npc", position);
// Add custom component
custom.getEntityStore().addComponent(new CustomBehaviorComponent());
// Set custom decision maker
custom.setDecisionMaker(new CustomDecisionMaker());
```
## Best Practices
{{< callout type="info" >}}
**NPC Guidelines:**
- Always set a Role for NPCs to define their behavior
- Use the Blackboard for all NPC state storage
- Configure appropriate sensors for the NPC's awareness needs
- Use the asset system for NPC definitions when possible
- Consider performance with large numbers of NPCs
{{< /callout >}}
{{< callout type="warning" >}}
**Thread Safety:** NPC operations should be performed on the world's ticking thread. Use `world.isInThread()` to verify before making changes.
{{< /callout >}}

View File

@@ -0,0 +1,217 @@
---
title: Bases NPC
type: docs
weight: 1
---
Ce guide couvre les fondamentaux de la création et de la configuration des NPCs dans Hytale.
**Package:** `com.hypixel.hytale.server.npc`
## Classe NPCEntity
`NPCEntity` est la classe de base pour tous les personnages non-joueurs. Elle étend la hiérarchie d'entités et fournit des fonctionnalités spécifiques aux NPCs.
```java
public class NPCEntity extends LivingEntity {
// Fonctionnalités NPC de base
private Blackboard blackboard;
private Role role;
private DecisionMaker decisionMaker;
private MotionController motionController;
}
```
### Créer un NPC
Les NPCs sont généralement créés via le système d'assets ou générés programmatiquement :
```java
// Générer un NPC depuis un asset
NPCEntity npc = world.spawnNPC("villager", position);
// Configurer le NPC après génération
npc.setRole(customRole);
npc.getBlackboard().setHomePosition(position);
```
## Assets NPC
Les définitions NPC sont configurées via des fichiers d'assets YAML :
```yaml
# npc/villager.yaml
Type: NPC
Id: villager
DisplayName: "Villageois"
Model: models/characters/villager
Role: roles/villager_role
Stats:
Health: 100
Speed: 3.0
Components:
- Type: NPCBrain
- Type: Interactable
- Type: DialogueCapable
```
### Structure d'Asset
| Propriété | Type | Description |
|-----------|------|-------------|
| `Type` | String | Doit être "NPC" |
| `Id` | String | Identifiant unique |
| `DisplayName` | String | Nom d'affichage |
| `Model` | String | Référence asset modèle |
| `Role` | String | Référence rôle par défaut |
| `Stats` | Object | Statistiques de base |
| `Components` | Array | Configurations de composants |
## Rôles NPC
Les rôles définissent le template comportemental d'un NPC. Ils spécifient quelles instructions, capteurs et actions le NPC peut utiliser.
```yaml
# roles/villager_role.yaml
Type: Role
Id: villager_role
Instructions:
- Wander
- ReactToThreats
- Interact
Sensors:
- Type: VisualSensor
Range: 15.0
- Type: AudioSensor
Range: 10.0
Actions:
- Walk
- Run
- Talk
- Trade
```
### Composants de Rôle
```java
public class Role {
private List<Instruction> instructions;
private List<Sensor> sensors;
private List<Action> availableActions;
// Obtenir l'instruction active
public Instruction getCurrentInstruction();
// Vérifier si une action est disponible
public boolean hasAction(String actionId);
}
```
## Systèmes NPC
Le module NPC enregistre plusieurs systèmes ECS pour traiter le comportement des NPCs :
| Système | Description |
|---------|-------------|
| `NPCBrainSystem` | Traite les décisions IA |
| `NPCMovementSystem` | Gère les mises à jour de mouvement |
| `NPCSensorSystem` | Traite les entrées des capteurs |
| `NPCAnimationSystem` | Met à jour les animations |
| `NPCInteractionSystem` | Gère les interactions |
### Enregistrement des Systèmes
```java
public class NPCPlugin extends JavaPlugin {
@Override
public void start() {
// Les systèmes sont auto-enregistrés par NPCPlugin
// Des systèmes personnalisés peuvent être ajoutés :
getEntityStoreRegistry().registerSystem(
new CustomNPCSystem()
);
}
}
```
## Utilitaires NPC
Le package `util/` fournit des classes d'aide :
### NPCUtils
```java
// Trouver le NPC le plus proche
NPCEntity nearest = NPCUtils.findNearest(position, world, 50.0);
// Obtenir tous les NPCs dans une zone
List<NPCEntity> npcsInArea = NPCUtils.getNPCsInRadius(
position, world, 25.0
);
// Vérifier la ligne de vue
boolean canSee = NPCUtils.hasLineOfSight(npc, target);
```
### NPCSpawner
```java
// Générer avec configuration
NPCEntity npc = NPCSpawner.spawn(
world,
"villager",
position,
config -> {
config.setRole("merchant");
config.setFaction("town");
}
);
```
## Patterns Courants
### Configurer une Boutique NPC
```java
NPCEntity merchant = world.spawnNPC("merchant", shopPosition);
merchant.getBlackboard().set("shop_inventory", inventory);
merchant.getBlackboard().set("is_merchant", true);
merchant.setRole(merchantRole);
```
### Créer un NPC Garde
```java
NPCEntity guard = world.spawnNPC("guard", guardPosition);
Blackboard bb = guard.getBlackboard();
bb.setPatrolPath(patrolWaypoints);
bb.setHostileToFactions(List.of("bandits", "monsters"));
guard.setRole(guardRole);
```
### NPC avec Comportement Personnalisé
```java
NPCEntity custom = world.spawnNPC("custom_npc", position);
// Ajouter un composant personnalisé
custom.getEntityStore().addComponent(new CustomBehaviorComponent());
// Définir un decision maker personnalisé
custom.setDecisionMaker(new CustomDecisionMaker());
```
## Bonnes Pratiques
{{< callout type="info" >}}
**Directives NPC :**
- Définissez toujours un Rôle pour les NPCs pour définir leur comportement
- Utilisez le Blackboard pour tout stockage d'état NPC
- Configurez les capteurs appropriés pour les besoins de perception du NPC
- Utilisez le système d'assets pour les définitions NPC quand possible
- Considérez les performances avec un grand nombre de NPCs
{{< /callout >}}
{{< callout type="warning" >}}
**Thread Safety :** Les opérations NPC doivent être effectuées sur le thread de tick du monde. Utilisez `world.isInThread()` pour vérifier avant de faire des changements.
{{< /callout >}}

View File

@@ -0,0 +1,374 @@
---
title: NPC Commands
type: docs
weight: 5
---
The NPC system includes 23 admin and debug commands for managing and testing NPCs.
**Package:** `com.hypixel.hytale.server.npc.commands`
## Spawning Commands
### /npc spawn
Spawns an NPC at a location:
```
/npc spawn <npc_type> [position] [--role <role>] [--name <name>]
```
**Arguments:**
| Argument | Type | Description |
|----------|------|-------------|
| `npc_type` | String | NPC asset ID |
| `position` | Position | Spawn location (default: player position) |
| `--role` | String | Override default role |
| `--name` | String | Custom display name |
**Examples:**
```
/npc spawn villager
/npc spawn guard ~ ~1 ~ --role patrol_guard
/npc spawn merchant --name "Bob the Trader"
```
### /npc despawn
Removes an NPC:
```
/npc despawn <target>
```
**Arguments:**
| Argument | Type | Description |
|----------|------|-------------|
| `target` | NPC | Target NPC (raycast or selector) |
### /npc despawnall
Removes all NPCs in radius:
```
/npc despawnall [radius]
```
**Arguments:**
| Argument | Type | Description |
|----------|------|-------------|
| `radius` | Float | Radius in blocks (default: 50) |
## Information Commands
### /npc info
Displays NPC information:
```
/npc info [target]
```
**Output:**
```
NPC Info: Villager (villager_001)
Position: 100.5, 64.0, -200.3
Role: villager_role
State: IDLE
Health: 100/100
Target: None
Current Instruction: Wander
```
### /npc list
Lists all NPCs:
```
/npc list [--radius <radius>] [--type <type>]
```
**Arguments:**
| Argument | Type | Description |
|----------|------|-------------|
| `--radius` | Float | Search radius |
| `--type` | String | Filter by NPC type |
### /npc debug
Toggles debug visualization:
```
/npc debug <mode>
```
**Modes:**
| Mode | Description |
|------|-------------|
| `path` | Show pathfinding |
| `sensors` | Show sensor ranges |
| `state` | Show AI state |
| `target` | Show targeting |
| `all` | Show everything |
| `off` | Disable debug |
## Behavior Commands
### /npc role
Changes NPC role:
```
/npc role <target> <role>
```
**Examples:**
```
/npc role @nearest guard_role
/npc role @e[type=villager] merchant_role
```
### /npc state
Forces NPC state:
```
/npc state <target> <state>
```
**States:**
```
/npc state @nearest IDLE
/npc state @nearest ATTACKING
/npc state @nearest FLEEING
```
### /npc target
Sets NPC target:
```
/npc target <npc> <target_entity>
```
**Examples:**
```
/npc target @nearest @p
/npc target guard_01 @e[type=zombie,limit=1]
```
### /npc cleartarget
Clears NPC target:
```
/npc cleartarget <target>
```
## Movement Commands
### /npc moveto
Commands NPC to move to position:
```
/npc moveto <target> <position>
```
**Examples:**
```
/npc moveto @nearest ~ ~ ~10
/npc moveto guard_01 100 64 -200
```
### /npc follow
Commands NPC to follow entity:
```
/npc follow <npc> <target> [distance]
```
**Examples:**
```
/npc follow @nearest @p 3.0
```
### /npc stop
Stops NPC movement:
```
/npc stop <target>
```
### /npc patrol
Sets patrol path:
```
/npc patrol <target> <point1> <point2> [point3...]
```
**Examples:**
```
/npc patrol guard_01 0 64 0 10 64 0 10 64 10 0 64 10
```
### /npc home
Sets NPC home position:
```
/npc home <target> [position]
```
## Blackboard Commands
### /npc blackboard get
Gets blackboard value:
```
/npc blackboard get <target> <key>
```
**Examples:**
```
/npc blackboard get @nearest alert_level
/npc blackboard get guard_01 home_position
```
### /npc blackboard set
Sets blackboard value:
```
/npc blackboard set <target> <key> <value>
```
**Examples:**
```
/npc blackboard set @nearest alert_level 1.0
/npc blackboard set @nearest is_hostile true
```
### /npc blackboard clear
Clears blackboard:
```
/npc blackboard clear <target> [key]
```
## AI Commands
### /npc think
Forces AI decision cycle:
```
/npc think <target>
```
### /npc instruction
Forces instruction:
```
/npc instruction <target> <instruction>
```
**Examples:**
```
/npc instruction @nearest flee
/npc instruction guard_01 attack
```
### /npc sensor
Toggles sensor:
```
/npc sensor <target> <sensor> <enabled>
```
**Examples:**
```
/npc sensor @nearest visual false
/npc sensor @nearest audio true
```
## Faction Commands
### /npc faction
Sets NPC faction:
```
/npc faction <target> <faction>
```
**Examples:**
```
/npc faction @nearest town_guard
/npc faction villager_01 merchants
```
### /npc relation
Sets faction relation:
```
/npc relation <faction1> <faction2> <relation>
```
**Relations:** `ALLIED`, `FRIENDLY`, `NEUTRAL`, `UNFRIENDLY`, `HOSTILE`
**Examples:**
```
/npc relation guards bandits HOSTILE
/npc relation merchants town_guard ALLIED
```
## Command Permissions
| Command | Permission |
|---------|------------|
| `/npc spawn` | `hytale.command.npc.spawn` |
| `/npc despawn` | `hytale.command.npc.despawn` |
| `/npc info` | `hytale.command.npc.info` |
| `/npc debug` | `hytale.command.npc.debug` |
| `/npc role` | `hytale.command.npc.role` |
| `/npc blackboard` | `hytale.command.npc.blackboard` |
## Registering Custom NPC Commands
```java
public class MyNPCCommand extends AbstractCommand {
public MyNPCCommand() {
super("npc custom", "Custom NPC command");
withRequiredArg("target", "Target NPC", ArgTypes.NPC_REF);
}
@Override
protected CompletableFuture<Void> execute(CommandContext ctx) {
NPCEntity npc = ctx.get("target");
// Custom logic
return null;
}
}
// Register in plugin setup
getCommandRegistry().register(new MyNPCCommand());
```
## Best Practices
{{< callout type="info" >}}
**Command Guidelines:**
- Use selectors like `@nearest` for targeting NPCs
- Debug commands are invaluable for testing AI
- Blackboard commands allow runtime behavior modification
- Use permission checks for admin commands
{{< /callout >}}

View File

@@ -0,0 +1,374 @@
---
title: Commandes NPC
type: docs
weight: 5
---
Le système NPC inclut 23 commandes admin et debug pour gérer et tester les NPCs.
**Package:** `com.hypixel.hytale.server.npc.commands`
## Commandes de Spawn
### /npc spawn
Fait apparaître un NPC à une position :
```
/npc spawn <npc_type> [position] [--role <role>] [--name <name>]
```
**Arguments :**
| Argument | Type | Description |
|----------|------|-------------|
| `npc_type` | String | ID d'asset NPC |
| `position` | Position | Position de spawn (défaut: position du joueur) |
| `--role` | String | Remplacer le rôle par défaut |
| `--name` | String | Nom d'affichage personnalisé |
**Exemples :**
```
/npc spawn villager
/npc spawn guard ~ ~1 ~ --role patrol_guard
/npc spawn merchant --name "Bob le Marchand"
```
### /npc despawn
Supprime un NPC :
```
/npc despawn <target>
```
**Arguments :**
| Argument | Type | Description |
|----------|------|-------------|
| `target` | NPC | NPC cible (raycast ou sélecteur) |
### /npc despawnall
Supprime tous les NPCs dans un rayon :
```
/npc despawnall [radius]
```
**Arguments :**
| Argument | Type | Description |
|----------|------|-------------|
| `radius` | Float | Rayon en blocs (défaut: 50) |
## Commandes d'Information
### /npc info
Affiche les informations d'un NPC :
```
/npc info [target]
```
**Sortie :**
```
NPC Info: Villageois (villager_001)
Position: 100.5, 64.0, -200.3
Role: villager_role
State: IDLE
Health: 100/100
Target: None
Current Instruction: Wander
```
### /npc list
Liste tous les NPCs :
```
/npc list [--radius <radius>] [--type <type>]
```
**Arguments :**
| Argument | Type | Description |
|----------|------|-------------|
| `--radius` | Float | Rayon de recherche |
| `--type` | String | Filtrer par type de NPC |
### /npc debug
Active/désactive la visualisation debug :
```
/npc debug <mode>
```
**Modes :**
| Mode | Description |
|------|-------------|
| `path` | Afficher le pathfinding |
| `sensors` | Afficher les portées des capteurs |
| `state` | Afficher l'état IA |
| `target` | Afficher le ciblage |
| `all` | Tout afficher |
| `off` | Désactiver le debug |
## Commandes de Comportement
### /npc role
Change le rôle du NPC :
```
/npc role <target> <role>
```
**Exemples :**
```
/npc role @nearest guard_role
/npc role @e[type=villager] merchant_role
```
### /npc state
Force l'état du NPC :
```
/npc state <target> <state>
```
**États :**
```
/npc state @nearest IDLE
/npc state @nearest ATTACKING
/npc state @nearest FLEEING
```
### /npc target
Définit la cible du NPC :
```
/npc target <npc> <target_entity>
```
**Exemples :**
```
/npc target @nearest @p
/npc target guard_01 @e[type=zombie,limit=1]
```
### /npc cleartarget
Efface la cible du NPC :
```
/npc cleartarget <target>
```
## Commandes de Mouvement
### /npc moveto
Ordonne au NPC de se déplacer vers une position :
```
/npc moveto <target> <position>
```
**Exemples :**
```
/npc moveto @nearest ~ ~ ~10
/npc moveto guard_01 100 64 -200
```
### /npc follow
Ordonne au NPC de suivre une entité :
```
/npc follow <npc> <target> [distance]
```
**Exemples :**
```
/npc follow @nearest @p 3.0
```
### /npc stop
Arrête le mouvement du NPC :
```
/npc stop <target>
```
### /npc patrol
Définit un chemin de patrouille :
```
/npc patrol <target> <point1> <point2> [point3...]
```
**Exemples :**
```
/npc patrol guard_01 0 64 0 10 64 0 10 64 10 0 64 10
```
### /npc home
Définit la position d'origine du NPC :
```
/npc home <target> [position]
```
## Commandes Blackboard
### /npc blackboard get
Obtient une valeur du blackboard :
```
/npc blackboard get <target> <key>
```
**Exemples :**
```
/npc blackboard get @nearest alert_level
/npc blackboard get guard_01 home_position
```
### /npc blackboard set
Définit une valeur du blackboard :
```
/npc blackboard set <target> <key> <value>
```
**Exemples :**
```
/npc blackboard set @nearest alert_level 1.0
/npc blackboard set @nearest is_hostile true
```
### /npc blackboard clear
Efface le blackboard :
```
/npc blackboard clear <target> [key]
```
## Commandes IA
### /npc think
Force un cycle de décision IA :
```
/npc think <target>
```
### /npc instruction
Force une instruction :
```
/npc instruction <target> <instruction>
```
**Exemples :**
```
/npc instruction @nearest flee
/npc instruction guard_01 attack
```
### /npc sensor
Active/désactive un capteur :
```
/npc sensor <target> <sensor> <enabled>
```
**Exemples :**
```
/npc sensor @nearest visual false
/npc sensor @nearest audio true
```
## Commandes de Faction
### /npc faction
Définit la faction du NPC :
```
/npc faction <target> <faction>
```
**Exemples :**
```
/npc faction @nearest town_guard
/npc faction villager_01 merchants
```
### /npc relation
Définit la relation entre factions :
```
/npc relation <faction1> <faction2> <relation>
```
**Relations :** `ALLIED`, `FRIENDLY`, `NEUTRAL`, `UNFRIENDLY`, `HOSTILE`
**Exemples :**
```
/npc relation guards bandits HOSTILE
/npc relation merchants town_guard ALLIED
```
## Permissions des Commandes
| Commande | Permission |
|----------|------------|
| `/npc spawn` | `hytale.command.npc.spawn` |
| `/npc despawn` | `hytale.command.npc.despawn` |
| `/npc info` | `hytale.command.npc.info` |
| `/npc debug` | `hytale.command.npc.debug` |
| `/npc role` | `hytale.command.npc.role` |
| `/npc blackboard` | `hytale.command.npc.blackboard` |
## Enregistrer des Commandes NPC Personnalisées
```java
public class MyNPCCommand extends AbstractCommand {
public MyNPCCommand() {
super("npc custom", "Commande NPC personnalisée");
withRequiredArg("target", "NPC cible", ArgTypes.NPC_REF);
}
@Override
protected CompletableFuture<Void> execute(CommandContext ctx) {
NPCEntity npc = ctx.get("target");
// Logique personnalisée
return null;
}
}
// Enregistrer dans le setup du plugin
getCommandRegistry().register(new MyNPCCommand());
```
## Bonnes Pratiques
{{< callout type="info" >}}
**Directives des Commandes :**
- Utilisez des sélecteurs comme `@nearest` pour cibler les NPCs
- Les commandes debug sont précieuses pour tester l'IA
- Les commandes blackboard permettent la modification du comportement à l'exécution
- Utilisez les vérifications de permissions pour les commandes admin
{{< /callout >}}

View File

@@ -0,0 +1,348 @@
---
title: NPC Components
type: docs
weight: 2
---
NPC components are ECS components that store data and state for NPCs. The system includes over 300 core components for various NPC functionalities.
**Package:** `com.hypixel.hytale.server.npc.corecomponents`
## Core Components Overview
NPC components follow the ECS pattern where components are pure data containers attached to entity stores.
```java
// Access NPC components
EntityStore store = npc.getEntityStore();
NPCBrainComponent brain = store.getComponent(NPCBrainComponent.class);
```
## Brain Components
### NPCBrainComponent
The main AI processing component:
```java
public class NPCBrainComponent {
private DecisionMaker decisionMaker;
private float thinkInterval;
private float lastThinkTime;
public void setDecisionMaker(DecisionMaker maker);
public DecisionMaker getDecisionMaker();
public boolean shouldThink(float currentTime);
}
```
### NPCMemoryComponent
Stores NPC memories and knowledge:
```java
public class NPCMemoryComponent {
private Map<String, Memory> memories;
private float memoryDuration;
public void remember(String key, Object value, float duration);
public <T> T recall(String key, Class<T> type);
public boolean hasMemory(String key);
public void forget(String key);
}
```
## State Components
### NPCStateComponent
Current behavioral state:
```java
public class NPCStateComponent {
private NPCState currentState;
private NPCState previousState;
private float stateEnterTime;
public enum NPCState {
IDLE,
WALKING,
RUNNING,
ATTACKING,
FLEEING,
INTERACTING,
SLEEPING,
DEAD
}
}
```
### NPCAlertComponent
Alertness and awareness level:
```java
public class NPCAlertComponent {
private AlertLevel alertLevel;
private float alertDecayRate;
private Entity alertSource;
public enum AlertLevel {
RELAXED, // Normal state
CURIOUS, // Something caught attention
ALERT, // Actively investigating
ALARMED, // Threat detected
COMBAT // In combat
}
}
```
## Target Components
### NPCTargetComponent
Current target tracking:
```java
public class NPCTargetComponent {
private Ref<EntityStore> currentTarget;
private TargetType targetType;
private float targetAcquiredTime;
private Vector3d lastKnownPosition;
public enum TargetType {
HOSTILE,
FRIENDLY,
NEUTRAL,
OBJECT
}
}
```
### NPCFocusComponent
Visual focus point:
```java
public class NPCFocusComponent {
private Vector3d focusPoint;
private Ref<EntityStore> focusEntity;
private float focusStrength;
private boolean shouldLookAt;
}
```
## Movement Components
### NPCMovementComponent
Movement configuration:
```java
public class NPCMovementComponent {
private float walkSpeed;
private float runSpeed;
private float turnSpeed;
private boolean canJump;
private boolean canSwim;
private boolean canClimb;
}
```
### NPCPathComponent
Path following data:
```java
public class NPCPathComponent {
private List<Vector3d> currentPath;
private int currentWaypointIndex;
private float pathRecalculateInterval;
private float lastPathTime;
public Vector3d getCurrentWaypoint();
public Vector3d getNextWaypoint();
public boolean hasReachedWaypoint(Vector3d position, float threshold);
}
```
### NPCNavigationComponent
Navigation settings:
```java
public class NPCNavigationComponent {
private float avoidanceRadius;
private float pathfindingRange;
private int maxPathLength;
private NavigationFlags flags;
public static class NavigationFlags {
public boolean avoidWater;
public boolean avoidFire;
public boolean canUseDoors;
public boolean canBreakBlocks;
}
}
```
## Combat Components
### NPCCombatComponent
Combat capabilities:
```java
public class NPCCombatComponent {
private float attackRange;
private float attackCooldown;
private float lastAttackTime;
private DamageType preferredDamageType;
private List<String> availableAttacks;
}
```
### NPCAggroComponent
Aggression management:
```java
public class NPCAggroComponent {
private Map<Ref<EntityStore>, Float> aggroTable;
private float aggroDecayRate;
private float aggroRange;
public void addAggro(Ref<EntityStore> entity, float amount);
public void removeAggro(Ref<EntityStore> entity);
public Ref<EntityStore> getHighestAggroTarget();
}
```
## Social Components
### NPCFactionComponent
Faction affiliation:
```java
public class NPCFactionComponent {
private String factionId;
private Map<String, FactionRelation> relations;
public enum FactionRelation {
ALLIED,
FRIENDLY,
NEUTRAL,
UNFRIENDLY,
HOSTILE
}
public FactionRelation getRelation(String otherFaction);
}
```
### NPCDialogueComponent
Dialogue capabilities:
```java
public class NPCDialogueComponent {
private String dialogueTreeId;
private Map<String, Boolean> dialogueFlags;
private Ref<EntityStore> currentSpeaker;
public boolean hasDialogue();
public void startDialogue(Player player);
}
```
## Utility Components
### NPCScheduleComponent
Daily schedule:
```java
public class NPCScheduleComponent {
private Map<Integer, ScheduleEntry> schedule;
public static class ScheduleEntry {
public int startHour;
public int endHour;
public String activity;
public Vector3d location;
}
public ScheduleEntry getCurrentActivity(int worldHour);
}
```
### NPCInventoryComponent
NPC inventory:
```java
public class NPCInventoryComponent {
private ItemContainer inventory;
private ItemStack equippedWeapon;
private ItemStack equippedArmor;
public ItemStack getEquippedWeapon();
public void equipItem(ItemStack item);
}
```
## Registering Custom Components
```java
public class MyPlugin extends JavaPlugin {
@Override
public void start() {
// Register custom NPC component
getEntityStoreRegistry().registerComponent(
"custom_npc_data",
CustomNPCComponent.class,
CustomNPCComponent::new
);
}
}
public class CustomNPCComponent {
private String customData;
private int customValue;
// Component data fields
}
```
## Component Access Patterns
```java
// Safe component access
public void processNPC(NPCEntity npc) {
EntityStore store = npc.getEntityStore();
// Check if component exists
if (store.hasComponent(NPCCombatComponent.class)) {
NPCCombatComponent combat = store.getComponent(NPCCombatComponent.class);
// Process combat logic
}
// Get or create component
NPCStateComponent state = store.getOrCreateComponent(
NPCStateComponent.class,
NPCStateComponent::new
);
}
```
## Best Practices
{{< callout type="info" >}}
**Component Guidelines:**
- Components should be pure data - no complex logic
- Use components for state that needs to persist
- Access components through EntityStore, not directly
- Check component existence before access
- Use appropriate component for each type of data
{{< /callout >}}

View File

@@ -0,0 +1,348 @@
---
title: Composants NPC
type: docs
weight: 2
---
Les composants NPC sont des composants ECS qui stockent les données et l'état des NPCs. Le système inclut plus de 300 composants de base pour diverses fonctionnalités NPC.
**Package:** `com.hypixel.hytale.server.npc.corecomponents`
## Vue d'Ensemble des Composants
Les composants NPC suivent le pattern ECS où les composants sont des conteneurs de données pures attachés aux entity stores.
```java
// Accéder aux composants NPC
EntityStore store = npc.getEntityStore();
NPCBrainComponent brain = store.getComponent(NPCBrainComponent.class);
```
## Composants Cerveau
### NPCBrainComponent
Le composant principal de traitement IA :
```java
public class NPCBrainComponent {
private DecisionMaker decisionMaker;
private float thinkInterval;
private float lastThinkTime;
public void setDecisionMaker(DecisionMaker maker);
public DecisionMaker getDecisionMaker();
public boolean shouldThink(float currentTime);
}
```
### NPCMemoryComponent
Stocke les mémoires et connaissances du NPC :
```java
public class NPCMemoryComponent {
private Map<String, Memory> memories;
private float memoryDuration;
public void remember(String key, Object value, float duration);
public <T> T recall(String key, Class<T> type);
public boolean hasMemory(String key);
public void forget(String key);
}
```
## Composants d'État
### NPCStateComponent
État comportemental actuel :
```java
public class NPCStateComponent {
private NPCState currentState;
private NPCState previousState;
private float stateEnterTime;
public enum NPCState {
IDLE,
WALKING,
RUNNING,
ATTACKING,
FLEEING,
INTERACTING,
SLEEPING,
DEAD
}
}
```
### NPCAlertComponent
Niveau de vigilance et de conscience :
```java
public class NPCAlertComponent {
private AlertLevel alertLevel;
private float alertDecayRate;
private Entity alertSource;
public enum AlertLevel {
RELAXED, // État normal
CURIOUS, // Quelque chose a attiré l'attention
ALERT, // Investigation active
ALARMED, // Menace détectée
COMBAT // En combat
}
}
```
## Composants de Cible
### NPCTargetComponent
Suivi de cible actuel :
```java
public class NPCTargetComponent {
private Ref<EntityStore> currentTarget;
private TargetType targetType;
private float targetAcquiredTime;
private Vector3d lastKnownPosition;
public enum TargetType {
HOSTILE,
FRIENDLY,
NEUTRAL,
OBJECT
}
}
```
### NPCFocusComponent
Point de focus visuel :
```java
public class NPCFocusComponent {
private Vector3d focusPoint;
private Ref<EntityStore> focusEntity;
private float focusStrength;
private boolean shouldLookAt;
}
```
## Composants de Mouvement
### NPCMovementComponent
Configuration de mouvement :
```java
public class NPCMovementComponent {
private float walkSpeed;
private float runSpeed;
private float turnSpeed;
private boolean canJump;
private boolean canSwim;
private boolean canClimb;
}
```
### NPCPathComponent
Données de suivi de chemin :
```java
public class NPCPathComponent {
private List<Vector3d> currentPath;
private int currentWaypointIndex;
private float pathRecalculateInterval;
private float lastPathTime;
public Vector3d getCurrentWaypoint();
public Vector3d getNextWaypoint();
public boolean hasReachedWaypoint(Vector3d position, float threshold);
}
```
### NPCNavigationComponent
Paramètres de navigation :
```java
public class NPCNavigationComponent {
private float avoidanceRadius;
private float pathfindingRange;
private int maxPathLength;
private NavigationFlags flags;
public static class NavigationFlags {
public boolean avoidWater;
public boolean avoidFire;
public boolean canUseDoors;
public boolean canBreakBlocks;
}
}
```
## Composants de Combat
### NPCCombatComponent
Capacités de combat :
```java
public class NPCCombatComponent {
private float attackRange;
private float attackCooldown;
private float lastAttackTime;
private DamageType preferredDamageType;
private List<String> availableAttacks;
}
```
### NPCAggroComponent
Gestion de l'aggro :
```java
public class NPCAggroComponent {
private Map<Ref<EntityStore>, Float> aggroTable;
private float aggroDecayRate;
private float aggroRange;
public void addAggro(Ref<EntityStore> entity, float amount);
public void removeAggro(Ref<EntityStore> entity);
public Ref<EntityStore> getHighestAggroTarget();
}
```
## Composants Sociaux
### NPCFactionComponent
Affiliation de faction :
```java
public class NPCFactionComponent {
private String factionId;
private Map<String, FactionRelation> relations;
public enum FactionRelation {
ALLIED,
FRIENDLY,
NEUTRAL,
UNFRIENDLY,
HOSTILE
}
public FactionRelation getRelation(String otherFaction);
}
```
### NPCDialogueComponent
Capacités de dialogue :
```java
public class NPCDialogueComponent {
private String dialogueTreeId;
private Map<String, Boolean> dialogueFlags;
private Ref<EntityStore> currentSpeaker;
public boolean hasDialogue();
public void startDialogue(Player player);
}
```
## Composants Utilitaires
### NPCScheduleComponent
Programme journalier :
```java
public class NPCScheduleComponent {
private Map<Integer, ScheduleEntry> schedule;
public static class ScheduleEntry {
public int startHour;
public int endHour;
public String activity;
public Vector3d location;
}
public ScheduleEntry getCurrentActivity(int worldHour);
}
```
### NPCInventoryComponent
Inventaire NPC :
```java
public class NPCInventoryComponent {
private ItemContainer inventory;
private ItemStack equippedWeapon;
private ItemStack equippedArmor;
public ItemStack getEquippedWeapon();
public void equipItem(ItemStack item);
}
```
## Enregistrer des Composants Personnalisés
```java
public class MyPlugin extends JavaPlugin {
@Override
public void start() {
// Enregistrer un composant NPC personnalisé
getEntityStoreRegistry().registerComponent(
"custom_npc_data",
CustomNPCComponent.class,
CustomNPCComponent::new
);
}
}
public class CustomNPCComponent {
private String customData;
private int customValue;
// Champs de données du composant
}
```
## Patterns d'Accès aux Composants
```java
// Accès sécurisé aux composants
public void processNPC(NPCEntity npc) {
EntityStore store = npc.getEntityStore();
// Vérifier si le composant existe
if (store.hasComponent(NPCCombatComponent.class)) {
NPCCombatComponent combat = store.getComponent(NPCCombatComponent.class);
// Traiter la logique de combat
}
// Obtenir ou créer un composant
NPCStateComponent state = store.getOrCreateComponent(
NPCStateComponent.class,
NPCStateComponent::new
);
}
```
## Bonnes Pratiques
{{< callout type="info" >}}
**Directives des Composants :**
- Les composants doivent être des données pures - pas de logique complexe
- Utilisez les composants pour l'état qui doit persister
- Accédez aux composants via EntityStore, pas directement
- Vérifiez l'existence du composant avant l'accès
- Utilisez le composant approprié pour chaque type de données
{{< /callout >}}

View File

@@ -0,0 +1,365 @@
---
title: NPC Movement
type: docs
weight: 4
---
The NPC movement system handles navigation, pathfinding, and motion control for NPCs.
**Packages:**
- `com.hypixel.hytale.server.npc.movement`
- `com.hypixel.hytale.server.npc.navigation`
## Motion Controller
The `MotionController` executes movement commands and manages NPC locomotion.
### MotionController Class
```java
public class MotionController {
private NPCEntity npc;
private MovementState state;
private float currentSpeed;
private Vector3d targetVelocity;
// Movement commands
public void moveTo(Vector3d target);
public void moveInDirection(Vector3d direction);
public void stop();
// Speed control
public void setSpeed(float speed);
public void walk();
public void run();
public void sprint();
// State queries
public boolean isMoving();
public boolean hasReachedTarget();
public MovementState getState();
}
```
### Movement States
```java
public enum MovementState {
IDLE, // Not moving
WALKING, // Normal movement
RUNNING, // Fast movement
SPRINTING, // Maximum speed
JUMPING, // In air (jump)
FALLING, // In air (fall)
SWIMMING, // In water
CLIMBING, // On ladder/vine
SLIDING // On slope
}
```
### Using MotionController
```java
NPCEntity npc = // get NPC
MotionController motion = npc.getMotionController();
// Move to position
motion.moveTo(targetPosition);
// Set movement speed
motion.run(); // or motion.setSpeed(5.0f);
// Check if arrived
if (motion.hasReachedTarget()) {
// Destination reached
}
// Stop movement
motion.stop();
```
## Path Follower
The `PathFollower` tracks and follows calculated paths.
### PathFollower Class
```java
public class PathFollower {
private List<Vector3d> path;
private int currentIndex;
private float waypointRadius;
private boolean smoothPath;
// Path management
public void setPath(List<Vector3d> path);
public void clearPath();
public boolean hasPath();
// Following
public Vector3d getNextWaypoint();
public void advanceToNextWaypoint();
public boolean hasReachedWaypoint(Vector3d position);
// Progress
public float getPathProgress(); // 0.0 to 1.0
public int getRemainingWaypoints();
}
```
### Path Following Example
```java
PathFollower pathFollower = npc.getPathFollower();
MotionController motion = npc.getMotionController();
// Set a path
pathFollower.setPath(calculatedPath);
// In update loop
if (pathFollower.hasPath()) {
Vector3d nextWaypoint = pathFollower.getNextWaypoint();
// Move towards waypoint
motion.moveTo(nextWaypoint);
// Check if reached
if (pathFollower.hasReachedWaypoint(npc.getPosition())) {
pathFollower.advanceToNextWaypoint();
}
}
```
## Navigation Graph
The navigation system uses A* pathfinding on a navigation graph.
### NavigationGraph Class
```java
public class NavigationGraph {
// Find path between points
public List<Vector3d> findPath(
Vector3d start,
Vector3d end,
NavigationConfig config
);
// Check if point is navigable
public boolean isNavigable(Vector3d position);
// Get nearest navigable point
public Vector3d getNearestNavigablePoint(Vector3d position);
}
```
### NavigationConfig
```java
public class NavigationConfig {
private float maxDistance; // Maximum path length
private float stepHeight; // Max step up height
private float entityWidth; // Entity collision width
private float entityHeight; // Entity collision height
private boolean canSwim; // Allow water paths
private boolean canClimb; // Allow ladder/vine paths
private boolean canOpenDoors; // Allow door traversal
private Set<String> avoidBlocks; // Blocks to avoid
// Builder pattern
public static NavigationConfig builder()
.maxDistance(100.0f)
.stepHeight(1.0f)
.entityWidth(0.6f)
.entityHeight(1.8f)
.canSwim(false)
.build();
}
```
### Pathfinding Example
```java
NavigationGraph navGraph = world.getNavigationGraph();
NavigationConfig config = NavigationConfig.builder()
.maxDistance(50.0f)
.canSwim(true)
.build();
List<Vector3d> path = navGraph.findPath(
npc.getPosition(),
targetPosition,
config
);
if (path != null && !path.isEmpty()) {
npc.getPathFollower().setPath(path);
}
```
## Movement Behaviors
Pre-built movement behaviors for common patterns.
### WanderBehavior
```java
public class WanderBehavior {
private float wanderRadius;
private float minPauseDuration;
private float maxPauseDuration;
public WanderBehavior(float radius) {
this.wanderRadius = radius;
}
public void update(NPCEntity npc, float deltaTime) {
if (!npc.getMotionController().isMoving()) {
Vector3d wanderTarget = calculateWanderTarget(npc);
npc.getMotionController().moveTo(wanderTarget);
}
}
}
```
### FollowBehavior
```java
public class FollowBehavior {
private Entity target;
private float followDistance;
private float catchUpDistance;
public void update(NPCEntity npc, float deltaTime) {
float distance = npc.getPosition().distance(target.getPosition());
if (distance > catchUpDistance) {
npc.getMotionController().run();
} else if (distance > followDistance) {
npc.getMotionController().walk();
npc.getMotionController().moveTo(target.getPosition());
} else {
npc.getMotionController().stop();
}
}
}
```
### PatrolBehavior
```java
public class PatrolBehavior {
private List<Vector3d> patrolPoints;
private int currentPointIndex;
private boolean loop;
private float waitTimeAtPoint;
public void update(NPCEntity npc, float deltaTime) {
Vector3d currentTarget = patrolPoints.get(currentPointIndex);
MotionController motion = npc.getMotionController();
if (motion.hasReachedTarget()) {
// Wait at point
currentPointIndex = (currentPointIndex + 1) % patrolPoints.size();
} else {
motion.moveTo(currentTarget);
}
}
}
```
### FleeBehavior
```java
public class FleeBehavior {
private float fleeDistance;
private Entity threat;
public void update(NPCEntity npc, float deltaTime) {
Vector3d awayFromThreat = npc.getPosition()
.subtract(threat.getPosition())
.normalize()
.multiply(fleeDistance);
Vector3d fleeTarget = npc.getPosition().add(awayFromThreat);
npc.getMotionController().sprint();
npc.getMotionController().moveTo(fleeTarget);
}
}
```
## Obstacle Avoidance
```java
public class ObstacleAvoidance {
private float avoidanceRadius;
private float lookAheadDistance;
public Vector3d calculateAvoidanceVector(
NPCEntity npc,
Vector3d desiredDirection
) {
// Cast rays to detect obstacles
List<RaycastHit> obstacles = castAvoidanceRays(npc, desiredDirection);
if (obstacles.isEmpty()) {
return desiredDirection;
}
// Calculate avoidance steering
Vector3d avoidance = Vector3d.ZERO;
for (RaycastHit hit : obstacles) {
Vector3d away = npc.getPosition().subtract(hit.position).normalize();
avoidance = avoidance.add(away);
}
return desiredDirection.add(avoidance.normalize()).normalize();
}
}
```
## Movement Systems
ECS systems that process NPC movement:
```java
// Movement update system
public class NPCMovementSystem implements System {
@Override
public void update(float deltaTime) {
for (NPCEntity npc : npcsWithMovement) {
MotionController motion = npc.getMotionController();
PathFollower path = npc.getPathFollower();
// Update path following
if (path.hasPath()) {
updatePathFollowing(npc, motion, path, deltaTime);
}
// Apply movement
motion.update(deltaTime);
}
}
}
```
## Best Practices
{{< callout type="info" >}}
**Movement Guidelines:**
- Use NavigationConfig appropriate for the NPC type
- Cache paths when possible to avoid frequent recalculation
- Use path smoothing for more natural movement
- Consider entity size when pathfinding
- Implement obstacle avoidance for dynamic environments
{{< /callout >}}
{{< callout type="warning" >}}
**Pathfinding Performance:**
- Limit pathfinding requests per frame
- Use shorter max distances when possible
- Cache frequently used paths
- Consider hierarchical pathfinding for large worlds
{{< /callout >}}

View File

@@ -0,0 +1,365 @@
---
title: Mouvement NPC
type: docs
weight: 4
---
Le système de mouvement NPC gère la navigation, le pathfinding et le contrôle de mouvement pour les NPCs.
**Packages:**
- `com.hypixel.hytale.server.npc.movement`
- `com.hypixel.hytale.server.npc.navigation`
## Motion Controller
Le `MotionController` exécute les commandes de mouvement et gère la locomotion des NPCs.
### Classe MotionController
```java
public class MotionController {
private NPCEntity npc;
private MovementState state;
private float currentSpeed;
private Vector3d targetVelocity;
// Commandes de mouvement
public void moveTo(Vector3d target);
public void moveInDirection(Vector3d direction);
public void stop();
// Contrôle de vitesse
public void setSpeed(float speed);
public void walk();
public void run();
public void sprint();
// Requêtes d'état
public boolean isMoving();
public boolean hasReachedTarget();
public MovementState getState();
}
```
### États de Mouvement
```java
public enum MovementState {
IDLE, // Immobile
WALKING, // Mouvement normal
RUNNING, // Mouvement rapide
SPRINTING, // Vitesse maximum
JUMPING, // En l'air (saut)
FALLING, // En l'air (chute)
SWIMMING, // Dans l'eau
CLIMBING, // Sur échelle/liane
SLIDING // Sur pente
}
```
### Utiliser MotionController
```java
NPCEntity npc = // obtenir le NPC
MotionController motion = npc.getMotionController();
// Se déplacer vers une position
motion.moveTo(targetPosition);
// Définir la vitesse de mouvement
motion.run(); // ou motion.setSpeed(5.0f);
// Vérifier si arrivé
if (motion.hasReachedTarget()) {
// Destination atteinte
}
// Arrêter le mouvement
motion.stop();
```
## Path Follower
Le `PathFollower` suit et parcourt les chemins calculés.
### Classe PathFollower
```java
public class PathFollower {
private List<Vector3d> path;
private int currentIndex;
private float waypointRadius;
private boolean smoothPath;
// Gestion de chemin
public void setPath(List<Vector3d> path);
public void clearPath();
public boolean hasPath();
// Suivi
public Vector3d getNextWaypoint();
public void advanceToNextWaypoint();
public boolean hasReachedWaypoint(Vector3d position);
// Progression
public float getPathProgress(); // 0.0 à 1.0
public int getRemainingWaypoints();
}
```
### Exemple de Suivi de Chemin
```java
PathFollower pathFollower = npc.getPathFollower();
MotionController motion = npc.getMotionController();
// Définir un chemin
pathFollower.setPath(calculatedPath);
// Dans la boucle de mise à jour
if (pathFollower.hasPath()) {
Vector3d nextWaypoint = pathFollower.getNextWaypoint();
// Se déplacer vers le waypoint
motion.moveTo(nextWaypoint);
// Vérifier si atteint
if (pathFollower.hasReachedWaypoint(npc.getPosition())) {
pathFollower.advanceToNextWaypoint();
}
}
```
## Navigation Graph
Le système de navigation utilise le pathfinding A* sur un graphe de navigation.
### Classe NavigationGraph
```java
public class NavigationGraph {
// Trouver un chemin entre deux points
public List<Vector3d> findPath(
Vector3d start,
Vector3d end,
NavigationConfig config
);
// Vérifier si un point est navigable
public boolean isNavigable(Vector3d position);
// Obtenir le point navigable le plus proche
public Vector3d getNearestNavigablePoint(Vector3d position);
}
```
### NavigationConfig
```java
public class NavigationConfig {
private float maxDistance; // Longueur max du chemin
private float stepHeight; // Hauteur max de marche
private float entityWidth; // Largeur de collision entité
private float entityHeight; // Hauteur de collision entité
private boolean canSwim; // Autoriser chemins aquatiques
private boolean canClimb; // Autoriser échelles/lianes
private boolean canOpenDoors; // Autoriser traversée de portes
private Set<String> avoidBlocks; // Blocs à éviter
// Pattern builder
public static NavigationConfig builder()
.maxDistance(100.0f)
.stepHeight(1.0f)
.entityWidth(0.6f)
.entityHeight(1.8f)
.canSwim(false)
.build();
}
```
### Exemple de Pathfinding
```java
NavigationGraph navGraph = world.getNavigationGraph();
NavigationConfig config = NavigationConfig.builder()
.maxDistance(50.0f)
.canSwim(true)
.build();
List<Vector3d> path = navGraph.findPath(
npc.getPosition(),
targetPosition,
config
);
if (path != null && !path.isEmpty()) {
npc.getPathFollower().setPath(path);
}
```
## Comportements de Mouvement
Comportements de mouvement pré-construits pour les patterns courants.
### WanderBehavior
```java
public class WanderBehavior {
private float wanderRadius;
private float minPauseDuration;
private float maxPauseDuration;
public WanderBehavior(float radius) {
this.wanderRadius = radius;
}
public void update(NPCEntity npc, float deltaTime) {
if (!npc.getMotionController().isMoving()) {
Vector3d wanderTarget = calculateWanderTarget(npc);
npc.getMotionController().moveTo(wanderTarget);
}
}
}
```
### FollowBehavior
```java
public class FollowBehavior {
private Entity target;
private float followDistance;
private float catchUpDistance;
public void update(NPCEntity npc, float deltaTime) {
float distance = npc.getPosition().distance(target.getPosition());
if (distance > catchUpDistance) {
npc.getMotionController().run();
} else if (distance > followDistance) {
npc.getMotionController().walk();
npc.getMotionController().moveTo(target.getPosition());
} else {
npc.getMotionController().stop();
}
}
}
```
### PatrolBehavior
```java
public class PatrolBehavior {
private List<Vector3d> patrolPoints;
private int currentPointIndex;
private boolean loop;
private float waitTimeAtPoint;
public void update(NPCEntity npc, float deltaTime) {
Vector3d currentTarget = patrolPoints.get(currentPointIndex);
MotionController motion = npc.getMotionController();
if (motion.hasReachedTarget()) {
// Attendre au point
currentPointIndex = (currentPointIndex + 1) % patrolPoints.size();
} else {
motion.moveTo(currentTarget);
}
}
}
```
### FleeBehavior
```java
public class FleeBehavior {
private float fleeDistance;
private Entity threat;
public void update(NPCEntity npc, float deltaTime) {
Vector3d awayFromThreat = npc.getPosition()
.subtract(threat.getPosition())
.normalize()
.multiply(fleeDistance);
Vector3d fleeTarget = npc.getPosition().add(awayFromThreat);
npc.getMotionController().sprint();
npc.getMotionController().moveTo(fleeTarget);
}
}
```
## Évitement d'Obstacles
```java
public class ObstacleAvoidance {
private float avoidanceRadius;
private float lookAheadDistance;
public Vector3d calculateAvoidanceVector(
NPCEntity npc,
Vector3d desiredDirection
) {
// Lancer des rayons pour détecter les obstacles
List<RaycastHit> obstacles = castAvoidanceRays(npc, desiredDirection);
if (obstacles.isEmpty()) {
return desiredDirection;
}
// Calculer la direction d'évitement
Vector3d avoidance = Vector3d.ZERO;
for (RaycastHit hit : obstacles) {
Vector3d away = npc.getPosition().subtract(hit.position).normalize();
avoidance = avoidance.add(away);
}
return desiredDirection.add(avoidance.normalize()).normalize();
}
}
```
## Systèmes de Mouvement
Systèmes ECS qui traitent le mouvement des NPCs :
```java
// Système de mise à jour de mouvement
public class NPCMovementSystem implements System {
@Override
public void update(float deltaTime) {
for (NPCEntity npc : npcsWithMovement) {
MotionController motion = npc.getMotionController();
PathFollower path = npc.getPathFollower();
// Mettre à jour le suivi de chemin
if (path.hasPath()) {
updatePathFollowing(npc, motion, path, deltaTime);
}
// Appliquer le mouvement
motion.update(deltaTime);
}
}
}
```
## Bonnes Pratiques
{{< callout type="info" >}}
**Directives de Mouvement :**
- Utilisez un NavigationConfig approprié au type de NPC
- Mettez en cache les chemins quand possible pour éviter les recalculs fréquents
- Utilisez le lissage de chemin pour un mouvement plus naturel
- Considérez la taille de l'entité lors du pathfinding
- Implémentez l'évitement d'obstacles pour les environnements dynamiques
{{< /callout >}}
{{< callout type="warning" >}}
**Performance du Pathfinding :**
- Limitez les requêtes de pathfinding par frame
- Utilisez des distances max plus courtes quand possible
- Mettez en cache les chemins fréquemment utilisés
- Considérez le pathfinding hiérarchique pour les grands mondes
{{< /callout >}}