Skip to content

Flock System

The Flock System manages group behaviors for NPCs, allowing them to move and act together as coordinated units. Flocks provide emergent group behaviors like alignment, cohesion, and separation.

Located at com.hypixel.hytale.server.flock

The FlockPlugin manages all flock functionality and provides:

  • Flock entities - Core flock management
  • Flock membership - NPC membership in flocks
  • Persistent flock data - Saved flock state
  • Flock behaviors - Group movement and coordination
  • Flock decision-making - Group-based AI decisions

The FlockPlugin class (com.hypixel.hytale.server.flock.FlockPlugin) serves as the central management point:

public class FlockPlugin extends JavaPlugin {
private ComponentType<EntityStore, Flock> flockComponentType;
private ComponentType<EntityStore, FlockMembership> flockMembershipComponentType;
private ComponentType<EntityStore, PersistentFlockData> persistentFlockDataComponentType;
}

Features:

  • Registers flock components
  • Manages flock lifecycle
  • Coordinates with NPC and spawning systems
  • Handles prefab flock remapping

Located at com.hypixel.hytale.server.flock.Flock

The Flock component represents a group of NPCs:

public class Flock implements Component<EntityStore> {
private boolean trace;
private PersistentFlockData flockData;
private DamageData nextDamageData;
private DamageData currentDamageData;
private DamageData nextLeaderDamageData;
private DamageData currentLeaderDamageData;
private FlockRemovedStatus removedStatus;
}

Debug tracing for flock behavior:

flock.setTrace(true); // Enable debug logging

Flocks track damage dealt by the group:

  • currentDamageData - Damage this tick
  • nextDamageData - Damage next tick (double buffered)
  • currentLeaderDamageData - Leader damage this tick
  • nextLeaderDamageData - Leader damage next tick

Damage data is double-buffered for thread safety:

flock.swapDamageDataBuffers();
public enum FlockRemovedStatus {
NOT_REMOVED,
DISSOLVED,
UNLOADED
}
  • NOT_REMOVED - Active flock
  • DISSOLVED - Flock disbanded
  • UNLOADED - Flock unloaded from world
ComponentType<EntityStore, Flock> flockType = Flock.getComponentType();
Flock flock = componentAccessor.getComponent(flockRef, flockType);

Located at com.hypixel.hytale.server.flock.FlockMembership

NPCs have a FlockMembership component when part of a flock:

public class FlockMembership implements Component<EntityStore> {
private Ref<EntityStore> flockRef;
private boolean isLeader;
private UUID flockId;
}
  • flockRef - Reference to flock entity
  • isLeader - Whether this NPC is the flock leader
  • flockId - Unique identifier for the flock

NPCs join flocks through the join action:

// From core components
BuilderActionFlockJoin joinAction = new BuilderActionFlockJoin();

NPCs leave flocks through:

// From core components
BuilderActionFlockLeave leaveAction = new BuilderActionFlockLeave();

Or automatically when:

  • NPC dies (unless corpseStaysInFlock is true)
  • NPC is removed
  • Flock is dissolved
ComponentType<EntityStore, FlockMembership> membershipType = FlockMembership.getComponentType();
FlockMembership membership = componentAccessor.getComponent(npcRef, membershipType);

Located at com.hypixel.hytale.server.flock.PersistentFlockData

Stores flock data that persists across saves:

public class PersistentFlockData implements Component<EntityStore> {
private FlockAsset flockDefinition;
private String[] allowedRoles;
private int currentSize;
private int maxSize;
}
  • flockDefinition - Reference to flock asset
  • allowedRoles - Roles allowed to join
  • currentSize - Current member count
  • maxSize - Maximum member count

Located at com.hypixel.hytale.server.flock.StoredFlock

Used for storing flock data in spawn markers:

public class StoredFlock {
private String flockAssetId;
private UUID flockId;
private int memberCount;
}

Located at com.hypixel.hytale.server.flock.config.FlockAsset

Defines flock behavior configuration:

{
"id": "wolf_pack",
"minSize": 3,
"maxSize": 8,
"alignment": 0.5,
"cohesion": 0.3,
"separation": 0.2,
"influenceRange": 10.0
}

Located at com.hypixel.hytale.server.flock.config.RangeSizeFlockAsset

Flock asset with size range configuration.

Flocks exhibit three core behaviors (boids algorithm):

Flocks align their velocity with nearby flock members:

class Role {
protected double flockWeightAlignment;
}

Higher weight = stronger alignment tendency.

Flocks move toward the center of nearby flock members:

class Role {
protected double flockWeightCohesion;
}

Higher weight = tighter grouping.

Flocks maintain distance from nearby flock members:

class Role {
protected double flockWeightSeparation;
}

Higher weight = more personal space.

How far flock members influence each other:

class Role {
protected double flockInfluenceRange;
}

Members beyond this distance don’t affect flock behavior.

One flock member is designated as the leader:

class Role {
protected boolean canLeadFlock;
}

