218 lines
4.8 KiB
Markdown
218 lines
4.8 KiB
Markdown
---
|
|
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 >}}
|