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

@jingx/part-six36

v0.1.4

Published

React package for the 3D lottery machine runtime.

Readme

3D Lottery Machine

Browser-based 3D lottery draw built with CreateJS, Cannon.js, and Three.js. The app loads a 3D lottery drum, simulates 36 numbered balls, and extracts 6 preset numbers after a short countdown.

Overview

This project is a canvas-based browser game with a lightweight static front end:

  • index.html loads the static assets and module entrypoint.
  • js/bootstrap.js builds the runtime config passed into CMain and starts the app.
  • js/appConfig.js contains the live draw and startup configuration.
  • js/CMain.js handles preload, asset registration, and game startup.
  • js/CGame.js controls countdown, shuffling, extraction, and reset.
  • js/CScenario.js builds the physics world and loads the machine mesh from models/sphere_machine.txt.
  • js/CBall.js renders and animates each numbered ball sprite.
  • js/settings.js stores canvas, camera, physics, and gameplay constants.

Tech Stack

  • CreateJS / EaselJS for stage management, sprites, and tweens
  • Cannon.js for physics simulation
  • Three.js plus FBXLoader for loading the lottery machine geometry
  • Howler.js for audio playback
  • jQuery and helper utilities from js/lib/

Current Game Flow

The current implementation is not a generic draw engine yet. It runs a fixed sequence defined in js/appConfig.js and passed through CMain into CGame:

  • TOTAL_NUMBERS = 36
  • NUMBERS_TO_PICK = 6
  • COUNTDOWN is set to 5
  • RESULT_NUMBERS is set to [12, 13, 14, 15, 16, 17]

After assets load, the game starts automatically, counts down, shuffles the balls, extracts those preset numbers in order, then resets and starts the loop again.

Running Locally

Use an HTTP server. Do not rely on opening index.html directly from the filesystem.

Option 1: Simple Static Server

cd /path/to/3d-game-v1
python3 -m http.server 8080

Then open http://localhost:8080.

Option 2: Vite

package.json includes Vite scripts:

npm install
npm run dev
npm run build
npm run build:react-package
npm run build:all
npm run preview

The current local Node version in this workspace is v18.18.0, so the repo is pinned below Vite 7. That is deliberate: Vite 5 and 6 support Node 18 / 20+, while Vite 7 requires Node 20.19+ or 22.12+.

If you only want the dev server:

npm start

React package compatibility:

  • @jingx/part-six36 supports React 16.8+, 17, 18, and 19

React Integration

This repo now includes a React package around the game runtime.

Current architecture:

  • the game still supports the original standalone page runtime
  • the React package now exports both a native component and an iframe wrapper
  • communication is handled through props and callbacks

The native component lives in src/react/LotteryMachine.js, the iframe wrapper lives in src/react/LotteryMachineFrame.js, and the package build uses vite.react-package.config.js.

Package Build

Build the standalone game and the React wrapper:

npm run build:all

Or build only the wrapper package:

npm run build:react-package

Run the local Vite consumer example:

npm run example:install
npm run example

Build the local Vite consumer example:

npm run example:build

Wrapper output:

  • dist-react/lottery-machine-react.js
  • dist-react/lottery-machine-react.cjs
  • emitted runtime assets in dist-react/ for sprites, sounds, fonts, and the model

From @jingx/[email protected] onward, the React package is shipped as a self-contained runtime bundle. Sprites, sounds, fonts, and the model are inlined into the package build, so consuming apps do not need to copy dist-react/ into their own public/ folder and older webpack-based React apps do not need to parse import.meta.url from the package.

Package export:

import {LotteryMachine, LotteryMachineFrame} from "@jingx/part-six36";

Install In Your React App

Local install from this repo:

npm install /absolute/path/to/3d-game-v1

Or in your React app package.json:

{
  "dependencies": {
    "@jingx/part-six36": "file:../3d-game-v1"
  }
}

Exact import shape in the React app:

import {LotteryMachine} from "@jingx/part-six36";

Native React Component

Use LotteryMachine if you want the lottery canvas to render directly inside your React tree without an iframe.

Example:

import {LotteryMachine} from "@jingx/part-six36";

export function LotteryMachinePanel() {
  return (
    <LotteryMachine
      countdown={10}
      resultNumbers={[12, 13, 14, 15, 16, 17]}
      onReady={(payload) => console.log("ready", payload)}
      onRoundComplete={(payload) => console.log("done", payload)}
      style={{width: 640, height: 640}}
    />
  );
}

A full consumer example is included in LotteryMachineConsumerExample.jsx.

There is also a runnable Vite app in examples/react-app/package.json. It consumes @jingx/part-six36 through a local file:../.. dependency, uses React 16.14.0, and forces a fresh Vite dev cache on startup so package rebuilds are picked up cleanly.

