refactor: extract ISkinAssetData so minecraft/ stops including DLCSkinFile.h

This commit is contained in:
MatthewBeshay 2026-04-09 21:11:41 +10:00
parent 80019158da
commit 8b202ba5f1
10 changed files with 89 additions and 51 deletions

View file

@ -1,5 +1,6 @@
#include "app/common/AppGameServices.h"
#include "app/common/DLC/DLCSkinFile.h"
#include "app/common/Game.h"
#include "java/Class.h" // eINSTANCEOF
#include "platform/game/game.h"
@ -386,7 +387,7 @@ void AppGameServices::debugPrintf(const char* msg) {
// -- DLC --
DLCSkinFile* AppGameServices::getDLCSkinFile(const std::string& name) {
ISkinAssetData* AppGameServices::getSkinAssetData(const std::string& name) {
return game_.m_dlcManager.getSkinFile(name);
}
bool AppGameServices::dlcNeedsCorruptCheck() {

View file

@ -4,6 +4,7 @@
class Game;
class IMenuService;
class ISkinAssetData;
class AppGameServices : public IGameServices {
public:
@ -150,7 +151,7 @@ public:
void debugPrintf(const char* msg) override;
// -- DLC --
DLCSkinFile* getDLCSkinFile(const std::string& name) override;
ISkinAssetData* getSkinAssetData(const std::string& name) override;
bool dlcNeedsCorruptCheck() override;
unsigned int dlcCheckForCorrupt(bool showMessage) override;
bool dlcReadDataFile(unsigned int& filesProcessed, const std::string& path,

View file

@ -8,8 +8,9 @@
#include "app/common/DLC/DLCManager.h"
#include "minecraft/client/model/HumanoidModel.h"
#include "minecraft/client/model/SkinBox.h"
#include "minecraft/client/skins/ISkinAssetData.h"
class DLCSkinFile : public DLCFile {
class DLCSkinFile : public DLCFile, public ISkinAssetData {
private:
std::string m_displayName;
std::string m_themeName;
@ -21,15 +22,23 @@ private:
public:
DLCSkinFile(const std::string& path);
virtual void addData(std::uint8_t* pbData, std::uint32_t dataBytes);
virtual void addParameter(DLCManager::EDLCParameterType type,
const std::string& value);
void addData(std::uint8_t* pbData, std::uint32_t dataBytes) override;
void addParameter(DLCManager::EDLCParameterType type,
const std::string& value) override;
std::string getParameterAsString(
DLCManager::EDLCParameterType type) override;
bool getParameterAsBool(DLCManager::EDLCParameterType type) override;
// ISkinAssetData
[[nodiscard]] std::uint32_t getSkinID() override {
return DLCFile::getSkinID();
}
[[nodiscard]] unsigned int getAnimOverrideBitmask() override {
return m_uiAnimOverrideBitmask;
}
[[nodiscard]] int getAdditionalBoxesCount() override;
[[nodiscard]] std::vector<SKIN_BOX*>* getAdditionalBoxes() override;
virtual std::string getParameterAsString(
DLCManager::EDLCParameterType type);
virtual bool getParameterAsBool(DLCManager::EDLCParameterType type);
std::vector<SKIN_BOX*>* getAdditionalBoxes();
int getAdditionalBoxesCount();
unsigned int getAnimOverrideBitmask() { return m_uiAnimOverrideBitmask; }
bool isFree() { return m_bIsFree; }
};

View file

@ -11,7 +11,7 @@ class LevelChunk;
class ModelPart;
// Forward declarations
class DLCSkinFile;
class ISkinAssetData;
class DLCPack;
#include "minecraft/GameEnums.h"
@ -199,7 +199,7 @@ public:
// -- DLC --
[[nodiscard]] virtual DLCSkinFile* getDLCSkinFile(
[[nodiscard]] virtual ISkinAssetData* getSkinAssetData(
const std::string& name) = 0;
[[nodiscard]] virtual bool dlcNeedsCorruptCheck() = 0;
virtual unsigned int dlcCheckForCorrupt(bool showMessage = true) = 0;

View file

@ -16,7 +16,7 @@
#include "app/common/ConsoleGameMode.h"
#include "app/common/DLC/DLCManager.h"
#include "app/common/DLC/DLCPack.h"
#include "app/common/DLC/DLCSkinFile.h"
#include "minecraft/client/skins/ISkinAssetData.h"
#include "app/common/Network/Socket.h"
#include "app/common/Tutorial/FullTutorialMode.h"
#include "app/common/Tutorial/Tutorial.h"
@ -2313,16 +2313,16 @@ void ClientConnection::handleTextureAndGeometry(
unsigned int dwBytes = 0;
gameServices().getMemFileDetails(packet->textureName, &pbData,
&dwBytes);
DLCSkinFile* pDLCSkinFile =
gameServices().getDLCSkinFile(packet->textureName);
ISkinAssetData* pSkinAsset =
gameServices().getSkinAssetData(packet->textureName);
if (dwBytes != 0) {
if (pDLCSkinFile) {
if (pDLCSkinFile->getAdditionalBoxesCount() != 0) {
if (pSkinAsset) {
if (pSkinAsset->getAdditionalBoxesCount() != 0) {
send(std::shared_ptr<TextureAndGeometryPacket>(
new TextureAndGeometryPacket(packet->textureName,
pbData, dwBytes,
pDLCSkinFile)));
pSkinAsset)));
} else {
send(std::shared_ptr<TextureAndGeometryPacket>(
new TextureAndGeometryPacket(packet->textureName,

View file

@ -0,0 +1,26 @@
#pragma once
#include <cstdint>
#include <vector>
#include "minecraft/client/model/SkinBox.h"
// Domain-shaped view of a custom skin asset.
//
// minecraft/ consumers (Player, the client/server connection layers,
// the texture packet) need a handful of fields off a custom skin
// asset: the skin id, the additional body parts geometry, and an
// animation override mask. Historically those fields were read off
// app/common/DLC/DLCSkinFile, which dragged the entire DLC subsystem
// up into minecraft/ headers and broke the layering invariant.
//
// This interface is the domain abstraction. The DLC implementation in
// app/ inherits from it; minecraft/ only ever sees ISkinAssetData.
class ISkinAssetData {
public:
virtual ~ISkinAssetData() = default;
[[nodiscard]] virtual std::uint32_t getSkinID() = 0;
[[nodiscard]] virtual unsigned int getAnimOverrideBitmask() = 0;
[[nodiscard]] virtual int getAdditionalBoxesCount() = 0;
[[nodiscard]] virtual std::vector<SKIN_BOX*>* getAdditionalBoxes() = 0;
};

View file

@ -4,10 +4,10 @@
#include <vector>
#include "PacketListener.h"
#include "app/common/DLC/DLCSkinFile.h"
#include "java/InputOutputStream/DataInputStream.h"
#include "java/InputOutputStream/DataOutputStream.h"
#include "minecraft/Minecraft_Macros.h"
#include "minecraft/client/skins/ISkinAssetData.h"
TextureAndGeometryPacket::TextureAndGeometryPacket() {
this->textureName = "";
@ -51,7 +51,7 @@ TextureAndGeometryPacket::TextureAndGeometryPacket(
TextureAndGeometryPacket::TextureAndGeometryPacket(
const std::string& textureName, std::uint8_t* pbData,
std::uint32_t dataBytes, DLCSkinFile* pDLCSkinFile) {
std::uint32_t dataBytes, ISkinAssetData* pSkinAssetData) {
this->textureName = textureName;
std::string skinValue = textureName.substr(7, textureName.size());
@ -63,11 +63,12 @@ TextureAndGeometryPacket::TextureAndGeometryPacket(
this->pbData = pbData;
this->dwTextureBytes = dataBytes;
this->uiAnimOverrideBitmask = pDLCSkinFile->getAnimOverrideBitmask();
this->dwBoxC = pDLCSkinFile->getAdditionalBoxesCount();
this->uiAnimOverrideBitmask = pSkinAssetData->getAnimOverrideBitmask();
this->dwBoxC = pSkinAssetData->getAdditionalBoxesCount();
if (this->dwBoxC != 0) {
this->BoxDataA = new SKIN_BOX[this->dwBoxC];
std::vector<SKIN_BOX*>* pSkinBoxes = pDLCSkinFile->getAdditionalBoxes();
std::vector<SKIN_BOX*>* pSkinBoxes =
pSkinAssetData->getAdditionalBoxes();
int iCount = 0;
for (auto it = pSkinBoxes->begin(); it != pSkinBoxes->end(); ++it) {

View file

@ -10,7 +10,7 @@
#include "minecraft/client/model/geom/Model.h"
#include "minecraft/network/packet/Packet.h"
class DLCSkinFile;
class ISkinAssetData;
class TextureAndGeometryPacket
: public Packet,
@ -30,7 +30,7 @@ public:
std::uint8_t* pbData, std::uint32_t dataBytes);
TextureAndGeometryPacket(const std::string& textureName,
std::uint8_t* pbData, std::uint32_t dataBytes,
DLCSkinFile* pDLCSkinFile);
ISkinAssetData* pSkinAssetData);
TextureAndGeometryPacket(const std::string& textureName,
std::uint8_t* pbData, std::uint32_t dataBytes,
std::vector<SKIN_BOX*>* pvSkinBoxes,

View file

@ -9,7 +9,6 @@
#include <utility>
#include "ServerConnection.h"
#include "app/common/DLC/DLCSkinFile.h"
#include "app/common/Network/Socket.h"
#include "java/Class.h"
#include "java/InputOutputStream/ByteArrayInputStream.h"
@ -24,6 +23,7 @@
#include "minecraft/IGameServices.h"
#include "minecraft/SharedConstants.h"
#include "minecraft/client/model/SkinBox.h"
#include "minecraft/client/skins/ISkinAssetData.h"
#include "minecraft/commands/CommandDispatcher.h"
#include "minecraft/commands/CommandsEnum.h"
#include "minecraft/network/Connection.h"
@ -850,16 +850,16 @@ void PlayerConnection::handleTextureAndGeometry(
unsigned int dwTextureBytes = 0;
gameServices().getMemFileDetails(packet->textureName, &pbData,
&dwTextureBytes);
DLCSkinFile* pDLCSkinFile =
gameServices().getDLCSkinFile(packet->textureName);
ISkinAssetData* pSkinAsset =
gameServices().getSkinAssetData(packet->textureName);
if (dwTextureBytes != 0) {
if (pDLCSkinFile) {
if (pDLCSkinFile->getAdditionalBoxesCount() != 0) {
if (pSkinAsset) {
if (pSkinAsset->getAdditionalBoxesCount() != 0) {
send(std::shared_ptr<TextureAndGeometryPacket>(
new TextureAndGeometryPacket(packet->textureName,
pbData, dwTextureBytes,
pDLCSkinFile)));
pSkinAsset)));
} else {
send(std::shared_ptr<TextureAndGeometryPacket>(
new TextureAndGeometryPacket(packet->textureName,
@ -938,14 +938,14 @@ void PlayerConnection::handleTextureAndGeometryReceived(
std::uint8_t* pbData = nullptr;
unsigned int dwTextureBytes = 0;
gameServices().getMemFileDetails(textureName, &pbData, &dwTextureBytes);
DLCSkinFile* pDLCSkinFile = gameServices().getDLCSkinFile(textureName);
ISkinAssetData* pSkinAsset =
gameServices().getSkinAssetData(textureName);
if (dwTextureBytes != 0) {
if (pDLCSkinFile &&
(pDLCSkinFile->getAdditionalBoxesCount() != 0)) {
if (pSkinAsset && (pSkinAsset->getAdditionalBoxesCount() != 0)) {
send(std::shared_ptr<TextureAndGeometryPacket>(
new TextureAndGeometryPacket(
textureName, pbData, dwTextureBytes, pDLCSkinFile)));
textureName, pbData, dwTextureBytes, pSkinAsset)));
} else {
// get the data from the app
std::uint32_t dwSkinID =

View file

@ -22,7 +22,7 @@
#include "Inventory.h"
#include "Player.h"
#include "app/common/App_structs.h"
#include "app/common/DLC/DLCSkinFile.h"
#include "minecraft/client/skins/ISkinAssetData.h"
#include "java/JavaMath.h"
#include "java/Random.h"
#include "minecraft/Direction.h"
@ -584,23 +584,23 @@ void Player::setCustomSkin(std::uint32_t skinId) {
Log::info("Couldn't get model parts for skin %X\n",m_dwSkinId);
// do we have it from the DLC pack?
DLCSkinFile *pDLCSkinFile =
gameServices().getDLCSkinFile(this->customTextureUrl);
ISkinAssetData *pSkinAsset =
gameServices().getSkinAssetData(this->customTextureUrl);
if(pDLCSkinFile!=nullptr)
if(pSkinAsset!=nullptr)
{
const int additionalBoxCount =
pDLCSkinFile->getAdditionalBoxesCount(); if(additionalBoxCount != 0)
pSkinAsset->getAdditionalBoxesCount(); if(additionalBoxCount != 0)
{
Log::info("Got model parts from DLCskin for skin %X\n",m_dwSkinId);
pvModelParts=gameServices().setAdditionalSkinBoxesFromVec(m_dwSkinId,pDLCSkinFile->getAdditionalBoxes());
pvModelParts=gameServices().setAdditionalSkinBoxesFromVec(m_dwSkinId,pSkinAsset->getAdditionalBoxes());
this->SetAdditionalModelParts(pvModelParts);
}
else
{
this->SetAdditionalModelParts(nullptr);
}
gameServices().setAnimOverrideBitmask(pDLCSkinFile->getSkinID(),pDLCSkinFile->getAnimOverrideBitmask());
gameServices().setAnimOverrideBitmask(pSkinAsset->getSkinID(),pSkinAsset->getAnimOverrideBitmask());
}
else
{
@ -2704,12 +2704,12 @@ std::vector<ModelPart*>* Player::GetAdditionalModelParts() {
m_dwSkinId);
// do we have it from the DLC pack?
DLCSkinFile* pDLCSkinFile =
gameServices().getDLCSkinFile(this->customTextureUrl);
ISkinAssetData* pSkinAsset =
gameServices().getSkinAssetData(this->customTextureUrl);
if (pDLCSkinFile != nullptr) {
if (pSkinAsset != nullptr) {
const int additionalBoxCount =
pDLCSkinFile->getAdditionalBoxesCount();
pSkinAsset->getAdditionalBoxesCount();
if (additionalBoxCount != 0) {
Log::info(
"m_bCheckedForModelParts Got model parts from DLCskin "
@ -2717,12 +2717,12 @@ std::vector<ModelPart*>* Player::GetAdditionalModelParts() {
m_dwSkinId);
m_ppAdditionalModelParts =
gameServices().setAdditionalSkinBoxesFromVec(
m_dwSkinId, pDLCSkinFile->getAdditionalBoxes());
m_dwSkinId, pSkinAsset->getAdditionalBoxes());
}
gameServices().setAnimOverrideBitmask(
pDLCSkinFile->getSkinID(),
pDLCSkinFile->getAnimOverrideBitmask());
pSkinAsset->getSkinID(),
pSkinAsset->getAnimOverrideBitmask());
m_bCheckedForModelParts = true;
}