Repository navigation
Conversation
The kerfur_flood arm has a joined client send 121 KerfurCommand and 121 KerfurConvertRequest in one tick, each naming an unused host-range id. The host judges by its own per-sender counts of requests that entered each lane's cost path and that the lane refused: the runs must reach the lane's cap, follow its pace from the first run, and stay within the cap plus what the pace pays. The lanes only count; RefusedFor reads 0 until a lane refuses into a tally. No lane behaviour changes. Evidence: kerfur_flood PASS on the lane's final bytes (8 and 6 run, 113 and 115 refused); RED on the old park (depth 49, cap 8) and on two never-landed variants; nine lane drills PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The cap leg now reads the messages the drain handed a lane, less its runs and its refusals, at every host read, and fails the moment that depth passes the lane's cap: a lane that queues without bound is caught however slowly it later serves. A kind that never ran by the failure bound is inconclusive (the lane never became ready), not a failure. Evidence: kerfur_flood PASS on the lane's final bytes (8 and 6 run, 113 and 115 refused); RED on the old park (depth 49, cap 8) and on two never-landed variants; nine lane drills PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The intent queue has no replace; the comment beside its boot selftest listed one among the cases. Evidence: kerfur_flood PASS on the lane's final bytes (8 and 6 run, 113 and 115 refused); RED on the old park (depth 49, cap 8) and on two never-landed variants; nine lane drills PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The door, keypad, Kerfus, desk, eraser and drone-console lanes hold each sender's queue, bucket and said-once latches in one per-slot state and serve one head per tick through IntentQueue. Budgets, caps, wait reasons, answers, denial counts and the refusal warning are unchanged. A leaver's queue now clears with its slot's occupant, so each lane's OnPeerLeft, the OnDisconnect loops that only called it, verb_lanes::OnPeerLeft and its call site are gone. Evidence: kerfur_flood PASS on the lane's final bytes (8 and 6 run, 113 and 115 refused); RED on the old park (depth 49, cap 8) and on two never-landed variants; nine lane drills PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each sender's purchases and bagging presses wait in one per-slot IntentQueue that serves one head per tick at the lane's pace; both lanes always finish a head, so they never wait. Budgets, caps, the pack warning and denial counts are unchanged. A leaver's queue clears with its slot's occupant, so both OnPeerLeft functions, the OnDisconnect loops over them and their call sites are gone. Evidence: kerfur_flood PASS on the lane's final bytes (8 and 6 run, 113 and 115 refused); RED on the old park (depth 49, cap 8) and on two never-landed variants; nine lane drills PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The host holds each sender's KerfurCommand requests in one per-slot queue of eight and serves a head each tick at four at once and two a second, in arrival order; the head waits with its token returned while the host has no body for the sender or the Omega's seams settle. An unknown sender, an unknown command, a short payload and a full queue are refused into the lane's tally, not logged per message. The unbounded park and its in-place replace are gone, with OnPeerLeft and its call. Evidence: kerfur_flood PASS on the lane's final bytes (8 and 6 run, 113 and 115 refused); RED on the old park (depth 49, cap 8) and on two never-landed variants; nine lane drills PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The host holds each sender's KerfurConvertRequest in one per-slot queue of four and serves a head each tick at two at once and one a second, in arrival order; the request is checked against the world as it is when served. An unknown sender, a request before install, an eid outside the host range, a short payload, a bad toProp and a full queue are refused into the lane's tally, not logged per message. A new host Tick runs right after the command lane's. Evidence: kerfur_flood PASS on the lane's final bytes (8 and 6 run, 113 and 115 refused); RED on the old park (depth 49, cap 8) and on two never-landed variants; nine lane drills PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Its tick drained local records and served and flushed its queues on any session, a client's included. The queues are the host's, and the roster's bringup resets them off the game thread, so the serve and the tally flush now run only on a running host session, as the conversion lane's tick does. The local-record drain is unchanged. Evidence: kerfur_flood PASS on the lane's final bytes (8 and 6 run, 113 and 115 refused); RED on the old park (depth 49, cap 8) and on two never-landed variants; nine lane drills PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Both kerfur lanes now refuse slot 0 with the unknown senders: the host's own requests never arrive over the wire, and a queued entry there would never be served. Their run and refusal counters return 0 for any slot outside the clients' range and never index the per-slot state with it, which would otherwise read the host's row. Evidence: kerfur_flood PASS on the lane's final bytes (8 and 6 run, 113 and 115 refused); RED on the old park (depth 49, cap 8) and on two never-landed variants; nine lane drills PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Serve now takes a clock function and calls it after the empty check, so a lane's idle slots cost no clock read per tick. All ten lanes pass their own millisecond clock, and the boot selftest gains a check that an empty queue never reads it. Evidence: kerfur_flood PASS on the lane's final bytes (8 and 6 run, 113 and 115 refused); RED on the old park (depth 49, cap 8) and on two never-landed variants; nine lane drills PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Source drops a client's excess past a token budget and MTA counts a player's client-triggered events and raises a script event past a threshold. The queue holds up to a cap and refuses past it, because the transport releases an honest client's held output at once and a drop would lose honest intents; the receive edge's budget ends a flooding link. Comment only. Evidence: kerfur_flood PASS on the lane's final bytes (8 and 6 run, 113 and 115 refused); RED on the old park (depth 49, cap 8) and on two never-landed variants; nine lane drills PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The precedent comment cited paths under the local reference trees, which the prose gate counts as dead. It now names the files as the neighbouring helper's comments do. Comment only. Evidence: kerfur_flood PASS on the lane's final bytes (8 and 6 run, 113 and 115 refused); RED on the old park (depth 49, cap 8) and on two never-landed variants; nine lane drills PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A request refused when it is served (no live kerfur of that form, not a kerfur, kill mode, an eid outside the host range) used to log once per message, which a sender holding its queue full could keep up at the lane's pace. Both lanes now put these in their refusal tally. They are not added to the refusal count, since the request already counted as a run, so a run plus a refusal per request still holds. Evidence: kerfur_flood PASS on the lane's final bytes (8 and 6 run, 113 and 115 refused); RED on the old park (depth 49, cap 8) and on two never-landed variants; nine lane drills PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Three comments in the subsystem wiring said the Kerfus and verb lanes clear their queues, rates and waiting states on a leaver or at the session's end. Those now clear with the slot's occupant, and the functions only follow followers, counters and summary lines. Comments only. Evidence: kerfur_flood PASS on the lane's final bytes (8 and 6 run, 113 and 115 refused); RED on the old park (depth 49, cap 8) and on two never-landed variants; nine lane drills PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The drill's counters are per-slot state that resets when the slot's occupant changes, so a replaced slot would wrap them into a false pace failure. It now remembers the occupant at arm and ends inconclusive as slot-replaced if it changes. A run count below the cap is worded as fewer than the cap ran, not as a lane that never became ready; that wording stays for the 180 s case where nothing ran. Evidence: kerfur_flood PASS on the lane's final bytes (8 and 6 run, 113 and 115 refused); RED on the old park (depth 49, cap 8) and on two never-landed variants; nine lane drills PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The command lane now refuses an eid outside the host range before its queue, as the conversion lane does, so it counts as a refusal and the serve keeps only the checks the world can change while a request waits. The refusal-count docs say what it counts: refusals before the serve; a refusal at the serve is a run. The drill fails a fully accounted kind that ran fewer than its cap, names the judge when a replaced slot hit both kinds, and the queue's Source cite adds where the excess is dropped. Evidence: kerfur_flood PASS on the lane's final bytes (8 and 6 run, 113 and 115 refused); RED on the old park (depth 49, cap 8) and on two never-landed variants; nine lane drills PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A kind fully accounted for with no run at all (every message refused before it could run) is inconclusive, never-ran, since nothing was judged of its cap. One that ran, but fewer than its cap, still fails as under-cap. The command lane's comment lists the host range among the refusals made before the queue. Evidence: kerfur_flood PASS on the lane's final bytes (8 and 6 run, 113 and 115 refused); RED on the old park (depth 49, cap 8) and on two never-landed variants; nine lane drills PASS. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The 85 trashBitsPile_C sharing four keys are content of the level, present before any save record loads, not records a save ships. A New Game saves them as they are, so the host's re-key persists for an actor that lives to a save. On a save's load, loadObjects destroys every actor_save and re-creates it from its records, so a pile re-keyed moments earlier takes its throwaway key with it. The tracker's comment and log, the expression map, the key mint, the tracker and echo-suppress headers and the destroy receiver said every re-key persists via the save. The line goes to INFO; the FAILED branch stays a warning. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
PropSnapPos rides Bulk and PropDriveEnd rides Normal, so a correction read before or during a drive could arrive after the drive's end and still be applied over the rest pose. The correction now carries the host's drive context for the prop (claim generation, drive open), and the client drops one older than a drive end it applied, on arrival and again at the drain. MTA's sync time context travels in the packet the same way. PropSnapPosPayload keeps its 32 bytes (a pad becomes the context); kProtocolVersion 225 -> 226. Evidence: hookdrag --role host on d7acba84 twice PASS (2.2 / 2.5 cm final): drive END then the stale (gen=1 open=1) correction superseded, no APPLIED after END; tip c3d5f1bc RED shows END then a stale APPLIED; 45 s smoke clean Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A prop a hand holds streams continuously and its release carries the pose, but a transient read in the join-window flush could land after that release on the Bulk lane and pull the copy back. The keyed flush now skips a prop in a hand and keeps its last-sent row; a driven prop is still sent, stamped with its drive context. The client's hold release drops a correction armed before its pose. prop_drive_host::InAHand is the former file-local hand test, made public. Evidence: hookdrag --role host on d7acba84 twice PASS (2.2 / 2.5 cm final): drive END then the stale (gen=1 open=1) correction superseded, no APPLIED after END; tip c3d5f1bc RED shows END then a stale APPLIED; 45 s smoke clean Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
IsCorrectionStale read g_endedGen, which survives the actor: an END that died with its actor (a load-tail re-create, a purge) or never landed (pending expiry, a hand's yield) still dropped the correction that would have restored the pose. ApplyEnd now records the generation and the actor it wrote onto; a correction is stale against it only while the eid's bound actor is that live actor. The impossible context open=1 with gen 0 is refused at the receive boundary. HandOwns is deleted for the host's InAHand, which asserts the game thread like its siblings. MTA cites are re-pointed and the four divergences from CanUpdateSync written down. Evidence: hookdrag --role host on d7acba84 twice PASS (2.2 / 2.5 cm final): drive END then the stale (gen=1 open=1) correction superseded, no APPLIED after END; tip c3d5f1bc RED shows END then a stale APPLIED; 45 s smoke clean Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The hole: a correction read before a grab rides Bulk behind the join snapshot and can land after the hand's release, which rides Normal, with nothing armed for the release to erase, so the copy was pulled back. The host now notes a keyed prop skipped for a hand once a correction for it had gone out, and keeps sending it its follow-up, read after the release on the same Bulk lane so it lands after the stale one, until it is out of the hand and at rest. Past the late window only those props stay watched, for at most 30 s; the keyed maps retire when the set empties or the window passes. The keyed body is one function for the scan and the settle phase. Evidence: hookdrag --role host on d7acba84 twice PASS (2.2 / 2.5 cm final): drive END then the stale (gen=1 open=1) correction superseded, no APPLIED after END; tip c3d5f1bc RED shows END then a stale APPLIED; 45 s smoke clean Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A join-window PropSnapPos carries the host's drive context for its prop, and the client drops one older than a drive END still on its copy; a keyed prop a hand held after its correction went out is sent a follow-up after the release. The props, piles and join pages and the payload's comment say so; the payload layout is unchanged. Evidence: hookdrag --role host on d7acba84 twice PASS (2.2 / 2.5 cm final): drive END then the stale (gen=1 open=1) correction superseded, no APPLIED after END; tip c3d5f1bc RED shows END then a stale APPLIED; 45 s smoke clean Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The settle phase after the join window kept the slot reported as the late window, so a drill waiting for it to close waited up to 30 s longer, though only the props a hand held were still watched. It now reads closed. A watched prop that died or turned out to be a pile stayed in the set until the settle timed out and warned; nothing is owed to it, so it leaves the set at once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The END-on-actor record carried a bare slot index, so an actor re-created in a recycled slot read as the one the pose was written onto: it is now a CachedObjRef. The row goes when a newer drive parks the prop. A re-announce during a hand settle is said once and does not re-open the flush. The joiner's own release supersedes an armed correction. The window's expiry notes a hold begun after the last keyed scan. The rest test reads the linear velocity only. A re-key under a live birth warns. MTA divergences carry their cite and reason; settle-phase comments corrected. Evidence: hookdrag --role host on d7acba84 twice PASS (2.2 / 2.5 cm final): drive END then the stale (gen=1 open=1) correction superseded, no APPLIED after END; tip c3d5f1bc RED shows END then a stale APPLIED; 45 s smoke clean Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
That the level places the duplicate-key clone families was never read from the map; what is verified is that they exist before loadObjects runs, at the same keys and places every load. The comments and the entity map now say so. The position corrections row in the join doc is re-wrapped to its list's width. Evidence: hookdrag --role host on d7acba84 twice PASS (2.2 / 2.5 cm final): drive END then the stale (gen=1 open=1) correction superseded, no APPLIED after END; tip c3d5f1bc RED shows END then a stale APPLIED; 45 s smoke clean Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
At the window's end only a prop in a hand at that instant joined the watch, so a grab and release both inside the last scan interval left a stale correction queued with no follow-up behind it. Every prop corrected this join is now read once more at expiry: one that moved since its last delivery is sent its follow-up on the same Bulk lane, one in a hand is watched. The census also runs at re-seeds, so its re-key line no longer calls what it finds a clone family. A clear of the settle deadline that the settle guard made unreachable is gone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every peer now sleeps natively; nothing waits for anyone. SleepState is op-multiplexed (ClientRest, HostAsleep, PeerRest) at one size, 36 bytes: a client's rest state goes to the host, which relays each peer's state and its own sleeping flag. A joiner is sent the flag and every peer not awake. The tally, accelerate, end, the waiting undo, the need clamp and the camera hold are removed. kProtocolVersion 226 -> 227; the land rule is main + 1 at the land, so the lane landing second renumbers. The two drills that read the old ops are converted in this commit so it builds; the sleep probe goes in the next one. Evidence: slp12 on 72742a09: sleep_drill host_asleep + client_rest PASS, hookdrag client/host/both/beside PASS (rest points 0.0 cm), hostile world_latest PASS, 45 s smoke clean Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The probe exercised the old gate (a client sleeps, then the host, then the host wakes and the End arrives); that gate is gone, and the sleep drills (midnight_drill, world_latest) already read the new states. The probe, its header, its ini row, its source-list line and its lane hooks are removed, and with them CallWakeup, which only the probe called. Evidence: slp12 on 72742a09: sleep_drill host_asleep + client_rest PASS, hookdrag client/host/both/beside PASS (rest points 0.0 cm), hostile world_latest PASS, 45 s smoke clean Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The players page, its wire table, its late-join paragraph and the status table now say what the code does: every peer sleeps with the game's own sleep, the wire carries each peer's rest state and the host's sleeping flag, and a joiner is sent both. The N-of-M tally and its accelerate and end phases are no longer described. Evidence: slp12 on 72742a09: sleep_drill host_asleep + client_rest PASS, hookdrag client/host/both/beside PASS (rest points 0.0 cm), hostile world_latest PASS, 45 s smoke clean Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The server breaker census watches ticker_serverBreaker_C's ReceiveTick, so the 0.9.0n reference gains that entry from the pak's offline tree; no existing row moved. Evidence: fact_rows_gate PASS Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
New ReliableKind CreatureEventActive = 184 (5 bytes: the creature's eid and its whole count of running events), on the Bulk lane with EntitySpawn and EntityDestroy, Host authorship; kProtocolVersion 232 -> 233. The host counts each enrolled creature's lib_C::setEvent at a script-gate POST, at its enrolment after BeginPlay and at a joiner's world-ready; a client applies the count to its mirror by reflection, after retracting what the mirror registered itself, refuses the mirror's own call, and takes the count back at the mirror's end. Killerwisp, fossilhound, antibreather and eg stay each viewer's own. event_active_sync no longer ships a creature with no row. Evidence: event_relay_drill on ec01a09f (proto 234, the only change since) GREEN PASS across a rejoin (c=1, retracted at the destroy); reds 467a6ec4 (no sends) c=0 and dba1748c (no bind retraction) c=2 FAIL. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A new drill (event_relay_drill=off|on, both peers, one rejoin): the host spawns an npc_krampus_C 1500 cm above itself, parks it and clears its four BeginPlay timers; each client life finds its mirror and, once its target and applied counts are 1, reads the mirror's own copies in the event registry (1 when the relay alone registered it) and getEvent; the host destroys the krampus at the second life's chat line and checks its count is back to its value before the spawn, the client that its count fell by one. A wait on a peer's join is the rig's own; the others are bounded 60 s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The client PRE tested the session, which Stop clears before the disconnect drain destroys the mirrors, so a mirror's own false ran and the disconnect retracted it again; it now cancels only a call the relay holds a bound entry for. A bind before the event registry resolved, or at a full table, makes no entry and the mirror counts its own. The host sends a zero at a creature's end, and its join snapshot skips an element the registry dropped. The lib_C default object is found once in Install, the death-seam subscribe warns once, the refusal INFO is once per eid. MTA cites added at each divergence; docs say what is and is not replayed. Evidence: event_relay_drill on ec01a09f (proto 234, the only change since) GREEN PASS across a rejoin (c=1, retracted at the destroy); reds 467a6ec4 (no sends) c=0 and dba1748c (no bind retraction) c=2 FAIL. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
coop-dispatch-visibility gains the lib_C::setEvent row: watched by name on any class, the host's POST counting an enrolled creature's call, a client's PRE refusing a bound mirror its own call. coop-entity-expression-map gains a creature's event count: relayed whole by element id, the mirror's own registrations taken back at its install and at its end, the four per-viewer classes each peer's own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Ready() did not cover the library's default object that Call needs, so a
bind at that moment retracted nothing and still made a bound entry (a
permanent +N); Ready now requires it and the bind refuses with its WARN.
The join snapshot erased a gone creature's entry without telling the
clients, so an unbound client entry kept its target: it now broadcasts
{eid,0}. The once-per-eid refusal set is erased at an entry's end and
cleared at a world sweep, so it no longer saturates. Cites corrected to
the lines that show the claim (ordering channel, disconnect teardown,
protected element data, source suppression, SetElementData); header text
that said nothing is sent at a creature's end now says 0 when it held a count.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The header said a world change retracts a mirror's applied count; the code drops it without a call, since the count went with its gamemode. Reconcile's readiness comment named only setEvent; Ready() also needs the event registry and lib_C's default object. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The host's connect replay enrolled each untracked creature and broadcast its EntitySpawn to every world-ready peer, the joiner included, and then sent the joiner its whole NPC set: two spawns, the second dropped by the receiver's duplicate guard. Session::SendReliable gains a skipSlot (the fan-out leaves that slot out); SendEntitySpawn passes it through and AnyWorldReadyPeer takes and applies it. RegisterExistingWorldNpcs takes the joiner's slot and skips it; NpcEnumOrigin goes (its converge value had no caller), the save-key policy becomes HasSaveKey. The interceptor send checks AnyWorldReadyPeer. Wire: none. Evidence: event_relay_drill rejoin on 65727d95: walk and snapshot present, no duplicate (RED c3a9e637 shows it). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The skip cited MTA's pSkip by name only and its callers not at all. The fan-out's skip now cites CPlayerManager.cpp:159-175; the enrolment's split cites MTA's join (CGame.cpp:1426, :1459), the gate asked before the send against MTA's returned receiver count, and the edge enrolment against MTA's registration at creation (CElement.cpp:39); the interceptor's no-send-while-loading cites CPlayerManager.cpp:167; the duplicate guard names why a re-announce re-sends the whole set. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A field report saw the rain effect inside the base on every peer, the host included. On the host rain runs untouched: our lane only mirrors the host's state to clients through the game's own setters, and never moves the emitter or the camera. The emitter follows the player's camera and spawns its drops below the roof's collision mesh. Known limits gains the row so the next report is answered here. Evidence: the lane's code and the decompiled day-night cycle Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The row said the hint on a trash-bits pile frames the game's own box by design. It rested on reading the decompiled Blueprints alone; it was never measured in the game, and the report it answers is disputed. It returns, in whichever direction, with the measurement. Evidence: none yet; a probe measures it in single player and in coop Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The base laptop and every portable PC render one ui_laptop_C widget, whose tabs are a UWidgetSwitcher. ue_wrap/devices/laptop_widget finds that widget from the gamemode's laptop field and reads the switcher's active index and tab count, and writes the index through SetActiveWidgetIndex alone: the game's switcherSwitched also runs createRC, which binds a viewer's keys to a remote drone, so it is never the write. Nothing calls it yet; the tab lane follows. Evidence: c9771d51 GREEN 10/10, handover 3/3, smoke; 5 REDs FAIL Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The base laptop and every portable PC render one ui_laptop_C widget, and its tab was each peer's own. The peer holding the laptop claim now reports the switcher's index at the post of switcherSwitched and the floppy and sub-game tab handlers; the host checks the sender holds the claim and the index is one of its own tabs, writes its widget and sends LaptopTabState to the others. A viewer writes the index alone, never switcherSwitched (its createRC binds a viewer's keys). A joiner gets the host's index at its world-ready. Protocol: kProtocolVersion 233 -> 234; kinds 185 (Client), 186 (Host). Evidence: c9771d51 GREEN 10/10, handover 3/3, smoke; 5 REDs FAIL Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Seven arms (tab, tab-host, tab-handover, tab-norc, tab-forged, tab-slot, tab-join) set by laptop_tab_drill on both peers. The holder walks to a point inside the laptop's Box with the director, enters with action 4, waits for the host's verdict on the claim, then switches tabs by the game's own tab call and the floppy tab's click handler; the other peer reads its widget's index. The norc arm counts a viewer's createRC, the forged arm sends a report holding nothing, the slot arm has the host stamp a state with another sender's slot. laptop_tab gains RefusedCount for the two refusal arms. Evidence: c9771d51 GREEN 10/10, handover 3/3, smoke; 5 REDs FAIL Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
tab-join passed on a client that was already in the session and read the host's tab 4 live. The client now passes only when the first state this process receives carries tab 4; a first state of another tab followed by a 4 prints the rejoin marker line and keeps reading, so the next life's first state is the connect snapshot. tab-handover's holder, when its claim is not confirmed after the enter, logs the game's enter conditions as it reads them first: the keyboard's and the mouse's up-Z, the distances, the Box overlap, the speeds, isOpened and the claim's holder. Evidence: c9771d51 GREEN 10/10, handover 3/3, smoke; 5 REDs FAIL Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
A move with no behaviour change: laptop_tab_drill.cpp was past the 800-line
soft cap. The holder (walk to the PC, enter, switch tabs), the reader (judge
the last tab), the verdict lines and the per-arm arrival baseline move to
laptop_tab_drill_steps.{h,cpp}; the arms stay in laptop_tab_drill.cpp. The
log lines and every condition are unchanged. The arm's log name is handed to
the steps at the arm's start instead of read from the config latch.
Evidence: c9771d51 GREEN 10/10, handover 3/3, smoke; 5 REDs FAIL
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The handover arm abandoned on 2 of 3 runs at the same standpoint with every condition its line read met: parts upright, still and near, the player in the Box. The laptop's actionOptionIndex returns without a hint before those checks while its boot or shutdown latent runs or the wall power is off, and the refusal line read neither. It now prints powered and anim from the power state it already read, and power=? when that read failed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
laptop_C::lookAt sets use_floppybox and use_zipBox from the component the player's trace hit, and action 4 checks them before anything else: either set ejects the floppy and returns without a hint. The holder pressed enter wherever the walk had left the camera, so the same standpoint entered on 1 run and refused on 2 with every other gate open (powered=1 anim=0). A new Aim step turns the camera through a fan of headings at the laptop's screen and presses enter only once the trace is on the laptop with both flags clear; the refusal line reads them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Aim step looked for the trace on the laptop at its screen widget and abandoned five arms: the widget is not what the trace takes. The laptop's getActionOptions offers action 4 as the enter only while the aimed component is boxScreen (on the floppy or zip hitbox it ejects), so the fan now turns onto boxScreen and the step is ready on exactly that offer, both hitbox flags clear. A fan that never gets there says what its last heading's trace hit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The first run of the boxScreen aim took the box at heading 11 of 15, on the 8 degree row: the box's centre is not what the trace takes from every standpoint. Two rows at -16 and +16 degrees give the fan the margin; 25 headings at 6 ticks each are about 2.5 s. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The Aim step hand-rolled a fan of headings and a hold per pose that coop::director::AimFan already provides to sack_drill and server_upgrade_drill, so it now ticks an AimFan onto boxScreen with the game's enter offer as the reading, and its own constants are gone. boxScreen and the two hitbox flag offsets resolve once at the step's start instead of three property walks a tick, and the step abandons if the laptop or boxScreen dies. The headers say the holder aims before it enters. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The holder kept the laptop, its Box and boxScreen as bare pointers from Find to the enter, checked by IsLive at best, which a recycled slot passes. They are CachedObjRef now: HolderTick reads the laptop and the Box once a tick past Find and ends the arm if either goes, and the helpers take the validated pointers. The Aim guard also checks the two hitbox flag offsets, so a flag that never resolved says so at once instead of after the whole fan. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The header grew to 18 lines when the aim before the enter joined its description, past the 15-line cap the public prose gate holds the tree to. The same text in 15 lines: the walk, the aim, the enter and the verdict share one paragraph, and the three refusal arms one entry. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Thank you -- and sorry for the silence while it waited. The Octa's attack ends in an explosion, and when this arrived nothing in the mod synced explosions, so the foundation went first: explosions are now decided by the host and shown once on every peer, and a client's own grenade or rocket asks the host for its blast. That is on main now. The Octa itself is next, built from your request: the host's roll of the Octa (and of the night egg) is what every peer shows, the classes are on the NPC allowlist, a client's own roll is refused, and the host's attack is relayed into each client's own copy of the Blueprint. The parts of yours that carry over -- the dev spawn button, the allowlist row, the explosion source row -- land as a commit under your name, with ours after it. I will post the shas here when it is in. |
The net of the commit below kept for the Geom Octa unit: geomOcta_C on the NPC allowlist, the mainGamemode_C row of the EX spawn-source table, and the dev menu's "Spawn geomOcta" button (spawn_npc SpawnGeomOcta). The rest of #48 (the pose-field packing, the laser as a world actor, the refused tick) is redone in the commits that follow. These hunks alone would build a live-brained mirror, so the set lands as one unit. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> (cherry picked from commit 519a9d4)
|
The Octa is in, on main as of
The drill checks it end to end: on a client, every laser the host fires is the same laser, a joiner sees the attack in progress, and with the relay off the drill fails. Thank you for starting it. |
What changed