Because that example uses a local file: dependency outside the app root, its Vite config also allows the repo root in server.fs.allow. That setting is needed for local linked development; it is not the normal requirement for a published npm install.

Notes:

  • the container must have a real width and height
  • the component observes container resizes and rescales the canvas to fit that box
  • the native component currently supports only one mounted instance at a time because the legacy engine still uses shared globals
  • if you need multiple simultaneous machines, use LotteryMachineFrame

iframe Wrapper

Use LotteryMachineFrame if you want stronger isolation or need multiple embeds.

Example:

import {LotteryMachineFrame} from "@jingx/part-six36";

export function LotteryMachineScreen() {
  return (
    <LotteryMachineFrame
      gameUrl="/lottery-machine/index.html"
      countdown={10}
      resultNumbers={[12, 13, 14, 15, 16, 17]}
      onReady={(payload) => console.log("ready", payload)}
      onRoundComplete={(payload) => console.log("done", payload)}
      style={{width: "100%", height: "100%", border: 0}}
    />
  );
}

Host The Standalone Game Assets

LotteryMachineFrame needs a URL for the actual game page.

Typical flow:

  1. Run npm run build
  2. Host this repo's dist/ output inside your React app's public assets, for example at /lottery-machine/
  3. Point the wrapper's gameUrl prop to that hosted page

Example hosted URL:

/lottery-machine/index.html

Why iframe Still Exists

LotteryMachineFrame is still useful because:

  • this project still uses a legacy global runtime internally
  • iframe keeps those globals isolated from your React app
  • it allows multiple simultaneous embeds
  • it works well when the standalone page is already hosted elsewhere

Initial Values Through URL

The runtime supports query parameters:

  • countdown
  • results

Example:

/lottery-machine/index.html?countdown=10&results=12,13,14,15,16,17

Live Updates From React

The embedded page listens for:

{
  type: "LOTTERY_MACHINE_UPDATE_DRAW",
  payload: {
    countdown: 10,
    resultNumbers: [12, 13, 14, 15, 16, 17]
  }
}

resultNumbers should contain exactly 6 integers in the 1-36 range.

The embedded page also exposes window.LotteryMachine with:

  • updateDraw({ countdown, resultNumbers })
  • getDrawConfig()

Result Complete Event To React

When the last ball fully reaches the end of the tube and stops, the embedded page sends this message to the parent:

{
  type: "LOTTERY_MACHINE_ROUND_COMPLETE",
  payload: {
    resultNumbers: [12, 13, 14, 15, 16, 17],
    releasedSum: 87,
    countdown: 10
  }
}

This is posted with window.parent.postMessage(...).

Behavior Notes

  • if React sends a new countdown before extraction starts, the game resets its countdown to the new value
  • if React sends new values while balls are already being extracted, the new config is applied to the next round
  • resultNumbers must contain exactly 6 integers in the 1-36 range

Configuration

The main places to change behavior are:

  • index.html
    • Static page shell and script loading order
  • js/appConfig.js
    • Active COUNTDOWN
    • Active RESULT_NUMBERS
    • CMain startup flags such as fullscreen and audio_enable_on_startup
  • js/settings.js
    • Canvas size
    • Camera settings
    • Physics constants
    • Shuffle timing
    • TOTAL_NUMBERS and NUMBERS_TO_PICK
  • js/CLang.js
    • UI text such as the start label

Project Structure

.
├── index.html
├── package.json
├── css/
├── js/
│   ├── appConfig.js
│   ├── bootstrap.js
│   ├── CMain.js
│   ├── CGame.js
│   ├── CScenario.js
│   ├── CBall.js
│   ├── CPreloader.js
│   ├── CInterface.js
│   ├── CLang.js
│   ├── settings.js
│   └── lib/
├── src/
│   └── react/
├── models/
│   └── sphere_machine.txt
├── sounds/
└── sprites/

Notes for Maintainers

  • The countdown and draw results in js/settings.js are legacy defaults only. Live values now come either from js/bootstrap.js / js/appConfig.js in standalone mode or from React props in the package runtime.
  • vite.config.js copies the legacy runtime directories into dist/ during build because the current game still loads many assets by string path at runtime instead of module import.
  • src/react/legacyRuntime.js packages the legacy scripts with raw imports and emits a manifest for sprites, sounds, models, and fonts so the native React component can resolve assets without hardcoded public paths.
  • js/CInterface.js exists, but the current game flow does not instantiate it.
  • js/CGame.js creates a start-extraction toggle and immediately unloads it, so the present behavior is effectively auto-start only.
  • LotteryMachine is a direct React mount, but it still wraps a legacy singleton engine under the hood. Only one native instance is supported at a time.
  • There is no automated test suite configured in package.json.

Assets

  • sprites/ contains UI, background, and ball sprite sheets
  • sounds/ contains panel, shuffle, extraction, and soundtrack audio
  • models/sphere_machine.txt is an FBX text export of the lottery machine mesh