---
title: Player API
type: docs
weight: 4
---

The Player class provides extensive APIs for player management, including communication, health, inventory, permissions, and more.

## API Overview

{{< cards cols="3" >}}
  {{< card link="#identity--connection" title="Identity & Connection" subtitle="Name, UUID, network" >}}
  {{< card link="#communication" title="Communication" subtitle="Messages, titles, sounds" >}}
  {{< card link="#health--combat" title="Health & Combat" subtitle="HP, damage, effects" >}}
  {{< card link="#inventory-api" title="Inventory" subtitle="Items, slots, armor" >}}
  {{< card link="#permissions" title="Permissions" subtitle="Access control" >}}
  {{< card link="#movement--teleportation" title="Movement" subtitle="Teleport, position" >}}
{{< /cards >}}

---

## Identity & Connection

### Basic Information

{{< tabs items="Methods,Example" >}}
{{< tab >}}

| Method | Return Type | Description |
|--------|-------------|-------------|
| `getUuid()` | `UUID` | Unique player identifier |
| `getDisplayName()` | `String` | Display name (from PlayerRef username) |
| `getClientViewRadius()` | `int` | Player's view radius in chunks |
| `getViewRadius()` | `int` | Effective view radius (min of client and server) |
| `hasPermission(String)` | `boolean` | Check permission |
| `sendMessage(Message)` | `void` | Send message to player |
| `getInventory()` | `Inventory` | Player's inventory |
| `getGameMode()` | `GameMode` | Current game mode |

{{< /tab >}}
{{< tab >}}

```java
// Get entity reference from command context
Ref<EntityStore> ref = context.senderAsPlayerRef();

// Access Player component via ref.getStore()
Player player = ref.getStore().getComponent(ref, Player.getComponentType());

UUID uuid = player.getUuid();
String displayName = player.getDisplayName();
int viewRadius = player.getViewRadius();
GameMode mode = player.getGameMode();

// Check permission
if (player.hasPermission("myplugin.admin")) {
    player.sendMessage(Message.raw("You are an admin!"));
}

// Get PlayerRef for more info
PlayerRef playerRef = ref.getStore().getComponent(ref, PlayerRef.getComponentType());
String username = playerRef.getUsername();
String language = playerRef.getLanguage();
```

{{< /tab >}}
{{< /tabs >}}

### PlayerRef (Thread-Safe Reference)

{{< callout type="info" >}}
**Important:** `PlayerRef` is a component that provides thread-safe access to player data. It's stored in the entity component system and manages the player's connection, position, and various managers.
{{< /callout >}}

{{< tabs items="Methods,Entity Reference,Connection & Messaging,Server Transfer" >}}
{{< tab >}}

| Method | Return Type | Description |
|--------|-------------|-------------|
| `getUuid()` | `UUID` | Player's unique identifier |
| `getUsername()` | `String` | Player's username |
| `getLanguage()` | `String` | Player's language setting |
| `setLanguage(String)` | `void` | Update language |
| `getReference()` | `Ref<EntityStore>` | Entity reference (null if not in world) |
| `getHolder()` | `Holder<EntityStore>` | Entity holder (when not in store) |
| `isValid()` | `boolean` | Whether reference or holder exists |
| `getTransform()` | `Transform` | Current position and rotation |
| `getHeadRotation()` | `Vector3f` | Head rotation |
| `getPacketHandler()` | `PacketHandler` | Network handler |
| `getChunkTracker()` | `ChunkTracker` | Chunk loading tracker |
| `getHiddenPlayersManager()` | `HiddenPlayersManager` | Player visibility manager |

{{< /tab >}}
{{< tab >}}

```java
// Get entity reference from command context
Ref<EntityStore> ref = context.senderAsPlayerRef();

// Get PlayerRef via ref.getStore()
PlayerRef playerRef = ref.getStore().getComponent(ref, PlayerRef.getComponentType());

// Check if player is valid
if (playerRef != null && playerRef.isValid()) {
    UUID uuid = playerRef.getUuid();
    String username = playerRef.getUsername();

    // Get entity reference
    Ref<EntityStore> entityRef = playerRef.getReference();
    if (entityRef != null) {
        // Player is in a world - access via entityRef.getStore()
        Player player = entityRef.getStore().getComponent(entityRef, Player.getComponentType());
    }
}

// Get component from PlayerRef (convenience method)
Player playerComponent = playerRef.getComponent(Player.getComponentType());
```

