Repository navigation
fix(server): read lobby entrants live, fix EntrantData struct size (#38) - #111
Merged
Merged
Conversation
echovr.exe indexes the entrant array at [lobby+0x360] with a 0xD8 stride in every site measured in ReVault: CNSLobby::SmiteEntrant 0x14061665d IMUL RAX, RDX, 0xd8 fcn_1406082b0 0x1406082c9 IMUL RDX, RDX, 0xd8 fcn 0x140616920 loop 0x14061698f ADD R8, 0xd8 The object is the same lobby IServerLib::Initialize receives: LoadServerSupport (0x14060bb70) stores the server library at this+0x38 and calls vtable+8 (Initialize) with `this` as the lobby argument, and SmiteEntrant reads this+0x130 (hosting) and this+0x8 (broadcaster) at the offsets Lobby already declares. The field offsets 0x00-0x9F still agree with echovr-reconstruction CServerConfig.h; 0xA0 there is the mapped prefix, not the element size. With the old sizeof, items[i] for i >= 1 read the wrong bytes. It was latent only because ServerContext's entrant copy was empty (#38). Adds the unmapped 0x38-byte tail and moves the static_assert to 0xD8. Co-Authored-By: nevr-runtime <agents@sprock.io>
…ialize (#38) ServerContext copied lobby->entrantData once in Initialize and served GetEntrant/GetEntrantCount from that copy. The game calls IServerLib::Initialize from CNSLobby LoadServerSupport (0x14060bb70) while the server boots, before anyone joins, so the copy was empty or stale for the life of the process. Every reader wanted the current lobby: - kLobbySmiteEntrant resolves an entrant to the slot index it hands the game; a stale copy can never find a player who joined later and could name a slot's previous occupant. - SaveLoadout / CurrentLoadout log the player in the given slot. - GameServerLib::Update scans entrants for the dirty flag. The copy came from 1b323fc ("lobby pointer invalid after Initialize returns"). That premise no longer holds in this code: 2e90317 restored m_lobby, and GetTcpBroadcaster and UnregisterAllCallbacks dereference it after Initialize. 2e90317 also notes FinalizeInitialization was never called before it, so the accessors returned null during 1b323fc's stability run and that run did not exercise entrant reads. Reading on demand is the refresh point the binary itself uses: CNSLobby::SmiteEntrant indexes [this+0x360] at call time, and CNSLobby::Update calls IServerLib::Update (0x1406178c3) before it touches the array, on the same thread. All three readers run on that thread (the ServerDB queue is drained inside Update). GetEntrantCount reports 0 while items is null, and the header documents that the returned pointer must not outlive the callback. The smite path now logs the resolved slot at Info and the entrant count on a miss, so an empty-lobby miss can be told apart from a bad id. Test: test_server_context, wired into test-auth-unit. Before the fix 6/7 failed; after it 7/7 pass. Dropping the null-items guard fails FreedArrayReadsAsEmpty. Co-Authored-By: nevr-runtime <agents@sprock.io>
This was referenced Oct 6, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Lobby::EntrantDatawas declared 0xA0 bytes; the game strides the entrant array at 0xD8 bytes in 3 places confirmed via ReVault disassembly (0x14061665d, 0x1406082c9, 0x14061698f). Every entrant after slot 0 was read at the wrong offset — garbage data. Fixed the struct size with the unmapped 0x38-byte tail added and a static_assert pinning it.Test plan
Not done
Open question for Andrew, not blocking
🤖 Generated with Claude Code