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

@adatechnology/game-characters-three

v0.9.4

Published

three.js presentation for @adatechnology/game-characters: the instanced crowd body (GPU animation, LOD, baking, variants, flying limbs) and the rich bodies (the Bestiário v17 builder, survivors with accessories and hands, the animator, wounds, eyes).

Readme

@adatechnology/game-characters-three

three.js presentation for @adatechnology/game-characters. three.js is passed in by the host (import * as THREE from 'three'), so the same code runs from a bundler or from a plain script (dist/index.global.js exposes the GameCharactersThree global).

Instanced crowd body (literal port of the game's, G 65336-65541):

  • buildInstancedBody(THREE, { segments, body? }): the merged geometry (torso, head, hair, jaw, eyes, arms, legs) tagged with bone, pivot and material; 16, 10 and 5 segments are the three levels of detail. body defaults to TEAM_GAME; any BodySpec moves the joints.
  • BODY_CHUNK / createBodyChunk: the GPU pose chunk, byte for byte from the game (only the hip joint is a parameter). createBodyMaterial adds the tints and glowing eyes.
  • createBodyBatch: begin, push per body, end; one draw call for a whole variant.
  • bakeBody and bakeVariants: bake a rich body into an instanceable geometry; the three variants rule of the game (7000 + c·101 + v·13).
  • createFlyingLimbs: 40 torn-off pieces that fly, bounce and stay, with injected blood effects.
import * as THREE from 'three'
import { buildInstancedBody, createBodyBatch } from '@adatechnology/game-characters-three'

const time = { value: 0 }
const batch = createBodyBatch(THREE, buildInstancedBody(THREE, { segments: 10 }), { max: 700, time })
scene.add(batch.mesh)
batch.begin()
batch.push({ a: [x, z, yaw, phase], b: [1.8, 1, stride, 0], c: [missingMask, infection, 1, skinTone], color: { r: 0.3, g: 0.4, b: 0.5 }, eye: { r: 1, g: 0.2, b: 0.1 } })
batch.end()
time.value += dt

Sound and blood of the bodies (on @adatechnology/game-audio and the running film of @adatechnology/game-fluids-three):

  • createCharacterSound(host.audio, { style? }): voice(typeId, 'idle' | 'alert' | 'special', position) for the 13 undead types (UNDEAD_VOICES: the game's groans and scream, the art scene's voice groan, scream and leap, with the class rule of the page for the types it does not have), body(event, position) (wound = flesh, cut = sever, burst or split = gore), player('grab' | 'bite' | 'hurt'). The 16 recipes (CHARACTER_SOUND_BANK) leave the same trace as the team code.
  • createFluidsBridge({ sink, film }) and bloodLookOfAge(age): a body event throws drops of blood into the film, in the fresh and dry colours of the infection age (ages.json), old_blood for the thin ones.

Player avatar. createPlayerAvatar(THREE, options?) is the team game's player body: the rich human of the Bestiário/Elenco built from presets/player-avatar.json ({ type: 'Lento', human: true, seed: 4242, skin, hs: 'short', hair }, shirt 0x3d5a73), overridable with { spec, shirtColor, clips, blend, fallSeconds, cascade, clipCascade } (clipCascade, default 5: how many times faster the joints follow while a clip that does not loop plays, so a strike reaches its pose by its impact).

const player = createPlayerAvatar(THREE)
scene.add(player.root)
player.update(dt, { speed, crouch, down, armed, pitch, hip }) // the gait is tied to the ground speed (cadence and swing from `walkCadence`/`walkGait`)
player.hand('R').add(weaponMesh) // a socket at the weapon hand
player.play('grabbed_bitten_human', { onEvent: (event) => event.type === 'impact' && applyBlow() }) // or player.play(myClip); player.on('event', fn); player.stop()

Crouch, down and the aimed arms are derived literally from the game's GPU pose code (BODY_CHUNK, lines quoted in src/player/avatar.ts): crouch is thigh -0.95, knee 1.9, trunk +0.25, hip -0.35; down turns the body about the hip (±1.5 rad, face up or down by the phase) with the limbs of pose 2; armed follows (pitch + 1) / 3. play overlays a PoseClip of @adatechnology/game-characters (channels: 'upper' leaves the legs to the gait; while crouched only a kick takes the legs, so a punch or the guard stays low) with a 0.12 s blend, and fires its events (impact, phase) once through onEvent and on('event'). hand('R') is the weapon hand (the puppet's right, at -x). A pose clip's armL/legL channels move that side (arms[1]/legs[0]), so punch_right and front_kick of ATTACK_CLIPS drive armL and legL, the same arm and leg the first-person view shows.

