Mounts System
The mounts system in Hytale allows entities to ride other entities or mount blocks. The system handles seats, beds, minecarts, and rideable NPCs with configurable mount points and controllers.
Core Components
Section titled “Core Components”MountedComponent
Section titled “MountedComponent”Located in com.hypixel.hytale.builtin.mounts, this component indicates that an entity is currently mounted on something.
public class MountedComponent implements Component<EntityStore> { private Ref<EntityStore> mountedToEntity; private Ref<ChunkStore> mountedToBlock; private MountController controller; private BlockMountType blockMountType; private Vector3f attachmentOffset; private long mountStartMs; private boolean isNetworkOutdated;}Fields:
mountedToEntity- Reference to the entity being mounted (for NPC/entity mounts)mountedToBlock- Reference to the block being mounted (for block mounts)controller- The type of mount controller (BlockMount, Minecart, etc.)blockMountType- Type of block mount (Seat, Bed)attachmentOffset- Offset from the mount pointmountStartMs- Timestamp when mounting startedisNetworkOutdated- Flag for network synchronization
Methods:
getMountedToEntity()- Get the mounted entity referencegetMountedToBlock()- Get the mounted block referencegetControllerType()- Get the mount controller typegetBlockMountType()- Get the block mount type (Seat/Bed)getMountedDurationMs()- Get how long the entity has been mounted
MountedByComponent
Section titled “MountedByComponent”This component indicates that an entity has passengers/riders.
public class MountedByComponent implements Component<EntityStore> { private final List<Ref<EntityStore>> passengers;}Methods:
getPassengers()- Get list of all passengers (auto-removes invalid refs)addPassenger(Ref<EntityStore>)- Add a passengerremovePassenger(Ref<EntityStore>)- Remove a passengerwithPassenger(Ref<EntityStore>)- Builder-style passenger addition
BlockMountComponent
Section titled “BlockMountComponent”Located on block entities, this component manages mount points on blocks.
public class BlockMountComponent implements Component<ChunkStore> { private BlockMountType type; private Vector3i blockPos; private BlockType expectedBlockType; private int expectedRotation; private Map<BlockMountPoint, Ref<EntityStore>> entitiesByMountPoint; private Map<Ref<EntityStore>, BlockMountPoint> mountPointByEntity;}Fields:
type- Mount type (Seat or Bed)blockPos- World position of the blockexpectedBlockType- The block type that should be at this positionexpectedRotation- Expected rotation of the blockentitiesByMountPoint- Maps mount points to seated entitiesmountPointByEntity- Reverse mapping for quick lookup
Methods:
putSeatedEntity(BlockMountPoint, Ref<EntityStore>)- Seat an entity at a mount pointremoveSeatedEntity(Ref<EntityStore>)- Remove a seated entitygetSeatBlockBySeatedEntity(Ref<EntityStore>)- Get the mount point an entity is usinggetSeatedEntities()- Get all seated entitiesfindAvailableSeat(Vector3i, BlockMountPoint[], Vector3f)- Find the closest available seatisDead()- Check if component should be removed (no seated entities)
NPCMountComponent
Section titled “NPCMountComponent”This component marks an NPC as a rideable mount.
public class NPCMountComponent implements Component<EntityStore> { private int originalRoleIndex; private PlayerRef ownerPlayerRef; private float anchorX, anchorY, anchorZ;}Fields:
originalRoleIndex- The NPC’s original role before being mountedownerPlayerRef- Reference to the player riding this mountanchorX/Y/Z- Anchor point for the rider
Methods:
getOriginalRoleIndex()- Get the original NPC rolegetOwnerPlayerRef()- Get the riding playersetAnchor(float, float, float)- Set the rider anchor position
MinecartComponent
Section titled “MinecartComponent”This component represents a minecart entity.
public class MinecartComponent implements Component<EntityStore> { private int numberOfHits; private Instant lastHit; private String sourceItem = "Rail_Kart";}Fields:
numberOfHits- Number of times the minecart has been hitlastHit- Timestamp of last hitsourceItem- Item ID used to create this minecart
Mount Types
Section titled “Mount Types”Block Mounts
Section titled “Block Mounts”Block mounts allow entities to sit on or lie in blocks.
BlockMountType
Section titled “BlockMountType”public enum BlockMountType { Seat, // Sitting position Bed // Lying position}Block Mount Points
Section titled “Block Mount Points”Mount points are defined in block assets using BlockMountPoint:
public class BlockMountPoint { // Position and rotation relative to block public Vector3f computeWorldSpacePosition(Vector3i blockPos); public Vector3f computeRotationEuler(int blockRotation);}Block types can define mount points in their asset configuration:
- Seats - Chair-like sitting positions
- Beds - Lying positions for sleeping
Entity Mounts
Section titled “Entity Mounts”Entity mounts allow entities to ride other entities (NPCs, vehicles, etc.).
MountController Types
Section titled “MountController Types”public enum MountController { BlockMount, // Mounted on a block Minecart, // Riding in a minecart // Additional controllers for different mount types}Minecarts
Section titled “Minecarts”Minecarts are special entities that can be mounted and move on rails.
Features:
- Created from items (default: “Rail_Kart”)
- Track number of hits for destruction
- Custom mount controller behavior
- Rail-based movement system
Mount Systems
Section titled “Mount Systems”Block Mounting System
Section titled “Block Mounting System”The BlockMountAPI provides utilities for mounting entities on blocks.
Mounting Process
Section titled “Mounting Process”public static BlockMountResult mountOnBlock( Ref<EntityStore> entity, CommandBuffer<EntityStore> commandBuffer, Vector3i targetBlock, Vector3f interactPos)Process:
- Check entity isn’t already mounted
- Validate chunk and block exist
- Get or create block entity reference
- Determine mount type (Seat or Bed)
- Get mount points from block type
- Find available mount point closest to interaction position
- Create
BlockMountComponentif needed - Position entity at mount point
- Add
MountedComponentto entity - Register entity in mount point map
Return Types:
public sealed interface BlockMountResult { record Mounted(BlockType blockType, MountedComponent component); enum DidNotMount { CHUNK_NOT_FOUND, CHUNK_REF_NOT_FOUND, BLOCK_REF_NOT_FOUND, INVALID_BLOCK, ALREADY_MOUNTED, UNKNOWN_BLOCKMOUNT_TYPE, NO_MOUNT_POINT_FOUND }}Mount System Events
Section titled “Mount System Events”MountedEntityDeath
Section titled “MountedEntityDeath”Handles cleanup when a mounted entity dies:
public static class MountedEntityDeath extends RefChangeSystem<EntityStore, DeathComponent> { @Override public Query<EntityStore> getQuery() { return MountedComponent.getComponentType(); }}Removes the entity from mount point when death component is added.
Dismount Handling
Section titled “Dismount Handling”When MountedComponent is removed, the system:
- Removes passenger from
MountedByComponentof mount - Removes entity from
BlockMountComponentif block mount - Cleans up block component if no remaining passengers
NPC Mount Systems
Section titled “NPC Mount Systems”NPCMountSystems.OnAdd
Section titled “NPCMountSystems.OnAdd”Handles NPC mount setup when component is added:
public static class OnAdd extends RefSystem<EntityStore> { @Override public void onEntityAdded(Ref<EntityStore> ref, AddReason reason, Store<EntityStore> store, CommandBuffer<EntityStore> commandBuffer) { NPCMountComponent mountComponent = store.getComponent(ref, type); PlayerRef playerRef = mountComponent.getOwnerPlayerRef();
if (playerRef != null) { // Send mount packet to player MountNPC packet = new MountNPC(anchorX, anchorY, anchorZ, networkId); playerComponent.setMountEntityId(networkId); playerRef.getPacketHandler().write(packet); } else { // Reset to original role if no owner resetOriginalRoleMount(ref, store, commandBuffer, mountComponent); } }}Death Handling
Section titled “Death Handling”DismountOnMountDeath - When the mount dies
- Removes player from mount
- Resets player movement settings
DismountOnPlayerDeath - When the rider dies
- Dismounts the player from any NPC mount
- Cleans up mount state
Mount Interactions
Section titled “Mount Interactions”Seating Interaction
Section titled “Seating Interaction”public class SeatingInteraction { // Handles clicking on seats to sit}Located in com.hypixel.hytale.builtin.mounts.interactions.
Mount Interaction
Section titled “Mount Interaction”public class MountInteraction { // Handles mounting entities}Spawn Minecart Interaction
Section titled “Spawn Minecart Interaction”public class SpawnMinecartInteraction { // Handles spawning minecarts from items}Mount Commands
Section titled “Mount Commands”MountCommand
Section titled “MountCommand”Allows mounting entities via command.
public class MountCommand { // Command: /mount <entity>}DismountCommand
Section titled “DismountCommand”Forces dismounting.
public class DismountCommand { // Command: /dismount}MountCheckCommand
Section titled “MountCheckCommand”Checks mount state.
public class MountCheckCommand { // Command: /mountcheck}Using the Mounts System
Section titled “Using the Mounts System”Mounting on a Block
Section titled “Mounting on a Block”// Player clicks on a chairVector3i blockPos = new Vector3i(x, y, z);Vector3f clickPos = new Vector3f(clickX, clickY, clickZ);
BlockMountAPI.BlockMountResult result = BlockMountAPI.mountOnBlock( playerRef, commandBuffer, blockPos, clickPos);
if (result instanceof BlockMountAPI.Mounted mounted) { // Successfully mounted BlockType blockType = mounted.blockType(); MountedComponent component = mounted.component();} else if (result instanceof BlockMountAPI.DidNotMount error) { // Handle error switch (error) { case ALREADY_MOUNTED -> // Already sitting case NO_MOUNT_POINT_FOUND -> // No available seat // ... other cases }}Dismounting
Section titled “Dismounting”// Remove the MountedComponent to dismountcommandBuffer.removeComponent(entityRef, MountedComponent.getComponentType());
// System automatically handles cleanupCreating a Rideable NPC
Section titled “Creating a Rideable NPC”// Add NPCMountComponent to an NPCNPCMountComponent mountComponent = new NPCMountComponent();mountComponent.setOriginalRoleIndex(npc.getRoleIndex());mountComponent.setOwnerPlayerRef(playerRef);mountComponent.setAnchor(0f, 1.5f, 0f);
commandBuffer.addComponent(npcRef, NPCMountComponent.getComponentType(), mountComponent);Spawning a Minecart
Section titled “Spawning a Minecart”// Create minecart entityHolder<EntityStore> minecartHolder = EntityStore.REGISTRY.newHolder();
// Add MinecartComponentMinecartComponent minecart = new MinecartComponent("Rail_Kart");minecartHolder.putComponent(MinecartComponent.getComponentType(), minecart);
// Add other required components (Transform, NetworkId, etc.)// ...
// Spawn the entityRef<EntityStore> minecartRef = store.addEntity(minecartHolder, AddReason.SPAWN);Checking Mount State
Section titled “Checking Mount State”// Check if entity is mountedMountedComponent mounted = store.getComponent(entityRef, MountedComponent.getComponentType());if (mounted != null) { if (mounted.getMountedToEntity() != null) { // Mounted on an entity Ref<EntityStore> mount = mounted.getMountedToEntity(); } else if (mounted.getMountedToBlock() != null) { // Mounted on a block Ref<ChunkStore> block = mounted.getMountedToBlock(); BlockMountType type = mounted.getBlockMountType(); // Seat or Bed }}
// Check if entity has passengersMountedByComponent mountedBy = store.getComponent(entityRef, MountedByComponent.getComponentType());if (mountedBy != null) { List<Ref<EntityStore>> passengers = mountedBy.getPassengers(); for (Ref<EntityStore> passenger : passengers) { // Process each passenger }}Finding Available Seats
Section titled “Finding Available Seats”// Get block typeBlockType blockType = world.getBlockType(blockPos);if (blockType.getSeats() != null) { // Get seats for current rotation int rotation = world.getRotationIndex(blockPos); BlockMountPoint[] seats = blockType.getSeats().getRotated(rotation);
// Get or create BlockMountComponent BlockMountComponent mountComponent = // ... get from block entity
// Find available seat Vector3f interactionPoint = new Vector3f(x, y, z); BlockMountPoint availableSeat = mountComponent.findAvailableSeat( blockPos, seats, interactionPoint );
if (availableSeat != null) { // Seat is available Vector3f seatWorldPos = availableSeat.computeWorldSpacePosition(blockPos); }}Movement States Integration
Section titled “Movement States Integration”When mounted, the mounting movement state is set:
MovementStatesComponent movement = store.getComponent(entityRef, MovementStatesComponent.getComponentType());movement.getMovementStates().mounting = true;This affects:
- Animation state (sitting/riding animations)
- Movement restrictions
- Physics behavior
- Input handling
Network Synchronization
Section titled “Network Synchronization”Mount state is synchronized to clients via:
- MountedUpdate packet - Updates mount state
- BlockMount protocol - Block mount information
- MountNPC packet - NPC mounting
- ComponentUpdate - General component sync
The MountGamePacketHandler handles client-server mount communication.
Best Practices
Section titled “Best Practices”- Always use the API - Use
BlockMountAPI.mountOnBlock()rather than manually creating components - Handle errors - Check the result type when mounting
- Clean up properly - Systems handle cleanup, but ensure custom logic doesn’t leave orphaned refs
- Validate before mounting - Check if entity is already mounted
- Use mount points - Define proper mount points in block assets for best positioning
- Network state - The
isNetworkOutdatedflag helps optimize network traffic - Death handling - Ensure dismounting on death for both rider and mount
- Chunk loading - Block mounts require chunks to be loaded
Configuration
Section titled “Configuration”Block Asset Configuration
Section titled “Block Asset Configuration”Define mount points in block assets:
{ "Seats": [ { "Offset": [0, 0.5, 0], "Rotation": [0, 0, 0] } ]}NPC Mount Configuration
Section titled “NPC Mount Configuration”Configure NPC mounts in prefabs:
{ "Components": { "NPCMountComponent": { "OriginalRoleIndex": 0 } }}Related Systems
Section titled “Related Systems”- Movement System - Sets
mountingstate when mounted - Transform System - Positions mounted entities
- Physics System - Handles mount movement
- Animation System - Plays sitting/riding animations
- Interaction System - Triggers mounting via interactions
- Death System - Handles dismounting on death
- Network System - Synchronizes mount state to clients
Advanced Features
Section titled “Advanced Features”Custom Mount Controllers
Section titled “Custom Mount Controllers”Extend the mount system by creating custom controllers:
- Implement specific movement behaviors
- Add custom input handling
- Create specialized mount types
Multi-seat Mounts
Section titled “Multi-seat Mounts”Blocks and entities can have multiple mount points:
- Each mount point tracked separately
- Independent passenger management
- Coordinate multiple riders
Dynamic Mounts
Section titled “Dynamic Mounts”Mounts can be created and destroyed dynamically:
- Minecarts spawned from items
- Temporary mount entities
- Mount point availability changes