Belts carry 4 grains deep; stalled belts warn and stop animating (t45)

This commit is contained in:
2026-10-29 23:21:27 -04:00
parent 99aae0aae0
commit ac5f5a06d1
27 changed files with 335 additions and 51 deletions
+28 -15
View File
@@ -167,6 +167,11 @@ flyers and blueprint ghosts. The GPU canvas sits behind the transparent overlay
`diagonal-screws.js` and `slope-belts.js` share the simulation join geometry with pixel colours,
smooth tags, ghosts and previews.
Transport backpressure lives in `src/sim/transport-status.js`: transient per-block load,
movement, jam age and animation clocks. Flat carry, screens, screws, cleats and bars report
progress; only the serial transport step updates it. Both looks use those clocks; smooth
receives a view-sized clock texture so geometry tags and shading fields remain intact.
## The browser shell
- `GAME` (`src/ui/state.js`) holds the UI state: tool, selected piece, build tab, drag,
@@ -244,7 +249,7 @@ Starter furnace designs and the milestone list shown in the notebook.
- functions: smelterBlueprint
- variables: STARTER_DESIGNS, MILESTONES
### src/sim/world.js (124 lines)
### src/sim/world.js (125 lines)
World state: the per-cell typed arrays, alloc(), ambient temperature by depth, waking.
- functions: emit, bagCap, discover, sharedArray, alloc, depthU, depthY, meanSurface, computeAmbient, fillNoise, renderDirtyXY, renderDirtyChunk, renderDirtyIdx, wakeXY, wakeHeatXY, wakeIdx, wakeHeatIdx
- variables: W, H, N, CW, CH, NCH, mat, temp, life, flags, stamp, part, mach, digp, noiseB, airS, netId, isPow, occ, surfY, dirtY, graniteY, basaltY, magmaY, roofY, AMB, worldSeed, surfBase, underD, shallowD, lapse, BW, BH, NB, blockP, blockV, ents, bgm, flyers, ghostBlocks, ghostMolds, renderDirty, awake, hot, hotLvl, powderArea, roofDirty, loadWakeOrder, loadWakePending, loadWakeIndex, tick, tickStamp, machines, molds, nets, pcells, powerDirty, beltL, beltR, screwLists, brokenMachines, ghostMachines, ghostBlocked, EV, bot, bag, bagTotal, player, seen, ledger, stats
@@ -284,7 +289,7 @@ Pipes, pumps and outlets: each joined line holds one liquid as a count, not as g
- functions: sideOf, pipeClosedSide, pipeJoins, rebuildPipes, pipeNetOf, pipeTakeShare, faceCell, pumpDraw, outletPour, pipesTick
- variables: PIPE_CAP, PUMP_RATE, OUTLET_RATE, PUMP_MAX_T, SIDE_V, PUMP_V, OUTLET_V, pipeNets, pipeNetAt, pipesDirty
### src/sim/machine-tick.js (158 lines)
### src/sim/machine-tick.js (160 lines)
Per-tick machine work: steam engines, fans, belts, filters, screw conveyors (machinesTick).
- functions: engineIntake, fanBlow, machinesTick
@@ -293,8 +298,8 @@ Travel-directed transport ends. Precomputed probes; world/plan queries allocate
- functions: pieceEnds, joinCandidate, endJoin, pieceJoins, endAt, joinIsDrop, joinSnap, nearMiss
- variables: JOIN_ENDS, NO_PIECE, NEAR_MISS_VIEW
### src/sim/conveyors.js (213 lines)
How belts, filters and screw conveyors move what is on or in them. What rests on a belt or filter rides along: the whole stack standing on the carrying surface steps one cell toward d together (belts run front of the line first, so the way ahead is clear). If a powder grain is blocked, the load above it stands still and the belt slips underneath. A filter's own material drops through it instead, unless it is already full.
### src/sim/conveyors.js (215 lines)
How belts, filters and screw conveyors move what is on or in them. What rests on a belt or filter rides along: the bottom four grains standing on the carrying surface steps one cell toward d together (belts run front of the line first, so the way ahead is clear). If a powder grain is blocked, the load above it stands still and the belt slips underneath. A filter's own material drops through it instead, unless it is already full.
- functions: conveyorStep, carryColumn, beltDrain, launchGrain, rebuildFilters, filterCarry, carryBeltsAndFilters, setFilter, filterRun, roomFor, screwSpread, screwIntake, screwAccepts, straightScrewNext, diagonalScrewNext
- variables: CARRY_DEPTH, filterR, filterL, filtersDirty
@@ -303,7 +308,12 @@ Throughput for the info overlay (t49): how many grains each belt, filter and scr
- functions: setFlowCounting, flowNote, flowCross, flowSlopeUnder, flowTick
- variables: flowOn, flowCount, flowRate
### src/sim/slope-conveyors.js (231 lines)
### src/sim/transport-status.js (38 lines)
Local backpressure: only loaded transport that cannot advance warns after half a second.
- functions: transportNote, transportStalled, transportClock, transportBegin, transportEnd, transportCleat, transportBar
- variables: STALL_TICKS, transportState
### src/sim/slope-conveyors.js (237 lines)
Cleats are rubber ribs standing up from a sloped belt's face, one every CLEAT_SPACING face cells. Loose grains treat them as solid (cleatMask). Nothing grips the bare face: grains slide down it until a cleat stops them. Each belt step moves every cleat one face cell along the belt, and the rib pushes whatever is in its way ahead of it, so the pocket in front rides along while anything heaped above the rib is left to roll back. If a rib can't push its way, its whole run stalls. Only uphill runs have cleats: downhill, the belt carries its load like a flat one.
- functions: ribMove, cleatFoot, ribCells, slopeUphill, slopeFaceAt, pushRow, scoop, pocketRoom, advanceCleat, slopeRunKey, slopeCleatsTick, rebuildCleatMask, expelFromRib, screenNudge, wakeCleatLoad
- variables: CLEAT_SPACING, CLEAT_HEIGHT, CLEAT_REACH, SCREEN_NUDGE_TICKS, cleatChunks, cleatMask, cleatCells, slopePhase, ribLog
@@ -317,7 +327,7 @@ Molds: cavities for castings; ingot troughs empty themselves below. Removal retu
- functions: moldCellsAt, canPlaceMold, newMoldRecord, addMold, castMix, cavityState, troughState, clearCavity, moldPlugCells, rakeAbove, furnaceJunkHint, unplugMold, ejectIngot, checkMolds, moldAt, tally, collectMold, removeMold
- variables: DROSS, grains, barWord
### src/sim/items.js (319 lines)
### src/sim/items.js (320 lines)
Bars and other loose objects (ents), and the bag: adding, taking, costs and refunds.
- functions: entSolidCell, entSupportCount, entFreeAt, entMark, spawnBar, removeEnt, entScrewAt, entScrewFree, entScrewMove, entScrewLane, entScrewEdge, entScrewEnter, entScrewTick, entDiagonalScrewTick, entBeltScrewEnter, entSlopeBeltTick, entTick, entsInCircle, bagAdd, bagTake, giveOrDrop, refundAt, canAfford, payCost, fmtMoney, costText, needText
- variables: BAR_W, BAR_H, entCurM, droppedLast
@@ -374,7 +384,7 @@ The same chunk schedule runs inline or in workers. Workers only own a pass at a
- functions: threadWorld, threadBind, threadContext, resetChunkWork, inlineChunkWork, chunkEvent, chunkWake, chunkHeat, chunkSeed, runChunks, mergeChunkWork, chunkPasses, threadParams, threadSetParams, threadSlot, threadExecute, threadPass, threadWait, threadFailure, threadMessage
- variables: simPool, chunkWork, inlineWork
### src/sim/tick.js (29 lines)
### src/sim/tick.js (31 lines)
simTick: one simulation step, in order.
- functions: simTick
@@ -412,7 +422,7 @@ Screw casing geometry shared by both looks, ghosts and placement previews. smoot
- functions: diagonalScrewJoins, straightScrewJoins, diagonalScrewShape, diagonalScrewBlock
- variables: SCREW_CLASS, diagonalJoins, diagonalAcross, diagonalAlong, diagonalCap
### src/render/cell.js (276 lines)
### src/render/cell.js (284 lines)
Rare-cell shading also treats built pieces as transparent surroundings.
- functions: builtForShade, cellPixel
@@ -443,7 +453,7 @@ GPU sources retain the CPU roof and transmission rules; directional relaxation f
Smooth slope geometry and cleats, ported from slope-belt-shader.js.
- variables: GPU_SMOOTH_SLOPE_HELPERS, GPU_SMOOTH_SLOPE_DRAW
### src/render/gpu/smooth-shader.js (369 lines)
### src/render/gpu/smooth-shader.js (371 lines)
Literal port of the legacy smooth shader; dpdy is reversed for WebGPU's top-left origin.
- variables: GPU_SMOOTH
@@ -451,7 +461,7 @@ Literal port of the legacy smooth shader; dpdy is reversed for WebGPU's top-left
- functions: smoothSurface
- variables: SM
### src/render/gpu/smooth.js (48 lines)
### src/render/gpu/smooth.js (50 lines)
Field mip levels preserve the legacy trilinear AO sample at level 2.2.
- functions: gpuSmoothInit, gpuSmoothTextures, gpuSmoothBindings, gpuSmoothUpload, gpuSmoothMips
- variables: GPU_FIELD_MIP
@@ -469,7 +479,7 @@ Whole-world textures retain clean chunks across camera moves.
Upload full chunks so scrolling within a resident chunk needs no extra copy.
- functions: gpuUploadChunks, gpuUploadStrip, gpuCheckUploads
### src/render/gpu/draw.js (92 lines)
### src/render/gpu/draw.js (94 lines)
Only exceptional blocks and their geometric neighbours run the CPU colour rules.
- functions: gpuOverrideHas, gpuOverrides, gpuDraw, gpuPresent
- variables: GPU_PATTERN
@@ -482,9 +492,9 @@ Scale colour without changing the smooth-look class.
Machine overlays: fans, engines, silo and the rest, drawn on top of the world.
- functions: cellRect, drawHazardRims, drawMachines, drawProcBlocks, drawSilo, drawSiloPixel, drawSiloWindow, drawRackBlocks
### src/render/overlays.js (370 lines)
### src/render/overlays.js (388 lines)
Other overlays: floating text, rain and snow, flow arrows, filter tags, molds, the bot, particles.
- functions: spawnFloater, drawRain, drawFlowArrows, drawJoinMark, drawJoinMarks, flowLoaded, drawFlowRates, pingImage, drawPing, drawHoveredVein, drawPingRecharge, drawRunOutline, drawFilterTags, drawFloaters, moldLabel, drawMolds, drawBot, spawnDebris, spawnSpark, spawnSuck, drawParticles
- functions: spawnFloater, drawRain, drawFlowArrows, drawJoinMark, drawJoinMarks, flowLoaded, drawFlowRates, pingImage, drawPing, drawHoveredVein, drawPingRecharge, drawRunOutline, drawFilterTags, drawFloaters, moldLabel, drawMolds, drawBot, spawnDebris, spawnSpark, spawnSuck, drawParticles, drawTransportStalls
- variables: PING_SPEED, PING_HOLD, PING_FADE, PING_BANDS, PING_GLINTS, GLINT_MS
### src/render/screw-heat.js (29 lines)
@@ -572,7 +582,7 @@ Hover work is shared by the cursor label and the vein outline.
- functions: oreLike, bitNeeded, pingVisible, cursorVein, hoveredVein, cursorLabelAlpha
- variables: CURSOR_ORES, cursorVeinCache, cursorLabelKey, cursorLabelSince
### src/ui/info.js (216 lines)
### src/ui/info.js (221 lines)
Discovery cards, hover info (I) and the cursor label.
- functions: showCard, howText, discoveryCard, reactionsOf, hoverInfo, renderInfo, drawCursorLabel, pipeContentsText
@@ -622,7 +632,7 @@ Shared world colours, minimap and full map.
Browser-only clocks; simulation code stays usable without a browser or a clock.
- variables: PERF_MARKS, PERF_FRAME, perfMarks, perfTimes, perfLast
### src/ui/loop.js (170 lines)
### src/ui/loop.js (171 lines)
The frame loop and boot.
- functions: scanVisible, frame, boot
- variables: lastT, acc, lastRender, frameMs, simMs, fpsSm, ambientT
@@ -686,6 +696,8 @@ The frame loop and boot.
- `test/t_slope_belts.js`: Sloped belts: transport, joins, sorting, persistence and the actual drag controls.
- `test/t_slopes.js`: Sloped walls: flow, sealed joints, building, refunds and persistence.
- `test/t_smooth.py`: The smooth look: the WebGPU pass compiles and draws, and the thermal lens still works.
- `test/t_stalls.js`: t45: finite carrying bed, local sustained jams, recovery, filters, screws and bars.
- `test/t_stalls.py`: t45: real transport warnings, hover, frozen animation and recovery in both looks.
- `test/t_stone.js`: Uses for waste rock and sand: glass bricks from a fan furnace, the Saw, the silo and builders' orders.
- `test/t_threads.js`: Shared allocation, checkerboard independence, and real worker-count determinism.
- `test/t_vacuum_collapse.js`: Real nozzle cuts into settled heaps, inline and through the real Node worker pool.
@@ -706,6 +718,7 @@ The frame loop and boot.
- `tools/test_perf.py`: Profiler checks: headers, summaries/comparison, and unchanged pixels/simulation with clocks on.
- `tools/use_venv.py`: Let browser scripts run with plain python3 by switching to the repo's .venv.
- `tools/where.py`: Turn a line number in dist/index.html into the source file and line it came from.
- `tools/experiments/belt-depth.js`: t45: sustained normal (one layer) and heavy (16 layers) flat-belt feeds, open sink.
- `tools/experiments/cast_sunk_mold.js`: Block-sized bit mold sunk into the ground with a stone furnace built over its funnel.
- `tools/experiments/factory_cost.js`: What does a running factory cost when the player is somewhere else? Builds K self-running modules in a generated world, far from the bot, and measures simulation time per tick. Each module: a coal + copper-ore furnace burning in a stone-block box, a spring feeding a water wheel, a shaft carrying its power to a 10-block belt that hauls sand off a hopper.
- `tools/experiments/flow.js`: Throughput of belts and screw conveyors: grains delivered per second. Whatever lands past the outlet is taken away, so the output pile never backs up into the line.