Init
This commit is contained in:
302
content/world/entities/flocking-behavior.en.md
Normal file
302
content/world/entities/flocking-behavior.en.md
Normal file
@@ -0,0 +1,302 @@
|
||||
---
|
||||
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)
|
||||
);
|
||||
```
|
||||
Reference in New Issue
Block a user