---
title: Entity Components
type: docs
weight: 2
---

Hytale uses an Entity Component System (ECS) where entities are composed of modular components. Each component adds specific functionality or data to an entity.

## Component Categories

{{< cards cols="3" >}}
  {{< card link="#transform--position" title="Transform & Position" subtitle="Location, rotation, collision" >}}
  {{< card link="#display--visual" title="Display & Visual" subtitle="Models, animations, effects" >}}
  {{< card link="#behavior-markers" title="Behavior Markers" subtitle="Interaction flags" >}}
  {{< card link="#physics" title="Physics" subtitle="Position data, collision" >}}
  {{< card link="#audio" title="Audio" subtitle="Movement sounds" >}}
  {{< card link="#custom-components" title="Custom Components" subtitle="Plugin-defined components" >}}
{{< /cards >}}

---

## Component Access Pattern

Before diving into specific components, understand how to access components in Hytale's ECS:

```java
// Get component type from the component class
ComponentType<EntityStore, TransformComponent> transformType =
    TransformComponent.getComponentType();

// Get Ref<EntityStore> from PlayerRef or other source
Ref<EntityStore> ref = playerRef.getReference();
if (ref == null || !ref.isValid()) {
    return;
}

// Get Store from Ref, then access component via Store
Store<EntityStore> store = ref.getStore();
TransformComponent transform = store.getComponent(ref, transformType);

// Check if entity has a component using Archetype
Archetype<EntityStore> archetype = store.getArchetype(ref);
boolean hasComponent = archetype.contains(transformType);
```

{{< callout type="warning" >}}
**Important:** `Ref<EntityStore>` does NOT have `getComponent()` or `hasComponent()` methods directly. You must get the `Store` first via `ref.getStore()`, then call `store.getComponent(ref, componentType)`.
{{< /callout >}}

{{< callout type="info" >}}
All entity components implement `Component<EntityStore>` and provide a static `getComponentType()` method to retrieve the `ComponentType` for component access.
{{< /callout >}}

---

## Transform & Position

### TransformComponent

Core component for entity position, rotation, and chunk reference.

**Package:** `com.hypixel.hytale.server.core.modules.entity.component`

{{< tabs items="Fields,Methods,Example" >}}
{{< tab >}}
| Field | Type | Description |
|-------|------|-------------|
| position | `Vector3d` | World position (x, y, z) |
| rotation | `Vector3f` | Rotation angles (x, y, z) |
| chunkRef | `Ref<ChunkStore>` | Reference to containing chunk |
{{< /tab >}}
{{< tab >}}
- `getPosition()` - Returns world position as Vector3d
- `setPosition(Vector3d)` - Sets world position (uses `assign()`)
- `getRotation()` - Returns rotation angles
- `setRotation(Vector3f)` - Sets rotation angles (uses `assign()`)
- `teleportPosition(Vector3d)` - Teleports entity to position
- `getTransform()` - Returns Transform object combining position/rotation
- `getChunkRef()` - Returns chunk reference (`Ref<ChunkStore>`)
- `getChunk()` - **Deprecated** - Returns WorldChunk directly

{{< callout type="warning" >}}
`getChunk()` is deprecated and marked for removal. Use `getChunkRef()` instead.
{{< /callout >}}
{{< /tab >}}
{{< tab >}}
```java
// Get store from ref
Store<EntityStore> store = ref.getStore();

ComponentType<EntityStore, TransformComponent> transformType =
    TransformComponent.getComponentType();
TransformComponent transform = store.getComponent(ref, transformType);

if (transform != null) {
    // Get current position
    Vector3d pos = transform.getPosition();
    getLogger().at(Level.INFO).log("Entity at: " + pos.x + ", " + pos.y + ", " + pos.z);

    // Get rotation
    Vector3f rot = transform.getRotation();

    // Get chunk reference (recommended)
    Ref<ChunkStore> chunkRef = transform.getChunkRef();
}
```
{{< /tab >}}
{{< /tabs >}}

---

### BoundingBox

Defines the collision bounds of an entity using a `Box` object.

**Package:** `com.hypixel.hytale.server.core.modules.entity.component`

