6 min

Component System (ECS)

Hytale uses an Entity-Component-System architecture. Learn how to read and modify entity components safely.

ECS Overview

In Hytale, entities (players, mobs, items) are composed of Componentsthat store data. Components are accessed through a Store system usingReferences.

conceptdescription
EntityA game object (Player, Creature, Item)
ComponentData attached to an entity (Model, Transform, Health)
StoreContainer that holds all components of a type
Reference (Ref)A handle to access an entity's components

Raw API (Verbose)

The native API for component access is verbose:

1// Getting a component - verbose way
2Ref ref = player.getReference();
3Store store = ref.getStore();
4ComponentType type = ModelComponent.getComponentType();
5ModelComponent model = store.getComponent(ref, type);
6
7// Setting a component - also verbose
8store.putComponent(ref, type, newModelComponent);
remember
All component modifications must run inside world.execute()!

Common Components

componentpurposenotes
ModelComponentEntity appearancemodel, scale, visibility
TransformComponentPosition/rotationgetPosition() returns Vector3d
MovementStatesComponentMovement statenot MovementComponent
VelocityPhysics velocityin physics module
inventory & health
Inventory is accessed via player.getInventory() directly, not as a component. Health handling varies - check LivingEntity methods.

Working with Components

Reading Components

1private void inspectPlayer(Player player) {
2 // Get the reference
3 Ref ref = player.getReference();
4 Store store = ref.getStore();
5
6 // Get transform component
7 TransformComponent transform = store.getComponent(
8 ref,
9 TransformComponent.getComponentType()
10 );
11
12 if (transform != null) {
13 Vector3d pos = transform.getPosition();
14 getLogger().at(Level.INFO).log("Player at: %f, %f, %f", pos.x, pos.y, pos.z);
15 }
16}

Modifying Components

1private void changePlayerModel(Player player, String modelName) {
2 World world = player.getWorld();
3
4 // MUST be in world.execute()
5 world.execute(() -> {
6 Ref ref = player.getReference();
7 Store store = ref.getStore();
8
9 // Get model asset
10 ModelAsset asset = ModelAsset.getAssetMap().getAsset(modelName);
11 Model model = Model.createUnitScaleModel(asset);
12
13 // Create and set new component
14 ModelComponent component = new ModelComponent(model);
15 store.putComponent(
16 ref,
17 ModelComponent.getComponentType(),
18 component
19 );
20 });
21}

Helper Pattern

Create utility methods to reduce boilerplate:

ComponentHelper.javajava
1public class ComponentHelper {
2
3 public static T getComponent(Entity entity, Class componentClass) {
4 Ref ref = entity.getReference();
5 Store store = ref.getStore();
6
7 // Use reflection or a map to get ComponentType
8 ComponentType type = getComponentType(componentClass);
9 return store.getComponent(ref, type);
10 }
11
12 public static void setComponent(Entity entity, T component) {
13 Ref ref = entity.getReference();
14 Store store = ref.getStore();
15
16 ComponentType type = getComponentType(component.getClass());
17 store.putComponent(ref, type, component);
18 }
19
20 // Usage:
21 // ModelComponent model = ComponentHelper.getComponent(player, ModelComponent.class);
22 // ComponentHelper.setComponent(player, newModelComponent);
23}

Discovering Components

Find available components in the server JAR:

1# List all component classes
2jar tf HytaleServer.jar | grep -i "component"
3
4# Inspect a specific component
5javap -public -cp HytaleServer.jar \
6 com.hypixel.hytale.server.core.entity.component.ModelComponent

Best Practices

do
Cache ComponentType references instead of calling getComponentType() repeatedly.
do
Check for null before using components - entities might not have all components.
avoid
Never store References long-term - they can become invalid after entity respawn.