303 lines
5.9 KiB
Markdown
303 lines
5.9 KiB
Markdown
---
|
|
title: Flocking Behavior
|
|
type: docs
|
|
weight: 10
|
|
---
|
|
|
|
The flock system enables NPCs to form and behave as coordinated groups.
|
|
|
|
**Package:** `com.hypixel.hytale.server.flock`
|
|
|
|
## Overview
|
|
|
|
Flocks are entity-based groups that allow NPCs to:
|
|
- Move and act as a coordinated unit
|
|
- Share damage information across members
|
|
- Spawn in configurable group sizes
|
|
- Have designated leaders
|
|
|
|
## Architecture
|
|
|
|
```
|
|
Flock System
|
|
├── Components
|
|
│ ├── Flock - Group entity component
|
|
│ ├── FlockMembership - Member reference
|
|
│ └── PersistentFlockData - Saved flock data
|
|
├── Assets
|
|
│ ├── FlockAsset - Flock configuration
|
|
│ ├── RangeSizeFlockAsset - Range-based size
|
|
│ └── WeightedSizeFlockAsset - Weighted size
|
|
├── Systems
|
|
│ ├── FlockSystems - Core flock logic
|
|
│ ├── FlockMembershipSystems - Member management
|
|
│ └── FlockDeathSystems - Death handling
|
|
└── NPC Components
|
|
├── BodyMotionFlock - Movement behavior
|
|
├── ActionFlockJoin/Leave - Join/leave actions
|
|
└── SensorFlockLeader - Leader detection
|
|
```
|
|
|
|
## Flock Component
|
|
|
|
The flock entity holds shared group state:
|
|
|
|
```java
|
|
public class Flock implements Component<EntityStore> {
|
|
// Shared damage data for combat coordination
|
|
private DamageData currentDamageData;
|
|
private DamageData nextDamageData;
|
|
|
|
// Leader-specific damage data
|
|
private DamageData currentLeaderDamageData;
|
|
private DamageData nextLeaderDamageData;
|
|
|
|
// Persistent group configuration
|
|
private PersistentFlockData flockData;
|
|
|
|
// Removal status
|
|
public enum FlockRemovedStatus {
|
|
NOT_REMOVED,
|
|
DISSOLVED,
|
|
UNLOADED
|
|
}
|
|
}
|
|
```
|
|
|
|
## FlockMembership Component
|
|
|
|
Each NPC member has a membership component:
|
|
|
|
```java
|
|
public class FlockMembership implements Component<EntityStore> {
|
|
// Reference to the flock entity
|
|
private Ref<EntityStore> flockRef;
|
|
}
|
|
```
|
|
|
|
## Creating Flocks
|
|
|
|
### Spawn with Flock
|
|
|
|
```java
|
|
// Spawn an NPC with its flock
|
|
Ref<EntityStore> flockRef = FlockPlugin.trySpawnFlock(
|
|
npcRef, // Initial NPC reference
|
|
npc, // NPC component
|
|
store, // Entity store
|
|
roleIndex, // NPC role index
|
|
position, // Spawn position
|
|
rotation, // Spawn rotation
|
|
flockDefinition, // FlockAsset config (determines size)
|
|
postSpawnCallback // Called for each spawned member
|
|
);
|
|
```
|
|
|
|
### Create Empty Flock
|
|
|
|
```java
|
|
// Create flock entity for manual member management
|
|
Ref<EntityStore> flockRef = FlockPlugin.createFlock(store, role);
|
|
|
|
// Or with explicit configuration
|
|
Ref<EntityStore> flockRef = FlockPlugin.createFlock(
|
|
store,
|
|
flockAsset, // FlockAsset configuration
|
|
allowedRoles // Roles that can join
|
|
);
|
|
```
|
|
|
|
### Join Existing Flock
|
|
|
|
```java
|
|
// Add NPC to existing flock
|
|
FlockMembershipSystems.join(npcRef, flockRef, store);
|
|
```
|
|
|
|
## Flock Assets
|
|
|
|
### FlockAsset
|
|
|
|
Base configuration for flocks:
|
|
|
|
```java
|
|
public class FlockAsset {
|
|
// Asset identifier
|
|
private String id;
|
|
|
|
// Pick group size for spawning
|
|
public abstract int pickFlockSize();
|
|
}
|
|
```
|
|
|
|
### RangeSizeFlockAsset
|
|
|
|
Flock with random size in range:
|
|
|
|
```json
|
|
{
|
|
"Type": "RangeSize",
|
|
"Id": "wolf_pack",
|
|
"MinSize": 3,
|
|
"MaxSize": 8
|
|
}
|
|
```
|
|
|
|
### WeightedSizeFlockAsset
|
|
|
|
Flock with weighted random size:
|
|
|
|
```json
|
|
{
|
|
"Type": "WeightedSize",
|
|
"Id": "deer_herd",
|
|
"Sizes": [
|
|
{ "Size": 2, "Weight": 1 },
|
|
{ "Size": 4, "Weight": 2 },
|
|
{ "Size": 6, "Weight": 1 }
|
|
]
|
|
}
|
|
```
|
|
|
|
## NPC Core Components
|
|
|
|
### BodyMotionFlock
|
|
|
|
Controls flocking movement behavior:
|
|
|
|
```json
|
|
{
|
|
"Type": "Flock",
|
|
"SeparationWeight": 1.5,
|
|
"AlignmentWeight": 1.0,
|
|
"CohesionWeight": 1.0
|
|
}
|
|
```
|
|
|
|
### ActionFlockJoin
|
|
|
|
Join a flock:
|
|
|
|
```json
|
|
{
|
|
"Type": "JoinFlock",
|
|
"FlockId": "wolf_pack"
|
|
}
|
|
```
|
|
|
|
### ActionFlockLeave
|
|
|
|
Leave current flock:
|
|
|
|
```json
|
|
{
|
|
"Type": "LeaveFlock"
|
|
}
|
|
```
|
|
|
|
### SensorFlockLeader
|
|
|
|
Detect flock leader:
|
|
|
|
```json
|
|
{
|
|
"Type": "FlockLeader",
|
|
"Output": "leader_ref"
|
|
}
|
|
```
|
|
|
|
### EntityFilterFlock
|
|
|
|
Filter entities by flock membership:
|
|
|
|
```json
|
|
{
|
|
"Type": "Flock",
|
|
"IncludeSelf": false,
|
|
"OnlyMembers": true
|
|
}
|
|
```
|
|
|
|
## Damage Sharing
|
|
|
|
Flocks share combat information:
|
|
|
|
```java
|
|
// Get damage data for the flock
|
|
Flock flock = store.getComponent(flockRef, Flock.getComponentType());
|
|
DamageData damageData = flock.getDamageData();
|
|
|
|
// Track kills for the flock
|
|
flock.onTargetKilled(componentAccessor, targetRef);
|
|
```
|
|
|
|
### Double Buffering
|
|
|
|
Damage data uses double buffering to avoid race conditions:
|
|
|
|
```java
|
|
// Called each tick
|
|
flock.swapDamageDataBuffers();
|
|
// currentDamageData contains last tick's data
|
|
// nextDamageData accumulates current tick's data
|
|
```
|
|
|
|
## Conditions
|
|
|
|
### FlockSizeCondition
|
|
|
|
Check flock size in decision making:
|
|
|
|
```json
|
|
{
|
|
"Type": "FlockSize",
|
|
"Min": 2,
|
|
"Max": 10
|
|
}
|
|
```
|
|
|
|
## Plugin Access
|
|
|
|
```java
|
|
FlockPlugin flockPlugin = FlockPlugin.get();
|
|
|
|
// Component types
|
|
ComponentType<EntityStore, Flock> flockType =
|
|
flockPlugin.getFlockComponentType();
|
|
ComponentType<EntityStore, FlockMembership> membershipType =
|
|
flockPlugin.getFlockMembershipComponentType();
|
|
ComponentType<EntityStore, PersistentFlockData> dataType =
|
|
flockPlugin.getPersistentFlockDataComponentType();
|
|
```
|
|
|
|
## Utility Methods
|
|
|
|
```java
|
|
// Check if entity is in a flock
|
|
boolean isMember = FlockPlugin.isFlockMember(npcRef, store);
|
|
|
|
// Get flock reference from entity
|
|
Ref<EntityStore> flockRef = FlockPlugin.getFlockReference(npcRef, store);
|
|
|
|
// Get flock component from entity
|
|
Flock flock = FlockPlugin.getFlock(store, npcRef);
|
|
```
|
|
|
|
## Flock Spawning Behavior
|
|
|
|
When spawning a flock:
|
|
1. Initial NPC is created
|
|
2. Flock entity is created with membership
|
|
3. Additional members spawn at same location
|
|
4. Members spread with slight random offset
|
|
5. Each member joins the flock
|
|
|
|
```java
|
|
// Members spawn with random offset
|
|
memberTransform.getPosition().assign(
|
|
x + RandomExtra.randomRange(-0.5, 0.5),
|
|
offsetY,
|
|
z + RandomExtra.randomRange(-0.5, 0.5)
|
|
);
|
|
```
|