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 🙏

© 2026 – Pkg Stats / Ryan Hefner

netcore-networking

v2.3.0

Published

Transport-agnostic, room-based networking library for multiplayer games

Readme

netcore-networking

Transport-agnostic, room-based networking library for multiplayer games. Zero game engine dependency — pure networking primitives.

Install

npm install netcore-networking

Browser / CDN

The library ships browser-ready builds alongside the Node.js version.

ESM (bundlers, Vite, etc.):

import { NetCoreClient, WebSocketClientTransport } from "netcore-networking/browser";

IIFE (CDN, script tag):

<script src="https://unpkg.com/netcore-networking/dist/netcore.iife.js"></script>
<script>
  const client = new netcore.NetCoreClient({ url: "ws://localhost:7777" });
</script>

Server-only classes (GameServer, WebSocketAdapter, NetCoreServer, etc.) are excluded from browser builds at runtime.

Quick Start

Server

import { GameServer } from "netcore-networking";

const server = new GameServer({ port: 7777, defaultTickRate: 64 });

server.on("connection", (client) => {
    const room = server.getOrCreateRoom("lobby", { maxClients: 16 });
    room.addClient(client);
});

server.on("message", (client, message) => {
    console.log(`Client ${client.id}:`, message);
});

await server.start();

Client

import { NetCoreClient } from "netcore-networking";

const client = new NetCoreClient({
    url: "ws://localhost:7777",
    handshake: { name: "Player1" },
});

client.on("open", () => {
    console.log("Connected as", client.clientId);
});

client.on("state", (state, tick) => {
    // Apply authoritative server state
});

client.on("close", (reason) => {
    console.log("Disconnected:", reason);
});

await client.connect();

Architecture

core/           Transport, codec, server, client — raw networking primitives
high-level/     Rooms, tick loops, input tracking, state sync
security/       Middleware pipeline (rate limiting, signing, anti-cheat)
client-utils/   Prediction, interpolation — client-side smoothing

Core API

| Class | Purpose | |-------|---------| | NetCoreServer | Transport-agnostic server with middleware pipeline | | NetCoreClient | Auto-reconnect, sequenced input, handshake protocol | | RemoteClient | Server-side representation of a connected client | | BinaryCodec | Compact 9-byte header wire format | | JsonCodec | JSON fallback for debugging | | WebSocketAdapter | Server-side WebSocket transport | | WebSocketClientTransport | Client-side WebSocket transport | | TypedEmitter | Type-safe event emitter | | NetCoreError | Base error class with code property | | CodecError | Codec encoding/decoding errors | | ConnectionError | Connection lifecycle errors | | SecurityError | Security violation errors |

Custom Transport

import { type TransportAdapter, type ClientTransport, NetCoreServer, NetCoreClient } from "netcore-networking";

// Server-side transport
const myTransport: TransportAdapter = {
    name: "my-transport",
    listen(port, callbacks) { /* ... */ return Promise.resolve(port); },
    send(peerId, data) { /* ... */ },
    broadcast(data, exclude) { /* ... */ },
    getPeerCount() { return 0; },
    close() { /* ... */ },
};

// Client-side transport
const myClientTransport: ClientTransport = {
    name: "my-client-transport",
    get isConnected() { return false; },
    connect(callbacks) { /* ... */ return Promise.resolve(); },
    send(data) { /* ... */ },
    close() { /* ... */ },
};

const server = new NetCoreServer({ transport: myTransport });
const client = new NetCoreClient({ transport: myClientTransport, handshake: {} });

Pluggable Codec

import { type MessageCodec, NetCoreServer } from "netcore-networking";

const myCodec: MessageCodec = {
    encode(message) { /* ... */ return new Uint8Array(); },
    decode(data) { /* ... */ return { type: 0, sequence: 0, payload: new Uint8Array() }; },
    extractPayload(wire) { return JSON.parse(new TextDecoder().decode(wire.payload)); },
};

const server = new NetCoreServer({ codec: myCodec });

High-Level API

| Class | Purpose | |-------|---------| | GameServer | Room management + input routing | | Room | Game instance with own tick loop and state sync | | StateSync | Authoritative state broadcasting with delta compression | | InputTracker | Input deduplication (144Hz client on 64Hz server) |

Rooms

// Create a room
const room = server.createRoom("arena", { maxClients: 8, tickRate: 64 });

// Game loop
room.on("tick", (inputs) => {
    // Process inputs, update game state
    room.setState(myGame.serialize());
});

