diff options
| author | kuwa <kuwa.com3@gmail.com> | 2026-03-06 15:01:36 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-03-06 00:01:36 -0600 |
| commit | 182d76f3916e17727e3dcf9e38db2132360215dd (patch) | |
| tree | 7c9993f0ffe90575ea1568f428ebe25d70f9b77d /Minecraft.Client/Minecraft.cpp | |
| parent | c45541080fc34ce57a9e49f917b8d847634987c4 (diff) | |
Introduce uid.dat (offline PlayerUIDs), fix multiplayer save data persistence (#536)
* 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).
* fix: preserve legacy host xuid (base xuid + 0) for existing world compatibility
- Add legacy embedded host XUID helper (base + 0).
- When Minecraft.Client is hosting, force only the first host player to use legacy host XUID.
- Keep name-based XUID for non-host players.
- Prevent old singleplayer/hosted worlds from losing/mismatching host player data.
* update: migrate Win64 player uid to `uid.dat`-backed XUID and add XUID based duplicate login guards
- Replace Win64 username-derived XUID resolution with persistent `uid.dat`-backed identity (`Windows64_Xuid` / `Win64Xuid`).
- Persist a per-client XUID next to the executable, with first-run generation, read/write, and process-local caching.
- Keep legacy host compatibility by pinning host self to legacy embedded `base + 0` XUID for existing world/playerdata continuity.
- Propagate packet-authoritative XUIDs into QNet player slots via `m_resolvedXuid`, and use it for `GetXuid`/`GetPlayerByXuid` with legacy fallback.
- Update Win64 profile/network paths to use persistent XUID for non-host clients and clear resolved identity on disconnect.
- Add login-time duplicate checks: reject connections when the same XUID is already connected (in addition to existing duplicate-name checks on Win64).
- Add inline compatibility comments around legacy/new identity coexistence paths for easier future maintenance.
* update: ensure uid.dat exists at startup in client mode for multiplayer
Diffstat (limited to 'Minecraft.Client/Minecraft.cpp')
| -rw-r--r-- | Minecraft.Client/Minecraft.cpp | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/Minecraft.Client/Minecraft.cpp b/Minecraft.Client/Minecraft.cpp index b87745f0..7ae206cf 100644 --- a/Minecraft.Client/Minecraft.cpp +++ b/Minecraft.Client/Minecraft.cpp @@ -52,6 +52,7 @@ #include "..\Minecraft.World\net.minecraft.world.level.dimension.h" #include "..\Minecraft.World\net.minecraft.world.item.h" #include "..\Minecraft.World\Minecraft.World.h" +#include "Windows64\Windows64_Xuid.h" #include "ClientConnection.h" #include "..\Minecraft.World\HellRandomLevelSource.h" #include "..\Minecraft.World\net.minecraft.world.entity.animal.h" @@ -1038,6 +1039,19 @@ shared_ptr<MultiplayerLocalPlayer> Minecraft::createExtraLocalPlayer(int idx, co PlayerUID playerXUIDOnline = INVALID_XUID; ProfileManager.GetXUID(idx,&playerXUIDOffline,false); ProfileManager.GetXUID(idx,&playerXUIDOnline,true); +#ifdef _WINDOWS64 + // Compatibility rule for Win64 id migration + // host keeps legacy host XUID, non-host uses persistent uid.dat XUID. + INetworkPlayer *localNetworkPlayer = g_NetworkManager.GetLocalPlayerByUserIndex(idx); + if(localNetworkPlayer != NULL && localNetworkPlayer->IsHost()) + { + playerXUIDOffline = Win64Xuid::GetLegacyEmbeddedHostXuid(); + } + else + { + playerXUIDOffline = Win64Xuid::ResolvePersistentXuid(); + } +#endif localplayers[idx]->setXuid(playerXUIDOffline); localplayers[idx]->setOnlineXuid(playerXUIDOnline); localplayers[idx]->setIsGuest(ProfileManager.IsGuest(idx)); @@ -4299,6 +4313,19 @@ void Minecraft::setLevel(MultiPlayerLevel *level, int message /*=-1*/, shared_pt playerXUIDOnline.setForAdhoc(); } #endif +#ifdef _WINDOWS64 + // On Windows, the implementation has been changed to use a per-client pseudo XUID based on `uid.dat`. + // To maintain player data compatibility with existing worlds, the world host (the first player) will use the previous embedded pseudo XUID. + INetworkPlayer *localNetworkPlayer = g_NetworkManager.GetLocalPlayerByUserIndex(iPrimaryPlayer); + if(localNetworkPlayer != NULL && localNetworkPlayer->IsHost()) + { + playerXUIDOffline = Win64Xuid::GetLegacyEmbeddedHostXuid(); + } + else + { + playerXUIDOffline = Win64Xuid::ResolvePersistentXuid(); + } +#endif player->setXuid(playerXUIDOffline); player->setOnlineXuid(playerXUIDOnline); @@ -4481,6 +4508,18 @@ void Minecraft::respawnPlayer(int iPad, int dimension, int newEntityId) PlayerUID playerXUIDOnline = INVALID_XUID; ProfileManager.GetXUID(iTempPad,&playerXUIDOffline,false); ProfileManager.GetXUID(iTempPad,&playerXUIDOnline,true); +#ifdef _WINDOWS64 + // Same compatibility rule as create/init paths. + INetworkPlayer *localNetworkPlayer = g_NetworkManager.GetLocalPlayerByUserIndex(iTempPad); + if(localNetworkPlayer != NULL && localNetworkPlayer->IsHost()) + { + playerXUIDOffline = Win64Xuid::GetLegacyEmbeddedHostXuid(); + } + else + { + playerXUIDOffline = Win64Xuid::ResolvePersistentXuid(); + } +#endif player->setXuid(playerXUIDOffline); player->setOnlineXuid(playerXUIDOnline); player->setIsGuest( ProfileManager.IsGuest(iTempPad) ); |
