refactor: hide DLC pack lookups behind TexturePack::needsPurchase and BufferedImage helper

This commit is contained in:
MatthewBeshay 2026-04-09 21:22:07 +10:00
parent 8b202ba5f1
commit 4d9db3ed3b
8 changed files with 117 additions and 106 deletions

View file

@ -7,9 +7,6 @@
#include <vector> #include <vector>
#include "PlatformTypes.h" #include "PlatformTypes.h"
#include "app/common/DLC/DLCFile.h"
#include "app/common/DLC/DLCManager.h"
#include "app/common/DLC/DLCPack.h"
#include "minecraft/IGameServices.h" #include "minecraft/IGameServices.h"
#include "platform/fs/fs.h" #include "platform/fs/fs.h"
#include "platform/renderer/renderer.h" #include "platform/renderer/renderer.h"
@ -121,43 +118,28 @@ BufferedImage::BufferedImage(const std::string& File, bool filenameHasExtension,
} }
} }
} }
BufferedImage::BufferedImage(DLCPack* dlcPack, const std::string& File, BufferedImage::BufferedImage() {
bool filenameHasExtension) {
int32_t hr;
std::string filePath = File;
std::uint8_t* pbData = nullptr;
std::uint32_t dataBytes = 0;
for (int l = 0; l < 10; l++) data[l] = nullptr; for (int l = 0; l < 10; l++) data[l] = nullptr;
width = 0;
height = 0;
}
for (int l = 0; l < 10; l++) { bool BufferedImage::loadMipmapPng(int level, std::uint8_t* bytes,
std::string name; std::uint32_t numBytes) {
std::string mipMapPath = if (level < 0 || level >= 10 || bytes == nullptr || numBytes == 0) {
(l != 0) ? "MipMapLevel" + toWString<int>(l + 1) : ""; return false;
name = "res" + (filenameHasExtension
? filePath
: filePath.substr(0, filePath.length() - 4) +
mipMapPath + ".png");
if (!dlcPack->doesPackContainFile(DLCManager::e_DLCType_All, name)) {
if (l == 0) gameServices().fatalLoadError();
return;
}
DLCFile* dlcFile = dlcPack->getFile(DLCManager::e_DLCType_All, name);
pbData = dlcFile->getData(dataBytes);
if (pbData == nullptr || dataBytes == 0) {
if (l == 0) gameServices().fatalLoadError();
return;
}
D3DXIMAGE_INFO ImageInfo;
hr = PlatformRenderer.LoadTextureData(pbData, dataBytes, &ImageInfo,
&data[l]);
if (hr == 0 && l == 0) {
width = ImageInfo.Width;
height = ImageInfo.Height;
}
} }
D3DXIMAGE_INFO ImageInfo;
int32_t hr = PlatformRenderer.LoadTextureData(bytes, numBytes, &ImageInfo,
&data[level]);
if (hr != 0) {
return false;
}
if (level == 0) {
width = ImageInfo.Width;
height = ImageInfo.Height;
}
return true;
} }
BufferedImage::BufferedImage(std::uint8_t* pbData, std::uint32_t dataBytes) { BufferedImage::BufferedImage(std::uint8_t* pbData, std::uint32_t dataBytes) {

View file

@ -4,7 +4,6 @@
#include <vector> #include <vector>
class Graphics; class Graphics;
class DLCPack;
class BufferedImage { class BufferedImage {
private: private:
@ -15,15 +14,19 @@ private:
public: public:
static const int TYPE_INT_ARGB = 0; static const int TYPE_INT_ARGB = 0;
static const int TYPE_INT_RGB = 1; static const int TYPE_INT_RGB = 1;
BufferedImage(); // empty image; fill with loadMipmapPng()
BufferedImage(int width, int height, int type); BufferedImage(int width, int height, int type);
BufferedImage(const std::string& File, bool filenameHasExtension = false, BufferedImage(const std::string& File, bool filenameHasExtension = false,
bool bTitleUpdateTexture = false, bool bTitleUpdateTexture = false,
const std::string& drive = ""); // 4J added const std::string& drive = ""); // 4J added
BufferedImage(DLCPack* dlcPack, const std::string& File,
bool filenameHasExtension = false); // 4J Added
BufferedImage(std::uint8_t* pbData, std::uint32_t dataBytes); // 4J added BufferedImage(std::uint8_t* pbData, std::uint32_t dataBytes); // 4J added
~BufferedImage(); ~BufferedImage();
// Decode `numBytes` of PNG-encoded texture data into mipmap slot
// `level`. The first call (level == 0) populates width/height.
// Returns true on success.
bool loadMipmapPng(int level, std::uint8_t* bytes, std::uint32_t numBytes);
int getWidth(); int getWidth();
int getHeight(); int getHeight();
void getRGB(int startX, int startY, int w, int h, std::vector<int>& out, void getRGB(int startX, int startY, int w, int h, std::vector<int>& out,

View file

@ -104,7 +104,6 @@
#include "minecraft/client/gui/inventory/CreativeInventoryScreen.h" #include "minecraft/client/gui/inventory/CreativeInventoryScreen.h"
#endif #endif
#include "app/common/ConsoleGameMode.h" #include "app/common/ConsoleGameMode.h"
#include "app/common/DLC/DLCPack.h"
#include "app/common/Tutorial/FullTutorialMode.h" #include "app/common/Tutorial/FullTutorialMode.h"
#include "app/common/UI/All Platforms/IUIScene_CreativeMenu.h" #include "app/common/UI/All Platforms/IUIScene_CreativeMenu.h"
#include "app/common/UI/UIFontData.h" #include "app/common/UI/UIFontData.h"
@ -123,7 +122,7 @@
#include "minecraft/client/player/Input.h" #include "minecraft/client/player/Input.h"
#include "minecraft/client/renderer/texture/TextureManager.h" #include "minecraft/client/renderer/texture/TextureManager.h"
#include "minecraft/client/resources/Colours/ColourTable.h" #include "minecraft/client/resources/Colours/ColourTable.h"
#include "minecraft/client/skins/DLCTexturePack.h" #include "minecraft/client/skins/TexturePack.h"
#include "minecraft/world/entity/npc/Villager.h" #include "minecraft/world/entity/npc/Villager.h"
#include "minecraft/world/item/alchemy/PotionMacros.h" #include "minecraft/world/item/alchemy/PotionMacros.h"
#include "minecraft/world/level/chunk/SparseDataStorage.h" #include "minecraft/world/level/chunk/SparseDataStorage.h"
@ -1097,18 +1096,8 @@ void Minecraft::run_middle() {
TexturePack* tPack = TexturePack* tPack =
Minecraft::GetInstance() Minecraft::GetInstance()
->skins->getSelected(); ->skins->getSelected();
DLCTexturePack* pDLCTexPack = if (tPack->needsPurchase()) {
(DLCTexturePack*)tPack; bTrialTexturepack = true;
DLCPack* pDLCPack =
pDLCTexPack->getDLCInfoParentPack();
if (pDLCPack) {
if (!pDLCPack->hasPurchasedFile(
DLCManager::e_DLCType_Texture,
"")) {
bTrialTexturepack = true;
}
} }
} }

View file

@ -14,8 +14,6 @@
#include "ReceivingLevelScreen.h" #include "ReceivingLevelScreen.h"
#include "app/common/App_structs.h" #include "app/common/App_structs.h"
#include "app/common/ConsoleGameMode.h" #include "app/common/ConsoleGameMode.h"
#include "app/common/DLC/DLCManager.h"
#include "app/common/DLC/DLCPack.h"
#include "minecraft/client/skins/ISkinAssetData.h" #include "minecraft/client/skins/ISkinAssetData.h"
#include "app/common/Network/Socket.h" #include "app/common/Network/Socket.h"
#include "app/common/Tutorial/FullTutorialMode.h" #include "app/common/Tutorial/FullTutorialMode.h"
@ -45,7 +43,7 @@
#include "minecraft/client/player/LocalPlayer.h" #include "minecraft/client/player/LocalPlayer.h"
#include "minecraft/client/player/RemotePlayer.h" #include "minecraft/client/player/RemotePlayer.h"
#include "minecraft/client/renderer/LevelRenderer.h" #include "minecraft/client/renderer/LevelRenderer.h"
#include "minecraft/client/skins/DLCTexturePack.h" #include "minecraft/client/skins/TexturePack.h"
#include "minecraft/client/skins/TexturePackRepository.h" #include "minecraft/client/skins/TexturePackRepository.h"
#include "minecraft/core/particles/ParticleTypes.h" #include "minecraft/core/particles/ParticleTypes.h"
#include "minecraft/network/INetworkService.h" #include "minecraft/network/INetworkService.h"
@ -3456,11 +3454,7 @@ int ClientConnection::HostDisconnectReturned(
// world // world
if (!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) { if (!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) {
TexturePack* tPack = Minecraft::GetInstance()->skins->getSelected(); TexturePack* tPack = Minecraft::GetInstance()->skins->getSelected();
DLCTexturePack* pDLCTexPack = (DLCTexturePack*)tPack; if (tPack->needsPurchase()) {
DLCPack* pDLCPack =
pDLCTexPack->getDLCInfoParentPack(); // tPack->getDLCPack();
if (!pDLCPack->hasPurchasedFile(DLCManager::e_DLCType_Texture, "")) {
// no upsell, we're about to quit // no upsell, we're about to quit
MinecraftServer::getInstance()->setSaveOnExit(false); MinecraftServer::getInstance()->setSaveOnExit(false);
// flag a app action of exit game // flag a app action of exit game

View file

@ -31,6 +31,7 @@
#include "platform/fs/fs.h" #include "platform/fs/fs.h"
#include "platform/input/input.h" #include "platform/input/input.h"
#include "platform/storage/storage.h" #include "platform/storage/storage.h"
#include "util/StringHelpers.h"
#if defined(_WINDOWS64) #if defined(_WINDOWS64)
#endif #endif
@ -192,12 +193,41 @@ std::string DLCTexturePack::getAnimationString(const std::string& textureName,
BufferedImage* DLCTexturePack::getImageResource( BufferedImage* DLCTexturePack::getImageResource(
const std::string& File, bool filenameHasExtension /*= false*/, const std::string& File, bool filenameHasExtension /*= false*/,
bool bTitleUpdateTexture /*=false*/, const std::string& drive /*=""*/) { bool bTitleUpdateTexture /*=false*/, const std::string& drive /*=""*/) {
if (m_dlcDataPack) if (!m_dlcDataPack) {
return new BufferedImage(m_dlcDataPack, "/" + File,
filenameHasExtension);
else
return fallback->getImageResource(File, filenameHasExtension, return fallback->getImageResource(File, filenameHasExtension,
bTitleUpdateTexture, drive); bTitleUpdateTexture, drive);
}
auto* image = new BufferedImage();
const std::string filePath = "/" + File;
for (int l = 0; l < 10; l++) {
std::string mipMapPath =
(l != 0) ? "MipMapLevel" + toWString<int>(l + 1) : "";
std::string name =
"res" + (filenameHasExtension
? filePath
: filePath.substr(0, filePath.length() - 4) +
mipMapPath + ".png");
if (!m_dlcDataPack->doesPackContainFile(DLCManager::e_DLCType_All,
name)) {
if (l == 0) gameServices().fatalLoadError();
break;
}
DLCFile* dlcFile =
m_dlcDataPack->getFile(DLCManager::e_DLCType_All, name);
std::uint32_t dataBytes = 0;
std::uint8_t* pbData = dlcFile->getData(dataBytes);
if (pbData == nullptr || dataBytes == 0) {
if (l == 0) gameServices().fatalLoadError();
break;
}
if (!image->loadMipmapPng(l, pbData, dataBytes)) {
break;
}
}
return image;
} }
DLCPack* DLCTexturePack::getDLCPack() { return m_dlcDataPack; } DLCPack* DLCTexturePack::getDLCPack() { return m_dlcDataPack; }
@ -471,3 +501,14 @@ DLCPack* DLCTexturePack::getDLCInfoParentPack() {
XCONTENTDEVICEID DLCTexturePack::GetDLCDeviceID() { XCONTENTDEVICEID DLCTexturePack::GetDLCDeviceID() {
return m_dlcInfoPack->GetDLCDeviceID(); return m_dlcInfoPack->GetDLCDeviceID();
} }
bool DLCTexturePack::needsPurchase() {
if (m_dlcInfoPack == nullptr) {
return false;
}
DLCPack* parent = m_dlcInfoPack->GetParentPack();
if (parent == nullptr) {
return false;
}
return !parent->hasPurchasedFile(DLCManager::e_DLCType_Texture, "");
}

View file

@ -27,47 +27,47 @@ public:
using AbstractTexturePack::getResource; using AbstractTexturePack::getResource;
DLCTexturePack(std::uint32_t id, DLCPack* pack, TexturePack* fallback); DLCTexturePack(std::uint32_t id, DLCPack* pack, TexturePack* fallback);
~DLCTexturePack(){}; ~DLCTexturePack() override = default;
virtual std::string getResource(const std::string& name); std::string getResource(const std::string& name) override;
virtual DLCPack* getDLCPack(); DLCPack* getDLCPack() override;
virtual std::string getDesc1() { std::string getDesc1() override {
return m_stringTable->getString("IDS_TP_DESCRIPTION"); return m_stringTable->getString("IDS_TP_DESCRIPTION");
} }
virtual std::string getName() { std::string getName() override {
return m_stringTable->getString("IDS_DISPLAY_NAME"); return m_stringTable->getString("IDS_DISPLAY_NAME");
} }
virtual std::string getWorldName() { std::string getWorldName() override {
return m_stringTable->getString("IDS_WORLD_NAME"); return m_stringTable->getString("IDS_WORLD_NAME");
} }
// Added for sound banks with MashUp packs // Added for sound banks with MashUp packs
protected: protected:
//@Override //@Override
void loadIcon(); void loadIcon() override;
void loadComparison(); void loadComparison() override;
void loadName(); void loadName() override;
void loadDescription(); void loadDescription() override;
InputStream* getResourceImplementation( InputStream* getResourceImplementation(
const std::string& name); // throws IOException const std::string& name) override; // throws IOException
public: public:
//@Override //@Override
bool hasFile(const std::string& name); bool hasFile(const std::string& name) override;
bool isTerrainUpdateCompatible(); bool isTerrainUpdateCompatible() override;
// 4J Added // 4J Added
virtual std::string getPath(bool bTitleUpdateTexture = false, std::string getPath(bool bTitleUpdateTexture = false,
const char* pchBDPatchFilename = nullptr); const char* pchBDPatchFilename = nullptr) override;
virtual std::string getAnimationString(const std::string& textureName, std::string getAnimationString(const std::string& textureName,
const std::string& path); const std::string& path) override;
virtual BufferedImage* getImageResource(const std::string& File, BufferedImage* getImageResource(const std::string& File,
bool filenameHasExtension = false, bool filenameHasExtension = false,
bool bTitleUpdateTexture = false, bool bTitleUpdateTexture = false,
const std::string& drive = ""); const std::string& drive = "") override;
virtual void loadColourTable(); void loadColourTable() override;
virtual bool hasData() { return m_bHasLoadedData; } bool hasData() override { return m_bHasLoadedData; }
virtual bool isLoadingData() { return m_bLoadingData; } bool isLoadingData() override { return m_bLoadingData; }
private: private:
static std::string getRootPath(std::uint32_t packId, bool allowOverride, static std::string getRootPath(std::uint32_t packId, bool allowOverride,
@ -78,14 +78,16 @@ private:
public: public:
int onPackMounted(int iPad, std::uint32_t dwErr, int onPackMounted(int iPad, std::uint32_t dwErr,
std::uint32_t dwLicenceMask); std::uint32_t dwLicenceMask);
virtual void loadData(); void loadData() override;
virtual void loadUI(); void loadUI() override;
virtual void unloadUI(); void unloadUI() override;
virtual std::string getXuiRootPath(); std::string getXuiRootPath() override;
virtual ArchiveFile* getArchiveFile() { return m_archiveFile; } ArchiveFile* getArchiveFile() override { return m_archiveFile; }
virtual unsigned int getDLCParentPackId(); unsigned int getDLCParentPackId() override;
virtual DLCPack* getDLCInfoParentPack(); virtual DLCPack* getDLCInfoParentPack();
virtual unsigned char getDLCSubPackId(); unsigned char getDLCSubPackId() override;
XCONTENTDEVICEID GetDLCDeviceID(); XCONTENTDEVICEID GetDLCDeviceID();
[[nodiscard]] bool needsPurchase() override;
}; };

View file

@ -47,6 +47,12 @@ return TexturePack.class.getResourceAsStream(name);
} }
virtual DLCPack* getDLCPack() { return nullptr; } virtual DLCPack* getDLCPack() { return nullptr; }
// True for trial skins / texture packs that the user has not yet
// purchased. The default (built-in) skin and any owned DLC pack
// returns false. Used by save and disconnect paths to refuse
// operations that would otherwise unlock paid content for free.
[[nodiscard]] virtual bool needsPurchase() { return false; }
// 4J Added // 4J Added
virtual std::string getPath(bool bTitleUpdateTexture = false, virtual std::string getPath(bool bTitleUpdateTexture = false,
const char* pchBDPatchFilename = nullptr); const char* pchBDPatchFilename = nullptr);

View file

@ -11,14 +11,12 @@
#include "ServerChunkCache.h" #include "ServerChunkCache.h"
#include "ServerLevelListener.h" #include "ServerLevelListener.h"
#include "ServerPlayer.h" #include "ServerPlayer.h"
#include "app/common/DLC/DLCManager.h"
#include "app/common/DLC/DLCPack.h"
#include "java/Class.h" #include "java/Class.h"
#include "java/Random.h" #include "java/Random.h"
#include "minecraft/Console_Debug_enum.h" #include "minecraft/Console_Debug_enum.h"
#include "minecraft/IGameServices.h" #include "minecraft/IGameServices.h"
#include "minecraft/client/Minecraft.h" #include "minecraft/client/Minecraft.h"
#include "minecraft/client/skins/DLCTexturePack.h" #include "minecraft/client/skins/TexturePack.h"
#include "minecraft/client/skins/TexturePackRepository.h" #include "minecraft/client/skins/TexturePackRepository.h"
#include "minecraft/network/packet/AddGlobalEntityPacket.h" #include "minecraft/network/packet/AddGlobalEntityPacket.h"
#include "minecraft/network/packet/EntityEventPacket.h" #include "minecraft/network/packet/EntityEventPacket.h"
@ -981,11 +979,7 @@ void ServerLevel::saveToDisc(ProgressListener* progressListener,
// the case for going into the mash-up pack world with a trial version) // the case for going into the mash-up pack world with a trial version)
if (!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) { if (!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) {
TexturePack* tPack = Minecraft::GetInstance()->skins->getSelected(); TexturePack* tPack = Minecraft::GetInstance()->skins->getSelected();
DLCTexturePack* pDLCTexPack = (DLCTexturePack*)tPack; if (tPack->needsPurchase()) {
DLCPack* pDLCPack = pDLCTexPack->getDLCInfoParentPack();
if (!pDLCPack->hasPurchasedFile(DLCManager::e_DLCType_Texture, "")) {
return; return;
} }
} }