Skip to content

Vote Rewards: resolve Steam ID via LivePlayerManager, not naive Steam_ prefix#54

Merged
AdaInTheLab merged 1 commit into
mainfrom
fix/vote-rewards-resolve-player-id
Apr 30, 2026
Merged

Vote Rewards: resolve Steam ID via LivePlayerManager, not naive Steam_ prefix#54
AdaInTheLab merged 1 commit into
mainfrom
fix/vote-rewards-resolve-player-id

Conversation

@AdaInTheLab
Copy link
Copy Markdown
Collaborator

Summary

Bug fix caught by Ada during real testing. Vote-grant rewards were landing on orphan player_id rows instead of merging with the voter's real account.

What was wrong

`DispatchReward` was calling `ToPlayerId(steamId) => $"Steam_{steamId}"` and using that as the points_info / vip_gifts player_id. But:

  • 7D2D V 2.x identifies players via EOS (Epic Online Services), not Steam, even for Steam-platform players
  • A player's `CrossplatformId` is `EOS_<32hex>` — that's what gets used as the player_id across KC's tables
  • A player's `PlatformId` is `Steam_<76digit>` — that's the Steam-shaped form
  • `points_info.id` is keyed by CrossplatformId

So every vote-grant created a fresh row keyed by `Steam_` that didn't match the player's real `EOS_` row. Result in Ada's Points panel:

Player Points Last Sign-In
NonToxThicc 836 4/30/2026 11:31 AM
NonToxThicc 100 Never

Fix

`ResolvePlayerId(steamId)` does the lookup properly:

  1. Online path: find the player in `LivePlayerManager` by matching `PlatformId` (`Steam_`) and return their actual `PlayerId` (the EOS-form CrossplatformId). Common case — votes typically arrive while the player is on the server or recently was.
  2. Offline fallback: return `Steam_` and log a clear warning. We can't map Steam ID → CrossplatformId without a persistent table, which is its own future card. The warning tells admins what happened so they can manually merge if needed.

The audit row + provider `MarkClaimed` flow is unchanged — only the dispatch step was wrong.

Files

File What
`Features/VoteRewardsFeature.cs` `ToPlayerId` → `ResolvePlayerId` with LivePlayerManager lookup

Test plan

  • Pull, build, deploy
  • Vote at the listing site while logged into the game server
  • Wait for sweep (or run `/vote`)
  • Points tab: NonToxThicc real row gets +100 points (no second "NonToxThicc" row appears)
  • Server log: `granted to ... — 100 points (balance: )`

What about the existing orphan row?

The 100 misallocated points are still on the orphan row. Ada can either:

  • Use the panel's adjust-points action to manually move them to her real row + delete the orphan
  • Leave them; future grants will land correctly

Future card worth considering: a one-time migration that walks points_info, finds rows where `id` starts with `Steam_`, looks up if a corresponding `EOS_` row exists for the same player (via `player_metadata` if we wire that), and merges them.

🤖 Generated with Claude Code

When granting points (or any future Steam-ID-keyed reward), I was naively
returning "Steam_<76digit>" as the player_id. That doesn't match the
actual cross-platform id the rest of KC uses, because in 7D2D V 2.x
CrossplatformId is "EOS_<32hex>" even for Steam-platform players. Result:
every vote-grant created an orphan points_info row that lived alongside
the player's real EOS-keyed row instead of merging with it.

Caught by Ada in the Points panel — her real NonToxThicc row had 836
points + a recent sign-in; a separate "NonToxThicc" row keyed by Steam_
form held the orphan 100 points from a vote grant.

Fix: ResolvePlayerId(steamId) finds the player in LivePlayerManager by
matching PlatformId (which IS in Steam_ form) and returns their actual
PlayerId (the EOS-form CrossplatformId). Falls back to Steam_<id> with
a warning when the player is offline at grant time — that's the only
case where we can't map without a persistent Steam-ID → CrossplatformId
table, which is its own future card.

Common case (vote arrives while the player is online or recently was)
now lands on the correct row.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@AdaInTheLab AdaInTheLab merged commit cf02775 into main Apr 30, 2026
2 checks passed
@AdaInTheLab AdaInTheLab deleted the fix/vote-rewards-resolve-player-id branch April 30, 2026 17:06
@AdaInTheLab AdaInTheLab mentioned this pull request Apr 30, 2026
4 tasks
@AdaInTheLab AdaInTheLab mentioned this pull request May 9, 2026
5 tasks
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