{{< tabs items="Fields,Methods,Example" >}}
{{< tab >}}
| Field | Type | Description |
|-------|------|-------------|
| boundingBox | `Box` | The collision box with min/max corners |
| detailBoxes | `Map<String, DetailBox[]>` | Named detail boxes for precise collision |
{{< /tab >}}
{{< tab >}}
- `getBoundingBox()` - Returns the `Box` object
- `setBoundingBox(Box)` - Sets the bounding box
- `getDetailBoxes()` - Returns map of detail boxes (can be null)
{{< /tab >}}
{{< tab >}}
```java
ComponentType<EntityStore, BoundingBox> boundsType = BoundingBox.getComponentType();
BoundingBox bounds = store.getComponent(ref, boundsType);

// Access the Box object
Box box = bounds.getBoundingBox();

// Box provides min/max as Vector3d
Vector3d min = box.getMin();
Vector3d max = box.getMax();

// Box utility methods
double width = box.width();    // max.x - min.x
double height = box.height();  // max.y - min.y
double depth = box.depth();    // max.z - min.z

// Center point
double centerX = box.middleX();
double centerY = box.middleY();
double centerZ = box.middleZ();

// Check intersection with another box
Box otherBox = otherBounds.getBoundingBox();
if (box.isIntersecting(otherBox)) {
    handleCollision();
}

// Modify box (mutates in place)
box.offset(1.0, 0, 0);  // Move box by offset
box.scale(2.0f);         // Scale box

// Access detail boxes for precise collision
Map<String, DetailBox[]> details = bounds.getDetailBoxes();
if (details != null) {
    for (Map.Entry<String, DetailBox[]> entry : details.entrySet()) {
        // Process named detail boxes
    }
}
```
{{< /tab >}}
{{< /tabs >}}

#### The Box Class

The `Box` class (`com.hypixel.hytale.math.shape.Box`) is a fundamental shape class:

| Method | Description |
|--------|-------------|
| `width()` | Returns width (X axis) |
| `height()` | Returns height (Y axis) |
| `depth()` | Returns depth (Z axis) |
| `middleX/Y/Z()` | Returns center coordinates |
| `getVolume()` | Returns total volume |
| `isIntersecting(Box)` | Checks intersection with another box |
| `containsPosition(x,y,z)` | Checks if point is inside |
| `offset(x,y,z)` | Moves box by offset (mutates) |
| `scale(float)` | Scales box (mutates) |
| `union(Box)` | Expands to contain another box |
| `clone()` | Creates a copy |

---

### CollisionResultComponent

Stores collision detection results from the physics system.

**Package:** `com.hypixel.hytale.server.core.modules.entity.component`

{{< tabs items="Fields,Methods,Example" >}}
{{< tab >}}
| Field | Type | Description |
|-------|------|-------------|
| collisionResult | `CollisionResult` | Full collision computation result |
| collisionStartPosition | `Vector3d` | Position where collision started |
| collisionPositionOffset | `Vector3d` | Offset from collision |
| pendingCollisionCheck | `boolean` | Whether collision check is pending |
{{< /tab >}}
{{< tab >}}
- `getCollisionResult()` - Returns the `CollisionResult` object
- `isPendingCollisionCheck()` - Returns true if collision needs recomputation
{{< /tab >}}
{{< tab >}}
```java
ComponentType<EntityStore, CollisionResultComponent> collisionType =
    CollisionResultComponent.getComponentType();
CollisionResultComponent collision = store.getComponent(ref,collisionType);

// Get collision result object
CollisionResult result = collision.getCollisionResult();

// Check for block collisions
int blockCollisionCount = result.getBlockCollisionCount();
if (blockCollisionCount > 0) {
    BlockCollisionData firstCollision = result.getFirstBlockCollision();
    // Process collision
}

// Check if sliding (on ground)
if (result.isSliding) {
    // Entity is sliding on a surface
    double slideStart = result.slideStart;
    double slideEnd = result.slideEnd;
}

// Check character collisions (if enabled)
int charCollisionCount = result.getCharacterCollisionCount();
CharacterCollisionData charCollision = result.getFirstCharacterCollision();

// Access trigger blocks (collision triggers)
CollisionDataArray<BlockCollisionData> triggers = result.getTriggerBlocks();
```
{{< /tab >}}
{{< /tabs >}}

{{< callout type="info" >}}
The `CollisionResult` class is complex and handles block collisions, character collisions, slides, and trigger blocks. It's primarily used internally by the collision system.
{{< /callout >}}

---

### PositionDataComponent

Tracks block type IDs at entity's position.

**Package:** `com.hypixel.hytale.server.core.modules.entity.component`

{{< tabs items="Fields,Methods,Example" >}}
{{< tab >}}
| Field | Type | Description |
|-------|------|-------------|
| insideBlockTypeId | `int` | Block type ID entity is inside |
| standingOnBlockTypeId | `int` | Block type ID entity is standing on |
{{< /tab >}}
{{< tab >}}
- `getInsideBlockTypeId()` - Returns block type ID entity is inside
- `setInsideBlockTypeId(int)` - Sets inside block type ID
- `getStandingOnBlockTypeId()` - Returns block type ID beneath entity
- `setStandingOnBlockTypeId(int)` - Sets standing-on block type ID
{{< /tab >}}
{{< tab >}}
```java
ComponentType<EntityStore, PositionDataComponent> posDataType =
    PositionDataComponent.getComponentType();
PositionDataComponent posData = store.getComponent(ref,posDataType);

// Check what block entity is standing on
int standingOn = posData.getStandingOnBlockTypeId();

// Check what block entity is inside
int insideBlock = posData.getInsideBlockTypeId();

// Use block type registry to get actual BlockType
BlockType blockType = BlockType.getAssetMap().getAsset(standingOn);
if (blockType != null) {
    getLogger().at(Level.INFO).log("Standing on: " + blockType.getId());
}
```
{{< /tab >}}
{{< /tabs >}}

---

## Display & Visual

### DisplayNameComponent

Controls the display name shown above an entity.

**Package:** `com.hypixel.hytale.server.core.modules.entity.component`

{{< tabs items="Fields,Methods,Example" >}}
{{< tab >}}
| Field | Type | Description |
|-------|------|-------------|
| displayName | `Message` | The displayed name as a Message object |
{{< /tab >}}
{{< tab >}}
- `getDisplayName()` - Returns the `Message` display name
{{< /tab >}}
{{< tab >}}
```java
ComponentType<EntityStore, DisplayNameComponent> nameType =
    DisplayNameComponent.getComponentType();
DisplayNameComponent nameComp = store.getComponent(ref,nameType);

// Get current display name
Message name = nameComp.getDisplayName();

// Message is the formatted text object used throughout Hytale
// Use Message.raw() or Message formatting methods to create new names
```
{{< /tab >}}
{{< /tabs >}}

{{< callout type="info" >}}
**Message Type:** Display names use Hytale's `Message` class, not plain strings. The `Message` class supports formatted text, colors, and localization.
{{< /callout >}}

---

### ModelComponent

Links an entity to its visual 3D model.

**Package:** `com.hypixel.hytale.server.core.modules.entity.component`

{{< tabs items="Fields,Methods,Example" >}}
{{< tab >}}
| Field | Type | Description |
|-------|------|-------------|
| model | `Model` | Reference to the model |
| isNetworkOutdated | `boolean` | Network sync flag |
{{< /tab >}}
{{< tab >}}
- `getModel()` - Returns the Model
- `setModel(Model)` - Sets the model
{{< /tab >}}
{{< tab >}}
```java
ComponentType<EntityStore, ModelComponent> modelType = ModelComponent.getComponentType();
ModelComponent model = store.getComponent(ref,modelType);

// Get current model
Model currentModel = model.getModel();

// Set new model
model.setModel(newModel);
```
{{< /tab >}}
{{< /tabs >}}

---

### EntityScaleComponent

Controls the scale/size of an entity.

**Package:** `com.hypixel.hytale.server.core.modules.entity.component`

{{< tabs items="Fields,Methods,Example" >}}
{{< tab >}}
| Field | Type | Description |
|-------|------|-------------|
| scale | `float` | Uniform scale factor (default: 1.0) |
| isNetworkOutdated | `boolean` | Network sync flag |
{{< /tab >}}
{{< tab >}}
- `getScale()` - Returns the scale factor (float)
- `setScale(float)` - Sets the uniform scale factor
{{< /tab >}}
{{< tab >}}
```java
ComponentType<EntityStore, EntityScaleComponent> scaleType =
    EntityScaleComponent.getComponentType();
EntityScaleComponent scale = store.getComponent(ref,scaleType);

// Get current scale
float currentScale = scale.getScale();  // Default: 1.0

// Make entity twice as large
scale.setScale(2.0f);

// Make entity half size
scale.setScale(0.5f);

// Giant boss spawn effect - track growth in tick handler
private final Map<Ref<EntityStore>, Float> growingBosses = new ConcurrentHashMap<>();

public void startGrowBoss(Ref<EntityStore> bossRef) {
    EntityScaleComponent scale = store.getComponent(bossRef, scaleType);
    scale.setScale(0.1f);  // Start small
    growingBosses.put(bossRef, 0.1f);
}

// Call this from your tick handler (every 5 ticks)
public void onTick() {
    growingBosses.entrySet().removeIf(entry -> {
        Ref<EntityStore> bossRef = entry.getKey();
        float currentScale = entry.getValue();

        if (currentScale >= 1.0f) {
            return true;  // Remove from map
        }

        EntityScaleComponent scale = store.getComponent(bossRef, scaleType);
        if (scale != null) {
            float newScale = currentScale + 0.1f;
            scale.setScale(newScale);
            entry.setValue(newScale);
        }
        return false;  // Keep in map
    });
}
```
{{< /tab >}}
{{< /tabs >}}

