Entity Groups
Entity Groups
Section titled “Entity Groups”The entity group system allows grouping multiple entities together for coordinated behavior like mounts, raids, or squads.
Package Location
Section titled “Package Location”com.hypixel.hytale.server.core.entity.group
Overview
Section titled “Overview”Entity groups are managed via the EntityGroup component. A group has a leader and members, supports iteration and queries, and can be dissolved when no longer needed.
Core Class
Section titled “Core Class”EntityGroup
Section titled “EntityGroup”Component that manages a group of entities:
package com.hypixel.hytale.server.core.entity.group;
public class EntityGroup implements Component<EntityStore> { // Member management public void add(Ref<EntityStore> reference); public void remove(Ref<EntityStore> reference); public void clear(); public boolean isMember(Ref<EntityStore> reference); public int size(); public Ref<EntityStore> getFirst();
// Leadership public Ref<EntityStore> getLeaderRef(); public void setLeaderRef(Ref<EntityStore> leaderRef);
// Status public boolean isDissolved(); public void setDissolved(boolean dissolved);
// Iteration public <T> void forEachMember( TriConsumer<Ref<EntityStore>, Ref<EntityStore>, T> consumer, Ref<EntityStore> sender, T arg );
public <T> void forEachMemberExcludingLeader( TriConsumer<Ref<EntityStore>, Ref<EntityStore>, T> consumer, Ref<EntityStore> sender, T arg );
public <T> void forEachMemberExcludingSelf( TriConsumer<Ref<EntityStore>, Ref<EntityStore>, T> consumer, Ref<EntityStore> sender, T arg );
public Ref<EntityStore> testMembers( Predicate<Ref<EntityStore>> predicate, boolean skipLeader );
// Direct list access public List<Ref<EntityStore>> getMemberList();
// Get component type public static ComponentType<EntityStore, EntityGroup> getComponentType();}Usage Examples
Section titled “Usage Examples”Creating a Group
Section titled “Creating a Group”import com.hypixel.hytale.server.core.entity.group.EntityGroup;import com.hypixel.hytale.component.Ref;import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
// Get or create group component on owner entityRef<EntityStore> ownerRef = /* owner entity reference */;EntityGroup group = componentAccessor.getOrCreateComponent( ownerRef, EntityGroup.getComponentType());
// Set leadergroup.setLeaderRef(ownerRef);Adding Members
Section titled “Adding Members”// Add members to groupRef<EntityStore> member1 = /* entity reference */;Ref<EntityStore> member2 = /* entity reference */;Ref<EntityStore> member3 = /* entity reference */;
group.add(member1);group.add(member2);group.add(member3);
// Check membershipif (group.isMember(member1)) { System.out.println("Member 1 is in the group");}
// Get group sizeint memberCount = group.size(); // Returns 3Removing Members
Section titled “Removing Members”// Remove specific membergroup.remove(member1);
// Clear all members (disband group)group.clear();Iterating Members
Section titled “Iterating Members”// Iterate all membersgroup.forEachMember( (memberRef, senderRef, data) -> { System.out.println("Processing member: " + memberRef); }, ownerRef, // Sender reference null // Additional data);
// Iterate excluding leadergroup.forEachMemberExcludingLeader( (memberRef, senderRef, data) -> { // Only non-leader members sendMessageToMember(memberRef, data); }, ownerRef, "Hello team!");
// Iterate excluding sendergroup.forEachMemberExcludingSelf( (memberRef, senderRef, context) -> { // All members except the sender notifyMember(memberRef); }, senderEntityRef, null);Finding Members
Section titled “Finding Members”// Find first member matching conditionRef<EntityStore> aliveMember = group.testMembers( member -> { // Check if member is alive return member.isValid() && !isDead(member); }, true // Skip leader);
if (aliveMember != null) { // Found an alive non-leader member}
// Find first member (any)Ref<EntityStore> firstMember = group.getFirst();Checking Group Status
Section titled “Checking Group Status”// Check if group is dissolvedif (group.isDissolved()) { // Group has been disbanded return;}
// Manually dissolve groupgroup.setDissolved(true);
// Get leaderRef<EntityStore> leader = group.getLeaderRef();if (leader != null && leader.isValid()) { // Leader is still valid}Direct List Access
Section titled “Direct List Access”// Get member list for more complex operationsList<Ref<EntityStore>> members = group.getMemberList();
// Filter membersList<Ref<EntityStore>> validMembers = members.stream() .filter(Ref::isValid) .collect(Collectors.toList());
// Count memberslong count = members.stream() .filter(m -> m.isValid()) .count();Use Cases
Section titled “Use Cases”Mount System
Section titled “Mount System”// Mount group: rider + mountEntityGroup mountGroup = getOrCreateGroup(mountRef);mountGroup.setLeaderRef(riderRef); // Rider is leadermountGroup.add(mountRef); // Mount is member
// DismountmountGroup.remove(mountRef);mountGroup.setDissolved(true);Squad/Party
Section titled “Squad/Party”// Party group: party leader + membersEntityGroup party = getOrCreateGroup(leaderRef);party.setLeaderRef(leaderRef);
// Invite playerparty.add(invitedPlayerRef);
// Leave partyparty.remove(leavingPlayerRef);
// Kick playerparty.remove(kickedPlayerRef);
// Disband partyparty.clear();Raid Group
Section titled “Raid Group”// Raid: boss + minionsEntityGroup raid = getOrCreateGroup(bossRef);raid.setLeaderRef(bossRef);
// Spawn minionsfor (int i = 0; i < 5; i++) { Ref<EntityStore> minionRef = spawnMinion(); raid.add(minionRef);}
// Boss death - kill all minionsraid.forEachMemberExcludingLeader( (memberRef, leaderRef, unused) -> { killEntity(memberRef); }, bossRef, null);raid.setDissolved(true);Synchronized Behavior
Section titled “Synchronized Behavior”// Make all group members face the same directionVector3f leaderRotation = getRotation(group.getLeaderRef());
group.forEachMemberExcludingLeader( (memberRef, leaderRef, rotation) -> { setRotation(memberRef, rotation); }, group.getLeaderRef(), leaderRotation);Group Lifecycle
Section titled “Group Lifecycle”1. Create EntityGroup on owner entity2. Set leader reference3. Add members as needed4. Iterate/query members during gameplay5. Remove members when they leave6. Clear and dissolve when group endsBest Practices
Section titled “Best Practices”Validate References
Section titled “Validate References”// Always check if member is still validgroup.forEachMember( (memberRef, senderRef, data) -> { if (!memberRef.isValid()) { return; // Skip invalid members } // Process valid member }, ownerRef, null);Clean Up Disbanded Groups
Section titled “Clean Up Disbanded Groups”// Remove group component when dissolvedif (group.isDissolved()) { componentAccessor.removeComponent( ownerRef, EntityGroup.getComponentType() );}Leader Death Handling
Section titled “Leader Death Handling”// When leader dies, either:// 1. Promote new leaderRef<EntityStore> newLeader = group.getFirst();if (newLeader != null && newLeader.isValid()) { group.setLeaderRef(newLeader);}
// 2. Or dissolve groupgroup.clear();group.setDissolved(true);Related
Section titled “Related”- Entity System - Entity management
- ECS Overview - Component system
- Component Catalog - All components