Entity Hierarchy
Hytale uses a component-based entity system. The core hierarchy is:
1Entity (abstract)2├── LivingEntity (abstract)3│ └── Player4└── BlockEntityNPCs and mobs implement INonPlayerCharacter interface on top of LivingEntity.
Entity Class
The base Entity class provides core functionality for all entities.
1// Core Entity methods2public abstract class Entity {3 // Identity4 public UUID getUuid();5 public int getNetworkId();6 public String getLegacyDisplayName();7 8 // World9 public World getWorld();10 public void loadIntoWorld(World world);11 public void unloadFromWorld();12 public boolean wasRemoved();13 14 // Transform15 public TransformComponent getTransformComponent();16 public void setTransformComponent(TransformComponent transform);17 public void moveTo(Ref ref, double x, double y, double z, 18 ComponentAccessor accessor); 19 20 // Lifecycle21 public boolean remove(); // Remove from world22 public void markNeedsSave();23 24 // Reference system25 public Ref getReference(); 26 public void setReference(Ref ref); 27 28 // Collision29 public boolean isCollidable();30 public boolean isHiddenFromLivingEntity(...);31}LivingEntity Class
LivingEntity extends Entity with inventory, stats, and other living creature features.
1public abstract class LivingEntity extends Entity {2 // Inventory3 public Inventory getInventory();4 public Inventory setInventory(Inventory inventory);5 public Inventory setInventory(Inventory inventory, boolean notify);6 7 // Stats8 public StatModifiersManager getStatModifiersManager();9 10 // Fall damage11 public double getCurrentFallDistance();12 public void setCurrentFallDistance(double distance);13 14 // Item durability15 public boolean canDecreaseItemStackDurability(...);16 public ItemStackSlotTransaction decreaseItemStackDurability(...);17 public ItemStackSlotTransaction updateItemStackDurability(...);18 19 // Equipment20 public void invalidateEquipmentNetwork();21 public boolean consumeEquipmentNetworkOutdated();22 23 // Movement (inherited from Entity)24 public void moveTo(...);25}Player Class
The Player class extends LivingEntity and implementsCommandSender and PermissionHolder.
1public class Player extends LivingEntity 2 implements CommandSender, PermissionHolder {3 4 // Connection5 public PacketHandler getPlayerConnection();6 7 // Managers8 public WindowManager getWindowManager();9 public PageManager getPageManager();10 public HudManager getHudManager();11 public HotbarManager getHotbarManager();12 public WorldMapTracker getWorldMapTracker();13 14 // Messaging15 public void sendMessage(Message message);16 17 // Permissions18 public boolean hasPermission(String permission);19 public boolean hasPermission(String permission, boolean defaultValue);20 21 // View22 public int getViewRadius();23 public int getClientViewRadius();24 public void setClientViewRadius(int radius);25 26 // Spawn27 public boolean isFirstSpawn();28 public void setFirstSpawn(boolean first);29 public boolean hasSpawnProtection();30 public long getSinceLastSpawnNanos();31 32 // Reference33 public PlayerRef getPlayerRef();34 35 // Config data36 public PlayerConfigData getPlayerConfigData();37 public CompletableFuture saveConfig(World world, Holder holder); 38}Spawning Entities
Use World.spawnEntity() to spawn entities at a position.
1// Spawning an entity2World world = player.getWorld();3Vector3d position = new Vector3d(100, 64, 100);4Vector3f rotation = new Vector3f(0, 0, 0); // yaw, pitch, roll56world.execute(() -> {7 // spawnEntity returns the spawned entity8 MyEntity entity = world.spawnEntity(9 new MyEntity(world), // Entity instance10 position, // Spawn position11 rotation // Initial rotation12 );13});addEntity vs spawnEntity
| method | use case |
|---|---|
| spawnEntity(entity, pos, rot) | Normal spawning - fires spawn events |
| addEntity(entity, pos, rot, reason) | Low-level add with custom AddReason |
1// Using addEntity with AddReason2world.addEntity(3 entity,4 position,5 rotation,6 AddReason.SPAWN // or LOAD, etc.7);INonPlayerCharacter Interface
NPCs and mobs implement this interface for type identification:
1public interface INonPlayerCharacter {2 String getNPCTypeId(); // e.g. "trork_warrior", "Chicken"3 int getNPCTypeIndex(); // Internal type index4}Spawning NPCs
Use NPCPlugin.get().spawnNPC() to spawn NPCs programmatically. This is the correct way to spawn mobs and creatures from plugins.
Basic NPC Spawning
1import com.hypixel.hytale.server.npc.NPCPlugin;2import com.hypixel.hytale.server.core.universe.world.npc.INonPlayerCharacter;3import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;4import com.hypixel.hytale.component.Ref;5import com.hypixel.hytale.component.Store;6import com.hypixel.hytale.math.vector.Vector3d;7import com.hypixel.hytale.math.vector.Vector3f;8import it.unimi.dsi.fastutil.Pair;910// Get the world's entity store11World world = player.getWorld();1213world.execute(() -> {14 NPCPlugin npcPlugin = NPCPlugin.get();15 Store store = world.getEntityStore().getStore(); 16 17 // Spawn position and rotation18 Vector3d position = new Vector3d(100, 64, 100);19 Vector3f rotation = new Vector3f(0, 0, 0); // yaw, pitch, roll20 23 store, // Entity store24 "Chicken", // NPC type ID (from assets)25 null, // Variant (null for default)26 position, // Spawn position27 rotation // Initial rotation28 );29 30 if (result != null) {31 Ref entityRef = result.first(); 32 INonPlayerCharacter npc = result.second();33 34 // NPC is now spawned and active35 String typeId = npc.getNPCTypeId(); // "Chicken"36 }37});NPCPlugin.spawnNPC() Signature
1public Pair, INonPlayerCharacter> spawnNPC(2 Store store, // From world.getEntityStore().getStore() 3 String npcTypeId, // NPC type identifier (e.g., "Chicken", "trork_warrior")4 String variant, // Variant name or null for default5 Vector3d position, // World position6 Vector3f rotation // Rotation (yaw, pitch, roll in radians)7)Return Value
| part | type | description |
|---|---|---|
| result.first() | Ref<EntityStore> | Reference for component access |
| result.second() | INonPlayerCharacter | The spawned NPC entity |
Freezing NPCs
Use the Frozen component to prevent an NPC from moving, attacking, or performing AI behaviors. This is essential for camera anchors, decorative NPCs, or cutscene actors.
Adding the Frozen Component
1import com.hypixel.hytale.server.core.entity.Frozen;23// After spawning the NPC...56if (result != null) {7 Ref entityRef = result.first(); 8 9 // Add the Frozen component to stop all NPC behavior10 store.addComponent(entityRef, Frozen.getComponentType(), Frozen.get());11 12 // The NPC is now completely frozen:13 // - No movement14 // - No AI behaviors15 // - No animations (idle state)16}Frozen Component API
1// Frozen is a singleton component2public class Frozen {3 public static ComponentType getComponentType(); 4 public static Frozen get(); // Returns the singleton instance5}Frozen to prevent the NPC from walking away or triggering AI.Getting Network ID
The network ID is required for camera attachment and other network operations. Cast INonPlayerCharacter to NPCEntity to access it.
1import com.hypixel.hytale.server.npc.entities.NPCEntity;23// After spawning...4INonPlayerCharacter npc = result.second();56// Cast to NPCEntity to get network ID7if (npc instanceof NPCEntity) {8 NPCEntity entity = (NPCEntity) npc;9 int networkId = entity.getNetworkId();10 11 // Use networkId for camera attachment:12 // settings.attachedToEntityId = networkId;13}getNetworkId() may be marked as deprecated but still works correctly. It's required for camera attachment via ServerCameraSettings.attachedToEntityId.Removing NPCs
Use the remove() method on NPCEntity to despawn.
1// Store the NPC reference2private INonPlayerCharacter spawnedNpc;34// Later, when you want to remove it...5if (spawnedNpc != null && spawnedNpc instanceof NPCEntity) {6 NPCEntity entity = (NPCEntity) spawnedNpc;7 8 world.execute(() -> {9 if (!entity.wasRemoved()) {10 entity.remove();11 }12 });13}Complete NPC Example
1import com.hypixel.hytale.server.core.plugin.JavaPlugin;2import com.hypixel.hytale.server.core.universe.world.World;3import com.hypixel.hytale.server.core.universe.PlayerRef;4import com.hypixel.hytale.server.core.universe.world.npc.INonPlayerCharacter;5import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;6import com.hypixel.hytale.server.npc.NPCPlugin;7import com.hypixel.hytale.server.npc.entities.NPCEntity;8import com.hypixel.hytale.server.core.entity.Frozen;9import com.hypixel.hytale.component.Ref;10import com.hypixel.hytale.component.Store;11import com.hypixel.hytale.math.vector.Vector3d;12import com.hypixel.hytale.math.vector.Vector3f;13import com.hypixel.hytale.math.vector.Transform;14import it.unimi.dsi.fastutil.Pair;1516public class NPCSpawnExample extends JavaPlugin {17 18 private INonPlayerCharacter spawnedNpc;19 private Ref npcRef; 20 21 public void spawnFrozenNPC(PlayerRef player, World world) {22 // Calculate spawn position in front of player23 Transform transform = player.getTransform();24 Vector3d playerPos = transform.getPosition();25 float yaw = transform.getRotation().getYaw();26 27 double spawnX = playerPos.getX() - Math.sin(yaw) * 3;28 double spawnZ = playerPos.getZ() - Math.cos(yaw) * 3;29 30 Vector3d spawnPos = new Vector3d(spawnX, playerPos.getY(), spawnZ);31 Vector3f spawnRot = new Vector3f(0, yaw + (float)Math.PI, 0); // Face player32 33 world.execute(() -> {34 NPCPlugin npcPlugin = NPCPlugin.get();35 Store store = world.getEntityStore().getStore(); 36 38 store, "Chicken", null, spawnPos, spawnRot39 );40 41 if (result != null) {42 npcRef = result.first();43 spawnedNpc = result.second();44 45 // Freeze the NPC46 store.addComponent(npcRef, Frozen.getComponentType(), Frozen.get());47 48 // Get network ID for camera attachment49 int networkId = ((NPCEntity) spawnedNpc).getNetworkId();50 getLogger().info("Spawned frozen NPC with network ID: " + networkId);51 }52 });53 }54 55 public void removeNPC(World world) {56 if (spawnedNpc != null && spawnedNpc instanceof NPCEntity) {57 NPCEntity entity = (NPCEntity) spawnedNpc;58 world.execute(() -> {59 if (!entity.wasRemoved()) {60 entity.remove();61 }62 });63 spawnedNpc = null;64 npcRef = null;65 }66 }67}Getting Entities
1World world = player.getWorld();23// Get all players in world4List<Player> players = world.getPlayers();5int playerCount = world.getPlayerCount();67// Get entity by UUID8Entity entity = world.getEntity(someUUID);910// Get entity reference by UUID11Ref ref = world.getEntityRef(someUUID); 1213// Get player refs14Collection playerRefs = world.getPlayerRefs(); Removing Entities
1// Remove an entity from the world2world.execute(() -> {3 boolean wasRemoved = entity.remove();4 5 // Check if already removed6 if (entity.wasRemoved()) {7 // Entity is gone8 }9});EntityRemoveEvent fires. There is no direct EntityDeathEvent - useEntityRemoveEvent and check the removal reason.Entity Components
Entities use the component system for data storage. Common components:
| component | purpose |
|---|---|
| TransformComponent | Position, rotation, scale |
| MovementStatesComponent | Walking, sprinting, jumping states |
| EffectControllerComponent | Active effects (buffs/debuffs) |
| UUIDComponent | Unique identifier storage |
1// Access transform component2TransformComponent transform = entity.getTransformComponent();34// Using the reference system for components5Ref ref = entity.getReference(); 6EntityStore store = ref.getStore();78// Get component through accessor9ComponentAccessor accessor = world.getEntityStore(); 10// ... use accessor to read/write componentsQuick Reference
1public class EntityExample extends JavaPlugin {2 3 @Override4 protected void start() {5 getEventRegistry().register(6 PlayerConnectEvent.class,7 this::onPlayerConnect8 );9 }10 11 private void onPlayerConnect(PlayerConnectEvent event) {12 Player player = event.getPlayer();13 World world = player.getWorld();14 15 // Log player info16 UUID uuid = player.getUuid();17 int networkId = player.getNetworkId();18 getLogger().info("Player " + uuid + " connected (network: " + networkId + ")");19 20 // Access inventory21 Inventory inventory = player.getInventory();22 23 // Check permissions24 if (player.hasPermission("example.vip")) {25 // VIP handling26 }27 28 // Get position via transform29 world.execute(() -> {30 TransformComponent transform = player.getTransformComponent();31 // transform.pos contains position32 });33 }34}