{{< /tab >}}
{{< tab >}}

```java
// Send message to player
playerRef.sendMessage(Message.translation("welcome.message"));

// Get packet handler for more advanced operations
PacketHandler handler = playerRef.getPacketHandler();

// Get player position info
Transform transform = playerRef.getTransform();
Vector3d position = transform.getPosition();
Vector3f rotation = transform.getRotation();
Vector3f headRotation = playerRef.getHeadRotation();

// Update position (called internally by systems)
playerRef.updatePosition(world, transform, headRotation);
```

{{< /tab >}}
{{< tab >}}

```java
// Transfer player to another server (for server networks)
playerRef.referToServer("play.example.com", 25565);

// With custom data payload
byte[] referralData = serializePlayerData(playerRef);
playerRef.referToServer("play.example.com", 25565, referralData);

// Note: Max referral data size is 4096 bytes
```

{{< /tab >}}
{{< /tabs >}}

---

## Communication

### Sending Messages

{{< tabs items="Chat Messages,Translation Messages,Notifications" >}}
{{< tab >}}

```java
// Get entity reference from command context
Ref<EntityStore> ref = context.senderAsPlayerRef();

// Send chat message via PlayerRef
PlayerRef playerRef = ref.getStore().getComponent(ref, PlayerRef.getComponentType());

// Simple message
playerRef.sendMessage(Message.raw("Hello, World!"));

// Raw message
playerRef.sendMessage(Message.raw("Plain text message"));

// Using Message interface (IMessageReceiver)
Player player = ref.getStore().getComponent(ref, Player.getComponentType());
player.sendMessage(Message.raw("Message via Player interface"));
```

{{< /tab >}}
{{< tab >}}

```java
// Using translation keys
playerRef.sendMessage(Message.translation("welcome.message"));

// With parameters
playerRef.sendMessage(
    Message.translation("greeting.message")
        .param("name", playerRef.getUsername())
);

// With color
playerRef.sendMessage(
    Message.translation("server.warning")
        .color("#ff5555")
);
```

{{< /tab >}}
{{< tab >}}

```java
// Hytale uses Notifications instead of titles/action bars
PacketHandler handler = playerRef.getPacketHandler();

// Simple notification
NotificationUtil.sendNotification(handler, "Welcome to the server!");

// Notification with style
NotificationUtil.sendNotification(handler,
    Message.raw("Achievement Unlocked!"),
    NotificationStyle.Default
);

// With secondary message
NotificationUtil.sendNotification(handler,
    Message.raw("Quest Complete"),
    Message.raw("You earned 100 XP"),
    NotificationStyle.Default
);

// With icon
NotificationUtil.sendNotification(handler,
    Message.raw("New Item"),
    "icon_name",
    NotificationStyle.Default
);

// With item display
NotificationUtil.sendNotification(handler,
    Message.raw("You received:"),
    Message.raw("Diamond x10"),
    itemWithMetadata,
    NotificationStyle.Default
);

// Send to all players in universe
NotificationUtil.sendNotificationToUniverse(
    Message.raw("Server restarting in 5 minutes!")
);
```

{{< /tab >}}
{{< /tabs >}}

### Playing Sounds

```java
// Play 3D sound to player
SoundUtil.playSoundEvent3dToPlayer(
    playerRef,
    TempAssetIdUtil.getSoundEventIndex("SFX_UI_Notification"),
    SoundCategory.UI,
    position,
    componentAccessor
);

// Play 2D sound (no position)
SoundUtil.playSoundEvent2d(
    ref,
    TempAssetIdUtil.getSoundEventIndex("SFX_Player_Pickup_Item"),
    SoundCategory.UI,
    componentAccessor
);

// Play sound via world
world.playSound(soundEvent, position, volume, pitch);
```

---

## Health & Stats

{{< callout type="info" >}}
Hytale uses an **EntityStats system** for managing health and other stats. Stats are managed via `EntityStatComponent` and include Health, Oxygen, Stamina, Mana, SignatureEnergy, and Ammo.
{{< /callout >}}

### Entity Stats System

{{< tabs items="Available Stats,Accessing Stats,Modifying Stats" >}}
{{< tab >}}

