fix: fix multiplayer player data mix between different players bug
Fixes a Win64 multiplayer issue where player data (`players/*.dat`) could be mismatched because identity was effectively tied to connection-order `smallId` XUIDs. Introduces a deterministic username-derived persistent XUID and integrates it into the existing XUID-based save pipeline. - Added `Windows64_NameXuid` for deterministic `name -> persistent xuid` resolution - On Win64 login (`PlayerList`), set `ServerPlayer::xuid` from username-based resolver - Aligned local player `xuid` assignment (`Minecraft`) for create/init/respawn paths to use the same resolver - Added Win64 local-self guard in `ClientConnection::handleAddPlayer` using name match to avoid duplicate local remote-player creation - Kept `IQNet::GetPlayerByXuid` compatibility fallback behavior, while extending lookup to also resolve username-based XUIDs - Moved implementation to `Minecraft.Client/Windows64/Windows64_NameXuid.h`; kept legacy `Win64NameXuid.h` as compatibility include Rename migration is intentionally out of scope (same-name identity only).
This commit is contained in:
46
Minecraft.Client/Windows64/Windows64_NameXuid.h
Normal file
46
Minecraft.Client/Windows64/Windows64_NameXuid.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef _WINDOWS64
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Win64NameXuid
|
||||
{
|
||||
/**
|
||||
* ## Resolves a persistent 64-bit player ID from the player's username.
|
||||
*
|
||||
* We keep this deterministic so existing player save/map systems can key off XUID.
|
||||
*
|
||||
* @param playerName The player's username.
|
||||
* @return The resolved PlayerUID.
|
||||
*/
|
||||
inline PlayerUID ResolvePersistentXuidFromName(const std::wstring &playerName)
|
||||
{
|
||||
const unsigned __int64 fnvOffset = 14695981039346656037ULL;
|
||||
const unsigned __int64 fnvPrime = 1099511628211ULL;
|
||||
unsigned __int64 hash = fnvOffset;
|
||||
|
||||
for (size_t i = 0; i < playerName.length(); ++i)
|
||||
{
|
||||
unsigned short codeUnit = (unsigned short)playerName[i];
|
||||
hash ^= (unsigned __int64)(codeUnit & 0xFF);
|
||||
hash *= fnvPrime;
|
||||
hash ^= (unsigned __int64)((codeUnit >> 8) & 0xFF);
|
||||
hash *= fnvPrime;
|
||||
}
|
||||
|
||||
// Namespace the hash away from legacy smallId-based values.
|
||||
hash ^= 0x9E3779B97F4A7C15ULL;
|
||||
hash |= 0x8000000000000000ULL;
|
||||
|
||||
if (hash == (unsigned __int64)INVALID_XUID)
|
||||
{
|
||||
hash ^= 0x0100000000000001ULL;
|
||||
}
|
||||
|
||||
return (PlayerUID)hash;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user