skills/hytopia-multiplayer/SKILL.md
Helps implement multiplayer features in HYTOPIA SDK games. Use when users need player management, server-authoritative gameplay, networking, or state synchronization. Covers Player class, server authority, network optimization, and player data.
npx skillsauth add abstrucked/hytopia-skills hytopia-multiplayerInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill helps you implement multiplayer features in HYTOPIA SDK games.
Documentation: https://dev.hytopia.com/sdk-guides/multiplayer
Use this skill when the user:
import { World, Player } from 'hytopia';
// Access all players
const players = world.players;
// Get specific player
const player = world.getPlayer(playerId);
// Iterate over players
for (const player of world.players) {
player.sendMessage('Hello!');
}
// Count players
const playerCount = world.players.length;
import { World, Player } from 'hytopia';
world.onPlayerJoin = (player: Player) => {
console.log(`${player.username} joined (${player.id})`);
// Send welcome message
player.sendMessage(`Welcome ${player.username}!`);
// Broadcast to others
world.broadcast(`${player.username} has joined the game!`, [player.id]);
// Spawn player at location
player.setPosition({ x: 0, y: 100, z: 0 });
};
world.onPlayerLeave = (player: Player) => {
console.log(`${player.username} left`);
world.broadcast(`${player.username} has left the game.`);
};
import { Player } from 'hytopia';
// Set custom data on player
player.setData('score', 0);
player.setData('kills', 0);
player.setData('inventory', []);
// Get player data
const score = player.getData('score');
const inventory = player.getData('inventory') || [];
// Persist data (saved across sessions)
player.setPersistedData('level', 5);
const level = player.getPersistedData('level');
import { Player } from 'hytopia';
// Server controls all movement - client sends inputs only
player.onInput = (input) => {
// Process input on server
if (input.isPressed('w')) {
// Calculate new position server-side
const newPosition = calculateMovement(player, input);
player.setPosition(newPosition);
}
};
// Never trust client position
// Always validate: check speed, bounds, collision
import { Entity } from 'hytopia';
class GameEntity extends Entity {
// Only sync what needs to be visible
syncProperties = ['position', 'rotation', 'health'];
tick(deltaTime: number) {
// Server updates state
this.updateAI(deltaTime);
// Changes automatically sync to clients
// for properties in syncProperties
}
}
import { Player } from 'hytopia';
function validatePlayerMovement(player: Player, newPos: Vector3) {
const oldPos = player.position;
const distance = oldPos.distance(newPos);
const maxDistance = player.maxSpeed * deltaTime;
// Check if moved too fast
if (distance > maxDistance * 1.1) { // 10% tolerance
console.warn(`Possible speed hack: ${player.username}`);
player.setPosition(oldPos); // Revert
return false;
}
// Check if in bounds
if (!world.isInBounds(newPos)) {
player.setPosition(oldPos);
return false;
}
return true;
}
import { World } from 'hytopia';
// Send to all players
world.broadcast('Game starting!');
// Send to specific players
world.broadcast('Team message', [], [player1.id, player2.id]);
// Send to all except some
world.broadcast('Secret message', [player1.id]);
// Send to nearby players only
function broadcastToNearby(origin: Vector3, message: string, radius: number) {
for (const player of world.players) {
if (player.position.distance(origin) <= radius) {
player.sendMessage(message);
}
}
}
import { Entity } from 'hytopia';
class OptimizedEntity extends Entity {
// Only sync when changed
private _health: number = 100;
get health() { return this._health; }
set health(value: number) {
if (this._health !== value) {
this._health = value;
this.sync('health', value); // Manual sync only on change
}
}
// Don't sync internal state
private pathfindingTarget: Vector3; // Server-only
private lastUpdate: number; // Server-only
}
import { Player } from 'hytopia';
// Simple team system
const teams = new Map<string, Player[]>();
function assignTeam(player: Player, teamName: string) {
// Remove from old team
const oldTeam = player.getData('team');
if (oldTeam) {
const oldPlayers = teams.get(oldTeam) || [];
teams.set(oldTeam, oldPlayers.filter(p => p.id !== player.id));
}
// Add to new team
player.setData('team', teamName);
const teamPlayers = teams.get(teamName) || [];
teamPlayers.push(player);
teams.set(teamName, teamPlayers);
// Notify team
for (const teammate of teamPlayers) {
teammate.sendMessage(`${player.username} joined ${teamName}!`);
}
}
function getTeamPlayers(teamName: string): Player[] {
return teams.get(teamName) || [];
}
const spawnPoints = [
{ x: 10, y: 100, z: 10 },
{ x: -10, y: 100, z: 10 },
{ x: 10, y: 100, z: -10 },
{ x: -10, y: 100, z: -10 }
];
function spawnPlayer(player: Player) {
const spawnIndex = world.players.length % spawnPoints.length;
player.setPosition(spawnPoints[spawnIndex]);
player.setHealth(100);
player.clearInventory();
}
function updateLeaderboard() {
const sorted = [...world.players].sort((a, b) =>
(b.getData('score') || 0) - (a.getData('score') || 0)
);
const leaderboard = sorted.slice(0, 10).map((p, i) =>
`${i + 1}. ${p.username}: ${p.getData('score') || 0}`
).join('\n');
world.broadcast('=== Leaderboard ===\n' + leaderboard);
}
development
Helps build and manage worlds in HYTOPIA SDK. Use when users need to create terrain, place blocks, manage chunks, or work with the world editor integration. Covers blocks, chunk loading, world generation, and build.hytopia.com workflow.
tools
Helps create and use plugins in HYTOPIA SDK games. Use when users need to add NPM packages, create reusable modules, or extend game functionality. Covers plugin requirements, installation, and best practices.
development
Helps implement physics and collision in HYTOPIA SDK games. Use when users need rigid bodies, collision detection, raycasting, forces, or physics-based gameplay. Covers PhysicsComponent, colliders, raycasting, and physics simulation.
development
Helps save and load persistent data in HYTOPIA SDK games. Use when users need to save player progress, leaderboards, game state, or any data that persists across sessions. Covers PersistenceManager, global data, and player data.