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

aicraft-pixel-engine

v0.2.0

Published

Pixel-based falling-sand cellular-automaton physics engine for AI Craft games. Zero runtime dependencies.

Readme

aicraft-pixel-engine

A pixel-based falling-sand cellular-automaton physics engine for AI Craft games. Zero runtime dependencies. Deterministic. DOM-free core, fully testable in Node.

Inspired by Noita / Worms-style destructible-terrain sims. Extracted from the arcane-antics game into a reusable, dependency-free library that ships in the same sibling-repo style as aicraft-engine.

What it does

Simulation core

  • Falling-sand simulation. A typed-array pixel grid (Uint8Array) of 23 materials — sand, tephra, water, lava, oil, acid, fire, smoke, steam, flammable gas, rock, wood, ice, walls, plus the life materials (grass, seed, tree tip, leaf, fern tip, frond, spore, coral). Density-driven displacement, granular flow, liquid leveling, gas rising.
  • Material interactions. Lava + water → rock + steam. Acid dissolves solids. Fire spreads via flammability and is extinguished by water. Flammable gas ignites and explodes. Ice melts near heat.
  • Destructible terrain + explosions. Carve circles out of walls/rock, scatter colored debris as ballistic particles, ignite fire/smoke cores.
  • Pluggable gravity models. Movement rules ask "which way is down here?" instead of assuming +Y.
    • FlatGravity (default) — classic top-down gravity, byte-identical to a flat-world sim.
    • RadialGravity — gravity toward a single planet center. For Reus / Godfinger-style circular-planet god games.
  • Deterministic. Seeded mulberry32 RNG; same seed + same inputs → identical grid evolution. Validated by golden tests under both gravity models.

Physical systems (all opt-in — a world that never uses one pays nothing)

  • Heat and climate. Turn on with enableHeat: true. Every thermal material conducts to its neighbours, radiates to the environment through exposed faces, and phase-changes: lava → rock, water → steam / ice, steam → water, ice → water. FIRE is an infinite heat source; LAVA is a finite body that cools. ambientTemperature is the climate dial — turn it down and the oceans freeze on their own.
  • Growth. Three rule kinds: spread (grass/moss — isotropic, moisture-gated, with a travel range), tip (trees/ferns — a directed, stateful growing point that leaves a trunk and branches behind it), and aggregate (seeds germinating, spores accreting onto coral). Growth is gravity-relative, so on a planet a tree grows radially outward. Tips always die, so a forest converges instead of consuming the grid.
  • Pressure transport. addPressureSource routes a liquid (v1: lava only) through its connected body to a real boundary outlet via a Dijkstra search, accounting for gravitational head and per-material resistance. Blocked sources accrue pressure and can fracture solids. injectLiquid is the one-shot version. This is the volcano engine.
  • Velocity field. setVelocity / applyImpulse give a cell a sub-cell velocity that integrates ballistically across frames under gravity and drag. Explosions and pressure outlets use it; hosts can use it for anything.
  • Fragmentation. An airborne lava cell that cools past its fragmentsAt threshold while still in flight becomes granular TEPHRA, which piles at its angle of repose and builds a cone. Grounded cells never fragment — they freeze to ROCK.
  • Yield strength. Lava is a Bingham plastic: it flows only while thick enough, stopping at a blunt front, which is why it looks like lava and not like orange water. Override per-cell via engine.stiffnessGrid as the melt cools.

Volcano subsystem (aicraft-pixel-enginesrc/volcano/)

  • A complete eruption cycle, composed from the primitives above rather than bolted on beside them: stampVolcano cuts a chamber and conduit into a planet, stepVolcanoFrame runs one frame of the explosive → effusive → repose cycle, and the plumbing maintenance (rechargeReservoir, remeltConduit, assimilateTephra) keeps a vent usable between episodes.
  • Temperature-driven rheology. stiffnessForTemp maps a lava cell's heat onto its yield thickness and syncFromHeat writes it back each frame, so a flow runs while molten, stalls into a blunt front as it chills, and sets into rock — the curve that makes lava read as lava.
  • Ash plumes, vent glow, and screen shake are not here; they are host-side renderables that never touch the grid, and this library ships no renderer. See showcase/helpers/volcano-effects.ts for a worked example.

Host-facing plumbing

  • Active-chunk optimization. Only simulate cells in 32×32 chunks flagged active, with border propagation so flow across chunk edges keeps regions alive. The heat field keeps its own independent chunk set, so a motionless flow still cools.
  • Render-dirty tracking. Consumers ask consumeRenderDirtyChunks() to know which regions of the grid changed since the last frame.
  • Settle detection. Turn-based games can beginSettle() and wait until the grid calms (or times out). Tunable per-engine via settleStableThreshold / settleTimeoutFrames / settleSwapThreshold.
  • Bulk stamping. beginBulk() / endBulk() skip per-cell bookkeeping while building a large world; stampDisc() is the brush primitive for everything smaller.