| Stat | Description |
|------|-------------|
| `Health` | Entity health points |
| `Oxygen` | Breath/oxygen level |
| `Stamina` | Physical stamina |
| `Mana` | Magical energy |
| `SignatureEnergy` | Special ability energy |
| `Ammo` | Ammunition count |

These stats are defined via asset configuration and indexed at runtime.

```java
// Get stat indices (from DefaultEntityStatTypes)
int healthIndex = DefaultEntityStatTypes.getHealth();
int staminaIndex = DefaultEntityStatTypes.getStamina();
int manaIndex = DefaultEntityStatTypes.getMana();
```

{{< /tab >}}
{{< tab >}}

```java
// Get entity reference from command context
Ref<EntityStore> ref = context.senderAsPlayerRef();

// Get EntityStatComponent from entity via ref.getStore()
EntityStatComponent statsComponent = ref.getStore().getComponent(
    ref,
    EntityStatComponent.getComponentType()
);

// Get specific stat value
int healthIndex = DefaultEntityStatTypes.getHealth();
float currentHealth = statsComponent.getValue(healthIndex);
float maxHealth = statsComponent.getMaxValue(healthIndex);

// Check percentage
float healthPercent = currentHealth / maxHealth;
```

{{< /tab >}}
{{< tab >}}

```java
// Modify stat values through the stats system
// Stats are typically modified through the EntityStatsModule
// and related systems (DamageSystems, HealSystems, etc.)

// Example: Apply damage via component
// The DamageSystems handle damage application
ref.getStore().putComponent(ref, Damage.getComponentType(),
    new Damage(damageAmount, damageSource));
```

{{< /tab >}}
{{< /tabs >}}

### Invulnerability

```java
// Get entity reference from command context
Ref<EntityStore> ref = context.senderAsPlayerRef();

// Make player invulnerable (adds Invulnerable component)
ref.getStore().putComponent(ref, Invulnerable.getComponentType(), Invulnerable.INSTANCE);

// Remove invulnerability
ref.getStore().tryRemoveComponent(ref, Invulnerable.getComponentType());

// Check invulnerability
boolean isInvulnerable = ref.getStore().getArchetype(ref)
    .contains(Invulnerable.getComponentType());

// Note: Creative mode automatically sets Invulnerable
```

### Spawn Protection

```java
// Get entity reference from command context
Ref<EntityStore> ref = context.senderAsPlayerRef();

// Players have temporary invulnerability after spawning
Player player = ref.getStore().getComponent(ref, Player.getComponentType());

// Check if player has spawn protection (3 seconds after spawn)
if (player.hasSpawnProtection()) {
    // Player is temporarily invulnerable
}

// Check if waiting for client ready
if (player.isWaitingForClientReady()) {
    // Player hasn't finished loading yet
}
```

---

## Inventory API

### Basic Inventory Operations

{{< tabs items="Get Items,Set Items,Utility Methods" >}}
{{< tab >}}
```java
// Get inventory
PlayerInventory inventory = player.getInventory();

// Get item in hand
ItemStack heldItem = player.getHeldItem();
ItemStack mainHand = player.getMainHandItem();
ItemStack offHand = player.getOffHandItem();

// Get specific slot
ItemStack slot5 = inventory.getItem(5);

// Get armor
ArmorInventory armor = player.getArmor();
ItemStack helmet = armor.getHelmet();
ItemStack chestplate = armor.getChestplate();
ItemStack leggings = armor.getLeggings();
ItemStack boots = armor.getBoots();
```
{{< /tab >}}
{{< tab >}}
```java
// Set held item
ItemStack sword = new ItemStack(ItemTypes.DIAMOND_SWORD);
player.setHeldItem(sword);

// Set specific slot
inventory.setItem(0, new ItemStack(ItemTypes.APPLE, 64));

// Set armor
armor.setHelmet(new ItemStack(ItemTypes.DIAMOND_HELMET));
armor.setChestplate(new ItemStack(ItemTypes.DIAMOND_CHESTPLATE));
armor.setLeggings(new ItemStack(ItemTypes.DIAMOND_LEGGINGS));
armor.setBoots(new ItemStack(ItemTypes.DIAMOND_BOOTS));

// Clear slot
inventory.setItem(5, null);
```
{{< /tab >}}
{{< tab >}}
```java
// Give item (finds empty slot)
ItemStack diamond = new ItemStack(ItemTypes.DIAMOND, 64);
boolean success = player.giveItem(diamond);

if (!success) {
    // Inventory full, drop at feet
    player.dropItem(diamond);
}

// Check for item
if (inventory.contains(ItemTypes.DIAMOND)) {
    getLogger().at(Level.INFO).log("Player has diamonds");
}

// Remove item
inventory.remove(ItemTypes.DIAMOND, 10);

// Clear inventory
inventory.clear();

// Count items
int diamondCount = inventory.countItem(ItemTypes.DIAMOND);
```
{{< /tab >}}
{{< /tabs >}}

