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

@tpgames/sdk

v0.4.1

Published

Public game authoring SDK for TPG.

Readme

@tpgames/sdk

Public game authoring SDK for TPG.

Most browser games that run inside TPG iframes should install @tpgames/game-kit instead. The game kit re-exports this SDK and owns the default iframe postMessage/runtime bootstrap, so game authors do not need to wire @tpgames/runtime-game or bridge packages directly.

Install

For normal iframe-hosted browser games:

bun add @tpgames/game-kit

For reusable non-iframe game logic packages or advanced bridge integrations:

bun add @tpgames/sdk @tpgames/core-types

Example

import { defineSimpleGame } from "@tpgames/sdk";

export default defineSimpleGame<{ phase: "lobby" | "prompt" }>({
  async surfacesReady(api) {
    if (!api.context().isAuthority) {
      return;
    }
    const controllers = api.controllerIds({ connectedOnly: true });
    const snapshot = api.getSharedStateSnapshot();
    const result = await api.setSharedState(
      { phase: controllers.length > 0 ? "prompt" : "lobby" },
      { expectedRevision: snapshot.revision }
    );
    if (result.status === "rejected") {
      console.warn(result.message);
    }
  }
});

Authoring helpers also include:

  • createDeadline(startedAt, durationMs) for round timers and vote windows
  • setPhase(state, nextPhase, updates) for phase transitions
  • syncPlayerValues(current, participantIds, createDefault) for player-scoped collections
  • FixedStepSimulation for host-authoritative ticks with explicit revisions and visible catch-up backlog
  • ClockOffsetEstimator for low-RTT timer/input timestamp alignment
  • SequencedInputBuffer for bounded reordering, contiguous consumption, and safe acknowledgements
  • interpolateSnapshot and reconcilePredictedState for remote rendering and optional local input replay
  • DeterministicFaultLink for seeded latency, jitter, loss, reordering, disconnect, and reconnect tests

Casual real-time pattern

Keep simulation state canonical on the authority. Send controller movement or aim on a latest-value channel, assign each input a participant-local sequence, and let the authority consume bounded contiguous inputs on fixed ticks. Publish tick, revision, and acknowledgement values with snapshots.

import {
  FixedStepSimulation,
  SequencedInputBuffer
} from "@tpgames/game-kit";

const inputs = new SequencedInputBuffer<MoveInput>(64);
const authority = new FixedStepSimulation({
  initialState,
  tickRateHz: 20,
  maxStepsPerAdvance: 8,
  step(state, { tick, revision, deltaMs }) {
    return simulate(state, inputs.drainContiguous(), {
      tick,
      revision,
      deltaMs
    });
  }
});

Render remote entities slightly behind server time and interpolate between two snapshots. Prediction is optional: apply local inputs immediately for visual responsiveness, then replace the base with each authoritative snapshot and replay only inputs newer than its acknowledgement. Smooth small corrections; snap large or safety-critical corrections. Never let predicted state decide scores, hits, authority, or persistence.

The reference envelope is a 20 Hz host simulation, at most eight catch-up steps per callback, 64 buffered inputs per participant, and small rooms on the published reliable/latest-value transport budget. Tank Arena exercises 80 ms one-way controller latency plus deterministic 80 ± 25 ms jitter/reordering tests. Packet loss, rollback fighting games, competitive FPS reconciliation, and audio-grade rhythm synchronization are not supported guarantees.

Each mounted surface executes its own definition. Use lifecycle hooks for the shell-owned game stage and repeatable surfacesLoading/surfacesReady hooks for iframe readiness. Shared-state setters reject non-authority surfaces. Player-state setters accept only the current participant's state unless the surface is authoritative. On request-capable bridges, setters resolve to applied or rejected; compatibility bridges resolve to accepted, and the later subscription echo remains canonical. Snapshot getters expose revisions for optimistic concurrency, so initialization hooks should pass expectedRevision and remain idempotent.

See the repo docs for the full runtime model and publishing flow.