Documents Hytale's player input system including packet interception (PacketAdapters, PacketWatcher, PacketFilter), SyncInteractionChains, InteractionTypes, client-to-server packet reference, and custom camera controls. Use when handling player input, intercepting packets, creating custom interactions, modifying camera behavior, or working with mouse/keyboard input. Triggers - player input, packet, PacketAdapters, PacketWatcher, PacketFilter, PlayerPacketWatcher, PlayerPacketFilter, SyncInteractionChains, InteractionType, MouseInteraction, ClientMovement, camera, SetServerCamera, ServerCameraSettings, camera controls, top-down, isometric, side-scroller, inbound packet, outbound packet, packet listener, input handling.
Documents Hytale's player input system including packet interception (PacketAdapters, PacketWatcher, PacketFilter), SyncInteractionChains, InteractionTypes, client-to-server packet reference, and custom camera controls. Use when handling player input, intercepting packets, creating custom interactions, modifying camera behavior, or working with mouse/keyboard input. Triggers - player input, packet, PacketAdapters, PacketWatcher, PacketFilter, PlayerPacketWatcher, PlayerPacketFilter, SyncInteractionChains, InteractionType, MouseInteraction, ClientMovement, camera, SetServerCamera, ServerCameraSettings, camera controls, top-down, isometric, side-scroller, inbound packet, outbound packet, packet listener, input handling.
Hytale Player Input Skill
Use this skill when working with player input handling in Hytale plugins. This covers how the client communicates input to the server via packets, how to intercept and filter those packets, the interaction types you will commonly use in plugins, a practical client-to-server packet reference, and custom camera controls.
Related skills: For hotbar-specific slot customization (ability slots), see hytale-hotbar-actions. For game events (PlayerReady, chat, damage, etc.), see hytale-events. For UI-based input, see hytale-ui-modding.
PacketAdapters.deregisterInbound(filter) or deregisterOutbound(watcher)
Part 1: How Player Input Works
Hytale servers do not receive raw keyboard input. The client interprets keypresses and sends packets describing what action the player wants to perform. To create custom input behavior, you intercept these packets server-side.
Key concepts:
Inbound packets = Client → Server (player actions)
Outbound packets = Server → Client (state updates, camera, etc.)
Packets are defined in com.hypixel.hytale.protocol and organized by category in com.hypixel.hytale.protocol.packets
Base class is Packet; the low-level Netty handler is PlayerChannelHandler which delegates to PacketAdapters
Part 2: PacketAdapters System
The PacketAdapters class provides the injection point for packet interception. You do not need to hook into Netty manually.
Part 3: Intercepting Interactions (SyncInteractionChains)
When a player performs interactions (left click, right click, F key, etc.), the client sends a SyncInteractionChains packet (ID 290) containing SyncInteractionChain objects.
SyncInteractionChain Fields
Field
Description
interactionType
The InteractionType enum value
activeHotbarSlot
The slot the player is currently on
data.targetSlot
The slot the player wants to switch to (for swap types)
initial
Whether this is the start of a new interaction chain
Use the official server/interaction-reference page as the canonical source for the full enum and any additions in newer server drops. The table below is the practical set commonly referenced in plugin code:
Name
Ordinal
Description
Primary
0
Left click
Secondary
1
Right click
Ability1
2
Ability slot 1
Ability2
3
Ability slot 2
Ability3
4
Ability slot 3
Use
5
Use key (F)
Pick
6
Pick action
Pickup
7
Pickup action
CollisionEnter
8
Entity collision start
CollisionLeave
9
Entity collision end
Collision
10
Ongoing collision
EntityStatEffect
11
Stat effect applied
SwapTo
12
Switching to a slot
SwapFrom
13
Switching from a slot
Death
14
Entity death
Wielding
15
Wielding an item
ProjectileSpawn
16
Projectile created
ProjectileHit
17
Projectile hits target
ProjectileMiss
18
Projectile misses
ProjectileBounce
19
Projectile bounces
Held
20
Item held in main hand
HeldOffhand
21
Item held in offhand
Equipped
22
Item equipped
Dodge
23
Dodge action
GameModeSwap
24
Game mode changed
Common input triggers:Primary (left click), Secondary (right click), Use (F key). For hotbar slot-based ability triggers, see the hytale-hotbar-actions skill.
PacketAdapters.registerInbound((PlayerPacketFilter) (player, packet) -> {
if (packet instanceof ClientMovement movementPacket) {
// Block movement — return true to cancelreturntrue;
}
returnfalse;
});
Warning: While you can cancel packets, client-side prediction still occurs. The player's client will still show movement locally. Preventing specific player actions requires additional work beyond just cancelling packets.
Packet Tracker Utility
Track all packets sent to/from players for debugging:
publicclassPlayerPacketTracker {
privatestaticfinalHytaleLoggerLOGGER= HytaleLogger.forEnclosingClass();
privatestaticclassPlayerStats {
final Map<String, AtomicInteger> sent = newConcurrentHashMap<>();
final Map<String, AtomicInteger> received = newConcurrentHashMap<>();
}
privatestaticfinal Map<String, PlayerStats> stats = newConcurrentHashMap<>();
privatestatic String getPlayerName(PacketHandler handler) {
if (handler instanceof GamePacketHandler gpHandler) {
return gpHandler.getPlayerRef().getUsername();
}
returnnull;
}
publicstaticvoidregisterPacketCounters() {
PacketAdapters.registerInbound((PacketHandler handler, Packet packet) -> {
StringplayerName= getPlayerName(handler);
if (playerName != null) {
stats.computeIfAbsent(playerName, k -> newPlayerStats())
.received.computeIfAbsent(packet.getClass().getSimpleName(),
k -> newAtomicInteger(0))
.incrementAndGet();
}
});
PacketAdapters.registerOutbound((PacketHandler handler, Packet packet) -> {
StringplayerName= getPlayerName(handler);
if (playerName != null) {
stats.computeIfAbsent(playerName, k -> newPlayerStats())
.sent.computeIfAbsent(packet.getClass().getSimpleName(),
k -> newAtomicInteger(0))
.incrementAndGet();
}
});
// Log every 3 seconds
HytaleServer.SCHEDULED_EXECUTOR.scheduleAtFixedRate(() -> {
if (stats.isEmpty()) return;
for (Map.Entry<String, PlayerStats> entry : stats.entrySet()) {
Stringplayer= entry.getKey();
PlayerStatspStats= entry.getValue();
StringBuildersb=newStringBuilder();
List<String> sentLogs = newArrayList<>();
pStats.sent.forEach((type, atomic) -> {
intcount= atomic.getAndSet(0);
if (count > 0) sentLogs.add(type + " x" + count);
});
if (!sentLogs.isEmpty()) {
sb.append("Sent ").append(String.join(", ", sentLogs));
}
List<String> recvLogs = newArrayList<>();
pStats.received.forEach((type, atomic) -> {
intcount= atomic.getAndSet(0);
if (count > 0) recvLogs.add(type + " x" + count);
});
if (!recvLogs.isEmpty()) {
if (!sb.isEmpty()) sb.append("\n");
sb.append("Received ").append(String.join(", ", recvLogs));
}
if (!sb.isEmpty()) {
LOGGER.atInfo().log("To " + player + ":\n" + sb);
}
}
}, 3, 3, TimeUnit.SECONDS);
}
}
Call PlayerPacketTracker.registerPacketCounters() in your plugin's setup() method.
Part 6: Plugin Registration & Cleanup
Always store references to registered filters/watchers and deregister them on shutdown:
This is a plugin-focused reference for the packets most relevant to input handling. For exhaustive protocol details, verify against the current packet registry in the decompiled server source.
Packets are found in: com.hypixel.hytale.protocol.packets
Set true in SetServerCamera to prevent player camera changes
Camera Tips
Zoom: Adjust distance (higher = further out)
Smoothness:positionLerpSpeed and rotationLerpSpeed control camera response speed
Wall clipping: Use PositionDistanceOffsetType.DistanceOffsetRaycast
Lock camera: Set isLocked = true in the SetServerCamera packet
2D movement: Set movementMultiplier to zero out an axis
Isometric cameras: Always set movementForceRotation to match camera yaw
Angle math: Use Math.toRadians(degrees) to convert degrees to radians
Key Warnings
Client-side prediction: Cancelling packets does not prevent client-side visual effects. The player will still see movement/actions locally even if the server blocks the packet.
Thread safety: When accessing ECS components from packet handlers, schedule work on the world thread via world.execute(() -> { ... }).
Packet IDs may change: Always use instanceof checks or class references rather than hardcoded packet IDs when possible. The ID-based approach (packet.getId() != 290) is brittle across server versions.
Deregister on shutdown: Always store filter/watcher references and deregister them in your plugin's shutdown() method.