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 "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 "platform/fs/fs.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,
bool filenameHasExtension) {
int32_t hr;
std::string filePath = File;
std::uint8_t* pbData = nullptr;
std::uint32_t dataBytes = 0;
BufferedImage::BufferedImage() {
for (int l = 0; l < 10; l++) data[l] = nullptr;
width = 0;
height = 0;
}
for (int l = 0; l < 10; l++) {
std::string name;
std::string mipMapPath =
(l != 0) ? "MipMapLevel" + toWString<int>(l + 1) : "";
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;
}
bool BufferedImage::loadMipmapPng(int level, std::uint8_t* bytes,
std::uint32_t numBytes) {
if (level < 0 || level >= 10 || bytes == nullptr || numBytes == 0) {
return false;
}
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) {

View file

@ -4,7 +4,6 @@
#include <vector>
class Graphics;
class DLCPack;
class BufferedImage {
private:
@ -15,15 +14,19 @@ private:
public:
static const int TYPE_INT_ARGB = 0;
static const int TYPE_INT_RGB = 1;
BufferedImage(); // empty image; fill with loadMipmapPng()
BufferedImage(int width, int height, int type);
BufferedImage(const std::string& File, bool filenameHasExtension = false,
bool bTitleUpdateTexture = false,
const std::string& drive = ""); // 4J added
BufferedImage(DLCPack* dlcPack, const std::string& File,
bool filenameHasExtension = false); // 4J Added
const std::string& drive = ""); // 4J added
BufferedImage(std::uint8_t* pbData, std::uint32_t dataBytes); // 4J added
~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 getHeight();
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"
#endif
#include "app/common/ConsoleGameMode.h"
#include "app/common/DLC/DLCPack.h"
#include "app/common/Tutorial/FullTutorialMode.h"
#include "app/common/UI/All Platforms/IUIScene_CreativeMenu.h"
#include "app/common/UI/UIFontData.h"
@ -123,7 +122,7 @@
#include "minecraft/client/player/Input.h"
#include "minecraft/client/renderer/texture/TextureManager.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/item/alchemy/PotionMacros.h"
#include "minecraft/world/level/chunk/SparseDataStorage.h"
@ -1097,18 +1096,8 @@ void Minecraft::run_middle() {
TexturePack* tPack =
Minecraft::GetInstance()
->skins->getSelected();
DLCTexturePack* pDLCTexPack =
(DLCTexturePack*)tPack;
DLCPack* pDLCPack =
pDLCTexPack->getDLCInfoParentPack();
if (pDLCPack) {
if (!pDLCPack->hasPurchasedFile(
DLCManager::e_DLCType_Texture,
"")) {
bTrialTexturepack = true;
}
if (tPack->needsPurchase()) {
bTrialTexturepack = true;
}
}

View file

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

View file

@ -31,6 +31,7 @@
#include "platform/fs/fs.h"
#include "platform/input/input.h"
#include "platform/storage/storage.h"
#include "util/StringHelpers.h"
#if defined(_WINDOWS64)
#endif
@ -192,12 +193,41 @@ std::string DLCTexturePack::getAnimationString(const std::string& textureName,
BufferedImage* DLCTexturePack::getImageResource(
const std::string& File, bool filenameHasExtension /*= false*/,
bool bTitleUpdateTexture /*=false*/, const std::string& drive /*=""*/) {
if (m_dlcDataPack)
return new BufferedImage(m_dlcDataPack, "/" + File,
filenameHasExtension);
else
if (!m_dlcDataPack) {
return fallback->getImageResource(File, filenameHasExtension,
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; }
@ -471,3 +501,14 @@ DLCPack* DLCTexturePack::getDLCInfoParentPack() {
XCONTENTDEVICEID DLCTexturePack::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;
DLCTexturePack(std::uint32_t id, DLCPack* pack, TexturePack* fallback);
~DLCTexturePack(){};
~DLCTexturePack() override = default;
virtual std::string getResource(const std::string& name);
virtual DLCPack* getDLCPack();
virtual std::string getDesc1() {
std::string getResource(const std::string& name) override;
DLCPack* getDLCPack() override;
std::string getDesc1() override {
return m_stringTable->getString("IDS_TP_DESCRIPTION");
}
virtual std::string getName() {
std::string getName() override {
return m_stringTable->getString("IDS_DISPLAY_NAME");
}
virtual std::string getWorldName() {
std::string getWorldName() override {
return m_stringTable->getString("IDS_WORLD_NAME");
}
// Added for sound banks with MashUp packs
protected:
//@Override
void loadIcon();
void loadComparison();
void loadName();
void loadDescription();
void loadIcon() override;
void loadComparison() override;
void loadName() override;
void loadDescription() override;
InputStream* getResourceImplementation(
const std::string& name); // throws IOException
const std::string& name) override; // throws IOException
public:
//@Override
bool hasFile(const std::string& name);
bool isTerrainUpdateCompatible();
bool hasFile(const std::string& name) override;
bool isTerrainUpdateCompatible() override;
// 4J Added
virtual std::string getPath(bool bTitleUpdateTexture = false,
const char* pchBDPatchFilename = nullptr);
virtual std::string getAnimationString(const std::string& textureName,
const std::string& path);
virtual BufferedImage* getImageResource(const std::string& File,
bool filenameHasExtension = false,
bool bTitleUpdateTexture = false,
const std::string& drive = "");
virtual void loadColourTable();
virtual bool hasData() { return m_bHasLoadedData; }
virtual bool isLoadingData() { return m_bLoadingData; }
std::string getPath(bool bTitleUpdateTexture = false,
const char* pchBDPatchFilename = nullptr) override;
std::string getAnimationString(const std::string& textureName,
const std::string& path) override;
BufferedImage* getImageResource(const std::string& File,
bool filenameHasExtension = false,
bool bTitleUpdateTexture = false,
const std::string& drive = "") override;
void loadColourTable() override;
bool hasData() override { return m_bHasLoadedData; }
bool isLoadingData() override { return m_bLoadingData; }
private:
static std::string getRootPath(std::uint32_t packId, bool allowOverride,
@ -78,14 +78,16 @@ private:
public:
int onPackMounted(int iPad, std::uint32_t dwErr,
std::uint32_t dwLicenceMask);
virtual void loadData();
virtual void loadUI();
virtual void unloadUI();
virtual std::string getXuiRootPath();
virtual ArchiveFile* getArchiveFile() { return m_archiveFile; }
void loadData() override;
void loadUI() override;
void unloadUI() override;
std::string getXuiRootPath() override;
ArchiveFile* getArchiveFile() override { return m_archiveFile; }
virtual unsigned int getDLCParentPackId();
unsigned int getDLCParentPackId() override;
virtual DLCPack* getDLCInfoParentPack();
virtual unsigned char getDLCSubPackId();
unsigned char getDLCSubPackId() override;
XCONTENTDEVICEID GetDLCDeviceID();
[[nodiscard]] bool needsPurchase() override;
};

View file

@ -47,6 +47,12 @@ return TexturePack.class.getResourceAsStream(name);
}
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
virtual std::string getPath(bool bTitleUpdateTexture = false,
const char* pchBDPatchFilename = nullptr);

View file

@ -11,14 +11,12 @@
#include "ServerChunkCache.h"
#include "ServerLevelListener.h"
#include "ServerPlayer.h"
#include "app/common/DLC/DLCManager.h"
#include "app/common/DLC/DLCPack.h"
#include "java/Class.h"
#include "java/Random.h"
#include "minecraft/Console_Debug_enum.h"
#include "minecraft/IGameServices.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/network/packet/AddGlobalEntityPacket.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)
if (!Minecraft::GetInstance()->skins->isUsingDefaultSkin()) {
TexturePack* tPack = Minecraft::GetInstance()->skins->getSelected();
DLCTexturePack* pDLCTexPack = (DLCTexturePack*)tPack;
DLCPack* pDLCPack = pDLCTexPack->getDLCInfoParentPack();
if (!pDLCPack->hasPurchasedFile(DLCManager::e_DLCType_Texture, "")) {
if (tPack->needsPurchase()) {
return;
}
}