// Client lifecycle
room.on("join", (client) => console.log(`${client.id} joined`));
room.on("leave", (client, reason) => console.log(`${client.id} left: ${reason}`));

// Move client between rooms
lobbyRoom.removeClient(client.id);
matchRoom.addClient(client);

Delta Compression

const room = server.createRoom("arena", {
    serializeDelta(prev, curr) {
        // Return only changed fields, or null for full state
        return diffState(prev, curr);
    },
});

Client Input

// Send sequenced input (auto-injects sequence + timestamp)
client.sendInput({ dx: 1, dy: 0, actions: ["jump"] });

// Track last acknowledged sequence for prediction
client.on("state", (state, tick) => {
    prediction.reconcile(state, client.lastAckedSequence);
});

Security

Middleware Pipeline

import { RateLimiter, MessageSigner, AntiCheatManager, SpeedDetector } from "netcore-networking";

server.use(new RateLimiter({ maxConnectionsPerIp: 5, maxMessagesPerSecond: 60 }));

server.use(new MessageSigner({
    secret: new Uint8Array(32), // your secret key
    maxAgeMs: 5000, // replay protection window
}));

server.use(new AntiCheatManager({
    plugins: [new SpeedDetector({ maxDistancePerTick: 10 })],
    autoKickOnCritical: true,
}));

Rate Limiter

const limiter = new RateLimiter({
    maxConnectionsPerIp: 5,
    maxMessagesPerSecond: 60,
    whitelistIps: ["127.0.0.1"],
});

limiter.banIp("1.2.3.4");
limiter.unbanIp("1.2.3.4");

Anti-Cheat Plugins

// Built-in plugins
const speedDetector = new SpeedDetector({
    maxDistancePerTick: 10,
    burstWindowTicks: 5,
    maxBurstAverage: 8,
});

const teleportDetector = new TeleportDetector({
    maxTeleportDistance: 50,
    minOccurrences: 2,
});

// Allow legitimate teleport zones
teleportDetector.addAllowedZone(clientId, spawnX, spawnY, 5);

// Write your own plugin
const myPlugin: AntiCheatPlugin = {
    name: "my-detector",
    description: "Custom cheat detection",
    onClientConnect(clientId) { },
    onClientUpdate(clientId, data) { return null; },
    onClientDisconnect(clientId) { },
    destroy() { },
};

Client Utilities

Prediction (Client-Side)

import { PredictionManager } from "netcore-networking";

const prediction = new PredictionManager({
    applyInput: (state, input) => ({
        ...state,
        x: state.x + input.dx * speed,
        y: state.y + input.dy * speed,
    }),
    serialize: (state) => JSON.stringify(state),
    deserialize: (data) => JSON.parse(data),
});

// Record input sent to server
prediction.recordInput(sequence++, { dx: 1, dy: 0 });

// On server state update, reconcile
const corrected = prediction.reconcile(serverState, serverLastSeq);

Interpolation (Remote Players)

import { InterpolationManager } from "netcore-networking";

const interp = new InterpolationManager({
    renderDelayMs: 31,
    interpolate: (a, b, t) => ({
        x: a.x + (b.x - a.x) * t,
        y: a.y + (b.y - a.y) * t,
    }),
});

// Feed server snapshots
interp.addSnapshot(playerId, { x: 100, y: 200 }, timestamp);

// Render at interpolated position
const pos = interp.getPosition(playerId, performance.now());

Message Wire Format

Default BinaryCodec uses a compact binary format:

[1B type][4B sequence LE][4B payload length LE][NB payload]

| Type | Value | Direction | |------|-------|-----------| | HANDSHAKE | 0x00 | Both | | INPUT | 0x01 | Client -> Server | | STATE | 0x02 | Server -> Client | | PING | 0x03 | Both | | PONG | 0x04 | Both | | ROOM_JOIN | 0x05 | Server -> Client | | ROOM_LEAVE | 0x06 | Server -> Client | | KICK | 0x07 | Server -> Client | | Custom | 0x80+ | Either |

Error Handling

All errors extend NetCoreError with a code property:

import { NetCoreError, CodecError, ConnectionError, SecurityError } from "netcore-networking";

try {
    await client.connect();
} catch (err) {
    if (err instanceof ConnectionError) {
        console.error(`[${err.code}] ${err.message}`);
    }
}

| Error | Code | When | |-------|------|------| | CodecError | ERR_CODEC | Invalid message encoding/decoding | | ConnectionError | ERR_CONNECTION | Connection failed, timeout, or rejected | | SecurityError | ERR_SECURITY | Rate limited, origin rejected, or HMAC failure |

License

MIT