From 692a1ffc8ed5a8520caa5fc50ffd8cb1b75006f5 Mon Sep 17 00:00:00 2001 From: Matthew Toro Date: Sat, 4 Apr 2026 02:17:59 -0400 Subject: [PATCH] optimized gameuuid handling --- Minecraft.Client/ClientConnection.cpp | 1 + Minecraft.Server/Access/Access.cpp | 5 +- Minecraft.Server/Access/BanManager.cpp | 3 + Minecraft.Server/Access/BanManager.h | 1 + Minecraft.Server/Access/WhitelistManager.cpp | 3 + Minecraft.Server/Access/WhitelistManager.h | 1 + Minecraft.World/AddPlayerPacket.cpp | 7 +- Minecraft.World/AddPlayerPacket.h | 2 + Minecraft.World/LoginPacket.cpp | 4 ++ Minecraft.World/LoginPacket.h | 2 + Minecraft.World/Player.cpp | 2 + Minecraft.World/Player.h | 5 +- Minecraft.World/UUID.cpp | 70 ++++++++------------ 13 files changed, 61 insertions(+), 45 deletions(-) diff --git a/Minecraft.Client/ClientConnection.cpp b/Minecraft.Client/ClientConnection.cpp index 26615352..5a33545b 100644 --- a/Minecraft.Client/ClientConnection.cpp +++ b/Minecraft.Client/ClientConnection.cpp @@ -877,6 +877,7 @@ void ClientConnection::handleAddPlayer(shared_ptr packet) player->yRotp = packet->yRot; player->yHeadRot = packet->yHeadRot * 360 / 256.0f; player->setXuid(packet->xuid); + player->setGameUUID(packet->gameUuid); #ifdef _DURANGO // On Durango request player display name from network manager diff --git a/Minecraft.Server/Access/Access.cpp b/Minecraft.Server/Access/Access.cpp index 5767a955..85c7642b 100644 --- a/Minecraft.Server/Access/Access.cpp +++ b/Minecraft.Server/Access/Access.cpp @@ -371,7 +371,10 @@ namespace ServerRuntime } auto whitelistManager = std::make_shared(*current); - const WhitelistedPlayerEntry entry = { formatted, name, metadata }; + WhitelistedPlayerEntry entry; + entry.xuid = formatted; + entry.name = name; + entry.metadata = metadata; if (!whitelistManager->AddPlayer(entry)) { return false; diff --git a/Minecraft.Server/Access/BanManager.cpp b/Minecraft.Server/Access/BanManager.cpp index 5447ab87..76f14b00 100644 --- a/Minecraft.Server/Access/BanManager.cpp +++ b/Minecraft.Server/Access/BanManager.cpp @@ -199,6 +199,7 @@ namespace ServerRuntime } AccessStorageUtils::TryGetStringField(object, "name", &entry.name); + AccessStorageUtils::TryGetStringField(object, "uuid", &entry.uuid); AccessStorageUtils::TryGetStringField(object, "created", &entry.metadata.created); AccessStorageUtils::TryGetStringField(object, "source", &entry.metadata.source); AccessStorageUtils::TryGetStringField(object, "expires", &entry.metadata.expires); @@ -302,6 +303,8 @@ namespace ServerRuntime { OrderedJson object = OrderedJson::object(); object["xuid"] = AccessStorageUtils::NormalizeXuid(entry.xuid); + if (!entry.uuid.empty()) + object["uuid"] = entry.uuid; object["name"] = entry.name; object["created"] = entry.metadata.created; object["source"] = entry.metadata.source; diff --git a/Minecraft.Server/Access/BanManager.h b/Minecraft.Server/Access/BanManager.h index 59103bec..f02c2383 100644 --- a/Minecraft.Server/Access/BanManager.h +++ b/Minecraft.Server/Access/BanManager.h @@ -22,6 +22,7 @@ namespace ServerRuntime struct BannedPlayerEntry { std::string xuid; + std::string uuid; std::string name; BanMetadata metadata; }; diff --git a/Minecraft.Server/Access/WhitelistManager.cpp b/Minecraft.Server/Access/WhitelistManager.cpp index 3629914e..ec0104b7 100644 --- a/Minecraft.Server/Access/WhitelistManager.cpp +++ b/Minecraft.Server/Access/WhitelistManager.cpp @@ -117,6 +117,7 @@ namespace ServerRuntime } AccessStorageUtils::TryGetStringField(object, "name", &entry.name); + AccessStorageUtils::TryGetStringField(object, "uuid", &entry.uuid); AccessStorageUtils::TryGetStringField(object, "created", &entry.metadata.created); AccessStorageUtils::TryGetStringField(object, "source", &entry.metadata.source); NormalizeMetadata(&entry.metadata); @@ -134,6 +135,8 @@ namespace ServerRuntime { OrderedJson object = OrderedJson::object(); object["xuid"] = AccessStorageUtils::NormalizeXuid(entry.xuid); + if (!entry.uuid.empty()) + object["uuid"] = entry.uuid; object["name"] = entry.name; object["created"] = entry.metadata.created; object["source"] = entry.metadata.source; diff --git a/Minecraft.Server/Access/WhitelistManager.h b/Minecraft.Server/Access/WhitelistManager.h index 1c2c5a0b..40139141 100644 --- a/Minecraft.Server/Access/WhitelistManager.h +++ b/Minecraft.Server/Access/WhitelistManager.h @@ -16,6 +16,7 @@ namespace ServerRuntime struct WhitelistedPlayerEntry { std::string xuid; + std::string uuid; std::string name; WhitelistMetadata metadata; }; diff --git a/Minecraft.World/AddPlayerPacket.cpp b/Minecraft.World/AddPlayerPacket.cpp index fbee1fc5..259fe758 100644 --- a/Minecraft.World/AddPlayerPacket.cpp +++ b/Minecraft.World/AddPlayerPacket.cpp @@ -55,6 +55,7 @@ AddPlayerPacket::AddPlayerPacket(shared_ptr player, PlayerUID xuid, Play this->xuid = xuid; this->OnlineXuid = OnlineXuid; + this->gameUuid = player->getGameUUID(); m_playerIndex = static_cast(player->getPlayerIndex()); m_skinId = player->getCustomSkin(); m_capeId = player->getCustomCape(); @@ -77,6 +78,8 @@ void AddPlayerPacket::read(DataInputStream *dis) //throws IOException carriedItem = dis->readShort(); xuid = dis->readPlayerUID(); OnlineXuid = dis->readPlayerUID(); + gameUuid.msb = dis->readLong(); + gameUuid.lsb = dis->readLong(); m_playerIndex = dis->readByte(); INT skinId = dis->readInt(); m_skinId = *(DWORD *)&skinId; @@ -102,6 +105,8 @@ void AddPlayerPacket::write(DataOutputStream *dos) //throws IOException dos->writeShort(carriedItem); dos->writePlayerUID(xuid); dos->writePlayerUID(OnlineXuid); + dos->writeLong(gameUuid.msb); + dos->writeLong(gameUuid.lsb); dos->writeByte(m_playerIndex); dos->writeInt(m_skinId); dos->writeInt(m_capeId); @@ -117,7 +122,7 @@ void AddPlayerPacket::handle(PacketListener *listener) int AddPlayerPacket::getEstimatedSize() { - int iSize= sizeof(int) + Player::MAX_NAME_LENGTH + sizeof(int) + sizeof(int) + sizeof(int) + sizeof(BYTE) + sizeof(BYTE) +sizeof(short) + sizeof(PlayerUID) + sizeof(PlayerUID) + sizeof(int) + sizeof(BYTE) + sizeof(unsigned int) + sizeof(byte); + int iSize= sizeof(int) + Player::MAX_NAME_LENGTH + sizeof(int) + sizeof(int) + sizeof(int) + sizeof(BYTE) + sizeof(BYTE) +sizeof(short) + sizeof(PlayerUID) + sizeof(PlayerUID) + sizeof(GameUUID) + sizeof(int) + sizeof(BYTE) + sizeof(unsigned int) + sizeof(byte); if( entityData != nullptr ) { diff --git a/Minecraft.World/AddPlayerPacket.h b/Minecraft.World/AddPlayerPacket.h index af90c97d..4bf44dee 100644 --- a/Minecraft.World/AddPlayerPacket.h +++ b/Minecraft.World/AddPlayerPacket.h @@ -3,6 +3,7 @@ using namespace std; #include "Packet.h" #include "SynchedEntityData.h" +#include "UUID.h" class Player; @@ -21,6 +22,7 @@ public: int carriedItem; PlayerUID xuid; // 4J Added PlayerUID OnlineXuid; // 4J Added + GameUUID gameUuid; BYTE m_playerIndex; // 4J Added DWORD m_skinId; // 4J Added DWORD m_capeId; // 4J Added diff --git a/Minecraft.World/LoginPacket.cpp b/Minecraft.World/LoginPacket.cpp index 79cdfbae..b8031810 100644 --- a/Minecraft.World/LoginPacket.cpp +++ b/Minecraft.World/LoginPacket.cpp @@ -111,6 +111,8 @@ void LoginPacket::read(DataInputStream *dis) //throws IOException maxPlayers = dis->readByte(); m_offlineXuid = dis->readPlayerUID(); m_onlineXuid = dis->readPlayerUID(); + m_gameUuid.msb = dis->readLong(); + m_gameUuid.lsb = dis->readLong(); m_friendsOnlyUGC = dis->readBoolean(); m_ugcPlayersVersion = dis->readInt(); difficulty = dis->readByte(); @@ -150,6 +152,8 @@ void LoginPacket::write(DataOutputStream *dos) //throws IOException dos->writeByte(maxPlayers); dos->writePlayerUID(m_offlineXuid); dos->writePlayerUID(m_onlineXuid); + dos->writeLong(m_gameUuid.msb); + dos->writeLong(m_gameUuid.lsb); dos->writeBoolean(m_friendsOnlyUGC); dos->writeInt(m_ugcPlayersVersion); dos->writeByte(difficulty); diff --git a/Minecraft.World/LoginPacket.h b/Minecraft.World/LoginPacket.h index 02a62b60..18d4afa3 100644 --- a/Minecraft.World/LoginPacket.h +++ b/Minecraft.World/LoginPacket.h @@ -2,6 +2,7 @@ using namespace std; #include "Packet.h" +#include "UUID.h" class LevelType; class LoginPacket : public Packet, public enable_shared_from_this @@ -12,6 +13,7 @@ public: int64_t seed; char dimension; PlayerUID m_offlineXuid, m_onlineXuid; // 4J Added + GameUUID m_gameUuid; char difficulty; // 4J Added bool m_friendsOnlyUGC; // 4J Added DWORD m_ugcPlayersVersion; // 4J Added diff --git a/Minecraft.World/Player.cpp b/Minecraft.World/Player.cpp index 00c7148e..e0e72ff2 100644 --- a/Minecraft.World/Player.cpp +++ b/Minecraft.World/Player.cpp @@ -762,6 +762,8 @@ unsigned int Player::getSkinAnimOverrideBitmask(DWORD skinId) void Player::setXuid(PlayerUID xuid) { m_xuid = xuid; + if (m_gameUuid.isNil() && xuid != INVALID_XUID) + m_gameUuid = GameUUID::fromXuid(xuid); #ifdef _XBOX_ONE // 4J Stu - For XboxOne (and probably in the future all other platforms) we store a UUID for the player to use as the owner key for tamed animals // This should just be a string version of the xuid diff --git a/Minecraft.World/Player.h b/Minecraft.World/Player.h index 2e223a1e..08e190bb 100644 --- a/Minecraft.World/Player.h +++ b/Minecraft.World/Player.h @@ -8,6 +8,7 @@ using namespace std; #include "PlayerEnderChestContainer.h" #include "CommandSender.h" #include "ScoreHolder.h" +#include "UUID.h" class AbstractContainerMenu; class Stats; @@ -417,7 +418,8 @@ public: PlayerUID getXuid() { return m_xuid; } void setOnlineXuid(PlayerUID xuid) { m_OnlineXuid = xuid; } PlayerUID getOnlineXuid() { return m_OnlineXuid; } - + void setGameUUID(const GameUUID& uuid) { m_gameUuid = uuid; } + GameUUID getGameUUID() const { return m_gameUuid; } void setPlayerIndex(DWORD dwIndex) { m_playerIndex = dwIndex; } DWORD getPlayerIndex() { return m_playerIndex; } @@ -431,6 +433,7 @@ public: private: PlayerUID m_xuid; PlayerUID m_OnlineXuid; + GameUUID m_gameUuid; protected: bool m_bShownOnMaps; diff --git a/Minecraft.World/UUID.cpp b/Minecraft.World/UUID.cpp index 45e1bf9b..381349cb 100644 --- a/Minecraft.World/UUID.cpp +++ b/Minecraft.World/UUID.cpp @@ -2,32 +2,37 @@ #include "UUID.h" #include "Random.h" #include +static void sha1_block(uint32_t h[5], const uint8_t block[64]) +{ + uint32_t w[80]; + for (int i = 0; i < 16; i++) + w[i] = (block[i * 4] << 24) | (block[i * 4 + 1] << 16) | (block[i * 4 + 2] << 8) | block[i * 4 + 3]; + for (int i = 16; i < 80; i++) { + uint32_t x = w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]; + w[i] = (x << 1) | (x >> 31); + } + uint32_t a = h[0], b = h[1], c = h[2], d = h[3], e = h[4]; + for (int i = 0; i < 80; i++) { + uint32_t f, k; + if (i < 20) { f = (b & c) | (~b & d); k = 0x5A827999; } + else if (i < 40) { f = b ^ c ^ d; k = 0x6ED9EBA1; } + else if (i < 60) { f = (b & c) | (b & d) | (c & d); k = 0x8F1BBCDC; } + else { f = b ^ c ^ d; k = 0xCA62C1D6; } + uint32_t tmp = ((a << 5) | (a >> 27)) + f + e + k + w[i]; + e = d; d = c; c = (b << 30) | (b >> 2); b = a; a = tmp; + } + h[0] += a; h[1] += b; h[2] += c; h[3] += d; h[4] += e; +} + static void sha1(const uint8_t* data, size_t len, uint8_t out[20]) { uint32_t h[5] = { 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 }; uint64_t bitLen = len * 8; + size_t fullBlocks = len / 64; - for (size_t blk = 0; blk < fullBlocks; blk++) { - const uint8_t* p = data + blk * 64; - uint32_t w[80]; - for (int i = 0; i < 16; i++) - w[i] = (p[i * 4] << 24) | (p[i * 4 + 1] << 16) | (p[i * 4 + 2] << 8) | p[i * 4 + 3]; - for (int i = 16; i < 80; i++) { - uint32_t x = w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]; - w[i] = (x << 1) | (x >> 31); - } - uint32_t a = h[0], b = h[1], c = h[2], d = h[3], e = h[4]; - for (int i = 0; i < 80; i++) { - uint32_t f, k; - if (i < 20) { f = (b & c) | (~b & d); k = 0x5A827999; } - else if (i < 40) { f = b ^ c ^ d; k = 0x6ED9EBA1; } - else if (i < 60) { f = (b & c) | (b & d) | (c & d); k = 0x8F1BBCDC; } - else { f = b ^ c ^ d; k = 0xCA62C1D6; } - uint32_t tmp = ((a << 5) | (a >> 27)) + f + e + k + w[i]; - e = d; d = c; c = (b << 30) | (b >> 2); b = a; a = tmp; - } - h[0] += a; h[1] += b; h[2] += c; h[3] += d; h[4] += e; - } + for (size_t blk = 0; blk < fullBlocks; blk++) + sha1_block(h, data + blk * 64); + uint8_t tail[128] = {}; size_t rem = len - fullBlocks * 64; if (rem) memcpy(tail, data + fullBlocks * 64, rem); @@ -36,27 +41,8 @@ static void sha1(const uint8_t* data, size_t len, uint8_t out[20]) for (int i = 0; i < 8; i++) tail[tailLen - 1 - i] = (uint8_t)(bitLen >> (i * 8)); - for (size_t off = 0; off < tailLen; off += 64) { - uint32_t w[80]; - for (int i = 0; i < 16; i++) - w[i] = (tail[off + i * 4] << 24) | (tail[off + i * 4 + 1] << 16) | - (tail[off + i * 4 + 2] << 8) | tail[off + i * 4 + 3]; - for (int i = 16; i < 80; i++) { - uint32_t x = w[i - 3] ^ w[i - 8] ^ w[i - 14] ^ w[i - 16]; - w[i] = (x << 1) | (x >> 31); - } - uint32_t a = h[0], b = h[1], c = h[2], d = h[3], e = h[4]; - for (int i = 0; i < 80; i++) { - uint32_t f, k; - if (i < 20) { f = (b & c) | (~b & d); k = 0x5A827999; } - else if (i < 40) { f = b ^ c ^ d; k = 0x6ED9EBA1; } - else if (i < 60) { f = (b & c) | (b & d) | (c & d); k = 0x8F1BBCDC; } - else { f = b ^ c ^ d; k = 0xCA62C1D6; } - uint32_t tmp = ((a << 5) | (a >> 27)) + f + e + k + w[i]; - e = d; d = c; c = (b << 30) | (b >> 2); b = a; a = tmp; - } - h[0] += a; h[1] += b; h[2] += c; h[3] += d; h[4] += e; - } + for (size_t off = 0; off < tailLen; off += 64) + sha1_block(h, tail + off); for (int i = 0; i < 5; i++) { out[i * 4] = (uint8_t)(h[i] >> 24);