hytopia-events

📁 abstrucked/hytopia-skills 📅 11 days ago
4
总安装量
2
周安装量
#47925
全站排名
安装命令
npx skills add https://github.com/abstrucked/hytopia-skills --skill hytopia-events

Agent 安装分布

opencode 2
claude-code 2
mcpjam 1
openhands 1
zencoder 1
crush 1

Skill 文档

HYTOPIA Events & Input

This skill helps you handle events and input in HYTOPIA SDK games.

Documentation: https://dev.hytopia.com/sdk-guides/events

When to Use This Skill

Use this skill when the user:

  • Wants to respond to player actions or game events
  • Needs to handle chat commands
  • Asks about player input (keyboard, mouse, touch)
  • Wants to create custom events
  • Needs to handle game lifecycle events (start, end, player join/leave)
  • Asks about event prioritization or cancellation

Core Event Concepts

Event Listeners

import { World, Player } from 'hytopia';

// Listen for player join
world.onPlayerJoin = (player: Player) => {
  console.log(`${player.username} joined!`);
  player.sendMessage('Welcome to the game!');
};

// Listen for player leave
world.onPlayerLeave = (player: Player) => {
  console.log(`${player.username} left!`);
};

// Listen for player chat
world.onPlayerChat = (player: Player, message: string) => {
  console.log(`${player.username}: ${message}`);
  return true; // Return false to block message
};

Chat Commands

import { World, Player } from 'hytopia';

world.onPlayerChat = (player: Player, message: string) => {
  if (message.startsWith('!')) {
    const args = message.slice(1).split(' ');
    const command = args[0];
    
    switch (command) {
      case 'help':
        player.sendMessage('Available commands: !spawn, !teleport, !kit');
        break;
      case 'spawn':
        player.setPosition({ x: 0, y: 100, z: 0 });
        player.sendMessage('Teleported to spawn!');
        break;
      case 'kit':
        giveStarterKit(player);
        break;
      default:
        player.sendMessage(`Unknown command: ${command}`);
    }
    
    return false; // Don't broadcast command to other players
  }
  
  return true; // Allow normal chat
};

Player Input

import { Player, Input } from 'hytopia';

// Handle player input
player.onInput = (input: Input) => {
  if (input.isPressed('space')) {
    // Jump
    player.applyImpulse({ x: 0, y: 10, z: 0 });
  }
  
  if (input.isPressed('e')) {
    // Interact
    handleInteraction(player);
  }
  
  if (input.mouseDelta.x !== 0) {
    // Mouse moved horizontally
    player.rotation.y += input.mouseDelta.x * 0.1;
  }
};

Custom Events

import { EventEmitter } from 'hytopia';

// Create custom event emitter
const gameEvents = new EventEmitter();

// Define event types
interface GameEvents {
  'player-kill': { killer: Player; victim: Player };
  'game-start': { map: string };
  'game-end': { winner: Player };
}

// Listen for events
gameEvents.on('player-kill', ({ killer, victim }) => {
  killer.sendMessage(`You eliminated ${victim.username}!`);
  victim.sendMessage(`You were eliminated by ${killer.username}!`);
});

// Emit events
gameEvents.emit('player-kill', { killer: player1, victim: player2 });

Input Handling Patterns

Movement Input

player.onInput = (input: Input) => {
  const moveSpeed = 5;
  const moveDirection = new Vector3(0, 0, 0);
  
  if (input.isPressed('w')) moveDirection.z += 1;
  if (input.isPressed('s')) moveDirection.z -= 1;
  if (input.isPressed('a')) moveDirection.x -= 1;
  if (input.isPressed('d')) moveDirection.x += 1;
  
  if (moveDirection.length() > 0) {
    moveDirection.normalize().multiply(moveSpeed);
    player.velocity.x = moveDirection.x;
    player.velocity.z = moveDirection.z;
  }
};

Mouse/Click Handling

player.onInput = (input: Input) => {
  // Left click
  if (input.isMousePressed(0)) {
    const raycast = world.raycast(player.position, player.lookDirection, 5);
    if (raycast.hit && raycast.entity) {
      // Attack entity
      raycast.entity.takeDamage(10);
    }
  }
  
  // Right click
  if (input.isMousePressed(1)) {
    // Place block or use item
    useHeldItem(player);
  }
};

Game Lifecycle Events

import { Game } from 'hytopia';

const game = new Game();

game.onStart = () => {
  console.log('Game started!');
  // Initialize game state
};

game.onEnd = () => {
  console.log('Game ended!');
  // Cleanup, save state
};

game.onTick = (deltaTime: number) => {
  // Update game logic every frame
  updateGameTimer(deltaTime);
  checkWinConditions();
};

Best Practices

  1. Keep event handlers short – delegate to functions for complex logic
  2. Return false to cancel – prevent default behavior when needed
  3. Use typed events – define interfaces for custom events
  4. Clean up listeners – remove listeners when entities despawn
  5. Debounce rapid inputs – prevent spamming with cooldowns

Common Mistakes

  • Don’t forget to return boolean in chat handler
  • Don’t block all chat when handling commands (return true for normal messages)
  • Don’t forget input can be null if player disconnects mid-frame
  • Don’t rely on client-side input alone – validate on server