npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

netplayjs

v0.4.1

Published

A framework for making P2P multiplayer games in Javascript.

Downloads

128

Readme

NetplayJS

Node.js CI npm

Make peer-to-peer WebRTC-based multiplayer games in JavaScript, no server hosting or network synchronization code required!

Quick Start

Here's how NetplayJS works:

  • You create your game within a single static HTML file.
  • You can use a variety of HTML5 game frameworks, including Three.js.
  • You can host this file anywhere (GitHub Pages, Itch.io, Glitch, and many more).

NetplayJS handles most of the complicated aspects of multiplayer game development, letting you create games almost as if they were local multiplayer games. Synchronization and matchmaking are handled automatically under the hood - and best of all you don't have to host any servers!

Let's make a very simple game. Create an HTML file and add the following script tag.

<script src="https://unpkg.com/[email protected]/dist/netplay.js"></script>

Now add this javascript code to the same HTML.

<script>
class SimpleGame extends netplayjs.Game {
  // In the constructor, we initialize the state of our game.
  constructor() {
    super();
    // Initialize our player positions.
    this.aPos = { x: 100, y: 150 };
    this.bPos = { x: 500, y: 150 };
  }

  // The tick function takes a map of Player -> Input and
  // simulates the game forward. Think of it like making
  // a local multiplayer game with multiple controllers.
  tick(playerInputs) {
    for (const [player, input] of playerInputs.entries()) {
      // Generate player velocity from input keys.
      const vel = {
        x:
          (input.pressed.ArrowLeft ? -1 : 0) +
          (input.pressed.ArrowRight ? 1 : 0),
        y:
          (input.pressed.ArrowDown ? -1 : 0) +
          (input.pressed.ArrowUp ? 1 : 0),
      };

      // Apply the velocity to the appropriate player.
      if (player.getID() == 0) {
        this.aPos.x += vel.x * 5;
        this.aPos.y -= vel.y * 5;
      } else if (player.getID() == 1) {
        this.bPos.x += vel.x * 5;
        this.bPos.y -= vel.y * 5;
      }
    }
  }

  // Normally, we have to implement a serialize / deserialize function
  // for our state. However, there is an autoserializer that can handle
  // simple states for us. We don't need to do anything here!
  // serialize() {}
  // deserialize(value) {}

  // Draw the state of our game onto a canvas.
  draw(canvas) {
    const ctx = canvas.getContext("2d");

    // Fill with black.
    ctx.fillStyle = "black";
    ctx.fillRect(0, 0, canvas.width, canvas.height);

    // Draw squares for the players.
    ctx.fillStyle = "red";
    ctx.fillRect(this.aPos.x - 5, this.aPos.y - 5, 10, 10);
    ctx.fillStyle = "blue";
    ctx.fillRect(this.bPos.x - 5, this.bPos.y - 5, 10, 10);
  }
}

SimpleGame.timestep = 1000 / 60; // Our game runs at 60 FPS
SimpleGame.canvasSize = { width: 600, height: 300 };

// Because our game can be easily rewound, we will use Rollback netcode
// If your game cannot be rewound, you should use LockstepWrapper instead.
new netplayjs.RollbackWrapper(SimpleGame).start();
</script>

And voila - a real-time networked game with rollback and client-side prediction.

Overview

NetplayJS is a framework designed to make the process of creating multiplayer browser games simple and fun. It consists of several different components.

  • netplayjs-server - The matchmaking and signaling server. You can host your own or use the public instance.
  • (WIP) netplayjs-netcode - Implementations of rollback netcode and lockstep netcode.
  • (WIP) netplayjs-connection - The client side code that communicates with the matchmaking server to establish connections.
  • netplayjs - A prototyping framework that lets you rapidly create multiplayer games.
  • netplayjs-demos - A collection of demos built in the prototyping framework to show off how to use it.

Installation

For simple usage, you can include NetplayJS directly from a script tag in an HTML file.

<script src="https://unpkg.com/[email protected]/dist/netplay.js"></script>

For larger projects, you should install NetplayJS from npm and bundle it with your application using Webpack or a similar module bundler.

npm install --save netplayjs

I also highly recommend that you use it with TypeScript, though this is not required. The examples following will be in TypeScript.

Usage

To create a game using NetplayJS, you create a new class that extends netplayjs.Game.

  • This class should implement functions for initailizing, updating, and drawing the game.
  • It should implement functions for serializing / deserializing the state (more info in the next section).
  • It should contain static properties used to configure the netcode (see here).
class MyGame extends netplayjs.Game {
  // NetplayJS games use a fixed timestep.
  static timestep = 1000 / 60;

  // NetplayJS games use a fixed canvas size.
  static canvasSize = { width: 600, height: 300 };

  // Initialize the game state.
  constructor(canvas: HTMLCanvasElement, players: Array<NetplayPlayer>) {}

  // Tick the game state forward given the inputs for each player.
  tick(playerInputs: Map<NetplayPlayer, DefaultInput>): void {}

  // Draw the current state of the game to a canvas.
  draw(canvas: HTMLCanvasElement) {}

  // Serialize the state of a game to JSON-compatible value.
  serialize(): JsonValue {}

  // Load the state of a game from a serialized JSON value.
  deserialize(value: JsonValue) {}
}

You can now start the game by passing your game class to one of several wrappers.

  • (WIP) new LocalWrapper(MyGame).start(); - Runs mutiple instances of the game in the same browser page. Use for local testing and rapid iteration.
  • new RollbackWrapper(MyGame).start(); - Runs the game using rollback netcode. Use for game states that can be rewound and replayed.
  • new LockstepWrapper(MyGame).start(); - Runs the game using lockstep netcode. Use for game states that can't be rewound.

Game State Serialization

The client-side prediction and rewind capabilities of netplayjs are based off of the ability to serialize and deserialize the state of the game. In the quickstart example above, we let the autoserializer take care of this. For most games, however, you will need to implement your own logic. You can do this by overriding Game.serialize and Game.deserialize in your subclass.

If you cannot serialize the game state, you can still use NetplayJS, but you will need to use Lockstep netcode, rather than predictive netcodes like Rollback, and you need to mark your game as deterministic.

Determinism

By default NetplayJS does not assume determinsim. It corrects for drift by having one player (the host) send authoritative state updates to the others. If you mark your game as deterministic, NetplayJS will skip sending these updates.

Whether or not JavaScript operations are cross-platform deterministic is a difficult question. We can safely assume integer arithmatic is deterministic. I can also confirm that floating point operations with WASM are generally cross platform deterministic (required by WASM spec). Anything else is potentially up in the air.

NetplayPlayer

A NetplayPlayer represents one player in a game. NetplayPlayer.getID() returns an ID that is stable across each network replication of the game.

DefaultInput

NetplayJS games are synchronized by sending inputs across a network. DefaultInput automatically captures and replicates keyboard events, mouse events, and touch events.

Assets Used from Other Projects

This repo contains code and assets from other open source projects.

  • https://github.com/mrdoob/three.js (MIT)
  • https://github.com/pinobatch/allpads-nes (zlib)
  • https://github.com/kripken/ammo.js (zlib)