SIGN IN SIGN UP

core: convert the 4 remaining run_chain dispatchers to fan_out_collapsing (#57)

A4c from the core stabilization audit (#49). Stacked on #56. Mechanical now
that #56 settled the collapse policy. Net -284 lines.

dispatch_output 103, dispatch_usercmd 76, dispatch_game_event_pre 75 and
dispatch_usermsg 55 all move onto fan_out_collapsing with StopAt::Stop. Each
payload body was lifted VERBATIM into build_args rather than retyped; the only
edit inside them is ctx_local.global(tc) -> tc.get_current_context().global(tc),
since the closure has the scope but no separate context binding.

A REAL BUG FOUND WHILE CONVERTING: all four mapped an out-of-range handler
return to Continue, with a comment saying so, while fan_out_collapsing (#56)
mapped _ => Stop. That meant a handler returning a garbage number (return 7, a
truthy non-HookResult) would have TRUNCATED every other plugin's dispatch --
the same composition failure as the damage Handled short-circuit fixed one PR
earlier, reintroduced through the back door of a default arm. Now
1 => Changed, 2 => Handled, 3 => Stop, _ => Continue: garbage means 'no
opinion', the only safe reading. Knock-on: dispatch_damage tested n >= 2 on an
int32, so an out-of-range return like 7 used to block damage and now does not
-- the same change of meaning applied consistently.

dispatch_onframe is DELIBERATELY NOT converted. It looks like the fifth
run_chain path and is not: it is the reference implementation, with real
priority through FRAME's multiplexer::Descriptor, apply_errors auto-disable,
note_js_location breadcrumbs and a different handler type (JsHandler).
Converting it would LOSE priority and auto-disable -- the two things the other
paths never had. It stays until Channels<H> gives the generic path those
capabilities.

Still hand-rolled by design: dispatch_concommand (no mux snapshot; iterates
CONCOMMANDS by name), dispatch_onframe, and the four pending-drain shells,
whose queue loop + terminal-close prune is the point.

cargo test -p s2script-core: 466 passed. CI=1 make ci: green.
G
Gabriel Hirakawa committed
fa1e5ec7df0d4c330cbfb98804b88b7078c87f9d
Parent: ff99f75
Committed by GitHub <noreply@github.com> on 8/1/2026, 6:07:39 AM