#include "app/common/SkinManager.h" #include #include #include #include #include "app/common/App_structs.h" #include "app/common/DLC/DLCManager.h" #include "app/common/DLC/DLCPack.h" #include "app/common/DLC/DLCSkinFile.h" #include "app/common/Minecraft_Macros.h" #include "app/linux/LinuxGame.h" #include "minecraft/client/Minecraft.h" #include "minecraft/client/model/geom/Model.h" #include "minecraft/client/multiplayer/MultiPlayerLocalPlayer.h" #include "minecraft/client/renderer/entity/EntityRenderer.h" #include "minecraft/client/renderer/entity/EntityRenderDispatcher.h" #include "minecraft/world/entity/player/Player.h" #include "platform/profile/profile.h" SkinManager::SkinManager() : m_xuidNotch(INVALID_XUID) { for (int i = 0; i < XUSER_MAX_COUNT; i++) { m_dwAdditionalModelParts[i] = 0; } } void SkinManager::setPlayerSkin(int iPad, const std::string& name, GAME_SETTINGS** gameSettingsA) { std::uint32_t skinId = getSkinIdFromPath(name); setPlayerSkin(iPad, skinId, gameSettingsA); } void SkinManager::setPlayerSkin(int iPad, std::uint32_t dwSkinId, GAME_SETTINGS** gameSettingsA) { app.DebugPrintf("Setting skin for %d to %08X\n", iPad, dwSkinId); gameSettingsA[iPad]->dwSelectedSkin = dwSkinId; gameSettingsA[iPad]->bSettingsChanged = true; if (Minecraft::GetInstance()->localplayers[iPad] != nullptr) Minecraft::GetInstance()->localplayers[iPad]->setAndBroadcastCustomSkin( dwSkinId); } std::string SkinManager::getPlayerSkinName(int iPad, GAME_SETTINGS** gameSettingsA) { return getSkinPathFromId(gameSettingsA[iPad]->dwSelectedSkin); } std::uint32_t SkinManager::getPlayerSkinId(int iPad, GAME_SETTINGS** gameSettingsA, DLCManager& dlcManager) { DLCPack* Pack = nullptr; DLCSkinFile* skinFile = nullptr; std::uint32_t dwSkin = gameSettingsA[iPad]->dwSelectedSkin; char chars[256]; if (GET_IS_DLC_SKIN_FROM_BITMASK(dwSkin)) { snprintf(chars, 256, "dlcskin%08d.png", GET_DLC_SKIN_ID_FROM_BITMASK(dwSkin)); Pack = dlcManager.getPackContainingSkin(chars); if (Pack) { skinFile = Pack->getSkinFile(chars); bool bSkinIsFree = skinFile->getParameterAsBool(DLCManager::e_DLCParamType_Free); bool bLicensed = Pack->hasPurchasedFile(DLCManager::e_DLCType_Skin, skinFile->getPath()); if (bSkinIsFree || bLicensed) { return dwSkin; } else { return 0; } } } return dwSkin; } std::uint32_t SkinManager::getAdditionalModelParts(int iPad) { return m_dwAdditionalModelParts[iPad]; } void SkinManager::setPlayerCape(int iPad, const std::string& name, GAME_SETTINGS** gameSettingsA) { std::uint32_t capeId = Player::getCapeIdFromPath(name); setPlayerCape(iPad, capeId, gameSettingsA); } void SkinManager::setPlayerCape(int iPad, std::uint32_t dwCapeId, GAME_SETTINGS** gameSettingsA) { app.DebugPrintf("Setting cape for %d to %08X\n", iPad, dwCapeId); gameSettingsA[iPad]->dwSelectedCape = dwCapeId; gameSettingsA[iPad]->bSettingsChanged = true; if (Minecraft::GetInstance()->localplayers[iPad] != nullptr) Minecraft::GetInstance()->localplayers[iPad]->setAndBroadcastCustomCape( dwCapeId); } std::string SkinManager::getPlayerCapeName(int iPad, GAME_SETTINGS** gameSettingsA) { return Player::getCapePathFromId(gameSettingsA[iPad]->dwSelectedCape); } std::uint32_t SkinManager::getPlayerCapeId(int iPad, GAME_SETTINGS** gameSettingsA) { return gameSettingsA[iPad]->dwSelectedCape; } void SkinManager::setPlayerFavoriteSkin(int iPad, int iIndex, unsigned int uiSkinID, GAME_SETTINGS** gameSettingsA) { app.DebugPrintf("Setting favorite skin for %d to %08X\n", iPad, uiSkinID); gameSettingsA[iPad]->uiFavoriteSkinA[iIndex] = uiSkinID; gameSettingsA[iPad]->bSettingsChanged = true; } unsigned int SkinManager::getPlayerFavoriteSkin( int iPad, int iIndex, GAME_SETTINGS** gameSettingsA) { return gameSettingsA[iPad]->uiFavoriteSkinA[iIndex]; } unsigned char SkinManager::getPlayerFavoriteSkinsPos( int iPad, GAME_SETTINGS** gameSettingsA) { return gameSettingsA[iPad]->ucCurrentFavoriteSkinPos; } void SkinManager::setPlayerFavoriteSkinsPos(int iPad, int iPos, GAME_SETTINGS** gameSettingsA) { gameSettingsA[iPad]->ucCurrentFavoriteSkinPos = (unsigned char)iPos; gameSettingsA[iPad]->bSettingsChanged = true; } unsigned int SkinManager::getPlayerFavoriteSkinsCount( int iPad, GAME_SETTINGS** gameSettingsA) { unsigned int uiCount = 0; for (int i = 0; i < MAX_FAVORITE_SKINS; i++) { if (gameSettingsA[iPad]->uiFavoriteSkinA[i] != 0xFFFFFFFF) { uiCount++; } else { break; } } return uiCount; } void SkinManager::validateFavoriteSkins(int iPad, GAME_SETTINGS** gameSettingsA, DLCManager& dlcManager) { unsigned int uiCount = getPlayerFavoriteSkinsCount(iPad, gameSettingsA); unsigned int uiValidSkin = 0; char chars[256]; for (unsigned int i = 0; i < uiCount; i++) { snprintf(chars, 256, "dlcskin%08d.png", getPlayerFavoriteSkin(iPad, i, gameSettingsA)); DLCPack* pDLCPack = dlcManager.getPackContainingSkin(chars); if (pDLCPack != nullptr) { DLCSkinFile* pSkinFile = pDLCPack->getSkinFile(chars); if (pDLCPack->hasPurchasedFile(DLCManager::e_DLCType_Skin, "") || (pSkinFile && pSkinFile->isFree())) { gameSettingsA[iPad]->uiFavoriteSkinA[uiValidSkin++] = gameSettingsA[iPad]->uiFavoriteSkinA[i]; } } } for (unsigned int i = uiValidSkin; i < MAX_FAVORITE_SKINS; i++) { gameSettingsA[iPad]->uiFavoriteSkinA[i] = 0xFFFFFFFF; } } bool SkinManager::isXuidNotch(PlayerUID xuid) { if (m_xuidNotch != INVALID_XUID && xuid != INVALID_XUID) { return PlatformProfile.AreXUIDSEqual(xuid, m_xuidNotch); } return false; } bool SkinManager::isXuidDeadmau5(PlayerUID xuid) { // Delegates back to static MojangData on Game - this is a simple forwarding // wrapper for now; the actual MojangData map stays on Game. return app.isXuidDeadmau5(xuid); } void SkinManager::addMemoryTextureFile(const std::string& wName, std::uint8_t* pbData, unsigned int byteCount) { std::lock_guard lock(csMemFilesLock); PMEMDATA pData = nullptr; auto it = m_MEM_Files.find(wName); if (it != m_MEM_Files.end()) { #if !defined(_CONTENT_PACKAGE) printf("Incrementing the memory texture file count for %s\n", wName.c_str()); #endif pData = (*it).second; if (pData->byteCount == 0 && byteCount != 0) { if (pData->pbData != nullptr) delete[] pData->pbData; pData->pbData = pbData; pData->byteCount = byteCount; } ++pData->ucRefCount; return; } pData = new MEMDATA(); pData->pbData = pbData; pData->byteCount = byteCount; pData->ucRefCount = 1; m_MEM_Files[wName] = pData; } void SkinManager::removeMemoryTextureFile(const std::string& wName) { std::lock_guard lock(csMemFilesLock); auto it = m_MEM_Files.find(wName); if (it != m_MEM_Files.end()) { #if !defined(_CONTENT_PACKAGE) printf("Decrementing the memory texture file count for %s\n", wName.c_str()); #endif PMEMDATA pData = (*it).second; --pData->ucRefCount; if (pData->ucRefCount <= 0) { #if !defined(_CONTENT_PACKAGE) printf("Erasing the memory texture file data for %s\n", wName.c_str()); #endif delete pData; m_MEM_Files.erase(wName); } } } bool SkinManager::defaultCapeExists() { std::string wTex = "Special_Cape.png"; bool val = false; { std::lock_guard lock(csMemFilesLock); auto it = m_MEM_Files.find(wTex); if (it != m_MEM_Files.end()) val = true; } return val; } bool SkinManager::isFileInMemoryTextures(const std::string& wName) { bool val = false; { std::lock_guard lock(csMemFilesLock); auto it = m_MEM_Files.find(wName); if (it != m_MEM_Files.end()) val = true; } return val; } void SkinManager::getMemFileDetails(const std::string& wName, std::uint8_t** ppbData, unsigned int* pByteCount) { std::lock_guard lock(csMemFilesLock); auto it = m_MEM_Files.find(wName); if (it != m_MEM_Files.end()) { PMEMDATA pData = (*it).second; *ppbData = pData->pbData; *pByteCount = pData->byteCount; } } void SkinManager::setAdditionalSkinBoxes(std::uint32_t dwSkinID, SKIN_BOX* SkinBoxA, unsigned int dwSkinBoxC) { EntityRenderer* renderer = EntityRenderDispatcher::instance->getRenderer(eTYPE_PLAYER); Model* pModel = renderer->getModel(); std::vector* pvModelPart = new std::vector; std::vector* pvSkinBoxes = new std::vector; { std::lock_guard lock_mp(csAdditionalModelParts); std::lock_guard lock_sb(csAdditionalSkinBoxes); app.DebugPrintf( "*** SetAdditionalSkinBoxes - Inserting model parts for skin %d " "from " "array of Skin Boxes\n", dwSkinID & 0x0FFFFFFF); for (unsigned int i = 0; i < dwSkinBoxC; i++) { if (pModel) { ModelPart* pModelPart = pModel->AddOrRetrievePart(&SkinBoxA[i]); pvModelPart->push_back(pModelPart); pvSkinBoxes->push_back(&SkinBoxA[i]); } } m_AdditionalModelParts.insert( std::pair*>(dwSkinID, pvModelPart)); m_AdditionalSkinBoxes.insert( std::pair*>(dwSkinID, pvSkinBoxes)); } } std::vector* SkinManager::setAdditionalSkinBoxes( std::uint32_t dwSkinID, std::vector* pvSkinBoxA) { EntityRenderer* renderer = EntityRenderDispatcher::instance->getRenderer(eTYPE_PLAYER); Model* pModel = renderer->getModel(); std::vector* pvModelPart = new std::vector; { std::lock_guard lock_mp(csAdditionalModelParts); std::lock_guard lock_sb(csAdditionalSkinBoxes); app.DebugPrintf( "*** SetAdditionalSkinBoxes - Inserting model parts for skin %d " "from " "array of Skin Boxes\n", dwSkinID & 0x0FFFFFFF); for (auto it = pvSkinBoxA->begin(); it != pvSkinBoxA->end(); ++it) { if (pModel) { ModelPart* pModelPart = pModel->AddOrRetrievePart(*it); pvModelPart->push_back(pModelPart); } } m_AdditionalModelParts.insert( std::pair*>(dwSkinID, pvModelPart)); m_AdditionalSkinBoxes.insert( std::pair*>(dwSkinID, pvSkinBoxA)); } return pvModelPart; } std::vector* SkinManager::getAdditionalModelParts( std::uint32_t dwSkinID) { std::lock_guard lock(csAdditionalModelParts); std::vector* pvModelParts = nullptr; if (m_AdditionalModelParts.size() > 0) { auto it = m_AdditionalModelParts.find(dwSkinID); if (it != m_AdditionalModelParts.end()) { pvModelParts = (*it).second; } } return pvModelParts; } std::vector* SkinManager::getAdditionalSkinBoxes( std::uint32_t dwSkinID) { std::lock_guard lock(csAdditionalSkinBoxes); std::vector* pvSkinBoxes = nullptr; if (m_AdditionalSkinBoxes.size() > 0) { auto it = m_AdditionalSkinBoxes.find(dwSkinID); if (it != m_AdditionalSkinBoxes.end()) { pvSkinBoxes = (*it).second; } } return pvSkinBoxes; } unsigned int SkinManager::getAnimOverrideBitmask(std::uint32_t dwSkinID) { std::lock_guard lock(csAnimOverrideBitmask); unsigned int uiAnimOverrideBitmask = 0L; if (m_AnimOverrides.size() > 0) { auto it = m_AnimOverrides.find(dwSkinID); if (it != m_AnimOverrides.end()) { uiAnimOverrideBitmask = (*it).second; } } return uiAnimOverrideBitmask; } void SkinManager::setAnimOverrideBitmask(std::uint32_t dwSkinID, unsigned int uiAnimOverrideBitmask) { std::lock_guard lock(csAnimOverrideBitmask); if (m_AnimOverrides.size() > 0) { auto it = m_AnimOverrides.find(dwSkinID); if (it != m_AnimOverrides.end()) { return; // already in here } } m_AnimOverrides.insert(std::pair( dwSkinID, uiAnimOverrideBitmask)); } std::uint32_t SkinManager::getSkinIdFromPath(const std::string& skin) { bool dlcSkin = false; unsigned int skinId = 0; if (skin.size() >= 14) { dlcSkin = skin.substr(0, 3).compare("dlc") == 0; std::string skinValue = skin.substr(7, skin.size()); skinValue = skinValue.substr(0, skinValue.find_first_of('.')); std::stringstream ss; if (dlcSkin) ss << std::dec << skinValue.c_str(); else ss << std::hex << skinValue.c_str(); ss >> skinId; skinId = MAKE_SKIN_BITMASK(dlcSkin, skinId); } return skinId; } std::string SkinManager::getSkinPathFromId(std::uint32_t skinId) { char chars[256]; if (GET_IS_DLC_SKIN_FROM_BITMASK(skinId)) { snprintf(chars, 256, "dlcskin%08d.png", GET_DLC_SKIN_ID_FROM_BITMASK(skinId)); } else { std::uint32_t ugcSkinIndex = GET_UGC_SKIN_ID_FROM_BITMASK(skinId); std::uint32_t defaultSkinIndex = GET_DEFAULT_SKIN_ID_FROM_BITMASK(skinId); if (ugcSkinIndex == 0) { snprintf(chars, 256, "defskin%08X.png", defaultSkinIndex); } else { snprintf(chars, 256, "ugcskin%08X.png", ugcSkinIndex); } } return chars; }