Entity System Overview
Entity System Overview
Section titled “Entity System Overview”The Entity System manages all game objects that exist within worlds, including players, mobs, items, projectiles, and other dynamic objects. Entities are implemented using the ECS architecture with components providing data and systems providing behavior.
Package Location
Section titled “Package Location”- Entity base:
com.hypixel.hytale.server.core.entity.Entity - PlayerRef:
com.hypixel.hytale.server.core.universe.PlayerRef - Player:
com.hypixel.hytale.server.core.entity.entities.Player - EntityStore:
com.hypixel.hytale.server.core.universe.world.storage.EntityStore - TransformComponent:
com.hypixel.hytale.server.core.modules.entity.component.TransformComponent
Core Concepts
Section titled “Core Concepts”Entity Hierarchy
Section titled “Entity Hierarchy”Entity (base class)├── LivingEntity│ ├── Player│ ├── Creature│ └── NPC├── ItemEntity├── ProjectileEntity└── ... other entity typesEntity as Component
Section titled “Entity as Component”In Hytale’s ECS, Entity subclasses are actually components themselves. Each entity type is registered as a component type:
ComponentType<EntityStore, MyEntity> entityType = getEntityStoreRegistry().registerComponent(MyEntity.class, ...);PlayerRef
Section titled “PlayerRef”PlayerRef is the primary interface for working with connected players. It bridges the network connection with the in-world entity.
Accessing PlayerRef
Section titled “Accessing PlayerRef”// From Universe (all players)List<PlayerRef> allPlayers = Universe.get().getPlayers();
// From World (players in world)Collection<PlayerRef> worldPlayers = world.getPlayerRefs();
// From eventgetEventRegistry().register(PlayerConnectEvent.class, event -> { PlayerRef player = event.getPlayerRef();});
// Find by namePlayerRef player = Universe.get().getPlayerByUsername("username", NameMatching.DEFAULT);PlayerRef Properties
Section titled “PlayerRef Properties”| Property | Type | Description |
|---|---|---|
uuid | UUID | Player’s unique identifier |
username | String | Player’s display name |
language | String | Player’s language preference |
packetHandler | PacketHandler | Network packet handler |
chunkTracker | ChunkTracker | Tracks loaded chunks |
PlayerRef Methods
Section titled “PlayerRef Methods”// Basic infoUUID uuid = player.getUuid();String name = player.getUsername();String language = player.getLanguage();
// Check if valid (connected)if (player.isValid()) { // Player is connected}
// Get entity reference (if in world)Ref<EntityStore> ref = player.getReference();if (ref != null && ref.isValid()) { // Access entity components}
// Get holder (for component access when between worlds)Holder<EntityStore> holder = player.getHolder();
// Get positionTransform transform = player.getTransform();Vector3f headRotation = player.getHeadRotation();
// Send messageplayer.sendMessage(Message.raw("Hello!"));
// Transfer to another serverplayer.referToServer("other-server.example.com", 25565);player.referToServer("other-server.example.com", 25565, customData);Entity Class
Section titled “Entity Class”The base Entity class provides common functionality for all entities.
Entity Properties
Section titled “Entity Properties”| Property | Type | Description |
|---|---|---|
networkId | int | Network identifier (-1 if not spawned) |
world | World | World the entity is in |
reference | Ref<EntityStore> | ECS reference |
wasRemoved | boolean | Whether entity was removed |
Entity Methods
Section titled “Entity Methods”// Get worldWorld world = entity.getWorld();
// Get entity referenceRef<EntityStore> ref = entity.getReference();
// Remove entity from worldboolean removed = entity.remove();
// Check if already removedif (entity.wasRemoved()) { return;}
// Check if collidableboolean collidable = entity.isCollidable();
// Convert to holder (for serialization/transfer)Holder<EntityStore> holder = entity.toHolder();Entity Lifecycle
Section titled “Entity Lifecycle”Create Entity Instance ↓loadIntoWorld(world) ← Assigns to world ↓setReference(ref) ← Links to ECS ↓ [Active] ↓ remove() ← Removes from world ↓unloadFromWorld() ← Cleans upWorking with Entity Components
Section titled “Working with Entity Components”Entities use the ECS system for data storage:
// Get entity storeEntityStore entityStore = world.getEntityStore();Store<EntityStore> store = entityStore.getStore();
// Get component from entityTransformComponent transform = store.getComponent(ref, TransformComponent.getComponentType());
// Check if entity has componentif (store.hasComponent(ref, HealthComponent.getComponentType())) { HealthComponent health = store.getComponent(ref, HealthComponent.getComponentType());}
// Add component to entitystore.addComponent(ref, myComponentType, new MyComponent());
// Remove componentstore.removeComponent(ref, myComponentType);Common Entity Components
Section titled “Common Entity Components”TransformComponent
Section titled “TransformComponent”Position and rotation in the world:
TransformComponent transform = store.getComponent(ref, TransformComponent.getComponentType());
// Get positionVector3d position = transform.getPosition();double x = position.x;double y = position.y;double z = position.z;
// Get rotationVector3f rotation = transform.getRotation();float pitch = rotation.x;float yaw = rotation.y;float roll = rotation.z;
// Set positionposition.assign(newX, newY, newZ);ModelComponent
Section titled “ModelComponent”Visual model and display:
ModelComponent model = store.getComponent(ref, ModelComponent.getComponentType());
// Get model referenceModel.ModelReference modelRef = model.getModel();UUIDComponent
Section titled “UUIDComponent”Unique identifier:
UUIDComponent uuidComp = store.getComponent(ref, UUIDComponent.getComponentType());UUID entityUuid = uuidComp.getUuid();Spawning Entities
Section titled “Spawning Entities”Creating and Spawning
Section titled “Creating and Spawning”// 1. Create holder with componentsHolder<EntityStore> holder = EntityStore.REGISTRY.newHolder();
// 2. Add entity componentMyEntity entity = new MyEntity();holder.addComponent(MyEntity.getComponentType(), entity);
// 3. Add required componentsholder.addComponent(TransformComponent.getComponentType(), new TransformComponent(x, y, z, 0, 0, 0));holder.addComponent(UUIDComponent.getComponentType(), new UUIDComponent(UUID.randomUUID()));
// 4. Spawn in storeStore<EntityStore> store = world.getEntityStore().getStore();Ref<EntityStore> ref = store.spawn(holder);Using Entity Utilities
Section titled “Using Entity Utilities”// EntityUtils provides helper methodsHolder<EntityStore> holder = EntityUtils.createEntityHolder( entityType, transform, world);Ref<EntityStore> ref = store.spawn(holder);Entity Events
Section titled “Entity Events”Entity Removal
Section titled “Entity Removal”getEventRegistry().register(EntityRemoveEvent.class, event -> { Entity entity = event.getEntity(); // Handle entity removal});Player Entity Events
Section titled “Player Entity Events”// Player added to worldgetEventRegistry().register(AddPlayerToWorldEvent.class, event -> { PlayerRef player = event.getPlayerRef(); World world = event.getWorld();});
// Player removed from worldgetEventRegistry().register(DrainPlayerFromWorldEvent.class, event -> { PlayerRef player = event.getPlayerRef();});Entity Animation
Section titled “Entity Animation”Entities support animations through the model system:
// Default animation namesString deathAnim = Entity.DefaultAnimations.DEATH; // "Death"String hurtAnim = Entity.DefaultAnimations.HURT; // "Hurt"String despawnAnim = Entity.DefaultAnimations.DESPAWN; // "Despawn"
// Get hurt animations based on stateString[] hurtAnims = Entity.DefaultAnimations.getHurtAnimationIds( movementStates, damageCause);Entity Serialization
Section titled “Entity Serialization”Entities can be serialized for persistence:
// Entity has a CODEC for serializationBuilderCodec<Entity> codec = Entity.CODEC;
// Clone entity (uses serialization)Entity cloned = (Entity) entity.clone();
// Convert to holder for persistenceHolder<EntityStore> holder = entity.toHolder();Player Entity Special Cases
Section titled “Player Entity Special Cases”Player entities have special handling:
// Player is both an Entity and has PlayerRefPlayer playerEntity = store.getComponent(ref, Player.getComponentType());PlayerRef playerRef = store.getComponent(ref, PlayerRef.getComponentType());
// Access player-specific featuresMovementManager movement = store.getComponent(ref, MovementManager.getComponentType());CameraManager camera = store.getComponent(ref, CameraManager.getComponentType());ChunkTracker chunkTracker = playerRef.getChunkTracker();Entity Queries
Section titled “Entity Queries”Query entities by their components:
// Query all entities with specific componentsQuery<EntityStore> query = new AndQuery<>( TransformComponent.getComponentType(), HealthComponent.getComponentType());
// Use in systempublic class MySystem extends EntityTickingSystem<EntityStore> { @Override public Query<EntityStore> getQuery() { return new AndQuery<>(entityType, transformType); }
@Override public void tick(float dt, int index, ArchetypeChunk<EntityStore> chunk, Store<EntityStore> store, CommandBuffer<EntityStore> commandBuffer) { // Process matching entities via chunk.getComponent(index, componentType) }}Best Practices
Section titled “Best Practices”- Use ECS pattern: Access entity data through components, not direct entity fields
- Check validity: Always check
ref.isValid()before accessing - Run on correct thread: Entity operations must run on the world thread
- Handle removal: Check
wasRemoved()before operations on entity references - Use PlayerRef: For players, work with
PlayerRefrather thanPlayerentity when possible
Related
Section titled “Related”- ECS Overview - Entity Component System
- World System - World and entity store
- Event System - Entity events