24 KiB
title, type, weight
| title | type | weight |
|---|---|---|
| Player API | docs | 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 >}}
// 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 >}}
// 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 >}}
// 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 >}}
// 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 >}}
// 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 >}}
// 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 >}}
// 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
// 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.
// Get stat indices (from DefaultEntityStatTypes)
int healthIndex = DefaultEntityStatTypes.getHealth();
int staminaIndex = DefaultEntityStatTypes.getStamina();
int manaIndex = DefaultEntityStatTypes.getMana();
{{< /tab >}} {{< tab >}}
// 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 >}}
// 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
// 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
// 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 >}}
// 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 >}}
// 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 >}}
// 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
// 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 >}}
// 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 >}}
// 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 >}}
// 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 >}} |
// 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 >}}
// 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 >}}
// 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 >}}
// 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:
- Add Teleport component to entity
- TeleportSystems.PlayerMoveSystem detects the component
- System sends
ClientTeleportpacket to player - PendingTeleport component tracks the teleport
- When client confirms, position is updated
- Teleport component is removed automatically
// 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 >}}
// 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 canFlyis enabled in MovementManagercanDecreaseItemStackDurabilityreturns falsecanApplyItemStackPenaltiesreturns false- Permission groups from GameModeType are applied
// GameMode affects these behaviors automatically:
// - Flight enabled/disabled
// - Invulnerability
// - Item durability loss
// - Block placement restrictions
{{< /tab >}} {{< /tabs >}}
Server Actions
Disconnecting Players
// 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
// 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
// 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
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
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
// 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
PlayerRefto 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 >}}