### Advanced Inventory

```java
// Open another inventory (chest, custom UI)
Inventory chest = world.getBlockEntity(chestPos).getInventory();
player.openInventory(chest);

// Create custom inventory
Inventory customInv = new Inventory(27, "Shop");  // 27 slots
customInv.setItem(13, new ItemStack(ItemTypes.DIAMOND, 1));
player.openInventory(customInv);

// Close open inventory
player.closeInventory();

// Get cursor item (what player is holding with mouse)
ItemStack cursor = player.getCursorItem();
player.setCursorItem(null);
```

---

## Permissions

### Permission Checking

{{< tabs items="Basic Checks,Permission Levels,Custom Permissions" >}}
{{< tab >}}
```java
// Check single permission
if (player.hasPermission("myplugin.admin")) {
    player.sendMessage("You are an admin!");
}

// Check operator status
if (player.isOp()) {
    player.sendMessage("You are an operator!");
}

// Multiple permission check
if (player.hasPermission("myplugin.fly") ||
    player.hasPermission("myplugin.admin")) {
    enableFlight(player);
}
```
{{< /tab >}}
{{< tab >}}
```java
// Permission hierarchy example
public boolean hasMinimumRank(Player player, String rank) {
    switch (rank) {
        case "owner":
            return player.hasPermission("rank.owner");
        case "admin":
            return player.hasPermission("rank.admin") ||
                   player.hasPermission("rank.owner");
        case "mod":
            return player.hasPermission("rank.mod") ||
                   player.hasPermission("rank.admin") ||
                   player.hasPermission("rank.owner");
        default:
            return true;
    }
}
```
{{< /tab >}}
{{< tab >}}
```java
// Grant permission
player.addPermission("myplugin.vip");

// Revoke permission
player.removePermission("myplugin.vip");

// Get all permissions
Set<String> permissions = player.getPermissions();
for (String perm : permissions) {
    getLogger().at(Level.INFO).log("Has permission: " + perm);
}

// Set operator status
player.setOp(true);
```
{{< /tab >}}
{{< /tabs >}}

---

## Movement & Teleportation

### Position & Movement

{{< tabs items="Position Methods,Movement State,Velocity" >}}
{{< tab >}}
| Method | Return Type | Description |
|--------|-------------|-------------|
| `getPosition()` | `Vector3d` | Current position |
| `setPosition(Vector3d)` | `void` | Set position |
| `getEyePosition()` | `Vector3d` | Eye level position |
| `getRotation()` | `Vector3f` | Look direction |
| `setRotation(Vector3f)` | `void` | Set look direction |
| `getEyeDirection()` | `Vector3d` | Normalized look vector |
{{< /tab >}}
{{< tab >}}
| Method | Return Type | Description |
|--------|-------------|-------------|
| `isOnGround()` | `boolean` | Whether on solid ground |
| `isSprinting()` | `boolean` | Whether sprinting |
| `setSprinting(boolean)` | `void` | Set sprint state |
| `isSneaking()` | `boolean` | Whether sneaking |
| `setSneaking(boolean)` | `void` | Set sneak state |
| `isFlying()` | `boolean` | Whether flying |
| `setFlying(boolean)` | `void` | Set flying state |
| `isSwimming()` | `boolean` | Whether swimming |
{{< /tab >}}
{{< tab >}}
```java
// Get velocity
Vector3d velocity = player.getVelocity();

// Set velocity (launch player)
player.setVelocity(new Vector3d(0, 1.5, 0));

// Add to velocity
player.addVelocity(new Vector3d(1, 0, 0));

// Apply knockback
player.knockback(new Vector3d(-0.5, 0.5, -0.5));
```
{{< /tab >}}
{{< /tabs >}}

