RPG-JS Framework

repository·v5·Indexed 11 days ago

https://github.com/RSamaium/RPG-JS

A framework for creating RPG and MMORPG games, featuring a deterministic 2D top-down physics engine (@rpgjs/physic) for server-authoritative gameplay and a comprehensive chat system (@rpgjs/chat). Version 5.0.0-beta.7 includes tools for managing characters, static obstacles, and complex movement patterns like dashing, knockback, and path-following.

Tokens
305.7K
Snippets
1.1K
Records
1.3K
Agent score
76%

What's inside RPG-JS

  1. Overview of the Player Dash playground

    v5

    The Player Dash playground is a minimal RPGJS implementation demonstrating the native player dash input. It showcases how the client predicts a dash through the standard movement channel while the server maintains authoritative validation of the dash action.

    ### Controls
    - **Move**: arrow keys
    - **Dash**: `Shift`
    - **Action**: `Space`
  2. Overview of the @rpgjs/chat module

    v5
    The @rpgjs/chat module provides chat functionality for RPGJS games. It is designed to be renderer-neutral, meaning the chat logic can be integrated with different UI layers such as a CanvasEngine or Vue components. In a typical implementation, the server validates messages and broadcasts them to the current map. You can also implement server-side logic, such as automated moderation or bot responses, using chat moderation hooks.
  3. Vue GUI features and interaction patterns

    v5

    The Vue GUI demonstration showcases how the detached @rpgjs/vue package integrates with RPGJS v5 to create various UI elements:

    UI Component Types

    • Fixed Overlays: e.g., vue-hud (Heads-Up Display).
    • Server-opened Modals: e.g., vue-inventory (triggered by the server).
    • Server-opened Panels: e.g., vue-quest-log (triggered by the server).
    • Sprite-attached GUIs: e.g., vue-nameplate (UI elements that follow a specific sprite).

    Interaction Events

    • Vue-to-server interactions: Handled through the rpgGuiInteraction event.
    • Closing GUIs: Vue close events are emitted via rpgGuiClose.
  4. Choose the right RPGJS component type

    v5

    RPGJS uses different component systems depending on whether the visual is client-side, server-controlled, or an interactive interface. Use the following guide to select the correct system:

    • Sprite Components: Use when you want to add a visual effect (like shadows or auras) to every matching sprite from the client side.
    • Authoritative Sprite Components: Use when the server must decide what appears around a player (like name tags, HP bars, or badges).
    • Prebuilt Components: Use when you want to reuse an existing visual effect provided by RPGJS instead of building a custom .ce component.
    • GUI: Use for interactive interfaces that open, close, or send actions (menus, HUDs, dialogs).
    • Attached GUI: Use when you need an interface that follows a sprite but is controlled like a GUI.
  5. Understand the RPGJS core architecture

    v5

    RPGJS is a TypeScript framework designed for building both standalone browser RPGs and networked MMORPGs using a unified architecture. The default technology stack includes:

    • TypeScript: For writing game logic.
    • Vite: For development and production builds.
    • CanvasEngine: For rendering the game world.
    • RPGJS server and client packages: For handling gameplay mechanics and networking.
  6. Explore Client Interaction API capabilities

    v5

    The Mouse Interactions playground demonstrates several key patterns for handling user input via a mouse in RPGJS:

    • Hover Popovers: Using DOMContainer to show UI elements on hover.
    • Client-only Selection: Managing selection state locally on the client.
    • Hit Testing: Implementing hitbox or custom-area hit testing.
    • Drag and Drop: Implementing drag/drop previews that only trigger server-side calls upon a successful drop.
    • Map Clicks: Handling clicks on the map to trigger server-side actions, such as player.moveTo({ x, y }).
  7. What is a Shape in RPGJS

    v5

    A Shape is an invisible zone defined on the map that acts as a trigger mechanism. When an entity (like a player or an NPC) enters or leaves the boundaries of a shape, it can trigger specific actions.

    Shapes can be used in several ways:

    • Fixed Zones: Static areas on the map (e.g., a room entrance or a trap zone).
    • Moving Zones: Shapes that move across the map.
    • Attached Areas: Shapes attached to a player or an event to create systems like vision ranges, interaction radii, or aura effects.
  8. What is a World in RPG-JS

    v5

    A World is an abstraction that links several maps together using a shared coordinate system (world coordinates). You should use a World when your game requires:

    • Map-to-map transitions
    • Overworld navigation
    • A large, connected game world composed of multiple discrete maps.
  9. How Server-Authoritative Gameplay works in RPGJS

    v5

    RPGJS follows a server-authoritative architecture to ensure multiplayer correctness.

    • The Server owns the state: This includes player progression, inventory, combat results, map state, shared events, save data, and the validation of all client actions.
    • The Client is a view/input layer: The client is responsible for rendering, predicting movement/actions, gathering user input, and reacting to the synchronized state sent by the server.
    • Prediction & Reconciliation: While the client can use prediction to improve feel, it must remain reconcilable with the authoritative results provided by the server. A visual component should never silently become the owner of gameplay state.
  10. Enable Global Chat with a broadcast adapter

    v5

    Global chat is opt-in. To enable it, you must add 'global' to the channels array and provide a broadcastGlobal(message, player) adapter. This adapter is responsible for delivering the message to all clients across different rooms, processes, or edge locations.

    provideChat({
      server: {
        channels: ['map', 'global'],
    
        async broadcastGlobal(message, player) {
          await applicationChatBus.publish(message, {
            senderId: player.id,
          })
        },
      },
    })
  11. Dependency resolution workflow for database IDs

    v5

    When an API request requires a reference to an existing item or database ID (e.g., setting a weaponId for a hero or an itemId for an enemy reward), follow this workflow to ensure the ID exists:

    1. Search: Perform a search using GET /api/database/:type?query=<search>.
    2. Match: If a matching record is found, use its _id.
    3. Create: If no match is found, create the record using POST /api/database/:type.
    4. Reuse: Use the _id returned in the creation response for your original request.