NetplayJS Documentation

repository·master·Indexed 20 days ago

https://github.com/rameshvarun/netplayjs

A framework for creating multiplayer games with WebRTC signaling and matchmaking. It includes netplayjs-server for P2P connection bootstrapping, a client-side MatchmakingClient, and various network synchronization wrappers including LockstepWrapper, RollbackWrapper, and LocalWrapper. The library provides a serialization framework using JSON-compatible objects and msgpack, a DefaultInputReader for capturing browser events, and a GameClass interface for defining game logic and rendering.

Tokens
12.4K
Snippets
38
Records
53
Agent score
68%

What's inside NetplayJS

  1. Overview of Network Synchronization Algorithms in NetplayJS

    master

    The netcode directory contains core implementations of various network synchronization algorithms. These implementations are designed to be generic and decoupled from the NetplayJS framework, allowing them to be used in other projects or applications independently.

    When choosing an algorithm, consider that each has specific benefits and trade-offs regarding latency, consistency, and complexity; there is no single 'one-size-fits-all' solution for network synchronization.

  2. Overview of netplayjs-server responsibilities

    master

    The netplayjs-server is a game-agnostic server that handles two primary tasks:

    1. WebRTC Signaling: Bootstrapping P2P data channels between two browsers by forwarding signaling messages.
    2. Matchmaking: Starting matches between strangers online who are playing the same game.

    The server uses a specific protocol defined in matchmaking-protocol.ts within the @vramesh/netplayjs-common package.

  3. Choose the right NetplayJS Game Wrapper

    master

    NetplayJS provides different wrappers depending on your game's architecture and your testing requirements:

    • LocalWrapper: Use this to create multiple instances of a game within the same browser window. This is primarily intended for local testing and development workflows.
    • LockstepWrapper: Use this to wrap your game in lockstep netcode. This is the appropriate choice for games that cannot be easily rewound, such as those utilizing complex physics engines.
    • RolbackWrapper: Use this for games designed to be rewound, allowing for the rollback networking model.
  4. Understand the NetplayJS Serialization Framework

    master

    Serialization in NetplayJS is used for two primary purposes:

    1. Network Synchronization: Sending game inputs and game states over the network.
    2. Rollback Netcode: Saving a rewindable history of the game state.

    Data Format and Interoperability

    • Primary Format: The framework uses JSON-compatible objects as the main format. Serializers must return JSON-compatible objects, and deserializers must accept them.
    • Transport Layer: While the logic uses JSON-compatible structures, messages are encoded using msgpack at the transport level to reduce overhead while maintaining interoperability with JavaScript.
    • Production Recommendation: Because JSON is schemaless and carries overhead, for production-grade games, it is recommended to consider using ProtoBufs for more efficient serialization.
  5. Configure a NetplayJS game to use a custom server

    master

    By default, NetplayJS games use a shared hosted instance. To point a game to your own netplayjs-server instance without changing the game's source code, append #server=https://your-server-url.com to the game's URL as a fragment.

    Example: https://rameshvarun.github.io/netplayjs/pong/#server=https://your-server-url.com

    https://rameshvarun.github.io/netplayjs/pong/#server=https://your-server-url.com
  6. Manage game state with NetplayState requirements

    master

    For RollbackNetcode to function, your game state object (TState) must implement the NetplayState interface. The rollback algorithm relies on these specific capabilities to rewind and replay time:

    1. tick(inputs: Map<NetplayPlayer, TInput>): void: Advances the game simulation by one frame using the provided inputs for all players.
    2. serialize(): JsonValue: Returns a serializable representation of the current state (e.g., a plain object) so it can be stored in the rollback history.
    3. deserialize(state: JsonValue): void: Replaces the current state with the provided serialized data. This is used during rollbacks to jump back to a known valid frame.
  7. Implement input prediction with NetplayInput

    master

    To support rollback, your input type (TInput) must implement the NetplayInput interface. The core requirement is the ability to predict what the next input will be when network data is delayed.

    • predictNext(): TInput: Returns a predicted version of the input. This is typically used to repeat the last known input (e.g., if a player is holding 'Right', the prediction is also 'Right').
  8. Manage peer-to-peer connections with PeerConnection

    master

    The PeerConnection class manages a reliable WebRTC data connection to a specific peer. It handles the signaling lifecycle (offers, answers, and ICE candidates) and provides a high-level interface for sending and receiving data.

    Key features:

    • Automatic Signaling: It uses the provided MatchmakingClient to exchange WebRTC offers, answers, and ICE candidates.
    • Reliable Data Channel: It establishes an ordered, reliable RTCDataChannel for data transmission.
    • Message Serialization: Data sent via .send() is automatically encoded using msgpack. Received data is automatically decoded from msgpack.
    • Event-driven: It emits events like open and data to notify you of connection state changes and incoming messages.
    import { PeerConnection } from "./peerconnection";
    
    // Note: PeerConnection is typically instantiated internally by the MatchmakingClient,
    // but its interface is used to interact with peers.
    
    peerConnection.on("open", () => {
      console.log("Connected to peer!");
    });
    
    peerConnection.on("data", (data) => {
      console.log("Received data:", data);
    });
    
    peerConnection.send({ type: "chat", text: "hello" });