### Teleportation

{{< callout type="warning" >}}
Hytale uses a **component-based teleportation system**. You don't call `player.teleport()` directly. Instead, you add a `Teleport` component to the entity, and the system handles the teleportation.
{{< /callout >}}

{{< tabs items="Basic Usage,Cross-World,Options,System Details" >}}
{{< tab >}}

```java
// Get player reference from command context
Ref<EntityStore> playerRef = context.senderAsPlayerRef();

// Teleport to position in same world
Teleport teleport = new Teleport(
    new Vector3d(100, 64, 100),     // position
    new Vector3f(0, 90, 0)          // rotation (pitch, yaw, roll)
);

// Add the teleport component to trigger teleportation
playerRef.getStore().putComponent(playerRef, Teleport.getComponentType(), teleport);

// Using Transform
Transform destination = new Transform(position, rotation);
Teleport teleportFromTransform = new Teleport(destination);
```

{{< /tab >}}
{{< tab >}}

```java
// Get player reference from command context
Ref<EntityStore> playerRef = context.senderAsPlayerRef();

// Teleport to another world
World targetWorld = Universe.get().getWorld("other_world");

Teleport teleport = new Teleport(
    targetWorld,                     // target world
    new Vector3d(0, 64, 0),          // position
    new Vector3f(0, 0, 0)            // rotation
);

playerRef.getStore().putComponent(playerRef, Teleport.getComponentType(), teleport);

// The TeleportSystems.PlayerMoveSystem handles:
// - Same world: Direct position update
// - Different world: Player removal and re-addition to target world
```

{{< /tab >}}
{{< tab >}}

```java
// Teleport with options using fluent builder
Teleport teleport = new Teleport(targetWorld, position, rotation)
    .withHeadRotation(new Vector3f(0, 45, 0))  // Set head rotation
    .withResetRoll()                            // Reset roll to 0
    .withoutVelocityReset();                    // Keep current velocity

// By default:
// - resetVelocity = true (player stops moving)
// - headRotation = same as body rotation
```

{{< /tab >}}
{{< tab >}}

The teleportation flow:

1. **Add Teleport component** to entity
2. **TeleportSystems.PlayerMoveSystem** detects the component
3. System sends `ClientTeleport` packet to player
4. **PendingTeleport** component tracks the teleport
5. When client confirms, position is updated
6. **Teleport component is removed** automatically

```java
// Internal packet sent:
ClientTeleport packet = new ClientTeleport(
    teleportId,
    new ModelTransform(position, direction, headRotation),
    resetVelocity
);
```

{{< /tab >}}
{{< /tabs >}}

---

## Game Mode

{{< callout type="info" >}}
Hytale currently has **two game modes**: `Adventure` and `Creative`. These differ from Minecraft's game modes.
{{< /callout >}}

{{< tabs items="Available Modes,Getting/Setting,Creative Features" >}}
{{< tab >}}

| Mode | Value | Description |
|------|-------|-------------|
| `GameMode.Adventure` | 0 | Standard gameplay with survival mechanics |
| `GameMode.Creative` | 1 | Creative mode with building freedom |

{{< /tab >}}
{{< tab >}}

```java
// Get current game mode
GameMode mode = player.getGameMode();

// Check game mode
if (mode == GameMode.Creative) {
    // Creative mode logic
} else if (mode == GameMode.Adventure) {
    // Adventure mode logic
}

// Set game mode (requires component accessor)
// Note: This is typically done through systems/commands
Player.setGameMode(playerRef, GameMode.Creative, componentAccessor);
```

{{< /tab >}}
{{< tab >}}

When in Creative mode:
- Player is marked as `Invulnerable`
- `canFly` is enabled in MovementManager
- `canDecreaseItemStackDurability` returns false
- `canApplyItemStackPenalties` returns false
- Permission groups from GameModeType are applied

```java
// GameMode affects these behaviors automatically:
// - Flight enabled/disabled
// - Invulnerability
// - Item durability loss
// - Block placement restrictions
```

{{< /tab >}}
{{< /tabs >}}

---

## Server Actions

### Disconnecting Players

