◆Plaster// After action report
After action report

Changelog

// 95 entries · newest first

Every real change to Plaster, added as part of the work, never batched later.

Ready to go online at play.plastergame.com

2026-10-27
  • Hosting plan: the game gets its own address, play.plastergame.com, on a free Oracle Cloud server; the website stays on Netlify at plastergame.com. Player accounts and progress will go in Supabase, saved by the game server so nobody can edit their own level.
  • deploy/: a one-time setup.sh (Node 22, Caddy for automatic HTTPS, firewall, a service that restarts the server and starts it at boot) and update.sh, which puts the latest production branch live. Step-by-step guide in deploy/README.md.
  • Public build: PLASTER_PUBLIC=1 builds the game without the map editor.
  • Server hardening: a malformed address (such as /%E0) used to crash the whole server and end every match; it now gets a 400. The file check no longer lets through folders whose names start with dist. New HOST setting so the server only listens behind Caddy.

Bigger scoreboards and Esc menu; a steady Tab board and overhead view

2026-10-27
  • Tab no longer flashes: the browser's own auto-repeat of a held Tab now gets stopped too. Before, it moved focus off the game, the window lost focus, the held keys cleared and the board blinked off and on. The board is also rebuilt only when a score changes, not every frame (T-125).
  • Bigger scoreboards: the Tab board and the end-of-match board are wider with larger text and rows, on a dark see-through panel so they read over the match (T-127).
  • Overhead view: the speedball turf sits 2 mm above the grass. From the high, turning view between rounds and at a match's end, the eye's 5 cm near plane left too little depth precision and the ground flickered. The overhead camera now uses a 1 m near plane (T-128).
  • Esc menu: fills most of the screen (up to 1500 px wide, the full height under a smaller logo), with larger tabs and text (T-129).

Everyone sees your paint job, and a clean hand-up

2026-10-27
  • Marker Paint online: the match roster and the lobby list carry each player's Marker Paint, so other players see your marker in your paint job, in their hands in the match and in the lobby lineup. A change made in the menu shows from your next spawn, like a new marker (T-122).
  • The "I'm out" hand: when an eliminated player raised their hand, the glove stretched into a long dark streak. The hand-up shape was made with the arm in its plain pose, but the hand holds the marker with fitted fingers; the left arm's bones now ease back to the plain pose as the hand goes up (T-123). New playtest out-pose checks it.

Marker Paint, Paintball Paint, and attachments you unlock

2026-10-26
  • Paint split in two: Marker Paint (the paint job, was "Paint"; earlier picks carry over) shows a swatch of each scheme, and the marker's picture in Loadout and in your operator's hands in the lobby take the paint you pick. Paintball Paint is the colour of the balls you fire and the splat they leave (on the world, on players, on the goggles of whoever you hit); each colour is shown as a splatter with balls. Stock is your team's paint. Online, every shot carries its colours, so everyone sees your paint.
  • Unlocks: every marker has its own level and headshot count. Eliminations with it give it XP (100 online, 50 in practice, +50 for a headshot). Barrels, mags, rounds and paintball colours unlock at marker levels (2 to 7); paint jobs unlock at 5, 15, 30 and 50 headshots with that marker. Locked options are greyed out with what's left; the Attachments screen shows the marker's level, XP and headshots, and each marker in Loadout shows its level. A headshot is a ball that touches the head; the game (and the server, online) checks it and a "Headshot" call-out shows under the crosshair.
  • POE › Attachments: every slot's options, what they change and what unlocks them, editable: add paint jobs and paintball colours, new parts, change the unlock levels and headshot counts. Saved to public/markers/attachments.json, which the game and the server read.
  • Only unlocked picks are fitted or sent to the server. Progress is kept per browser, like your career XP.

Three characters to play, and Customize on the Loadout panels

2026-10-26
  • Characters (Operators › Character): Woodland (the player so far), Ranger (arid camo shirt, ranger-green pants, a coyote plate carrier with three mag pouches, an admin pouch and MOLLE on the back, a cap worn backwards, tan mask) and Urban (charcoal top, urban camo pants, a black chest rig with four pouches and an H harness, a beanie, white mask). All three are the same MPFB body on the same rig, so they're the same size and are hit the same way; only the kit differs. Your first-person sleeves and gloves are your character's. Online, everyone sees the character you picked.
  • How: tools/blender/character_mpfb.py --variant ranger|urban dresses the body, and character_game.py bakes and exports public/builtin/character-ranger.glb and character-urban.glb (about 10 MB each, like the first). On the Ranger the number patch sits on the carrier's back panel.
  • Loadout: the list on the left only picks your marker now. Each slot's panel in the middle says Customize; pressing it opens that marker's attachments.

Marker attachments, idle / sprint / equip clips, and steadier aiming

