Skip to content

refactor: move the input hook and the proxy into core - #28

Merged
ResurrectedTrader merged 1 commit into
mainfrom
split/core-moves
Sep 16, 2026
Merged

ResurrectedTrader merged 1 commit into
mainfrom
split/core-moves

Conversation

@ResurrectedTrader

@ResurrectedTrader ResurrectedTrader commented Sep 16, 2026

Copy link
Copy Markdown
Owner

Targets main directly; #27 has landed. Last of the five PRs that replaced the original combined branch.

Neither the input hook nor the SOCKS5 proxy depends on the game version, so neither belongs in a backend.

The moves

  • core/input/ — the WH_GETMESSAGE hook, the game-window WndProc subclass, and the injected-input tagging. The backend now hands core a table of callbacks rather than core reaching into the backend, so the dependency runs one way.
  • core/proxy/ — the SOCKS5 connect hook, previously lod114d/hooks/Socks5Proxy.cpp. A near-verbatim move; git shows it as a rename.

Two things in here that are not just moves

The input callbacks are plain function pointers, not std::function. Remove() clears the table from a different thread than the one dispatching, and tearing down a std::function under a caller destroys the callable while it is executing. They're fed from GameCallbacks entries, which were already raw pointers, so nothing had to adapt. Each dispatch site also loads its pointer once into a local — otherwise a clear landing between the null check and the call turns the guard into a null call.

Unhooking has to run on the window thread, the only one that runs the hook procedure and the subclass, so neither can be mid-call while it happens. GameThread::Execute can't carry it there: by teardown the frontend has shut its engine down and the per-frame drain no longer runs, so the post would never land. Remove therefore sends a private WM_REMOVE_INPUT_HOOKS and falls back to retiring from the caller's thread if the window doesn't answer within two seconds.

That fallback has a cost worth knowing about: teardown runs under the loader lock, so if the game thread is itself blocked there, unload stalls for the full two seconds before falling through.

Contract changes

  • InstallHooks returns bool, and the frontend aborts init rather than running on half-installed hooks. The 1.14d backend always returns true today, so this is a contract change with no behaviour change yet.
  • game::console::BackendPanel lets a backend contribute console tabs as an interface instead of a list of function pointers. The 1.14d backend contributes none.

Both exist so a second backend has somewhere to plug in; neither does anything visible in this tree.

Docs

docs/window_message_handling.md is updated for the move, the function-pointer change, and the teardown handshake — the last of which the doc never described.

Verification

clang-format clean; clang-tidy clean (118 files, full no-cache run). Not exercised at runtime by me; the teardown path in particular deserves a live check, since it's the one with new cross-thread behaviour.

🤖 Generated with Claude Code

Base automatically changed from land-stack to main September 16, 2026 22:29
Neither depends on the game version. The WH_GETMESSAGE hook, the
game-window WndProc subclass and the injected-input tagging move to
core/input; the SOCKS5 connect hook moves to core/proxy. The backend now
hands core a table of callbacks instead of core reaching into the backend,
so the dependency runs one way.

The input callbacks are plain function pointers, matching the GameCallbacks
entries they are fed from. Remove() clears the table from a different thread
than the one dispatching, and under std::function that destroyed a callable
while it was executing; each dispatch site also loads its pointer once, so a
clear between the guard and the call cannot turn it into a null call.

Unhooking has to happen on the window thread, the only one that runs the
hook procedure and the subclass. GameThread::Execute cannot carry it there -
by teardown the frontend has shut its engine down and the per-frame drain no
longer runs - so Remove sends a private message and falls back to the
caller thread if the window does not answer.

Contract. InstallHooks returns bool and the frontend aborts init rather than
running on half-installed hooks. game::console::BackendPanel lets a backend
contribute console tabs as an interface instead of a list of function
pointers; the 1.14d backend contributes none.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ResurrectedTrader
ResurrectedTrader merged commit 886dd28 into main Sep 16, 2026
1 check passed
@ResurrectedTrader
ResurrectedTrader deleted the split/core-moves branch September 16, 2026 22:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant