Init
This commit is contained in:
259
content/world/entities/entity-hierarchy.en.md
Normal file
259
content/world/entities/entity-hierarchy.en.md
Normal file
@@ -0,0 +1,259 @@
|
||||
---
|
||||
title: Entity Hierarchy
|
||||
type: docs
|
||||
weight: 1
|
||||
---
|
||||
|
||||
Hytale uses an **Entity Component System (ECS)** architecture. Unlike traditional OOP where entities have methods directly on them, Hytale entities are composed of components stored in an `EntityStore`.
|
||||
|
||||
{{< callout type="warning" >}}
|
||||
**ECS Architecture:** Entity classes like `Player` and `LivingEntity` are themselves `Component<EntityStore>` instances. Data is accessed through component lookup, not direct method calls on entities.
|
||||
{{< /callout >}}
|
||||
|
||||
## Class Hierarchy Overview
|
||||
|
||||
{{< filetree/container >}}
|
||||
{{< filetree/folder name="Entity (Component)" state="open" >}}
|
||||
{{< filetree/folder name="LivingEntity" state="open" >}}
|
||||
{{< filetree/file name="Player" >}}
|
||||
{{< /filetree/folder >}}
|
||||
{{< /filetree/folder >}}
|
||||
{{< /filetree/container >}}
|
||||
|
||||
---
|
||||
|
||||
## Entity (Base Class)
|
||||
|
||||
**Package:** `com.hypixel.hytale.server.core.entity`
|
||||
|
||||
The base class for all entities. `Entity` implements `Component<EntityStore>` - it is stored as a component in the ECS system.
|
||||
|
||||
### Available Methods
|
||||
|
||||
| Method | Return Type | Description | Notes |
|
||||
|--------|-------------|-------------|-------|
|
||||
| `getWorld()` | `World` | The world this entity is in | |
|
||||
| `getUuid()` | `UUID` | Unique identifier | Deprecated |
|
||||
| `wasRemoved()` | `boolean` | Whether entity was removed | |
|
||||
| `remove()` | `boolean` | Remove entity from world | |
|
||||
| `getNetworkId()` | `int` | Network ID for this entity | Deprecated |
|
||||
| `getTransformComponent()` | `TransformComponent` | Position/rotation data | Deprecated |
|
||||
| `getReference()` | `Ref<EntityStore>` | ECS reference | |
|
||||
|
||||
```java
|
||||
// Example: Accessing entity data
|
||||
Entity entity = ...; // obtained from event or lookup
|
||||
|
||||
if (!entity.wasRemoved()) {
|
||||
World world = entity.getWorld();
|
||||
|
||||
// Position access (deprecated but works)
|
||||
TransformComponent transform = entity.getTransformComponent();
|
||||
Vector3d position = transform.getPosition();
|
||||
|
||||
// ECS reference for component access
|
||||
Ref<EntityStore> ref = entity.getReference();
|
||||
if (ref != null && ref.isValid()) {
|
||||
Store<EntityStore> store = ref.getStore();
|
||||
// Access other components via store
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## LivingEntity
|
||||
|
||||
**Package:** `com.hypixel.hytale.server.core.entity`
|
||||
|
||||
Extends Entity with inventory capabilities. Base class for entities that can hold items.
|
||||
|
||||
### Available Methods
|
||||
|
||||
| Method | Return Type | Description |
|
||||
|--------|-------------|-------------|
|
||||
| `getInventory()` | `Inventory` | Entity's inventory |
|
||||
| `setInventory(Inventory)` | `Inventory` | Set inventory |
|
||||
| `getCurrentFallDistance()` | `double` | Current fall distance |
|
||||
| `getStatModifiersManager()` | `StatModifiersManager` | Stat modifiers |
|
||||
|
||||
```java
|
||||
LivingEntity living = (LivingEntity) entity;
|
||||
|
||||
// Inventory access
|
||||
Inventory inventory = living.getInventory();
|
||||
|
||||
// Fall distance tracking
|
||||
double fallDistance = living.getCurrentFallDistance();
|
||||
|
||||
// Stat modifiers
|
||||
StatModifiersManager stats = living.getStatModifiersManager();
|
||||
```
|
||||
|
||||
{{< callout type="info" >}}
|
||||
Health, damage, and effects are managed through the ECS system, not directly on LivingEntity. See [Entity Components]({{< relref "entity-components" >}}) for component-based data access.
|
||||
{{< /callout >}}
|
||||
|
||||
---
|
||||
|
||||
## Player
|
||||
|
||||
**Package:** `com.hypixel.hytale.server.core.entity.entities`
|
||||
|
||||
Extends LivingEntity with player-specific features.
|
||||
|
||||
### Available Methods
|
||||
|
||||
| Method | Return Type | Description |
|
||||
|--------|-------------|-------------|
|
||||
| `sendMessage(Message)` | `void` | Send message to player |
|
||||
| `hasPermission(String)` | `boolean` | Check permission |
|
||||
| `hasPermission(String, boolean)` | `boolean` | Check with default |
|
||||
| `getDisplayName()` | `String` | Player display name |
|
||||
| `getGameMode()` | `GameMode` | Current game mode |
|
||||
| `getInventory()` | `Inventory` | Player inventory |
|
||||
| `getPlayerRef()` | `PlayerRef` | Thread-safe reference (deprecated) |
|
||||
| `getWindowManager()` | `WindowManager` | Window management |
|
||||
| `getPageManager()` | `PageManager` | Page management |
|
||||
| `getHudManager()` | `HudManager` | HUD management |
|
||||
| `getHotbarManager()` | `HotbarManager` | Hotbar management |
|
||||
|
||||
```java
|
||||
Player player = event.getPlayer();
|
||||
|
||||
if (player != null) {
|
||||
// Send messages (requires Message object)
|
||||
player.sendMessage(Message.raw("Welcome!"));
|
||||
player.sendMessage(Message.translation("greeting.key")
|
||||
.param("name", player.getDisplayName()));
|
||||
|
||||
// Check permissions
|
||||
if (player.hasPermission("admin.teleport")) {
|
||||
// Has permission
|
||||
}
|
||||
|
||||
// Get display name
|
||||
String name = player.getDisplayName();
|
||||
|
||||
// Get inventory
|
||||
Inventory inventory = player.getInventory();
|
||||
|
||||
// Get position via TransformComponent (deprecated)
|
||||
TransformComponent transform = player.getTransformComponent();
|
||||
Vector3d position = transform.getPosition();
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## PlayerRef (Thread-Safe Reference)
|
||||
|
||||
**Package:** `com.hypixel.hytale.server.core.universe`
|
||||
|
||||
`PlayerRef` provides thread-safe access to player data. Use it for async operations or storing references.
|
||||
|
||||
### Available Methods
|
||||
|
||||
| Method | Return Type | Description |
|
||||
|--------|-------------|-------------|
|
||||
| `getUsername()` | `String` | Player username |
|
||||
| `getUuid()` | `UUID` | Player UUID |
|
||||
| `getWorldUuid()` | `UUID` | Current world UUID |
|
||||
| `sendMessage(Message)` | `void` | Send message |
|
||||
| `getReference()` | `Ref<EntityStore>` | ECS reference (may be null) |
|
||||
| `getPacketHandler()` | `PacketHandler` | Network handler |
|
||||
|
||||
```java
|
||||
// Get PlayerRef from event
|
||||
PlayerRef playerRef = event.getPlayerRef();
|
||||
|
||||
// Thread-safe access to player data
|
||||
String username = playerRef.getUsername();
|
||||
UUID uuid = playerRef.getUuid();
|
||||
|
||||
// Send message (thread-safe)
|
||||
playerRef.sendMessage(Message.raw("Hello, " + username + "!"));
|
||||
|
||||
// Get ECS reference for component access
|
||||
Ref<EntityStore> ref = playerRef.getReference();
|
||||
if (ref != null && ref.isValid()) {
|
||||
Store<EntityStore> store = ref.getStore();
|
||||
|
||||
// Access Player component
|
||||
Player player = store.getComponent(ref, Player.getComponentType());
|
||||
|
||||
// Access TransformComponent for position
|
||||
TransformComponent transform = store.getComponent(ref, TransformComponent.getComponentType());
|
||||
if (transform != null) {
|
||||
Vector3d position = transform.getPosition();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ECS Component Access Pattern
|
||||
|
||||
The correct way to access entity data in Hytale's ECS:
|
||||
|
||||
```java
|
||||
getEventRegistry().register(PlayerConnectEvent.class, event -> {
|
||||
PlayerRef playerRef = event.getPlayerRef();
|
||||
|
||||
// Get ECS reference
|
||||
Ref<EntityStore> ref = playerRef.getReference();
|
||||
if (ref == null || !ref.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get store for component access
|
||||
Store<EntityStore> store = ref.getStore();
|
||||
|
||||
// Access various components
|
||||
Player player = store.getComponent(ref, Player.getComponentType());
|
||||
TransformComponent transform = store.getComponent(ref, TransformComponent.getComponentType());
|
||||
|
||||
if (player != null && transform != null) {
|
||||
Vector3d position = transform.getPosition();
|
||||
player.sendMessage(Message.raw("You are at: " + position.toString()));
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Type Checking & Casting
|
||||
|
||||
Use pattern matching for safe type checking:
|
||||
|
||||
```java
|
||||
public void handleEntity(Entity entity) {
|
||||
if (entity instanceof Player player) {
|
||||
player.sendMessage(Message.raw("You're a player!"));
|
||||
|
||||
} else if (entity instanceof LivingEntity living) {
|
||||
Inventory inv = living.getInventory();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Best Practices
|
||||
|
||||
{{< callout type="info" >}}
|
||||
**Entity Handling Guidelines:**
|
||||
- Always check `wasRemoved()` before using stored entity references
|
||||
- Use `PlayerRef` for storing player references across ticks
|
||||
- Access position via `TransformComponent` (deprecated methods work but ECS is preferred)
|
||||
- Check `ref.isValid()` before accessing ECS components
|
||||
{{< /callout >}}
|
||||
|
||||
{{< callout type="warning" >}}
|
||||
**Thread Safety:** Entity objects are not thread-safe. Use `PlayerRef` for async operations. Never store direct entity references in long-lived data structures without proper cleanup.
|
||||
{{< /callout >}}
|
||||
|
||||
{{< callout type="error" >}}
|
||||
**Critical:** Never store `Entity` or `Player` references in static fields or maps without proper cleanup. Use UUIDs and look up entities when needed.
|
||||
{{< /callout >}}
|
||||
|
||||
Reference in New Issue
Block a user