This commit is contained in:
2026-01-20 20:33:59 +01:00
commit b16a40e431
583 changed files with 87339 additions and 0 deletions

View File

@@ -0,0 +1,828 @@
---
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 |