In the test room. room.setAvatar(toRoomAvatar(player, { strikeClips: ATTACK_CLIPS })) (or defaultCharacterClips() of game-kit-defaults, which also has the first-person clips) shows the body at the player's feet (toRoomAvatar only flips the pitch: the room counts a look up as positive, the team game a look down) and V switches between the first and the third person of @adatechnology/game-test-room. createAvatarTestModule({ avatar, camera, state }) is the module of the area avatar_area (AVATAR_AREA_ID): bench buttons for the view (1st/3rd person), crouch, stand, fall, get up, armed on/off, one button per registered clip (Tocar: grabbed_bitten_human, grab_bite_zombie, and with clips: [...POSE_CLIPS, ...ATTACK_CLIPS] the punch, shove, kick and the recoils; clipLocales gives the phase texts) and stop; metrics for the camera, the clip playing, the last clip event and the joints. Every action is a JSON line in the room log ({"type":"avatar","action":"play_clip","clip":...}), clip events included, and an impact event also gets its own {"action":"impact","clip":...,"t":...} line. The module takes the body, the view (camera: { mode, set }) and the state (state: { set }) by option and imports only @adatechnology/game-contracts.

toRoomAvatar also gives the room strike(clipId), which plays the attack clip on the body (the only source of a strike, first and third person) and answers the seconds to the impact read from that clip (the same in both views). strike(clip, { leg: 'left' }) kicks with the left leg and strike(clip, { hand: 'left' }) punches with the left hand: the mirror of the clip on the body (mirrorPoseClip, id <clip>_left). After a punch (an impact of kind punch) the body holds the guard (guardClip, default 'fight_guard', false for none) for guardHold seconds (default 1.2) while it stands still, so a combo goes guard, punch, guard; the punch blends in over punchBlend (default 0.05 s). Walking, running, a weapon or a held item drop the guard.

First-person arms. createFirstPersonArms(THREE, { colors?, rig?, stances?, clips?, blend?, bob? }) builds sleeves (upper arm, forearm, elbow, cuff) and hands of skin (palm, four fingers of three segments, a thumb that close on a grip) drawn in the camera's space, plus the right leg that only shows during a kick. arms.update(dt, { camera, targets, stance, speed, running, crouch, contact? }): the relaxed and fists stances are rest poses (FIRST_PERSON_STANCES, from presets/first-person-arms.json), hold follows the HandTargets of game-contracts (world space) with a two-bone IK from fixed shoulders, the elbow bending down and out; a target out of reach is clamped (the shoulder moves reachShift toward it first). arms.play('punch_right' | 'shove_two_hands' | 'front_kick') overlays a FirstPersonClip (FIRST_PERSON_CLIPS of game-characters-people, same durations and impact seconds as the attack clips); arms.on('event', fn) gives its impact; arms.handPose(side) reads where a hand is drawn. contact(origin, direction, maxDistance) (optional; distance to the first surface or null) makes the hands and the kick foot stop a few millimetres before a surface along the camera forward (the elbow bends); arms.play('front_kick', { leg: 'left' }) kicks with the left leg and arms.play('punch_right', { hand: 'left' }) punches with the left hand (the hands of the clip in a mirror). Hand frame: x wrist to knuckles, y back of the hand, z little-finger side; a left hand is the right one mirrored.

Geometry

The builders (createPersonBuilder, createBestBuilder, bakeBody, buildInstancedBody, createFlyingLimbs, createEye) draw with shapeGeometries(host) of game-shapes-three: boxes, cylinders, cones, spheres, circles, rings, lathes and tori come from game-shapes with the same bytes; dodecahedron, shape and capsule geometries are three's. tests/exact-golden.test.ts holds every bit as the old path made them.