Skip to content

Refactor: User/Player distinction - #5178

Merged
Loobinex merged 2 commits into
dkfans:masterfrom
nstbayless:user-player-distinction
Sep 6, 2026
Merged

Refactor: User/Player distinction#5178
Loobinex merged 2 commits into
dkfans:masterfrom
nstbayless:user-player-distinction

Conversation

@nstbayless

Copy link
Copy Markdown
Contributor

User: a human/device connected to the game.
Player: a faction such as PLAYER0 (the red keeper), PLAYER1( the blue keeper), PLAYER2, ... the heroes, neutrals, etc.

Sometimes the code is a bit imprecise on the distinction. Users on the network are occasionally referred to as "players". In order to eventually implement "archon mode" (allowing multiple users to control the same player co-operatively), I've gone through the codebase to try to solidify this distinction.

In particular, where possible, I've switched away from ever inferring the user from the player, as future work on archon mode may mean that players can have multiple users. Instead, using a user id is generally preferred to using a player idx anywhere the distinction between two users of the same player might someday be important. To this end, I've added PlayerNumber get_net_user_player_number(NetUserId user). I'd like to eventually deprecate and remove the user_id field in PlayerInfo entirely.

TL;DR: prefer the direction User --> Player, avoid Player --> User.

Sorry for the largeish diff, but it's mostly a couple consistent find/replace rules, and it should allow for smaller bite-sized work toward archon mode in the future. Hopefully.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are verified authorization/spoofing issues in the refactored frontend chat handling that can misattribute/privilege messages before approval.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR refactors network/input handling to consistently distinguish Net users (connected humans/devices) from in-game players/factions, as groundwork for future “archon mode” (multiple users controlling one player).

Changes:

  • Replace packet addressing and packet processing paths from “player index” semantics to NetUserId semantics (including new helpers like get_local_user() / get_local_packet()).
  • Introduce and use get_net_user_player_number(NetUserId) to map User → Player, updating many gameplay/front-end call sites accordingly.
  • Rename/refactor network structures and APIs to use “user” terminology (net_user_info, max_users, network_user_active/name, network_is_host()).
File summaries
File Description
src/roomspace.c Uses user-based packet lookup for roomspace input handling; switches local packet acquisition.
src/roomspace_prediction.c Updates prediction paths to use local user/packet helpers and user-based history.
src/player_utils.c Initializes local player’s user_id for non-network games.
src/player_data.h Replaces packet_num with user_id in PlayerInfo.
src/packets.h Refactors packet API to user-centric functions and updates processing function signatures.
src/packets.c Converts packet processing pipeline from player-indexed to user-indexed processing.
src/packets_misc.c Implements get_local_user() / get_local_packet() and redefines get_packet() to take NetUserId.
src/packets_input.c Refactors dungeon input processing to take NetUserId and use user packets/history.
src/packets_cheats.c Renames global cheats processing entrypoint for consistency.
src/net_resync.cpp Uses network_is_host() for host checks.
src/net_matchmaking.c Switches lobby JSON reporting to user-centric helpers.
src/net_main.h Renames “player” concepts to “user” in net state/public types; adds SOLO_HUMAN_ID.
src/net_main.c Renames internal storage and loops to max_users / user-centric naming.
src/net_lobby.c Updates lobby flows to use max_users and user-centric checks.
src/net_input_lag.c Updates lag logic to host checks and user-based packet history.
src/net_game.h Renames exported network user helpers and adds user→player mapping API.
src/net_game.c Adds network_is_host() and introduces net_user_player_number[] mapping used by get_net_user_player_number().
src/net_exchange_gameplay.h Refactors packet history and chat message APIs to be user-based.
src/net_exchange_gameplay.c Moves gameplay chat + packet history storage/lookup to NetUserId.
src/net_exchange_common.h Refactors chat send signature to use NetUserId.
src/net_exchange_common.c Writes/reads chat sender as NetUserId and converts loops/host checks to max_users.
src/net_checksums.c Refactors checksum comparison/update to use user packets and local packet helper.
src/main.cpp Updates mouse light logic to use user-based packet/history access.
src/local_camera.c Uses local user history and local packet helper for camera syncing.
src/frontmenu_specials.c Switches UI packet usage to local packet helper.
src/frontmenu_options.c Switches options UI packet usage to local packet helper.
src/frontmenu_net.c Refactors frontend chat send/process to use NetUserId; updates net user info references.
src/frontmenu_ingame_tabs.c Switches various GUI actions to use local packet helper; simplifies a spell helper signature.
src/frontmenu_ingame_evnt.c Switches in-game event GUI packet usage to local packet helper.
src/frontend.cpp Updates message bookkeeping and host-loss logic to user-based structures/mapping.
src/front_torture.c Refactors torture frontend input to use local/user packets.
src/front_network.h Updates frontend chat processing signature to NetUserId.
src/front_network.c Refactors frontend chat flow and host checks to user semantics.
src/front_landview_multiplayer.c Switches host checks and naming to user-centric helpers; refactors loops to NetUserId.
src/front_input.c Updates in-game chat send + various packet accesses to local packet helper; updates host-loss logic.
src/console_cmd.h Changes command execution API to accept NetUserId.
src/console_cmd.c Converts console commands to accept NetUserId and map to PlayerNumber internally.
Review details
  • Files reviewed: 37/37 changed files
  • Comments generated: 3
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/front_network.c Outdated
Comment thread src/net_exchange_common.c
Comment thread src/packets_input.c Outdated
@nstbayless

