hytopia
Version:
The HYTOPIA SDK makes it easy for developers to create massively multiplayer games using JavaScript or TypeScript.
127 lines (112 loc) • 4.03 kB
text/typescript
import {
startServer,
PlayerEntity,
PlayerEvent,
Player,
PersistenceManager,
} from 'hytopia';
import worldMap from './assets/map.json';
startServer(world => {
world.loadMap(worldMap);
// Handle player join
world.on(PlayerEvent.JOINED_WORLD, ({ player }) => {
const playerEntity = new PlayerEntity({
player,
name: 'Player',
modelUri: 'models/players/player.gltf',
modelLoopedAnimations: ['idle'],
modelScale: 0.5,
});
playerEntity.spawn(world, { x: 0, y: 10, z: 0 });
help(player);
});
// Handle player leave
world.on(PlayerEvent.LEFT_WORLD, ({ player }) => {
world.entityManager.getPlayerEntitiesByPlayer(player).forEach(entity => entity.despawn());
});
// Command definitions with help text
type Command = {
command: string;
description: string;
args?: string;
handler: (player: Player, args: string[]) => void;
};
const commands: Record<string, Command> = {
help: {
command: '/help',
description: 'Shows all available commands',
handler: (player: Player) => help(player),
},
whoami: {
command: '/whoami',
description: 'Shows your username and ID',
handler: (player: Player) => {
sendMessage(player, `You are ${player.username} | Your ID is ${player.id}`);
}
},
setPlayerKeyValue: {
command: '/setplayerkeyvalue',
description: 'Sets a player state key with a string value',
args: '<key> <value>',
handler: (player: Player, args: string[]) => {
const [key, ...value] = args;
if (!key || value.length === 0) return sendMessage(player, 'Usage: /setplayerkeyvalue <key> <value>', 'FF0000');
player.setPersistedData({ [key]: value.join(' ') });
sendMessage(player, `Set player state: ${key} = ${value.join(' ')}`);
}
},
setPlayerKeyJson: {
command: '/setplayerkeyjson',
description: 'Sets a player state key with a JSON value',
args: '<key> <json>',
handler: (player: Player, args: string[]) => {
const [key, ...value] = args;
if (!key || value.length === 0) return sendMessage(player, 'Usage: /setplayerkeyjson <key> <json>', 'FF0000');
try {
const jsonValue = JSON.parse(value.join(' '));
player.setPersistedData({ [key]: jsonValue });
sendMessage(player, `Set player state: ${key} = ${JSON.stringify(jsonValue)}`);
} catch (e) {
sendMessage(player, 'Invalid JSON value', 'FF0000');
}
}
},
getPlayerState: {
command: '/getplayerstate',
description: 'Gets all player state',
handler: async (player: Player) => {
const value = await player.getPersistedData();
sendMessage(player, `Player state: ${JSON.stringify(value, null, 2)}`);
}
},
deletePlayerKey: {
command: '/deleteplayerkey',
description: 'Deletes a player state key',
args: '<key>',
handler: (player: Player, args: string[]) => {
const [key] = args;
if (!key) return sendMessage(player, 'Usage: /deleteplayerkey <key>', 'FF0000');
player.setPersistedData({ [key]: undefined });
sendMessage(player, `Deleted player state key: ${key}`);
}
}
};
// Helper function for sending messages
function sendMessage(player: Player, message: string, color = '00FF00') {
world.chatManager.sendPlayerMessage(player, message, color);
}
// Register all commands
Object.values(commands).forEach(({ command, handler }) => {
world.chatManager.registerCommand(command, handler);
});
// Help command implementation
function help(player: Player) {
sendMessage(player, '=== Available Commands ===');
Object.values(commands).forEach(cmd => {
const usage = cmd.args ? `${cmd.command} ${cmd.args}` : cmd.command;
sendMessage(player, `${usage}`);
sendMessage(player, ` ${cmd.description}`);
sendMessage(player, '---');
});
}
});