hytale-npc-ai
4
总安装量
3
周安装量
#54497
全站排名
安装命令
npx skills add https://github.com/z3nlotus/hytale-agent-skills --skill hytale-npc-ai
Agent 安装分布
codex
3
github-copilot
3
gemini-cli
3
opencode
2
cursor
2
claude-code
2
Skill 文档
Hytale NPC & AI
Create intelligent NPCs and AI-driven characters for Hytale.
NPC Types
| Type | Behavior | Examples |
|---|---|---|
| Passive | Wanders, flees from danger | Villagers, animals |
| Neutral | Ignores unless provoked | Guards, merchants |
| Hostile | Actively attacks players | Monsters, enemies |
| Companion | Follows and assists player | Pets, allies |
Basic NPC Structure
NPC Components (ECS Pattern)
// An NPC is an entity with these components
Entity npc = world.createEntity();
npc.addComponent(new PositionComponent(x, y, z));
npc.addComponent(new HealthComponent(100, 100));
npc.addComponent(new NPCTypeComponent(NPCType.VILLAGER));
npc.addComponent(new AIControllerComponent());
npc.addComponent(new InventoryComponent());
npc.addComponent(new DialogueComponent("villager_greeting"));
Behavior Trees
Hytale uses behavior trees for AI decision making:
[Selector]
â
âââââââââââââââââ¼ââââââââââââââââ
â¼ â¼ â¼
[Is Danger?] [Has Task?] [Wander]
â â
â¼ â¼
[Flee] [Do Task]
Node Types
| Node | Behavior |
|---|---|
| Selector | Try children until one succeeds |
| Sequence | Run all children in order |
| Condition | Check if something is true |
| Action | Do something |
Example: Villager AI
BehaviorTree villagerAI = BehaviorTree.builder()
.selector()
.sequence() // Danger response
.condition(this::isInDanger)
.action(this::fleeFromDanger)
.end()
.sequence() // Work during day
.condition(this::isDaytime)
.condition(this::hasWorkstation)
.action(this::goToWorkstation)
.action(this::doWork)
.end()
.sequence() // Sleep at night
.condition(this::isNighttime)
.action(this::goToBed)
.action(this::sleep)
.end()
.action(this::wanderRandomly) // Default
.end()
.build();
State Machine Pattern
Alternative to behavior trees for simpler AI:
public enum NPCState {
IDLE,
WALKING,
WORKING,
FLEEING,
SLEEPING,
TALKING
}
public class VillagerAI {
private NPCState currentState = NPCState.IDLE;
public void update(Entity npc, float deltaTime) {
switch (currentState) {
case IDLE -> handleIdle(npc);
case WALKING -> handleWalking(npc);
case WORKING -> handleWorking(npc);
case FLEEING -> handleFleeing(npc);
// ...
}
}
private void handleIdle(Entity npc) {
if (isInDanger(npc)) {
currentState = NPCState.FLEEING;
} else if (shouldWork()) {
currentState = NPCState.WALKING;
setDestination(getWorkstation());
}
}
}
Dialogue System
Dialogue Structure
{
"dialogueId": "villager_greeting",
"entries": [
{
"text": "server.dialogue.villager.hello",
"responses": [
{
"text": "server.dialogue.player.trade",
"action": "open_trade",
"next": null
},
{
"text": "server.dialogue.player.quest",
"action": null,
"next": "villager_quest_info"
},
{
"text": "server.dialogue.player.goodbye",
"action": "close",
"next": null
}
]
}
]
}
Triggering Dialogue
registerEventListener(PlayerInteractEvent.class, event -> {
Entity target = event.getTarget();
if (target.hasComponent(DialogueComponent.class)) {
var dialogue = target.getComponent(DialogueComponent.class);
event.getPlayer().openDialogue(dialogue.getDialogueId());
}
});
Combat AI
Aggro System
public class AggroComponent {
private Map<Entity, Float> threatTable = new HashMap<>();
private float aggroRange = 10.0f;
public void addThreat(Entity source, float amount) {
threatTable.merge(source, amount, Float::sum);
}
public Entity getTopThreat() {
return threatTable.entrySet().stream()
.max(Map.Entry.comparingByValue())
.map(Map.Entry::getKey)
.orElse(null);
}
}
Attack Patterns
public class CombatAI {
private float attackCooldown = 0;
private float attackRange = 2.0f;
public void update(Entity npc, Entity target, float deltaTime) {
attackCooldown -= deltaTime;
float distance = npc.distanceTo(target);
if (distance > attackRange) {
// Move toward target
moveToward(npc, target);
} else if (attackCooldown <= 0) {
// Attack!
attack(npc, target);
attackCooldown = 1.5f; // Reset cooldown
}
}
}
Pathfinding
Basic Pathfinding
// Request path from current position to target
Path path = pathfinder.findPath(
npc.getPosition(),
targetPosition
);
// Follow the path
if (path != null && !path.isEmpty()) {
Position nextWaypoint = path.getNextWaypoint();
moveToward(npc, nextWaypoint);
if (npc.distanceTo(nextWaypoint) < 0.5f) {
path.advanceWaypoint();
}
}
Pathfinding Options
| Option | Description |
|---|---|
avoidWater |
Don’t path through water |
avoidDanger |
Avoid hostile areas |
maxDistance |
Limit path length |
canOpenDoors |
Allow door navigation |
Spawning NPCs
Via Plugin
public void spawnVillager(World world, Position pos) {
Entity villager = world.spawnEntity("hytale:villager", pos);
// Customize
villager.getComponent(NameComponent.class)
.setName("Bob the Builder");
villager.addComponent(new ProfessionComponent("builder"));
}
Via Pack (JSON)
{
"type": "npc_spawner",
"entityType": "hytale:villager",
"spawnCount": { "min": 2, "max": 5 },
"spawnArea": { "radius": 10 },
"conditions": {
"biome": "village",
"minLightLevel": 8
}
}
Common AI Patterns
Patrol Route
public class PatrolAI {
private List<Position> waypoints;
private int currentWaypoint = 0;
public void update(Entity npc) {
Position target = waypoints.get(currentWaypoint);
if (npc.distanceTo(target) < 1.0f) {
currentWaypoint = (currentWaypoint + 1) % waypoints.size();
} else {
moveToward(npc, target);
}
}
}
Follow Player
public class FollowAI {
private Entity owner;
private float followDistance = 3.0f;
private float maxDistance = 20.0f;
public void update(Entity pet) {
float distance = pet.distanceTo(owner);
if (distance > maxDistance) {
teleportTo(pet, owner.getPosition());
} else if (distance > followDistance) {
moveToward(pet, owner);
}
}
}
Quick Reference
| AI Type | Best Pattern | Use Case |
|---|---|---|
| Simple NPC | State Machine | Basic villagers |
| Complex NPC | Behavior Tree | Quest givers, bosses |
| Combat | Aggro + State | Enemies |
| Companions | Follow + Commands | Pets |
Resources
- ECS Architecture: See
hytale-ecsskill - Plugin Development: See
hytale-plugin-devskill - Animation: See
hytale-animationskill