What it does NOT do (v1)

  • No rigid bodies. No planck / Box2D, no rotated boxes, no joints. The explosion API exposes a hook so a future rigid-body layer can apply its own impulses.
  • No rendering. The library owns the simulation; you own the canvas. Read grid, colorGrid, and consumeRenderDirtyChunks() and draw however you like.
  • No level generation, loading, or serialization. Only the simulation core ships in v1.

Install

The library is structured to be consumable three ways (mirrors aicraft-engine):

Option A — Git submodule (recommended for AI Craft sibling games)

git submodule add <aicraft-pixel-engine-git-url> src/lib/aicraft-pixel-engine
import { PixelEngine } from './lib/aicraft-pixel-engine/src/sand';
import { FlatGravity } from './lib/aicraft-pixel-engine/src/gravity';

Requires moduleResolution: "bundler" in your tsconfig.json. Vite resolves the path transparently.

Option B — Vendored copy

cp -r /path/to/aicraft-pixel-engine/src /path/to/game/src/lib/aicraft-pixel-engine/

Option C — npm package

npm install aicraft-pixel-engine
import { PixelEngine, FlatGravity } from 'aicraft-pixel-engine';

ESM only. The package is "type": "module" and its exports map publishes no require condition, so require('aicraft-pixel-engine') fails with ERR_REQUIRE_ESM on Node. Use import, or await import() from CommonJS. Only the package root (.) is exported — deep subpaths like aicraft-pixel-engine/src/sand are not part of the public surface.

Quick start

import { PixelEngine } from './lib/aicraft-pixel-engine/src/sand';
import { MaterialType } from './lib/aicraft-pixel-engine/src/materials';
import { FlatGravity } from './lib/aicraft-pixel-engine/src/gravity';

const engine = new PixelEngine({ width: 200, height: 150, seed: 12345, gravity: new FlatGravity() });

// Pour some sand
engine.setMaterial(100, 10, MaterialType.SAND);

// Step the simulation
engine.update();

// Read dirty chunks for rendering
const dirty = engine.consumeRenderDirtyChunks();

Circular planet (god-game mode)

import { PixelEngine } from './lib/aicraft-pixel-engine/src/sand';
import { RadialGravity } from './lib/aicraft-pixel-engine/src/gravity';
import { MaterialType } from './lib/aicraft-pixel-engine/src/materials';

const W = 200, H = 200, cx = 100, cy = 100;
const engine = new PixelEngine({
  width: W, height: H, seed: 1,
  gravity: new RadialGravity({ centerX: cx, centerY: cy }),
});

// Stamp a disc planet out of rock, then drop sand around it.
for (let y = 0; y < H; y++) {
  for (let x = 0; x < W; x++) {
    const dx = x - cx, dy = y - cy;
    if (dx * dx + dy * dy <= 30 * 30) engine.setMaterial(x, y, MaterialType.ROCK);
  }
}
engine.setMaterial(cx + 35, cy, MaterialType.SAND);

engine.update(); // sand falls radially toward the planet surface

Architecture

src/
├── materials/   # MaterialType enum + MaterialDef table (pure data)
├── gravity/     # GravityModel seam: FlatGravity (default), RadialGravity (planets)
├── sand/        # PixelEngine core + neighbor frame (the gravity-relative movement seam)
├── volcano/     # Opt-in subsystem: eruption cycle composed from the core's primitives
├── rng.ts       # mulberry32, shared by the engine stream and host side-streams
├── index.ts     # top-level barrel
└── tests/       # vitest suites (+ tests/helpers/ fixtures, never shipped)

volcano/ is the one subsystem rather than a core module: nothing in sand/, materials/, or gravity/ imports it, so a world that never builds a volcano never loads it. It composes pressure sources, the heat field, fragmentation, stiffnessGrid, and the velocity field into an eruption that ascends a conduit, fountains ballistically, and stacks a cone that stops growing — the arrangement that is hard to rediscover from the primitives.

Layer discipline (mirrors aicraft-engine): the entire v1 library is the deterministic core — pure functions, no DOM, no Math.random, no Date.now, no side effects. This keeps it fast to test in Node and safe to run headless or in a worker.

End-to-end wiring — install options, the render loop, input handling, and the per-system recipes — is in docs/integration.md.

Game prompts

Ready-to-paste build briefs for games built on the engine live in games/ — start with the god game, a one-screen circular-planet terraforming toy.

License

MIT