```java
// Get entity reference from command context
Ref<EntityStore> ref = context.senderAsPlayerRef();

// Disconnect player via PacketHandler
PlayerRef playerRef = ref.getStore().getComponent(ref, PlayerRef.getComponentType());

// Disconnect with reason
playerRef.getPacketHandler().disconnect("You have been kicked!");

// Disconnect with translation message
playerRef.getPacketHandler().disconnect(
    Message.translation("server.kick.reason").toString()
);
```

### Player Lookup

```java
// Get all online players through Universe
Universe universe = Universe.get();

// Players are accessed through world contexts
World world = universe.getWorld("main");

// Iterate players in world via entity store
// Players are entities with PlayerRef component
world.getEntityStore().forEach((ref, store) -> {
    PlayerRef playerRef = store.getComponent(ref, PlayerRef.getComponentType());
    if (playerRef != null) {
        String username = playerRef.getUsername();
        UUID uuid = playerRef.getUuid();
        // Process player...
    }
});
```

### Server Transfer

```java
// Get entity reference from command context
Ref<EntityStore> ref = context.senderAsPlayerRef();

// Transfer player to another server (for server networks)
PlayerRef playerRef = ref.getStore().getComponent(ref, PlayerRef.getComponentType());

// Redirect player to another server
playerRef.referToServer("play.example.com", 25565);

// With custom data (max 4096 bytes)
byte[] playerData = serializePlayerState(playerRef);
playerRef.referToServer("play.example.com", 25565, playerData);
```

---

## Practical Examples

### Welcome Plugin

```java
public class WelcomePlugin extends ServerPlugin {

    @Override
    public void setup(PluginSetup pluginSetup) {
        // Register event listeners
    }

    @Override
    public void start() {
        // Subscribe to player connect event
        HytaleServer.get().getEventBus()
            .subscribe(PlayerConnectEvent.class, this::onPlayerConnect);
    }

    private void onPlayerConnect(PlayerConnectEvent event) {
        String username = event.getUsername();
        UUID uuid = event.getUuid();

        getLogger().at(Level.INFO).log("Player connected: " + username + " (" + uuid + ")");

        // Send welcome message after player is ready
        // Note: PlayerReadyEvent has String key, so use registerGlobal
        getEventRegistry().registerGlobal(PlayerReadyEvent.class, readyEvent -> {
            Player player = readyEvent.getPlayer();
            player.sendMessage(Message.raw("Welcome to the server, " + username + "!"));
        });
    }

    @Override
    public void shutdown() {
        // Cleanup
    }
}
```

### Permission Check Example

```java
public class PermissionPlugin extends ServerPlugin {

    @Override
    public void start() {
        CommandRegistry registry = getCommandRegistry();

        registry.register("admin", context -> {
            CommandSender sender = context.getSource();

            // Check permission
            if (sender instanceof Player player) {
                if (!player.hasPermission("myplugin.admin")) {
                    player.sendMessage(Message.raw("No permission!"));
                    return;
                }

                player.sendMessage(Message.raw("You are an admin!"));
            }
        });
    }
}
```

### Inventory Management

```java
// Get entity reference from command context
Ref<EntityStore> ref = context.senderAsPlayerRef();

// Working with player inventory
Player player = ref.getStore().getComponent(ref, Player.getComponentType());
Inventory inventory = player.getInventory();

// Add item to inventory
ItemStack itemStack = new ItemStack(itemType, amount);
inventory.addItem(itemStack);

// Send inventory update to client
player.sendInventory();

// Access hotbar
HotbarManager hotbar = player.getHotbarManager();
```

---

## Best Practices

{{< callout type="info" >}}
**Player API Guidelines:**
- Use `PlayerRef` to get thread-safe player information
- Check `isValid()` before operations on stored references
- Use permissions via `player.hasPermission()` for access control
- Understand the component system: players are entities with components
{{< /callout >}}

{{< callout type="warning" >}}
**Component System:** Players in Hytale are entities managed by an ECS. Access player data via `ref.getStore()` and appropriate component types (`Player.getComponentType()`, `PlayerRef.getComponentType()`).
{{< /callout >}}

{{< callout type="error" >}}
**Critical:** Never store `Ref<EntityStore>` or `Player` references directly in static fields. Use `UUID` for storage and retrieve references via the component system when needed.
{{< /callout >}}