Only NPCs with canLeadFlock = true can be leaders.

The leader:

  • Makes decisions for the flock
  • Other members follow the leader
  • Can have different AI instructions than followers

Flock tracks damage dealt by the leader separately:

DamageData leaderDamage = flock.getLeaderDamageData();

Located at com.hypixel.hytale.server.flock.corecomponents.builders

Core components for flock behaviors:

Flock movement behavior:

BuilderBodyMotionFlock flockMotion = new BuilderBodyMotionFlock();

Implements alignment, cohesion, and separation.

Join a flock:

{
"type": "JoinFlock",
"flockId": "wolf_pack"
}

Leave current flock:

{
"type": "LeaveFlock"
}

Change flock state:

{
"type": "FlockState",
"state": "aggressive"
}

Set flock target:

{
"type": "FlockTarget",
"target": "nearest_enemy"
}

Create a flock beacon:

{
"type": "FlockBeacon",
"duration": 30.0
}

Filter for flock members:

{
"type": "Flock",
"sameFlock": true
}

Senses flock combat damage:

{
"type": "FlockCombatDamage",
"threshold": 50.0
}

Senses damage dealt by flock:

{
"type": "InflictedDamage",
"threshold": 100.0
}

Senses flock leader:

{
"type": "FlockLeader",
"mustBeAlive": true
}

Located at com.hypixel.hytale.server.flock.decisionmaker

Located at com.hypixel.hytale.server.flock.decisionmaker.conditions.FlockSizeCondition

Condition based on flock size:

{
"type": "FlockSize",
"min": 3,
"max": 8
}

Returns true if flock size is within range.

Located at com.hypixel.hytale.server.flock

Various systems that manage flock behavior:

Handles entity removal from flocks.

Updates flock state each tick:

  • Swaps damage buffers
  • Updates flock behavior
  • Checks flock validity

FlockSystems.PlayerChangeGameModeEventSystem

Section titled “FlockSystems.PlayerChangeGameModeEventSystem”

Handles player game mode changes affecting flocks.

Systems managing flock membership:

Manages entity references in flocks.

Handles membership reference changes.

Located at com.hypixel.hytale.server.flock.FlockDeathSystems

Handles NPC death in flocks:

class Role {
protected boolean corpseStaysInFlock;
}

If false, dead NPCs leave the flock.

Spawn markers can spawn entire flocks:

class Role {
protected String[] flockSpawnTypes;
protected boolean flockSpawnTypesRandom;
protected String[] flockAllowedRoles;
}
  • flockSpawnTypes - NPC types to spawn in flock
  • flockSpawnTypesRandom - Random selection from types
  • flockAllowedRoles - Roles allowed in this flock
  1. Create flock entity
  2. Spawn leader
  3. Spawn flock members
  4. Assign all to flock
  5. Initialize flock behavior

Flocks in prefabs are handled specially:

class FlockPlugin {
private Int2ObjectConcurrentHashMap<Map<UUID, UUID>> prefabFlockRemappings;
}

Located in FlockPlugin

Handles flock remapping when prefabs are pasted:

class PrefabPasteEventSystem extends WorldEventSystem<PrefabPasteEvent>

Ensures flock UUIDs are unique when prefabs are duplicated.

  1. Create flock entity
  2. Add Flock component
  3. Set flock data
  4. Add initial members

Each tick:

  1. Swap damage buffers
  2. Update member positions
  3. Compute flock behaviors
  4. Update leader state
  5. Check for dissolution

Flocks dissolve when:

  • All members die/despawn
  • Manually disbanded
  • World unloads
flock.setRemovedStatus(FlockRemovedStatus.DISSOLVED);
{
"id": "bird_flock",
"minSize": 5,
"maxSize": 15,
"alignment": 0.6,
"cohesion": 0.3,
"separation": 0.1,
"influenceRange": 8.0
}
{
"id": "wolf_pack",
"minSize": 3,
"maxSize": 6,
"alignment": 0.4,
"cohesion": 0.5,
"separation": 0.1,
"influenceRange": 12.0
}

With NPC role:

{
"canLeadFlock": true,
"flockWeightAlignment": 0.4,
"flockWeightCohesion": 0.5,
"flockWeightSeparation": 0.1,
"corpseStaysInFlock": false
}
  1. Balance flock weights - Sum of weights should be reasonable
  2. Set appropriate influence range - Based on flock spacing
  3. Limit flock size - Large flocks impact performance
  4. Use leader AI - Give leaders smarter behavior
  5. Handle death properly - Decide if corpses stay or leave
  6. Test coordination - Ensure flocks behave naturally
  • Flock updates are distributed across ticks
  • Member queries use spatial indexing
  • Influence range limits computation
  • Smaller flocks perform better
  • Cached position data reduces lookups

Enable flock tracing:

flock.setTrace(true);

This logs:

  • Member additions/removals
  • Leadership changes
  • Damage events
  • Behavior decisions