Easy Multiplayer
Rollback netcode for the browser. Add deterministic multiplayer to any game with a few lines of code.
Get Started See Examplesimport { EasyMultiplayer } from 'easy-multiplayer/EasyMultiplayer.js';
const game = new EasyMultiplayer({
room: 'my-game',
tickRate: 20,
canvas: document.getElementById('game'),
state: { players: {}, coins: [] }
});
game.defineInput('left', () => keys.ArrowLeft || false);
game.defineInput('right', () => keys.ArrowRight || false);
game.on('tick', ({ state, query, random, players }) => {
for (const pid of players) {
if (query(pid, i => i.left && !i.right)) state.players[pid].x--;
if (query(pid, i => i.right && !i.left)) state.players[pid].x++;
}
});
game.on('draw', ({ state, myId, canvas }) => { /* render */ });
game.start();
Key Features
No Class Inheritance
Define your game with callbacks: on('tick'), on('draw'), on('playerJoined'). No base classes to extend.
Query-Based Input
Ask questions about input with predicates: query(pid, i => i.left && !i.right). Rollback only happens when an answer changes.
Automatic State Sync
Your game state is a plain JS object. The library snapshots, hashes, and syncs it automatically across all peers.
One-Line Networking
Pass a room name and call start(). Peer-to-peer connections via WebTorrent are handled for you.
Deterministic RNG
Use random() in your tick callback. It's seeded, deterministic, and automatically synced across rollbacks.
Visual Test Suite
Run multiple game instances side-by-side with simulated network delay. Detect desyncs, inspect state diffs, check determinism.
How It Works
Easy Multiplayer uses rollback netcode — the same approach used in fighting games and fast-paced multiplayer games. Every peer runs the game simulation locally at a fixed tick rate. Inputs are predicted, then corrected when the real inputs arrive over the network. If a prediction was wrong, the game rolls back and resimulates.
The query system is what makes this practical. Instead of comparing raw input values to decide whether to rollback, the game asks questions about input ("is the player pressing left?"). Only when a question's answer changes does a rollback happen. This dramatically reduces unnecessary rollbacks.
Learn more about the internals →
Get Started
Import the library via a CDN import map, create a game, define inputs, write your tick and draw logic, and call start(). That's it.