2026-10-26
  • Attachments (T-108): in Loadout, the list on the left picks the marker; pressing its panel in the middle (marked Customize) opens its Attachments screen, full width with no operator beside it. Four slots: Barrel (stock; long: spread ×0.8, reloads ×1.1; short: spread ×1.25, reloads ×0.9; primaries only), Magazine (standard; extended: ×1.5 paint, one spare less, reloads ×1.15; speed: ×0.75 paint, reloads ×0.75), Rounds (field paint; First Strike: velocity ×1.1, drag ×0.6, spread ×0.7, one spare less) and Paint (factory, desert tan, olive drab, arctic, hi-vis: the marker body's colours). A panel shows each number stock → fitted, better in lime and worse in red. Picks are kept per marker. Online, the server fits the same parts (src/sim/attachments.js is shared), so the stats it sends at spawn match. First values, to tune.
  • Marker animation slots (T-50): an imported model's clips can now also be set as Equip (plays when the marker is drawn), Idle and Sprint (looped underneath; sprint while sprinting). Fire, reload and equip play over the loop, which fades out while they run. Set them in POE under Animations.
  • Fix: aiming flicking out and back in (T-120): a worn mouse switch can report one right-button press as down-up-down within a few milliseconds, and each bounce dropped the sights. A release now counts once it has lasted 60 ms. A right-button release missed while the pointer was locked no longer leaves you aiming.
  • New playtests: aim (holding, releasing, a bouncing switch), attachments (fitted stats, First Strike speed, paint job) and marker-anims (a test GLB whose clips each move it on its own axis, served to the test browser only).

Automated playtests, and the quick reload at low frame rates

2026-10-25
  • Playtests (tests/playtest/): node tests/playtest/run.mjs opens the real game in a headless browser, plays it with real key presses and checks what happened, saving screenshots and a report. First scenarios: the game loads to the menu; shooting (one paintball per trigger pull, a miss leaves the bot standing, one chest hit eliminates it); reloading (tap swaps, hold drops, a full mag doesn't reload, a dry trigger pull reloads). Any console error fails the run.
  • Fix: holding R for the quick reload was timed on the game's clock, which runs slower than real time below 20 fps. On a slow machine a 0.3 s hold did the slower swap reload instead, unless held for several seconds. It's now timed in real seconds, and letting go after 0.3 s counts as a hold even if no frame came in between. Found by the reload playtest.

Fingers that hold the markers properly

2026-10-24
  • Every hand refitted with the new finger bones: on the character (what you see on other players), the first-person rifle and the first-person pistol. Fingers wrap the grip and handguard and rest on them instead of floating or sinking in.
  • Character: its right hand lay flat beside the grip with straight fingers; it now holds the grip as the first-person hands do (the pose set in Blender), index finger on the trigger, support hand under the handguard.
  • Pistol: the hands were apart with the fingers hanging open; now a two-handed grip, the support hand closed over the strong hand's fingers.
  • New tool, tools/blender/hand_fit.py: stands the marker in with exact convex shapes of its grip, receiver and handguard, and for each finger searches all three joints together for the bend that puts the pads on the surface without going in. Re-run it after posing hands in Blender to tidy the fingers.

Fix: frame drop when a player is out (T-121)

2026-10-24
  • Paint landing on a player cost about 180 ms on the frame of the hit (measured in the test browser): finding the exact spot on the 43k-triangle character meant skinning every triangle on the CPU, and the splat was cut from the whole mesh. The hit now goes bone by bone through each bone's rest shape (only the bones the shot passes), and the splat is cut from the few hundred triangles around the hit: 1 to 3 ms for the hit, about 3 ms for a splat on the body, up to 18 ms on the dense mask.
  • The skinned splat's shader is compiled when play starts, with the fade shaders, instead of on the first hit.

Hands and fingers you can pose in Blender

2026-10-24
  • Finger bones: the player character's rig keeps its nine game bones and now also has each arm's upper arm, forearm, hand and all fifteen finger and thumb joints (under gun and leftArm), and the mesh is skinned to them. The first-person arms (rifle and pistol) are skinned meshes on rigs of the same bones.
  • Pose, then export: in blender-out/character-game/character_game.blend, select Rig, ViewArms or ViewArmsPistol, Ctrl+Tab for Pose Mode, rotate the bones, then run the Export to game.py text (or tools/blender/character_export.py). The game shows the hands as posed. Each rig holds a reference marker or pistol so you can see what the fingers wrap round.
  • Poses are saved to tools/blender/hand_poses.json, and rebuilding the character (character_game.py) applies them again, so they aren't lost.

First-person arms from the new character, with hands on the grip

2026-10-24
  • Your own arms: the arms you see in first person are now the MPFB character's own sleeves (pocket, elbow patch, armband) and gloves, posed on the marker where the first-person camera sees it and cut off at the shoulder. Before, they were the old character's tube arms in the new camo.
  • Pistol too: the P17 has its own pose: the strong hand on the grip, its finger through the guard onto the trigger, and the support hand wrapped round the front over the strong hand's fingers. Before, the hands were built in code and didn't match the gloves.
  • Fingers on the surface: each finger joint now curls until it touches the marker (or the other hand), and the hand moves out until no part of the glove is inside the grip. Before, the curls were set by eye and fingers and thumbs went through the grip. The third-person character's hands use the same fit.
  • How: tools/blender/character_game.py poses the study three times (third-person hold, first-person rifle, first-person pistol), bakes both sets of arms onto their own 2048 maps and exports them as ViewArms and ViewArmsPistol. character.glb 9.4 MB (was 5.4).

A new player character, right-handed

2026-10-24
  • New look: everyone is now the MPFB character from the Blender study: a full human body in a camo field jacket and cargo pants (pockets, flaps, pads), gloves, laced boots, and an i5-style mask fitted snug over a balaclava. 37k triangles; the detail of the 400k-triangle study is baked into its textures. character.glb 5.4 MB (was 3.6).
  • Right-handed: players used to hold the marker on their left side, right hand on the handguard. Now the right hand is on the grip and the left hand is under the handguard. Aiming down sights leans the head onto the sight on that side.
  • "I'm out": the raised hand is modelled through the collarbone, shoulder and elbow, so the shoulder no longer stretches when the arm goes up.
  • Team colour on both armbands and the mask strap, and the number on a patch high on the back. The first-person arms wear the new jacket and gloves.
  • How: tools/blender/character_game.py poses the study onto the marker, decimates it, bakes it and exports it with the game's rig. The old model's script (character.py) stays for reference.

PolyHaven scans on trees, rocks, logs, metal and sandbags

2026-10-24
  • Tree bark: spruces wear PolyHaven's pine_bark and broadleaves bark_brown_02 (warmed a little, or the shade turns it blue), instead of bark painted in code. trees.glb 7.1 MB (was 5.5).
  • Rocks: mossy_rock, a grey stone with lichen, projected onto each sculpt and baked with the moss on top and the dirt at the foot as before. Fallen logs and stumps: bark_brown_01 along the grain. The peeled deadwood and end grain stay painted (there's no scan of those).
  • Metal: sheds, roofs and fences are corrugated_iron_02; painted metal (vehicles, containers) is rusty_metal_02 made greyscale, so the colour you pick paints it and its rust and wear show as darker patches; steel frames are metal_plate_02. Sandbags are burlap (hessian_230).
  • Oil drums keep their own painted wear (chips, stencil, any colour), and the bare rust is now a scan (rust_coarse_01).
  • How: node tools/fetch-polyhaven.mjs downloads the sets (not kept in git), tools/blender/ph_convert.py makes the game's WebP sets, and the Blender scripts use the scans when they're there. The canvas and painted textures stay as fallbacks. Not changed: leaves and needles (PolyHaven has no leaf cards), the inflatable bunkers, characters and markers.

Fix: players looking down or up can be hit in the head

2026-10-24
  • A player's upper body bends with where they look: forward when they look down, back when they look up, a little forward when crouched. Their head can move up to 0.7 m that way, but the hitbox's head stayed upright, so shots at the head you could see missed. Hitboxes (players and bots) now bend exactly like the avatar, together with the Q / E lean.

Moderation for public playtests

2026-10-23
  • Name filter on the server: names are checked against server/blocked-words.txt (editable; look-alike spellings like F4ck or f.u.c.k are caught, ordinary names like Scunthorpe or Cassie aren't). A blocked name becomes Player N and the player is told why.
  • Kick and ban: from the lobby's player list, or from a new Players tab in the Esc menu during a match. The person running the server can remove anyone, and a private lobby's host can remove players from their own lobby. A kicked player goes back to the main menu and a bot takes their place. A ban covers their browser and IP until the server stops.

Fix: leaning players can be hit in the head

2026-10-23
  • The lean (Q / E) now reaches the server: the head and upper body of the hitbox move out with it, and other players see your avatar lean the same distance.

Fix: frame drop when someone is out

2026-10-23
  • The fade-out shaders for an eliminated player are now compiled when play starts, not at the first elimination.

Fix: lobby name tags

2026-10-23
  • Name tags over the lineup no longer slide under the side panels (a figure standing behind a panel has no tag), tags don't overlap each other, and the Open · bot fills tags are readable.

Go live for the Test build too

2026-10-23
  • The hub's Test card has its own Go live button, so a build can be playtested with people before it goes to production. Test and Production each get their own link and player count, and both can be live at the same time.

Go live: a public link for playtests, from the hub

2026-10-23
  • The Production card in Plaster Engine's hub has a Go live button once the production build is running. It opens a Cloudflare quick tunnel and shows the public trycloudflare.com link with Copy, the number of players online and Stop.
  • Players connect through Cloudflare, so your IP address isn't shown, and nothing is opened on the router. Only the built game and multiplayer are reachable. The link stops when you stop, when production stops or when the engine quits. Needs cloudflared on Windows (winget install Cloudflare.cloudflared).

Touch controls for phones and tablets

2026-10-23
  • A floating move stick where your left thumb lands (push it to the edge to sprint) and drag to look on the right half. Fire also works as a look pad.
  • Buttons: Fire, Aim (a toggle), Jump, Crouch, Reload, Swap (it becomes Plant / Defuse in Search & Destroy), Scores and Menu. They act as a second controller, appear on the first touch and hide again when a mouse or key is used. Phones go fullscreen in landscape where the browser allows it.

Fix: paint on Woodland's trees

2026-10-23
  • Splats on trees used the wrong rotation: every tree in a forest is turned its own way, and the hit didn't account for it, so paint stuck out sideways or hid inside the bark. Now each splat sits on the bark facing you.
  • Thick branches now stop paint too (leaves still let it through).

Scoreboard K/D; time to celebrate a defuse

2026-10-23
  • The Tab scoreboard has a K/D column: eliminations per time out.
  • In Search & Destroy a defuse still wins the round straight away, but play goes on for 3 more seconds with a Bomb defused banner before the round result.

Fix: a starburst in the sniper scope's glass

2026-10-23
  • The scope's eyepiece showed a radial starburst. Two copies of the same dark disc inside the scope were fighting each other behind the lens. The sniper model is rebuilt with one disc each, and the lens reads as clean glass, like the red dot's.

Settings › Graphics

2026-10-23
  • A new Graphics group: a Quality preset (High, Medium, Low; Custom once you change one setting yourself), Shadows (high / low / off), Resolution 50–100%, Tree detail, Textures and Anti-aliasing. The last two apply on the next load, the rest straight away.
  • Frame rate: in a browser it always matches the screen; in Plaster Engine it can be Uncapped, which applies when the engine next starts.

Fix: a dark flash when switching markers while aiming

2026-10-23
  • Switching between the primary and the sidearm while aiming down sights filled the screen with your own sleeve for a frame. The incoming marker was tipped muzzle-down as it came up, and from the aimed position, right in front of your eye, that swung the arms (which reach back to the shoulder) up through the camera.
  • It now comes up from below tipped slightly muzzle-up, so the arms swing down out of view, from the hip or aimed, in both directions.

Loadout trimmed: no stat bars, no right-hand column

2026-10-23
  • The stat bars (range, accuracy, rate of fire, reload) are gone from the primary and sidearm panels, which keep the name, firing mode, magazines and picture.
  • The right-hand column (Operator, Loadout and Kit colour cards) is gone too, so your operator stands in clear view. The kit preview is still on the Operators tab. Paint will be picked with a marker's attachments on a later screen.

A sidearm: the P17 pistol, and two loadout slots

2026-10-23
  • Two slots: every loadout now has a primary marker and a secondary (sidearm). Switch between them with 1 / 2, the mouse wheel or Ⓨ on a controller (Ⓨ still plants and defuses where that's possible in Search & Destroy). The other marker comes up from below in 0.45 s, and you can't fire or aim until it's up. Each marker keeps its own magazine and spare mags; every life starts on the primary with both full.
  • The P17 pistol, the built-in sidearm: a .43 cal mag-fed pistol modelled in Blender after the T4E G17 Gen 5 (tools/blender/pistol.py, 202 mm, traced from a side photo in inspiration/marker/). Semi-auto, 8-round mags with the CO2 inside, 3 spares, quick reloads, light paint that leaves fast but slows sooner. The slide blows back on every shot and locks back on an empty mag. Iron sights line up dead centre when aiming.
  • Two-handed grip in first person: the strong hand high on the grip with the index finger on the trigger, the support hand cupping it from the left, both thumbs forward. The sleeves come from the Blender arms; the hands are built in code around the pistol's grip.
  • Loadout (main menu and Esc menu) lists primaries and sidearms separately, with a panel for each. Online the server tracks both slots: it checks every shot against the marker in your hands, and other players see you holding your sidearm when it's out. POE gets a Loadout slot field, a Pistol frame and Iron sights.
  • Fixed while finishing it: the pistol was being held with the rifle's arms and aimed with the rifle's offset, so its sights sat well below the centre. The HUD's ammo box shows only the count and spare mags, as before; it doesn't list the two slots.

Menus redesigned after the reference shots, on Woodland

2026-10-23
  • New layout after the two reference shots in inspiration/menus/: the Plaster logo with its splat and five tabs across the top (Play, Loadout, Operators, Barracks, which was Progression, and Settings), cards down the left, a player card top right with your level, name, online status and a portrait of your operator, the map card bottom left, the player list on the right and button hints along the bottom.
  • Loadout: the equipped marker in a big panel with a picture rendered from its real model, its firing mode and bars for range, accuracy, rate of fire and reload; a magazine panel; operator, loadout and kit colour summaries on the right. Pictures come from a small offscreen renderer (src/menu/pictures.js), so they always match the game's models.
  • Settings grouped into Controls, Display and Audio, with Fullscreen and Reset to defaults underneath.
  • On Woodland: the main menu now loads Woodland and stands you in front of the watchtower; in a lobby your squad lines up in a V. Name plates only show over a squad.
  • Esc menu restyled to match: card-style items with the lime selection, a solid dark panel and the new logo.

Website: model pictures on transparent backgrounds, no grain over images

2026-10-20
  • No more white boxes: the marker, sniper, first-person rig, every player pose, the Can, the oil drums and the old Can, drum, sniper and player versions are re-rendered from the model showcase (tools/showcase.html) as transparent PNGs with a soft shadow, so they sit on the page's dark backdrop. The Can now faces the camera with its PLASTER stripe.
  • Clearer pictures: the film-grain texture was drawn over the whole page, images and text included. It now sits behind the content and only textures the backdrop.
  • The showcase takes ?procedural to skip the Blender models, so pictures of the old code-built versions can be made again.

Leaf litter and mud from PolyHaven: all of Woodland's ground is photo-scanned

2026-10-20
  • Leaf litter under every forest patch is now PolyHaven's forest_leaves_04: real broadleaf leaves, twigs and needles instead of painted ellipses. A second rotated sample hides the small scan's tiling, and it's kept rough so dry leaves don't glare grey in the sun.
  • Mud at the outpost and in the creek is brown_mud_02: trampled soil with clods and boot prints, tinted wet and still glossy on top.
  • Colour, normal and roughness maps at 2048 px (leaves_* 5.5 MB, mud_* 3.8 MB). The ground shader now treats all four kinds the same way: each has its own size, contrast, tint and roughness floor, and each one's normal and roughness follow how much of it shows. The canvas textures stay as fallbacks.
  • Lobby picture for Woodland (public/maps/previews/woodland.jpg) re-saved with the new ground.

Woodland's grass is a photo-scanned PolyHaven texture too

2026-10-20
  • Forest-floor grass: the ground under the field's grass is now PolyHaven's forrest_ground_01, real grass with twigs, dead leaves and bare patches, instead of the canvas blades drawn in code. It sits between the grass tufts, which are unchanged.
  • Same tone as before: the scan is pale khaki in the field's light, so the shader gives it more contrast and a green tint, keeping its browns. Its normal and roughness maps fade out under leaves, dirt and mud.
  • Colour, normal and roughness maps at 2048 px (public/builtin/textures/grass_*.webp, 5 MB). The ground shader now takes any PolyHaven set with its own size, tint and contrast, so leaves and mud can follow. The canvas grass stays as the fallback.

Trails on Woodland use a photo-scanned PolyHaven texture

2026-10-20
  • First texture from PolyHaven (polyhaven.com, free CC0 textures): the dirt on Woodland's trails and dirt patches is now forest_ground_04, a scanned forest trail of packed earth, gravel and small stones, instead of the canvas dirt drawn in code.
  • Full PBR set: colour, normal and roughness maps at 2048 px (public/builtin/textures/dirt_*.webp, 4.6 MB). The stones catch the light and the ground is rough where it's dirt, fading out where the trail meets the grass. A warm tint keeps it in tone with the leaf litter.
  • Grass, leaf litter and mud are unchanged for now. The canvas dirt stays as the fallback if the files can't load.

Realistic rocks, fallen logs, stumps, bushes and grass

2026-10-20
  • Made in Blender (tools/blender/nature.py) to match the new trees. Rocks, logs and stumps are sculpted at high detail and baked onto light game meshes: granite boulders with fracture faces, cracks, lichen and moss; logs with bark ridges, peeled deadwood, a sawn end with growth rings or a snapped, splintered one; stumps with roots flaring into the ground and a sawn top with hinge splinters.
  • Bushes are grown like the trees (stems, twigs, leaf twigs) and wear the trees' leaves and bark; in the field they cast shadows now. Grass tufts are painted in Blender: denser clumps of green and dry blades with seed heads.
  • Same sizes and collision as before: every rock, log and stump on a map keeps its size. The code-built ones stay as the fallback if nature.glb (2.1 MB) can't load.

New trees on the menu field and in the map pictures

2026-10-20
  • Speedball's treeline (the field behind the main menu) was still the old low-poly blobs. It's now Woodland's Blender spruces and broadleaves, at their cheaper levels of detail and without shadows.
  • Map pictures in the lobby (public/maps/previews/) re-saved for Speedball and Woodland, so they show the new trees.
  • A little faster: full-detail trees now within 24 m of you (was 32 m). The swap to the next level isn't visible at that distance. The deep woods' lowest level has bigger cards, so it looks fuller at the same triangle count.

Realistic trees, grown in Blender

2026-10-19
  • New trees made in Blender (tools/blender/trees.py): three Norway spruces and three oak-like broadleaves, grown from seeds. Spruces have whorls of drooping branches covered in needle sprays and dead stubs below the crown; broadleaves fork into limbs and fine branches carrying leaf twigs. Painted bark (scaly spruce, furrowed oak), needle and leaf textures.
  • Everywhere on Woodland: the forest patches, single trees, the woods outside the net and the distant ring that used to be flat cones. Trees near you are drawn at full detail (about 12k triangles a spruce), further ones and the rows past the net with a 2k version, the deep woods with 0.8k. Shadows use the next level down, so the forest costs about a third of what drawing every tree in full would.
  • Collision matches the bark: each tree's trunk circle is now sized from the model's stem. Trees stay where they were on every map; a few trunks are a little thicker or thinner than before.
  • Bushes are still the code-built ones, and the old cone trees stay as the fallback if trees.glb (5.5 MB) can't load. blender-out/trees/trees.blend opens all six trees in Blender.

Sniper scope: no more lens caps

2026-10-19
  • Open lenses: both ends of the sniper's scope were closed by flat discs, so it looked like the caps were on. The rings round the lenses were built as open shapes and the modelling script filled their ends. They're proper rings now, and each end has a curved glass lens with a violet multi-coating sheen, a retaining ring and a dark interior; the eyepiece keeps its rubber cup.
  • Nothing else on the sniper changed; the scope view still uses the game's own reticle.

Realistic weathered wood for the plank walls

2026-10-19
  • New wood textures made in Blender (tools/blender/planks.py): full PBR sets (colour, normal, ambient occlusion and roughness) for a 2 m sheet of boards at 1 mm a pixel, and a rough-sawn beam. Real grain from growth rings (arches on flat-sawn boards, straight lines on rift-sawn ones), raised latewood, knots with the grain bending round them, butt joints, gaps, rounded edges, cracks, saw marks, nails with rust running down, silvering, lichen and grime. The tiles wrap seamlessly, with no shading that bands at the seams.
  • Everywhere on Woodland: plank walls, the fort, shacks, decks, stairs, crates, the watchtower and the bridge. Posts, rails and braces now run their grain along their length instead of always upwards.
  • 4.4 MB of WebP in public/builtin/textures/, loaded with the Blender models; if they can't load, the old canvas planks are used. blender-out/planks/planks.blend opens a lit wall with them in Blender.

The sniper, modelled in Blender

2026-10-19
  • New sniper after a real bolt-action DMR (the 468 PTR "Black King"), built by the marker script (tools/blender/marker.py --frame sniper): long quad-rail handguard, thin barrel into a ported suppressor-style shroud, a long scope with three turrets on two rings, a precision stock with an adjustable cheek riser, a folded bipod, a short 5-round mag.
  • The real bolt handle is what goes back and forward after every shot; the scope view, ballistics and POE colours are unchanged. Other players carry an 8k-triangle version.

A magfed player, modelled in Blender

2026-10-19
  • New player character (tools/blender/character.py), kitted for magfed instead of speedball: bump helmet over a full paintball mask (mirrored lens, vented mouthpiece), neck gaiter, camo shirt and pants, plate carrier with mag pouches, admin pouch and radio, battle belt with a dump pouch, knee pads, gloves, boots. No jerseys: teams wear coloured armbands and helmet tape, and the number is a patch on the carrier's back.
  • Same animations: the model is skinned to the old rig's joints, so walking, running, crouching, aiming, aiming down sights and the hand-up when eliminated all carry over, for bots, online players and the menu. New: each shot kicks the marker back.
  • First person: your arms are the same camo sleeves, gloves and armbands, the left hand wrapped round the handguard.
  • Paint splats stick to the skinned body and move with it. 41k triangles; the old character is the fallback. A packed character.blend opens in Blender.

The oil drum, modelled in Blender

2026-10-19
  • New oil drum (tools/blender/barrel.py) for Woodland's outposts: a real 200 L steel drum with rolled chimes, rolling hoops, a recessed lid with embossed UN markings and two bungs, a welded seam and dents; paint chipped to rust and scratched to steel, rust streaks, grime and a stencilled FUEL / DIESEL 200 L. 6.2k triangles.
  • The editor's Paint option (blue, rust, olive, red) still works: the texture is a mask the game paints. The drums still batch into a few draw calls; the old cylinders are the fallback.
  • The script also saves a packed, lit barrel.blend to open in Blender.

Marker fixes: markers vanishing, cloudy red dot

2026-10-19
  • Markers no longer vanish when someone is eliminated: every copy of the new marker shared its materials, so one player's elimination fade made every marker (yours included) fade out until they respawned. Each copy now has its own.
  • Clear red dot: the lens was two double-sided, milky layers that washed out about a fifth of the sight picture. It's now one faint, dark, single-sided glass that only shows reflections.

A new mag-fed marker, modelled in Blender

2026-10-19
  • New marker (tools/blender/marker.py): modelled after a real mag-fed marker (Tippmann TMC style), traced at real scale from a photo. AR lower with the grip, trigger guard and magwell in one piece, M-LOK handguard, short barrel with a flash hider, flat-top upper with a red dot and flip-up rear sight, PMAG-style mag, skeleton stock with a carbon air tank through it and a gauge on the regulator.
  • In the game: it's the stock rifle in first person (62k triangles) and on every character (an 8k version). Grip, hand and sight points are unchanged, so aiming down sights lines up as before; the left hand sits a little further back under the shorter handguard. Body and accent colours and the body texture still come from POE. The sniper frame keeps the earlier, code-built marker for now.
  • Animations: the mag drops out and goes back in along the magwell's angle, the charging handle pulls back on an empty-mag reload, and the trigger moves on every shot.
  • The built-in Blender models now live in public/builtin/ (the Can moved there too).

The Can, modelled in Blender

2026-10-19
  • Blender in the sandbox: Blender 5.0 runs headless, so Claude can script models, render previews to check them, and export GLB.
  • New Can bunker (tools/blender/can.py): eight sewn panels that bulge between the seams, a pinched top seam with gathered wrinkles, puckered stitching, a raised stripe band with PLASTER printed on it, dirt at the base, a fill valve and stake tabs with D-rings. A 2.6M-triangle sculpt baked onto a 7.8k-triangle game mesh (0.7 MB). Every Can on every map uses it.
  • Editor colors still work: the texture is a mask the game paints with the base and stripe colors. If the file can't load, the old procedural Can is used. See Models.
  • The map editor, POE (Gameplay objects, which now names the Blender script) and the model showcase (?model=can, and v1-can for the old one) all show the new Can.

Task board run R-10: magazines that keep their paint, overhead view between rounds

2026-10-18
  • Magazines (T-99): everyone carries 3 spare magazines, each keeping its own paint. Tap reload to swap: the magazine in the marker goes back in the pouch (shoot 10 and swap, and that mag still has 10), and the next one with paint comes in, cycling through them. Hold reload for the quicker reload: the old magazine drops to the ground and is gone. The ammo counter shows each spare as a bar filled to its paint; the server keeps the same count online. Markers have a spare magazines setting in POE instead of reserve paint, and their two reload times are now keep the mag and quick reload.
  • Between rounds (T-96): when a Search & Destroy round ends, and at the end of any match, the camera rises to a slow, turning view of the whole field with the scoreboard up.
  • Defused means quiet (T-97): a defused bomb stops beeping (a steady green light) and the defuse prompt goes.
  • Team Elimination to 100 (T-98), with the 5-minute clock as before.

Task board run R-9: Training range, bots with any marker, Esc menu on a controller

2026-10-18
  • Training range (T-93): Practice opens a new map with player-shaped targets instead of bots: lanes for distance (10–50 m), long range (60–102 m), moving targets, leaning out from cover and quick aim, with a readout of hits, shots, accuracy and the last hit's distance. Targets drop when hit and pop back up. Two new map editor objects make it: the Training target (static or moving) and the Sign (also as a plaque on the floor). Practice against bots is still there for every other map.
  • Bots with any marker (T-51): private lobbies choose what bots carry (stock, a random marker each, or one for all); bots fire at their marker's pace, bolt action included, and aim for its paint's flight.
  • Spectating shows aiming (T-94): when the teammate you're watching aims down sights, your view zooms with them (through the scope too).
  • Markers fade at the crosshair (T-95): bomb site letters, the BOMB tag and name tags fade when they're over what you're aiming at.
  • Esc menu with a controller (T-89): D-pad / stick, LB / RB tabs, Ⓐ select, sliders with left / right, Ⓑ back. Changing your marker mid-match (T-46) was already in from run R-7.

Task board run R-8: sniper, 6v6 public matches, bots aim and spread out

2026-10-18
  • Bolt-action sniper (T-91): a new marker with a 4× scope, a 5-round mag and faster, flatter shaped paint; you work the bolt after every shot. Markers can now be bolt action, have a scope (with zoom) instead of the red dot, and use a sniper frame for the built-in model; POE shows the new options. Aiming a scoped marker fills the screen with the scope and slows your look; hip fire with it is a gamble. Fixed the same day: online, the server refused every sniper shot because its longer barrel put the muzzle past the server's 1.3 m limit from the eye (the paint vanished, except aimed at the ground). The limit now follows each marker's barrel length, and the game logs refused shots in the console.
  • Public matches are 6v6 (T-88), with bots filling empty slots as before.
  • Bots aim down sights (T-90): lined up on someone more than 7 m away, or watching where an enemy was just seen, a bot brings its marker up to its face: steadier aim, slower feet. Players' aiming is sent too, so online everyone sees who's aiming.
  • Search & Destroy bots spread out (T-92): instead of walking to the site in a line, escorting attackers take lanes of their own, wait at staging points and close in from different angles; defenders spread round the sites, one holds forward, and they move spots now and then. Bunching (attackers within 2.5 m of a teammate) fell from about 75% of the time to 18–25%.

Plaster Engine: play each branch as a release

2026-10-18
  • Game versions on the Engine hub: Development, Test and Production, each the latest commit of its branch, built and served by the production server (multiplayer included) on its own port (8081 / 8082 / 8083) and opened in its own window, side by side with the live dev server. Builds are skipped when nothing changed; a running version offers Update & play when its branch moves on. Each one is a separate git checkout in the engine's settings folder, so the working folder is never touched.

Plaster website, docs navigation, branches

2026-10-18
  • Website: a landing page for Plaster (website/) in the same Tactical Briefing style. Hero, gameplay (mag-fed, paint ballistics, one hit and you're out), what's in the build, a screenshot gallery with a full-size viewer, development status with the latest changelog entry, and links into these docs. Every Play button reads "Playtest coming soon" until a hosted game address is set. Only real screenshots and facts from the build.
  • Docs as part of the site: npm run site builds the website with these docs at /docs/ (a Home link is added to their nav) into dist-site/, ready for Netlify (netlify.toml). Long pages now have an On this page list: a sidebar on wide screens, a fold-out above the content on narrower ones.
  • Branches: development for everyday work, test and production promoted from it; GitHub is up to date. How it all works is in DEPLOYMENT.md.

Task board run R-7: Esc menu, sides switch every round, first-person spectating, map pictures in lobbies, bots on trails

2026-10-18
  • Esc menu (T-82): the pause screen is a proper menu in the main menu's style: Resume, Settings (the main menu's settings, applied live), Loadout, Controls (the key lists moved here from under the title) and Leave match / Main menu. Picking a marker in Loadout puts it in your hands at once in practice; online the server hands it over at your next spawn (next round in Search & Destroy), with its stats, and everyone sees the new marker.
  • Sides switch every round (T-83): Search & Destroy has a fixed attacking end and a fixed defending end (where the bomb sites are). The teams swap attack and defence every round, and with it ends: attackers always come from the same end. Halftime is gone; the round banner says "Sides switched".
  • Timings (T-85): plant 5 s (was 3), defuse 5 s, bomb 45 s from the plant (was 30).
  • First-person spectating (T-84): once you're out you see through a living teammate's eyes, marker in hand, instead of from behind them.
  • Who's out (T-81): the held-Tab scoreboard in Search & Destroy strikes through everyone who's out for the round with a red OUT tag and shows how many are left per team.
  • Bots follow trails and doorways (T-65): bots plan routes over a walking grid built from the map's collision (trails cheap, doorways open, wall edges a little dearer) instead of walking straight lines between cover. On Woodland they now spend about half their moving time on trails (19% before; 72% in Search & Destroy) and can climb the watchtower by its stairs. The same routes run in practice and on the server; Speedball plays as before.
  • Map picture in the lobby (T-79): lobbies show the map being played at the top, with its name and the mode. The map editor renders the picture every time you save (from above blue's end, editor helpers hidden) into public/maps/previews/; Speedball's and Woodland's are in.
  • Map editor: blank new map (T-41): File › New is a blank field (sky, grid floor, netting, a spawn zone per team), and Blank (grid floor) is a new field type.
  • Map editor: the netting follows the field size (T-86): changing width, length, net height or type now rebuilds the field at once, marks the map unsaved and can be undone. Before, field changes weren't seen as edits at all.
  • Launch Claude from the Engine (T-72): the hub has a Claude panel. Work through tasks opens a terminal in the Plaster folder running your Claude command with "work through the task board"; Open Claude just starts it. The command is set on the hub (plain claude, or whatever starts your sandbox session). Not tried on Windows yet.
  • Task board (T-87): folding Recent runs shut now sticks (also across reloads) instead of springing open whenever the board redraws.

Task board run R-6: bomb carrier, spectating, sprint stamina, stats page fixes

2026-10-17
  • The bomb has a carrier (T-78, T-74): each Search & Destroy round the bomb lies on the ground just out of the attackers' spawn; an attacker picks it up by running over it and only the carrier can plant. When the carrier is out it drops where they were, for any attacker to pick up. Attackers see a BOMB tag through cover over the loose bomb or its carrier, and the round bar says whether to pick it up, escort the carrier or plant. Bots fetch it, the carrier heads for the site and the rest escort.
  • Spectating (T-73): once you're out you watch a living teammate from just behind them; Space / Ⓐ switches teammate.
  • Sprint stamina (T-76): sprint is 6.2 m/s instead of 7, and lasts about 4.5 s from full. It refills over 3.5 s after you stop; run it dry and you're winded until it's back to 35%. A thin bar over the ammo counter shows it while it isn't full. The server's speed check follows the shared rule.
  • Lobby countdown (T-56): the public lobby's countdown updates its text instead of rebuilding the panel each second, so clicks (Leave) aren't lost.
  • Stats page (T-60, T-77): token totals stay short enough for their tile (464M, then 1.2B) and labels no longer wrap; token times and days are in Eastern time instead of UTC.

Task board run R-5: Search & Destroy, public map rotation, everyone's own marker

2026-10-17
  • Search & Destroy (T-71): a second online mode, in public matchmaking and private lobbies. Rounds with one life each and no respawns; attackers plant the paintball bomb at site A or B (hold F / Ⓨ for 3 s inside the ring), defenders stop them or defuse it (5 s next to the bomb). Attackers win a round when the bomb goes off (30 s after the plant) or every defender is out; defenders win by defusing, by eliminating the attackers before a plant, or when the 90 s round clock runs out. First to 4 rounds; attack and defence swap after round 3. Planting or defusing holds you still and you can't fire.
  • On screen: a round bar under the score (round, your role and goal, players left on each team), A / B letters you can see through cover and rings on the ground, the Hold F prompt and progress bar, round banners, a canister bomb that blinks and beeps faster as it runs down, and a burst of paint over the site when it goes off (anyone within 7 m is out). New sounds: bomb beep, armed, defused, blast.
  • Bomb sites: a new Bomb site object in the map editor's Gameplay group (A or B, radius). Maps without any, Speedball and Woodland included, get two automatic sites between the middle and the defenders' end; at halftime the sites mirror to the other end, so team colours and spawns never change.
  • Bots play the objective: attackers push the round's site while shooting and plant when they reach it, then guard the bomb; defenders hold both sites, then the nearest goes to defuse. The mode's rules live in server/snd.mjs, apart from the match code.
  • Public map rotation (T-67): Find Match has a mode picker, players only meet others who picked the same mode, and public matches rotate through the maps (Speedball → Woodland → …): each new public lobby, and each rematch in one, plays the next map.
  • Your marker in third person (T-43): other players' figures online, and the figures in the menu and lobby, now hold the marker each player picked in Loadout, with its colours, texture or imported model, instead of always the stock one. Bots keep the stock marker. A custom built-in marker costs the same draw calls as the stock one.

Task board run R-4: hitmarker

2026-10-17
  • Hitmarker (T-61): when your paint hits an opponent, four white ticks pop out around the crosshair and fade in about a third of a second, with the hit-confirm tick sound. Works against bots and online players, and shows while aiming down the sights too.

Plaster Engine: the desktop app

2026-10-17
  • Plaster Engine (electron/, npm run engine): a Windows desktop hub for the game, the map editor, POE, the task board, the model showcase and the design docs, each in its own window. The tools are the browser pages, unchanged; the browser versions keep working.
  • Windows: one per tool (opening it again focuses it); links between tools go to the right window; Ctrl+Shift+H back to the hub; unsaved-changes prompts in the map editor and POE; sizes remembered.
  • Dev server: uses one that's running, or starts its own and stops it on quit; a waiting page in tool windows while it's down, which reopens the tool when it's back.
  • Hot reload: tool pages through Vite, the hub by itself; only main-process edits need Engine › Restart. Fixed along the way: edits to the task board's code (src/tasks/) never hot-reloaded, because the dev server ignored every tasks/ folder.
  • Locked down: sandboxed pages without Node; files only through the dev server's APIs.
  • Desktop and Start-menu shortcut: npm run engine:shortcut. Icon built from the game's logo. New Plaster Engine page; installer plan in electron/README.md.

Task board run R-3: crouch, pause screen, Woodland textures, smooth stairs

2026-10-17
  • Crouch ends a sprint (T-59): pressing C / Ctrl / Ⓑ while sprinting crouches at crouch speed even with Shift held; you can't sprint crouched. Shift or L3 still stands you up and sprints.
  • No pause screen when it isn't a pause (T-62): joining a match, starting Practice and the end of a match no longer show it. You're dropped straight in; if the browser hasn't given the game the mouse yet, keys and controller work at once and a hint says Click to aim with the mouse (that click doesn't fire). At the end only the scoreboard shows. Esc / Start still pause.
  • Woodland texture glitches (T-63): the plank texture's top-to-bottom shading made a hard band every metre on walls and a checkerboard on decks and stairs (removed); flush faces flickered where wall posts met plank ends, where the top rail met the plank tops, at container corners and on stair risers (now 1 cm apart).
  • Smooth stairs (T-69): players and bots walk an invisible ramp through the steps instead of hopping each one; paint and sight still hit the steps. Same collision on the server; the editor's collision view draws the slope.
  • New Woodland screenshots; Woodland map v2 on the Versions page.

8v8 private matches

2026-10-17
  • Private lobbies up to 8v8: the host picks 1v1 to 8v8; bots fill the rest. Public matchmaking stays 4v4. Server settings PLASTER_MAX_TEAM and PLASTER_PUBLIC_TEAM.
  • Measured first (all-bot server matches, 3 minutes each): at 8v8 on Woodland the server uses about 0.4 ms of its 33 ms tick and sends each player about 19 KB/s (twice 4v4).
  • Faster collision: each shape has a bounding circle, so movement, paint and sight checks skip far-away ones: about 4× less server time on Woodland, identical results (20,000-check comparison on each map).
  • Lighter player figures: each figure's parts are merged per joint and material (102 meshes → 30), so 16 players cost about 1,100 draw calls on Woodland instead of 2,800. Animation unchanged.
  • Lobby: above 4 per team, a team's open slots share one row so the lobby and Start fit on screen. Four more bot names.

Woodland: the first woodsball map

2026-10-17
  • Woodland (public/maps/woodland.json): 64 × 96 m, about 3.6× Speedball. A plank fort with four doorways and windows in a clearing, an abandoned outpost (shacks, walk-in containers, truck, barrels, crates, pallets, sandbags), a watchtower over a meadow, a sunken creek with a broken footbridge, woods, and winding trails with cross links. Blue's half is mirrored onto red's.
  • Checked: all three routes walk spawn to spawn; tower stairs, fort doors, container and shack all enterable; windows block; no line of sight into a spawn from the far half, the fort or the tower; bots play it offline and on the server; a private online match on it keeps both players in sync.
  • Engine: each map can set its field (Speedball or Woodland look, size, net height); terrain from Hill objects used by movement, paint, sight, bots and the server; objects with several collision parts (doorways you walk under, decks you stand on); stairs you walk up. Speedball plays exactly as before (20,000 random checks, no differences).
  • Looks and speed: grass, dirt, leaf litter and mud blended on the ground; instanced trees, bushes and grass; shared generated textures; static pieces merged per area. About the same draw calls as Speedball.
  • Choosing it: Practice now asks which map; private lobbies already list it. Editor: each map shows its own field, the inspector sets field type and size, new objects land on the terrain, End drops the selection onto it.
  • New Maps page.

Task board run R-2: no dev-tool links in the game, FPS and ping readout

2026-10-16
  • No dev tools in the game: Loadout no longer links to POE; nothing players see points at the editor, POE or the task board (T-57).
  • Settings › FPS counter and Ping: off by default; a small readout top left while playing shows frames per second and, in online matches, the round trip to the game server (T-58).

Task board run R-1: menu tidy, play again with the same players, POE rename/delete

2026-10-16
  • Main menu: Quit and the Task board link removed (T-53).
  • Public matches: when a match ends everyone goes back to the same lobby, with a new countdown, instead of the main menu, so the same players keep playing together; Leave (or Esc) to go (T-54). The menu now also follows its room straight into a match that already started.
  • POE: rename and delete imported models, textures and sounds; delete is refused while a saved map or marker uses the asset, and backs the file up (T-48).
  • The first run worked through by Claude from the task board.

POE: the Plaster Object Editor, configurable markers, asset imports

2026-10-16
  • POE (/poe.html, dev server): asset browser (markers, models, textures, sounds, animations, gameplay objects), 3D preview with a ballistics readout, properties panel, import button.
  • Markers: create, duplicate, rename, delete, restore defaults. Magazine and reserve paint, semi / burst / full-auto, rate of fire, spread, muzzle velocity, drag and drop, reload times, look (colours, texture, or an imported model with clips) and sounds. Validated in POE and again on save; unsaved changes are marked and survive a refresh. Saved to public/markers/markers.json.
  • Real game integration: the game and the multiplayer server use the picked marker's values in the existing weapon code (no second weapon system). Online, the server looks your marker up itself and sends back the stats it plays with. The built-in marker keeps the exact old values.
  • Loadout lists every marker with its real stats and lets you pick one; the HUD shows spare paint for limited-reserve markers.
  • Imports: .glb and .gltf (+ .bin, converted) models, .png/.jpg/.webp textures and .wav/.mp3/.ogg sounds, each checked before it's stored; the same file is never stored twice and nothing is replaced without asking.
  • Map editor: shares the model library with POE and picks up new imports when its tab is focused; File › Manage assets in POE.
  • Fixes on the way: held fire keeps its rate at any frame rate; the server's fire-rate check tolerates network bunching; the editor's key hint says 1 / 2 / 3.
  • New POE page. Unfinished parts are on the task board (T-43 to T-52).

Task board, voice capture, and Claude working through tasks

2026-10-16
  • Task board (/tasks.html, dev server; linked from the main menu): add, edit, delete and complete tasks with a type (feature, bug, improvement, idea), priority, optional area and notes; Pending and Completed lists, filters and search; every task keeps its history. Saved in tasks/board.json in git. The old TODO.md was imported (39 done, 1 needing your input) and archived.
  • Voice capture: a Dictate button on the board, and hold T on the board, the main menu or in a match (dev builds). Release to review: edit the text, type, priority, area and notes before saving. It only adds to the board, never sends anything to Claude; V stays separate.
  • Work through tasks: pick tasks and start a run. Claude plans it (dependencies, related changes batched together), moves tasks to in progress, marks each done only after verifying it, leaves anything that needs you open with the reason, and adds tasks it discovers. Progress, plan and summary show live on the board.
  • Claude link: the board shows when a Claude session is connected (tools/claude-link.mjs); without one, runs wait in the queue and capturing still works.
  • Removed: the old /api/todo and “auto-work”, which could send T items straight to Claude.
  • Works when the dev server drops: new tasks wait in the browser and sync later.
  • New Task board page.

Browser icon; hero splat no longer cut off

2026-10-16
  • Favicon: a lime paint splat on the dark tile now shows in the browser tab for the game, the map editor and every design doc page (also used for bookmarks and home-screen shortcuts).
  • Overview splat: the big paint splat behind the title was cut off: its left-hand drop was sliced at the edge of the image, and the top drips ran under the nav bar. The splat is re-rendered with a margin on every side, stays centred on the title, and is sized so it clears the nav bar on short screens too.

New main menu: 3D lobby, Operators, Progression

2026-10-16
  • Layout: tabs down the left (Play, Loadout, Operators, Progression, Settings, then Fullscreen and Quit), the selected screen in a glass panel, a player card with level and XP, and button hints along the bottom. New bundled fonts (Barlow Condensed, Oswald, Inter).
  • 3D lobby: instead of the fly-around, your player stands at the blue start with the field behind. In Public Match and lobbies your team lines up beside you (bots and see-through open slots included). The camera moves to a different shot per tab: close on the marker for Loadout, full body and turning for Operators.
  • Loadout: the marker's rate of fire, magazine, velocity and reload, read from the game's rules.
  • Operators: call sign, jersey number (1–99) and a blue / red kit preview. Your number is sent to the server and shown in lobbies and matches.
  • Progression: XP and levels, plus career stats for online matches and practice (eliminations, outs, wins, best match, hit rate, time played), saved in this browser.
  • Controls: mouse, keyboard (arrows, Enter, Esc) and controller (D-pad / stick, Ⓐ, Ⓑ, LB/RB to switch tabs).
  • New Main menu page; the old menu is kept on Versions.

Multiplayer

2026-10-16
  • Main menu: Play Online, Practice (the existing offline game), Settings, Fullscreen and Quit, over a fly-around of the field; works with mouse, keyboard and controller.
  • Public matchmaking: joins a forming lobby or a running match (taking over a bot), else opens one. Humans are balanced between teams and bots fill every empty slot for 4v4.
  • Private matches: room code and invite link; the host picks map, team size (1–4) and bots, moves players and starts for everyone; never visible to matchmaking; back to the same lobby after the match.
  • Authoritative server (runs inside npm run dev; npm run server for builds): owns paintballs, hits, eliminations, respawns, score, clock and bots; checks every player's movement and fire request. Leaving or disconnecting hands your place to a bot; reconnecting within the grace time puts you back.
  • In match: other players and bots with team colours and name tags on teammates, score bar and clock, kill feed, hold-Tab scoreboard, end-of-match board. First to 30 eliminations or 5 minutes.
  • Shared simulation: collision, hitboxes, rules and the bot AI now run without graphics (src/sim/), so the server uses the game's own code. Single player is unchanged.
  • Settings: name, mouse sensitivity, controller look speed and invert, field of view, volume.
  • New Multiplayer page.

Controller support and keyboard-only play

2026-10-16
  • Controller: Xbox / PlayStation / standard-layout controllers. Left stick moves (analog: push further to go faster), right stick looks, RT shoots, LT aims, Ⓐ jump, Ⓑ crouch, Ⓧ reload, LB/RB lean, L3 sprint, Start pause. Stick dead zones, a fine-aim response curve, and rumble on firing and on being hit. The menu shows the layout when a controller is connected.
  • Keyboard only: arrow keys look around, Enter shoots, Right Shift aims. Arrow keys no longer move the player (WASD does), and sprint is Left Shift.
  • No mouse capture needed: press Enter or Ⓐ on the menu to play without pointer lock (Esc / Start pauses). If the browser refuses to capture the mouse, as some remote-desktop setups do, the game switches to this mode automatically.
  • Map editor: the arrow keys now look around (WASD still moves), so the editor works without a mouse too.
  • New Controls page.

Import your own models; Unreal-style editor camera

2026-10-16
  • Import 3D models: GLB files (e.g. exported from Blender) can be imported with the asset browser's Import button or by dropping them on the editor. They're saved to public/models/, listed in models.json, and stay in the library after restarts. The game loads them too: placed models render, block players and bots with a box around their bounds, and take paint. Re-importing a model with the same name can replace it (every placed copy updates; the old file is backed up).
  • Real previews: every asset tile in the browser now shows a preview rendered from its actual 3D model instead of a placeholder icon.
  • Camera: hold the right mouse button to look around in place (mouse captured, like Unreal) and fly with WASD, E/Q up/down, Shift faster; the mouse wheel while flying changes camera speed. Alt+left-drag orbits; middle mouse still pans.
  • Fix: maps created with Save As (and newly imported models) couldn't be loaded by the game until the dev server restarted. They're now served straight from disk.

Dev HUD removed; WASD in the map editor

2026-10-16
  • The in-game dev HUD is gone: FPS, Claude usage, tokens, activity feed and to-do panels, plus the V (talk to Claude), T (add a to-do), O (toggle HUD) and M (free the mouse) keys. Building now happens in the map editor, so the game shows only the crosshair, ammo counter and match UI. Esc pause moved into the main controls on the menu.
  • Map editor: WASD or the arrow keys now move the camera on their own (level over the field), with Q/E for down/up and Shift for faster. Holding the right mouse button still lets you look around and fly where you look. The gizmo tools moved from W/E/R to 1/2/3 to make room.
  • The viewport's controls hint now sits on a dark backing so it's readable over the turf.

Design doc catch-up

2026-10-16
  • New menu and Dev HUD screenshots with the green accent and the tokens panel. The old ones are kept as v2 on the Versions page, which also gains the map editor.
  • Stats brought up to date (days, changes, versions, Session 3 log), and the Models page notes which bunker settings the map editor exposes.

Map editor

2026-10-16
  • New visual map editor at editor.html, styled after Unity/Unreal: toolbar, 3D viewport, asset browser, searchable hierarchy and an inspector. See the Map editor page.
  • Select objects in the viewport or hierarchy, move/rotate/scale them with gizmos or exact values, and duplicate, rename, hide, lock or delete them. Supports multi-select, snapping, world/local axes, a grid and a collision overlay, plus full undo/redo.
  • The inspector is built from the asset registry, so each bunker and prop shows its own settings (size, length, team, colors) and only settings the game actually uses.
  • Save, Save As and Open write JSON maps in public/maps/. Every overwrite backs up the old file to map-backups/, the editor checks for changes made on disk, and unsaved work can be recovered after a crash.
  • Play runs the real game on the scene being edited, unsaved changes included, with the same movement, marker, paint, bots and collision. Stop returns you to the editor with selection and undo history intact, and nothing in the game can change the editor’s data.

Maps moved into data files

2026-10-16
  • The speedball field is no longer hard-coded: bunkers, props and spawn zones are loaded from public/maps/default.json through a shared asset registry. index.html?map=name plays another map.
  • Converted from the original code one call at a time. All 31 colliders match the original to within half a micrometre, and before/after screenshots are identical. The original layout stays built in as a fallback, so the game always starts.
  • Spawn zones now set which way you face when you spawn.

Total tokens on the Stats page

2026-10-16
  • The Stats page now leads with total tokens used, with exact counts.
  • Sessions from Windows and from the sandbox now add up instead of overwriting each other.

Green accent

2026-10-16
  • The game menu and the design doc switched their accent from orange to green #A6FF00, including the splat artwork.

Real token tracking

2026-10-12
  • Token usage is now counted from Claude Code's own session transcripts (each response records its exact usage). The dev HUD has a live "Tokens · this project" panel, and the Stats page shows totals per session and per model.
  • Replaces the old "can't be read from inside a session" placeholder on the Stats page, which was wrong.

Design doc rebuilt: briefing look + version history

2026-10-12
  • Restyled the whole design doc to the Plaster motion-graphics look: dark briefing-table backdrop with topo lines, grid, grain and vignette; HUD corner brackets and REC timecode; cut-corner panels; condensed military headings; one orange accent.
  • New Versions page: every model, graphic and sound shows each of its versions side by side. Models and Sounds pages show version history inline, and replaced sounds have play buttons for their old versions.
  • Rebuilt the original v1 models and sounds from the 2026-10-11 code so they can be shown next to the current ones.
  • Models page is now an armory layout with callouts on the marker. Sounds page uses comms-style rows with keycap play buttons and real waveforms.

Full quality pass: field, models, lighting, sound, bots, dev HUD

2026-10-12
FieldGraybox → speedball field: 34 × 50 m turf with paint lines, 5.5 m nets, inflatable bunkers, flags, tents, treeline. Shape-accurate collision; jump onto low bunkers.
LightingSky bounce light and reflections, player-following sharp shadows, contact shadows under bunkers, distance haze.
ModelsNew mag-fed marker (rail, red dot, curved mag, HPA-tank stock) with first-person arms; paintball players with jerseys, masks, pod packs and animation.
Shooting~88 m/s with air drag — paint arcs (~40 m level shot). Red dot centered in ADS. Spread, sway, bob, sprint pose, mag-drop reload. 20-rd mags.
PaintWet, glossy splats that wrap curved bunkers and stick to the body part hit; goggle splat when you're hit.
BotsUse real cover, need line of sight, react, tighten aim, arc shots for drop, lead moving targets, no spawn camping.
Sound20 synthesized sound effects; opponents positioned in 3D.
FixesShots spawning from last frame's camera; round-bunker corner collision; removed muzzle flash (markers don't have one).
Dev HUD"Claude is listening" indicator; voice popup says Sent vs. Saved for later; usage bars.
UIIn-game UI kept minimal on purpose: crosshair dot, ammo counter, start countdown.

Opponent shooting sounds

2026-10-11
  • The opponent's shots now play the same synthesized shot sound as yours, scaled quieter with distance rather than always full volume.

Start-of-match countdown

2026-10-11
  • First time you click to play, a 5-second countdown runs before anything can act (player movement/shooting and the opponent are frozen) — doesn't repeat on later re-locks after Esc or M.

Elimination, magazine/reload, and opponent polish

2026-10-11
  • Any hit now eliminates — real paintball rules, no health bar. The opponent's left arm swings up, it fades out, then respawns elsewhere a bit over a second later. The player has no body model yet for the same animation, so getting hit fades the screen to black, teleports back to spawn, and fades back in; movement freezes for that moment.
  • A hit on the opponent now leaves a paint splat stuck to its actual body (parented to it, so it moves along), not just on walls/floor.
  • Opponent now turns to face you whenever you're in its engagement range, even while stationary — it used to only face its movement direction, so it could be shooting one way while visually facing another.
  • Added a magazine: 15 rounds, R to reload (1.5s, can't fire mid-reload or empty), with a small ammo counter on screen.

First AI opponent, lean/ADS, and a round of bug fixes

2026-10-11
  • First graybox opponent: a red humanoid that wanders the field (same collision as the player) and takes occasional shots at you when in range — green paintballs so you can tell enemy fire apart from your own. No health/damage system yet, so nothing happens on a hit this pass.
  • Lean (Q/E, tilt + sideways peek) and aim-down-sights (right click: narrower FOV, slower movement) shipped, then both needed real fixes: leaning was corrupting the look controls at steep angles (fixed by applying lean only at render time and reverting it immediately, never writing it into the camera's persistent state), and shots fired while leaning spawned from the wrong position (fixed by making the shot computation use that same transient lean transform).
  • The gun viewmodel now renders in its own pass so it stops clipping through nearby walls — and fixing that introduced, then fixed, a regression that blacked out the whole screen (the second render pass's auto-clear was wiping the first one).
  • Lighting: brighter ambient + a dim fill light opposite the sun, so shadowed faces aren't near-black.
  • Paintball flight tuned to go further before dropping (muzzle velocity 40→55, gravity 18→9) — it was landing well short of the far side of the field.

First-person marker, with shooting and real projectile physics

2026-10-11
  • A mag-fed paintball marker viewmodel (body/barrel/foregrip/magazine/grip/stock, built from primitives — no model file) held bottom-right of view. Deliberately no hopper on top, since mag-fed markers load through the magazine, not a gravity loader.
  • Left click fires (150ms cooldown), with a muzzle flash and a recoil kick on the viewmodel.
  • Paintballs spawn from the actual muzzle tip and have real projectile motion — initial velocity plus gravity, so they visibly drop over distance like a real paintball, not a hitscan laser. They disappear on hitting a bunker, wall, or the floor, or after 3 seconds. No splat decals yet.

Crouch (C)

2026-10-11
  • Press C to toggle crouch: half movement speed, camera height drops smoothly from 1.7 to 1.0, and crouching overrides sprint.

First graybox map, and an activity feed filter

2026-10-11
  • A small walkable paintball field: 10 gray box bunkers (two sizes/shades) loosely laid out around spawn, plus a boundary wall marking roughly a 60×60 unit arena. Basic AABB collision — you can't walk through the boxes (no jump/crouch yet).
  • The Claude Activity panel now has a "Show: All / Text only" toggle — Text only hides tool-call lines and shows just what I say. Remembered per-browser.
  • Both shipped via the auto-work toggle chaining straight through the two items that were already queued when it was turned on.

Auto-work toggle for the backlog

2026-10-11
  • A button on the To-Do panel (Auto-work: ON/OFF) controls whether a new item added with T gets worked on immediately versus just sitting queued like before. When on, new items surface to Claude through the same channel V uses, and Claude chains through the rest of the pending list rather than stopping after one.
  • State persists to .auto-work-state.json and is off by default — nothing runs on autopilot until it's explicitly turned on.

Fixed to-do list not updating live, and a true terminal mirror

2026-10-11
  • Found the root cause of the to-do panel not updating right after adding an item with T: the project folder is mounted over virtiofs, which doesn't reliably deliver inotify events — so fs.watch() on TODO.md was silently not firing. The T-command path now broadcasts directly instead of waiting on a watcher, and the watcher itself switched to mtime polling (fs.watchFile) so external edits (me checking items off) still update live too.
  • Replaced manual activity-feed pushes with an automatic relay: a small script tails this Claude Code session's own transcript file and mirrors every real tool call and message into the HUD in near-real-time — a true terminal mirror instead of curated snippets.

Real Claude usage numbers in the HUD

2026-10-11
  • The "5-hour window" / "weekly window" usage panel now shows real percentages, polled server-side from the same (undocumented) endpoint Claude Code's own /usage uses.
  • The OAuth token is read from ~/.claude/.credentials.json and used only on the server — it's never sent to the browser, only the resulting percentages/reset times are.
  • Polling backs off automatically on rate limiting/errors (up to 30 min) and persists its schedule to .claude-usage-cache.json so a server restart doesn't trigger an immediate re-fetch.

HUD follow-ups: scrollable, pending-only, denser activity feed

2026-10-11
  • Hold M to release the mouse without opening the full menu overlay — lets you scroll the HUD panels, press M again to re-lock and resume play.
  • To-do panel now shows only pending items; completed items disappear instead of showing struck-through.
  • Activity feed is much denser now (a line per real action, not just milestones) with a taller panel to match — closer to watching a live terminal.

Dev HUD (toggle with O)

2026-10-11
  • Top-right: a live Claude activity feed (pushed over Vite's dev websocket whenever Claude does something notable) and a to-do panel showing TODO.md's pending/done items plus what's currently being worked on.
  • Top-left: an FPS counter (current + session minimum) and a Claude-usage panel for 5-hour/weekly limits — built but intentionally shows "N/A": there's no way for Claude to read actual account usage numbers from inside a coding session, so it's not faked.
  • TODO.md is watched on disk, so checking an item off updates the HUD live without a page reload.

Hold T to add a voice backlog item

2026-10-11
  • Hold T instead of V to speak something that gets added to TODO.md as a checklist item instead of acted on immediately — for queuing up requests to work through later.
  • Q-to-cancel works for both V and T. The listening indicator is now color-coded: orange for an immediate command, blue for a backlog item.

Cancel a voice command mid-talk

2026-10-11
  • Hold Q while holding V to abort the current voice command — it's discarded instead of sent, with a brief "Cancelled" indicator.

Game concept defined: mag-fed paintball multiplayer FPS

2026-10-11
  • Plaster is a first-person multiplayer shooter built around real mag-fed paintball markers, not firearms.
  • Pacing/movement target: old-school CoD4 (2007) / World at War (2008) feel.
  • Design document site created (this site) with Overview, Changelog, Stats, and Features pages.

Push-to-talk voice commands

2026-10-11
  • Hold V in-game to speak a command; browser transcribes via the Web Speech API and posts it to a same-origin /api/voice route baked into the Vite dev server.
  • Commands are appended to voice-commands.log and watched live during dev sessions so spoken requests can be acted on without leaving the game.

Three.js deprecation cleanup

2026-10-11
  • Replaced deprecated THREE.Clock with THREE.Timer in the main render loop.
  • PCFSoftShadowMap was removed upstream in r186; switched to PCFShadowMap.

Fixed dev server not reachable over published port

2026-10-11
  • Host published both an IPv4 (127.0.0.1) and IPv6 (::1) mapping for port 5173, but Vite was only bound to IPv4 — browsers resolving localhost to IPv6 first got nothing.
  • Bound Vite's dev server to :: for dual-stack IPv4/IPv6 so both mappings work.

Fixed broken first-person controls on spawn

2026-10-11
  • The installed three.js version removed PointerLockControls.getObject() — the camera is now driven directly via controls.object. Updated movement code accordingly.

Initial scaffold

2026-10-11
  • Project set up with Vite + three.js.
  • Empty-world spawn: procedural physically-based sky (Sky addon, no external HDRI) with a matching directional sun light.
  • 60×60 tiled floor with a procedurally generated grout texture, shadow-receiving.
  • First-person spawn with PointerLockControls — WASD + mouse look, shift to sprint.