Copy link
Copy Markdown
Contributor Author

Resolved Copilot threads. Ready for review from @rainlizard.

@rainlizard

Copy link
Copy Markdown
Contributor

Issues:

  • Lobby chat maps users before the mapping exists — [src/front_network.c:150]
    net_user_player_number is initialized only after leaving the lobby. During lobby chat, non-host users therefore map to -1, which reaches prepare_network_chat_message() and then indexes net_user_info[-1] in add_message(). Frontend chat should remain user-indexed, and the original user must be passed to the host authorization check.

  • cmd_exec no longer matches the public API contract — [src/console_cmd.c:3222]
    api.c:1339 still passes a PlayerNumber, including the API’s explicit "player" selection, but this function now interprets it as NetUserId. Commands target the wrong player or map to -1, especially for nonzero local players and compacted multiplayer mappings.

  • Merge resolution drops Abyss room input support — [src/roomspace.c:1362]
    The recent master change from Abyss slab #5169 added RoRoF_PassAbyss here. Its omission means Abyss-only rooms no longer use bridge drag/paint controls.

(I'm assuming that last one would be handled as a merge conflict but I don't know)

@nstbayless

nstbayless commented Sep 3, 2026

Copy link
Copy Markdown
Contributor Author

The first one is a small fix (done). The last one is just a merge conflict yeah.

Regarding the command API, yeah, it's a good point. I've reverted most of the changes there for now. I'll have to think about how to handle those commands in archon mode, but come to think, most of them will probably just work fine as is.

Also, squashed.

@nstbayless
nstbayless force-pushed the user-player-distinction branch 3 times, most recently from ce9e8b7 to ba2350b Compare September 4, 2026 00:43
@nstbayless
nstbayless force-pushed the user-player-distinction branch from ba2350b to 4b49a89 Compare September 4, 2026 00:51
@rainlizard

Copy link
Copy Markdown
Contributor
  1. Reset the surviving player's user ID when converting a network game to local
    stop_network_game_state() clears GSF_NetworkActive without changing get_my_player()->user_id. A client can therefore retain user ID 1–3 after the host disconnects and the game continues locally.
    Once networking is inactive, get_local_user() returns SOLO_HUMAN_ID (0), while player-based helpers such as set_players_packet_action() continue writing through the stale player->user_id. Local input is then split between packet 0 and the old network packet, but process_packets() processes only the local user mapping. Actions written through the stale ID are consequently ignored.
    Set the surviving local player's user_id to SOLO_HUMAN_ID as part of the transition.

  2. Frontend chat now passes a user ID to a player-indexed helper
    process_frontend_chat_message() passes a NetUserId to prepare_network_chat_message(), but that helper still calls get_player(player_id) and manipulates PlayerInfo::mp_message_text.
    This fails after a sparse lobby has been compacted into player numbers. For example, users 0 and 2 become players 0 and 1. When user 2 returns to the lobby after a match, frontnet_start_input() edits get_my_player()—player 1—but frontend processing passes user 2 and therefore prepares and clears player 2's buffer. Player 1's entered text remains uncleared and can be resent, while received messages are staged on the wrong PlayerInfo.
    Frontend chat should remain entirely user-indexed and avoid PlayerInfo scratch storage, or the helper must have explicit user/player variants with correct mapping and buffer ownership.

@rainlizard

rainlizard commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

That's probably almost everything solved.

Did find this one:

  • process_user_global_packet_action receives the authoritative user, but determines host_packet from player->user_id. Once multiple users control one player, packets will be misclassified according to the player’s single stored user. Use user == SERVER_ID and line 726 should similarly pass user to process_gameplay_chat_message().

Under the current one-user-per-player mapping, there is no behavioral consequence because player->user_id == user. But once Archon mode allows multiple users to control one player:

  • A non-host user’s PckA_FinishGame packet may be mistaken for the host’s, potentially triggering host-specific level termination or quit behavior for every peer.
  • The actual host’s packet may be treated as a client packet, skipping those host-specific rules.
  • Chat from every user sharing that player may be attributed to the one stored player->user_id, producing incorrect sender logging and local/remote notification sounds.

So it is a dormant correctness issue: harmless today, but likely to become a hard-to-diagnose multiplayer bug when the many-users-to-one-player mapping is introduced.

@nstbayless

Copy link
Copy Markdown
Contributor Author

This is really the kind of thing I was hoping to handle in follow-up PRs. There are still many instances in the codebase of user being derived from player number. All will be addressed eventually as archon mode materializes.

For that to happen, the codebase needs to be in a position to accommodate small fixes that reorient the scattered player->user lookup toward the archon-correct user->player direction. So let's land this PR, then start grafting the smaller changes that will enable archon mode afterward.

@rainlizard

Copy link
Copy Markdown
Contributor

merging time @Loobinex

@Loobinex
Loobinex merged commit 328b5e1 into dkfans:master Sep 6, 2026
2 checks passed
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.

5 participants