{{< callout type="warning" >}}
**Uniform Scale Only:** Hytale's EntityScaleComponent uses a single `float` for uniform scaling on all axes, not per-axis Vector3f scaling.
{{< /callout >}}

---

### ActiveAnimationComponent

Manages currently playing animations per animation slot.

**Package:** `com.hypixel.hytale.server.core.modules.entity.component`

{{< tabs items="Fields,Methods,Example" >}}
{{< tab >}}
| Field | Type | Description |
|-------|------|-------------|
| activeAnimations | `String[]` | Animation names per slot |
| isNetworkOutdated | `boolean` | Network sync flag |
{{< /tab >}}
{{< tab >}}
- `getActiveAnimations()` - Returns array of animation names indexed by `AnimationSlot`
- `setPlayingAnimation(AnimationSlot, String)` - Sets animation for a specific slot
{{< /tab >}}
{{< tab >}}
```java
ComponentType<EntityStore, ActiveAnimationComponent> animType =
    ActiveAnimationComponent.getComponentType();
ActiveAnimationComponent anim = store.getComponent(ref,animType);

// Get all active animations
String[] animations = anim.getActiveAnimations();

// Set animation for specific slot
anim.setPlayingAnimation(AnimationSlot.Action, "attack_swing");
anim.setPlayingAnimation(AnimationSlot.Movement, "walk");

// Clear animation on a slot
anim.setPlayingAnimation(AnimationSlot.Emote, null);
```
{{< /tab >}}
{{< /tabs >}}

#### AnimationSlot Enum

Hytale uses animation slots to layer animations:

| Slot | Value | Purpose |
|------|-------|---------|
| `Movement` | 0 | Locomotion (walk, run, jump) |
| `Status` | 1 | Status effects |
| `Action` | 2 | Actions (attack, use item) |
| `Face` | 3 | Facial expressions |
| `Emote` | 4 | Social emotes |

---

### DynamicLight

Emits dynamic light from an entity using a `ColorLight` structure.

**Package:** `com.hypixel.hytale.server.core.modules.entity.component`

{{< tabs items="Fields,Methods,Example" >}}
{{< tab >}}
| Field | Type | Description |
|-------|------|-------------|
| colorLight | `ColorLight` | Light data (radius, RGB) |
| isNetworkOutdated | `boolean` | Network sync flag |
{{< /tab >}}
{{< tab >}}
- `getColorLight()` - Returns the `ColorLight` object
- `setColorLight(ColorLight)` - Sets the light configuration
{{< /tab >}}
{{< tab >}}
```java
ComponentType<EntityStore, DynamicLight> lightType = DynamicLight.getComponentType();
DynamicLight light = store.getComponent(ref,lightType);

// Get current light
ColorLight currentLight = light.getColorLight();

// Create new light configuration
// ColorLight has public fields: radius, red, green, blue (all bytes)
ColorLight torchLight = new ColorLight();
torchLight.radius = 8;      // Light radius
torchLight.red = (byte)255;   // Warm orange color
torchLight.green = (byte)200;
torchLight.blue = (byte)100;

light.setColorLight(torchLight);

// Or use constructor
ColorLight blueLight = new ColorLight(
    (byte)12,   // radius
    (byte)50,   // red
    (byte)100,  // green
    (byte)255   // blue
);
light.setColorLight(blueLight);
```
{{< /tab >}}
{{< /tabs >}}

#### ColorLight Structure

The `ColorLight` class (`com.hypixel.hytale.protocol.ColorLight`) has public fields:

| Field | Type | Description |
|-------|------|-------------|
| `radius` | `byte` | Light radius |
| `red` | `byte` | Red component (0-255) |
| `green` | `byte` | Green component (0-255) |
| `blue` | `byte` | Blue component (0-255) |

---

### HeadRotation

Controls head rotation independently from body.

**Package:** `com.hypixel.hytale.server.core.modules.entity.component`

{{< tabs items="Fields,Methods,Example" >}}
{{< tab >}}
| Field | Type | Description |
|-------|------|-------------|
| rotation | `Vector3f` | Head rotation (x, y, z) |
{{< /tab >}}
{{< tab >}}
- `getRotation()` - Returns head rotation as Vector3f
- `setRotation(Vector3f)` - Sets head rotation (uses `assign()`)
- `getDirection()` - Returns look direction as Vector3d
- `getAxisDirection()` - Returns axis-aligned direction as Vector3i
- `teleportRotation(Vector3f)` - Teleports head rotation
{{< /tab >}}
{{< tab >}}
```java
ComponentType<EntityStore, HeadRotation> headType = HeadRotation.getComponentType();
HeadRotation head = store.getComponent(ref,headType);

// Get current head rotation
Vector3f rot = head.getRotation();

// Set head rotation (pitch, yaw, roll)
head.setRotation(new Vector3f(-30, 45, 0));  // Look up-right

// Get look direction as normalized vector
Vector3d direction = head.getDirection();

// Get axis direction (discrete: -1, 0, or 1 per axis)
Vector3i axisDir = head.getAxisDirection();

// Teleport rotation (instant, no interpolation)
head.teleportRotation(new Vector3f(0, 180, 0));  // Face backward
```
{{< /tab >}}
{{< /tabs >}}

---

## Behavior Markers

Singleton components that act as flags modifying entity behavior. They use the singleton pattern with an `INSTANCE` field.

### Interactable

{{< badge "Singleton" >}}

Marks an entity as interactable by players.

```java
ComponentType<EntityStore, Interactable> type = Interactable.getComponentType();

// Check if entity has component using archetype
Store<EntityStore> store = ref.getStore();
Archetype<EntityStore> archetype = store.getArchetype(ref);
if (archetype.contains(type)) {
    // Entity is interactable
}

// Component is singleton - use INSTANCE
Interactable component = Interactable.INSTANCE;
```

---

### Invulnerable

{{< badge "Singleton" >}}

Makes an entity immune to damage.

```java
ComponentType<EntityStore, Invulnerable> type = Invulnerable.getComponentType();

// Check invulnerability in damage handler
getEventRegistry().register(EntityDamageEvent.class, event -> {
    Ref<EntityStore> targetRef = event.getTarget();
    if (targetRef != null && targetRef.isValid()) {
        Store<EntityStore> store = targetRef.getStore();
        Archetype<EntityStore> archetype = store.getArchetype(targetRef);
        if (archetype.contains(type)) {
            event.setCancelled(true);
        }
    }
});
```

---

### Intangible

{{< badge "Singleton" >}}

Makes an entity pass through other entities and blocks (no collision).

```java
ComponentType<EntityStore, Intangible> type = Intangible.getComponentType();

// Ghost entity - no collision
Store<EntityStore> store = ref.getStore();
Archetype<EntityStore> archetype = store.getArchetype(ref);
if (archetype.contains(type)) {
    // Entity passes through obstacles
}
```

---

## Audio

### MovementAudioComponent

Handles movement-related sounds with a predicate system.

**Package:** `com.hypixel.hytale.server.core.modules.entity.component`

{{< tabs items="Fields,Methods,Example" >}}
{{< tab >}}
| Field | Type | Description |
|-------|------|-------------|
| shouldHearPredicate | `ShouldHearPredicate` | Predicate for who hears sounds |
| lastInsideBlockTypeId | `int` | Last block entity was inside |
| nextMoveInRepeat | `float` | Timer for movement sound repeat |
{{< /tab >}}
{{< tab >}}
- `getShouldHearPredicate(Ref<EntityStore>)` - Returns predicate for sound hearing
- `getLastInsideBlockTypeId()` - Returns last inside block ID
- `setLastInsideBlockTypeId(int)` - Sets last inside block ID
- `canMoveInRepeat()` - Returns true if repeat timer is active
- `tickMoveInRepeat(float)` - Advances repeat timer, returns true if elapsed
- `setNextMoveInRepeat(float)` - Sets next repeat interval
{{< /tab >}}
{{< tab >}}
```java
ComponentType<EntityStore, MovementAudioComponent> audioType =
    MovementAudioComponent.getComponentType();
MovementAudioComponent movementAudio = store.getComponent(ref,audioType);

// Get predicate for who should hear movement sounds
MovementAudioComponent.ShouldHearPredicate predicate =
    movementAudio.getShouldHearPredicate(entityRef);

// The predicate returns true for entities that should hear the sound
// (excludes the owner by default)
boolean shouldHear = predicate.test(otherEntityRef);

// Check move-in repeat timer
if (movementAudio.canMoveInRepeat()) {
    float dt = 1.0f / 20.0f;  // Delta time
    if (movementAudio.tickMoveInRepeat(dt)) {
        // Timer elapsed, play repeat sound
    }
}

// Disable repeat sounds
movementAudio.setNextMoveInRepeat(MovementAudioComponent.NO_REPEAT);
```
{{< /tab >}}
{{< /tabs >}}

---

## Custom Components

### Creating Custom Components

Create custom components by implementing `Component<EntityStore>`:

```java
public class CustomDataComponent implements Component<EntityStore> {
    // Static component type reference (set during registration)
    private static ComponentType<EntityStore, CustomDataComponent> TYPE;

    // Component data
    private int level = 1;
    private String faction = "neutral";

    public static ComponentType<EntityStore, CustomDataComponent> getComponentType() {
        return TYPE;
    }

    public int getLevel() { return level; }
    public void setLevel(int level) { this.level = level; }

    public String getFaction() { return faction; }
    public void setFaction(String faction) { this.faction = faction; }

    @Override
    @Nonnull
    public Component<EntityStore> clone() {
        CustomDataComponent copy = new CustomDataComponent();
        copy.level = this.level;
        copy.faction = this.faction;
        return copy;
    }
}
```

### Registering Components

Register components during plugin start:

```java
@Override
public void start() {
    // Register with EntityStoreRegistry
    ComponentType<EntityStore, CustomDataComponent> type =
        getEntityStoreRegistry().register(
            "custom_data",
            CustomDataComponent.class,
            CustomDataComponent::new
        );

    // Store type reference for static access
    CustomDataComponent.TYPE = type;
}
```

### Using Custom Components

```java
// Get component type
ComponentType<EntityStore, CustomDataComponent> type =
    CustomDataComponent.getComponentType();

// Get store from ref
Store<EntityStore> store = ref.getStore();

// Check if entity has component
Archetype<EntityStore> archetype = store.getArchetype(ref);
if (archetype.contains(type)) {
    CustomDataComponent data = store.getComponent(ref, type);

    if (data.getLevel() > 10) {
        // High level entity logic
    }
}
```

---

## Best Practices

{{< callout type="info" >}}
**Component Guidelines:**
- Use `getComponentType()` static method to get the `ComponentType` for access
- Always check if a component exists using `hasComponent()` before accessing
- Register custom components in `start()`, after all plugins have completed setup
- Implement `clone()` for components that need copying
- Use singleton pattern (static `INSTANCE`) for marker components
{{< /callout >}}

{{< callout type="warning" >}}
**Network Sync:** Many components have an `isNetworkOutdated` flag. This is managed automatically by the network system - avoid setting it manually unless you understand the networking layer.
{{< /callout >}}

{{< callout type="error" >}}
**Thread Safety:** Component access should be done on the world's ticking thread. Use `world.isInThread()` to verify, or use the task system for cross-thread operations.
{{< /callout >}}

---

## Component Type Reference

| Component | Package | Type | Purpose |
|-----------|---------|------|---------|
| TransformComponent | entity.component | Data | Position, rotation, chunk |
| BoundingBox | entity.component | Data | Collision bounds |
| CollisionResultComponent | entity.component | Data | Collision results |
| PositionDataComponent | entity.component | Data | Block context |
| DisplayNameComponent | entity.component | Data | Visible name |
| ModelComponent | entity.component | Data | 3D model |
| EntityScaleComponent | entity.component | Data | Size scaling |
| ActiveAnimationComponent | entity.component | Data | Animations |
| DynamicLight | entity.component | Data | Light emission |
| HeadRotation | entity.component | Data | Head direction |
| MovementAudioComponent | entity.component | Data | Movement sounds |
| Interactable | entity.component | Singleton | Can be interacted |
| Invulnerable | entity.component | Singleton | Cannot be damaged |
| Intangible | entity.component | Singleton | No collision |
