--- 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 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` | Entity reference (null if not in world) | | `getHolder()` | `Holder` | 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 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 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 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 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 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 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 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 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 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 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 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 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` or `Player` references directly in static fields. Use `UUID` for storage and retrieve references via the component system when needed. {{< /callout >}}