• src/doors/syncconquer/door/door_input.c door_io.c door_io.h door_node.

    From Rob Swindell (on Debian Linux)@1:103/705 to Git commit to main/sbbs/master on Thu Jul 23 00:08:00 2026
    https://gitlab.synchro.net/main/sbbs/-/commit/dd3251e868afce35dcc6005f
    Modified Files:
    src/doors/syncconquer/door/door_input.c door_io.c door_io.h door_node.c door_node.h xtrn/syncalert/syncalert.example.ini xtrn/syncdawn/syncdawn.example.ini
    Log Message:
    syncconquer: end the game when the player has stopped playing

    The second door to adopt the shared idle-user clock, and the reference for the ones with no JS lobby. Same reasoning as SyncRetro: the BBS's own "Maximum Inactivity" is structurally inert here, because it is reset by any socket traffic and DSR frame pacing makes the terminal answer ~10x/second on its own. Presence has to be judged on real input, which only the door can tell apart from its own pace-acks.

    Warn-then-terminate, with the countdown on the bottom row and the same wording the sibling door uses. Both keyboard AND mouse feed the clock, and mouse
    MOTION counts, not just clicks -- Red Alert is mouse-driven, so a player commanding units with no keystrokes at all must not be judged absent. Configured by -i<seconds> or the door's own [idle] section, defaulting to 10 minutes; the argument wins when given, so a launcher can pass -i0 to excuse an exempt user.

    Input that answers the countdown is CONSUMED rather than delivered. "Press any key" must not also fire whatever that key does -- F1 would open the help card, Esc the Options menu, a click would issue an order to the selected unit. The hook therefore sits above the F1/Esc handling in emit_key(), and the release edge still falls through so no key is left stuck down.

    Three things live testing found that no offline run would have:

    - The overlay never erased itself. banner_live() simply stopped drawing, and
    since the game picture does not reach the margins, nothing repainted those
    cells -- a dismissed countdown sat on screen indefinitely. It now records
    what it drew and wipes those rows. This fixes the page and who's-online
    notices too, which had the same fate anywhere the image does not cover.
    - Wiping is not enough on its own. door_io_present() skips the whole overlay
    draw on a deduped frame, so an erase queued while the game sat at a static
    menu was never emitted. A pending erase now keeps the overlay "active" for
    the one extra frame it takes to flush.
    - ...and the wipe clears a whole row, which on a top-anchored banner cuts a
    black band through the game UI. So it also forces a full repaint, letting
    the next present redraw the picture over those rows.

    The countdown is bottom-anchored while the multi-row page/who's-online banners stay on top, so it lands where this door already puts its Ctrl-S stats strip, and where the sibling door puts the same countdown. The strip yields the row while a notice is up and is forced back when it clears, since it otherwise repaints only when its own text changes.

    -i is parsed AND neutered in door_sanitize_argv(). That matters more here than in the sibling: this door really does hand argv to Vanilla Conquer's Parse_Command_Line(), so an unstripped flag could misfire an engine option.

    A repaint request cannot simply clear g_have_last, incidentally: the overlay draws near the END of a present, and that same call then sets g_have_last = 1 and swallows it. It lives in its own flag, consumed at the top of the NEXT present -- and forces a whole frame rather than a dirty-rect patch, because
    the wipe changed the screen without changing the framebuffer, so a diff
    against the unchanged previous frame would find nothing to send.

    Verified offline against both binaries (-i fires to the millisecond, -i0 never does, the ini alone works with no -i, and an explicit -i overrides it), and on a live node for the parts capture mode cannot show: the countdown renders and clears, and mouse motion dismisses it (with the pointer over a focused window -- a terminal reports no motion to an unfocused one).

    KNOWN ROUGH EDGE, left as-is: overlapping notices still leave artifacts, e.g.
    a node message arriving while the who's-online listing is up. The repaint machinery above assumes one banner at a time, and a second notice replacing a live one does not re-run the wipe for the rows the first occupied.

    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
    --- SBBSecho 3.37-Linux
    * Origin: Vertrauen - [vert/cvs/bbs].synchro.net (1:103/705)