From fd2fd6590848627e8bddc5344bae18487a14b3bc Mon Sep 17 00:00:00 2001 From: Langtanium <94726057+Langtanium@users.noreply.github.com> Date: Thu, 9 Apr 2026 17:59:13 -0700 Subject: [PATCH] Added code for more DLC skin geometry Added code to DLCSkinFile.cpp to store skin box scale value. Added code to HumanoidModel.cpp and HumanoidModel.h to handle skin boxes added to the armor layer of skin. Added another float value to SkinBox.h --- Minecraft.Client/Common/DLC/DLCSkinFile.cpp | 9 +- Minecraft.Client/Common/DLC/DLCSkinFile.h | 2 - Minecraft.Client/HumanoidModel.cpp | 229 ++++++++++++++++++- Minecraft.Client/HumanoidModel.h | 8 +- Minecraft.Client/LivingEntityRenderer.cpp | 6 +- Minecraft.Client/LivingEntityRenderer.h | 2 +- Minecraft.Client/PlayerRenderer.cpp | 4 +- Minecraft.Client/SkinBox.h | 2 +- Minecraft.World/TextureAndGeometryPacket.cpp | 2 + 9 files changed, 248 insertions(+), 16 deletions(-) diff --git a/Minecraft.Client/Common/DLC/DLCSkinFile.cpp b/Minecraft.Client/Common/DLC/DLCSkinFile.cpp index 3e36f36f6..9b519e289 100644 --- a/Minecraft.Client/Common/DLC/DLCSkinFile.cpp +++ b/Minecraft.Client/Common/DLC/DLCSkinFile.cpp @@ -110,15 +110,15 @@ void DLCSkinFile::addParameter(DLCManager::EDLCParameterType type, const wstring break; case DLCManager::e_DLCParamType_Box: { - WCHAR wchBodyPart[10]; + WCHAR wchBodyPart[11]; SKIN_BOX *pSkinBox = new SKIN_BOX; ZeroMemory(pSkinBox,sizeof(SKIN_BOX)); #ifdef __PS3__ // 4J Stu - The Xbox version used swscanf_s which isn't available in GCC. - swscanf(value.c_str(), L"%10ls%f%f%f%f%f%f%f%f%f%f", wchBodyPart, + swscanf(value.c_str(), L"%10ls%f%f%f%f%f%f%f%f%f%f%f", wchBodyPart, #else - swscanf_s(value.c_str(), L"%9ls%f%f%f%f%f%f%f%f%f%f", wchBodyPart,10, + swscanf_s(value.c_str(), L"%9ls%f%f%f%f%f%f%f%f%f%f%f", wchBodyPart,11, #endif &pSkinBox->fX, &pSkinBox->fY, @@ -129,7 +129,8 @@ void DLCSkinFile::addParameter(DLCManager::EDLCParameterType type, const wstring &pSkinBox->fU, &pSkinBox->fV, &pSkinBox->fA, - &pSkinBox->fM); + &pSkinBox->fM, + &pSkinBox->fS); if(wcscmp(wchBodyPart,L"HEAD")==0) { diff --git a/Minecraft.Client/Common/DLC/DLCSkinFile.h b/Minecraft.Client/Common/DLC/DLCSkinFile.h index 3b25861e8..55d8a070a 100644 --- a/Minecraft.Client/Common/DLC/DLCSkinFile.h +++ b/Minecraft.Client/Common/DLC/DLCSkinFile.h @@ -1,8 +1,6 @@ #pragma once #include "DLCFile.h" #include "..\..\..\Minecraft.Client\HumanoidModel.h" -// This is added to prevent a building failure, probably should move it to HumanoidModel.h later - Langtanium -#include "..\..\..\Minecraft.Client\SkinOffset.h" class DLCSkinFile : public DLCFile { diff --git a/Minecraft.Client/HumanoidModel.cpp b/Minecraft.Client/HumanoidModel.cpp index 509da6d36..a790861f2 100644 --- a/Minecraft.Client/HumanoidModel.cpp +++ b/Minecraft.Client/HumanoidModel.cpp @@ -31,6 +31,9 @@ ModelPart * HumanoidModel::AddOrRetrievePart(SKIN_BOX *pBox) case eBodyPart_Leg1: pAttachTo=leg1; break; + case eBodyPart_Headwear: + pAttachTo=hair; + break; case eBodyPart_Jacket: pAttachTo=jacket; scale=0.25; @@ -51,7 +54,42 @@ ModelPart * HumanoidModel::AddOrRetrievePart(SKIN_BOX *pBox) pAttachTo=pants1; scale=0.25; break; + case eBodyPart_Waist: + pAttachTo=waist; + break; + case eBodyPart_Belt: + pAttachTo=belt; + break; + case eBodyPart_BodyArmor: + pAttachTo=bodyArmor; + break; + case eBodyPart_ArmArmor0: + pAttachTo=armArmor0; + break; + case eBodyPart_ArmArmor1: + pAttachTo=armArmor1; + break; + case eBodyPart_Legging0: + pAttachTo=legging0; + break; + case eBodyPart_Legging1: + pAttachTo=legging1; + break; + case eBodyPart_Sock0: + pAttachTo=sock0; + break; + case eBodyPart_Sock1: + pAttachTo=sock1; + break; + case eBodyPart_Boot0: + pAttachTo=boot0; + break; + case eBodyPart_Boot1: + pAttachTo=boot1; + break; } + // check if this box has a declared scale + if (pBox->fS > 0) scale = pBox->fS; // first check this box doesn't already exist ModelPart *pNewBox = pAttachTo->retrieveChild(pBox); @@ -70,7 +108,7 @@ ModelPart * HumanoidModel::AddOrRetrievePart(SKIN_BOX *pBox) pNewBox = new ModelPart(this, static_cast(pBox->fU), static_cast(pBox->fV)); pNewBox->visible=false; - if (pBox->fM > 0) pNewBox->bMirror = true; + if (pBox->fM > 0) pNewBox->bMirror = true; // check if this box has the mirror flag pNewBox->addHumanoidBox(pBox->fX, pBox->fY, pBox->fZ, pBox->fW, pBox->fH, pBox->fD, scale); // 4J-PB - don't compile here, since the lighting isn't set up. It'll be compiled on first use. //pNewBox->compile(1.0f/16.0f); @@ -90,6 +128,18 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b sleeve1 = nullptr; pants0 = nullptr; pants1 = nullptr; + + waist = nullptr; + belt = nullptr; + bodyArmor = nullptr; + armArmor0 = nullptr; + armArmor1 = nullptr; + legging0 = nullptr; + legging1 = nullptr; + sock0 = nullptr; + sock1 = nullptr; + boot0 = nullptr; + boot1 = nullptr; m_fYOffset=yOffset; cloak = new ModelPart(this, 0, 0); @@ -115,6 +165,40 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b jacket = new ModelPart(this, 16, 32); jacket->addHumanoidBox(-4, 0, -2, 8, 12, 4, g + 0.25); // Jacket jacket->setPos(0, 0 + yOffset, 0); + + waist = new ModelPart(this, 0, 0); + waist->addHumanoidBox(0, 0, 0, 0, 0, 0, g); // Waist + waist->setPos(0, 0 + yOffset, 0); + belt = new ModelPart(this, 0, 0); + belt->addHumanoidBox(0, 0, 0, 0, 0, 0, g); // Belt + belt->setPos(0, 0 + yOffset, 0); + bodyArmor = new ModelPart(this, 0, 0); + bodyArmor->addHumanoidBox(0, 0, 0, 0, 0, 0, g); // BodyArmor + bodyArmor->setPos(0, 0 + yOffset, 0); + armArmor0 = new ModelPart(this, 0, 0); + armArmor0->addHumanoidBox(0, 0, 0, 0, 0, 0, g); // ArmArmor0 + armArmor0->setPos(-5, 2 + yOffset, 0); + armArmor1 = new ModelPart(this, 0, 0); + armArmor1->addHumanoidBox(0, 0, 0, 0, 0, 0, g); // ArmArmor1 + armArmor1->setPos(5, 2 + yOffset, 0); + legging0 = new ModelPart(this, 0, 0); + legging0->addHumanoidBox(0, 0, 0, 0, 0, 0, g); // Legging0 + legging0->setPos(-1.9, 12 + yOffset, 0); + legging1 = new ModelPart(this, 0, 0); + legging1->addHumanoidBox(0, 0, 0, 0, 0, 0, g); // Legging1 + legging1->setPos(1.9, 12 + yOffset, 0); + sock0 = new ModelPart(this, 0, 0); + sock0->addHumanoidBox(0, 0, 0, 0, 0, 0, g); // Sock0 + sock0->setPos(-1.9, 12 + yOffset, 0); + sock1 = new ModelPart(this, 0, 0); + sock1->addHumanoidBox(0, 0, 0, 0, 0, 0, g); // Sock1 + sock1->setPos(1.9, 12 + yOffset, 0); + boot0 = new ModelPart(this, 0, 0); + boot0->addHumanoidBox(0, 0, 0, 0, 0, 0, g); // Boot0 + boot0->setPos(-1.9, 12 + yOffset, 0); + boot1 = new ModelPart(this, 0, 0); + boot1->addHumanoidBox(0, 0, 0, 0, 0, 0, g); // Boot1 + boot1->setPos(1.9, 12 + yOffset, 0); } if (texHeight == 64) @@ -207,6 +291,28 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b pants0->compile(1.0f/16.0f); if (pants1 != 0) pants1->compile(1.0f/16.0f); + if (waist != 0) + waist->compile(1.0f/16.0f); + if (belt != 0) + belt->compile(1.0f/16.0f); + if (bodyArmor != 0) + bodyArmor->compile(1.0f/16.0f); + if (armArmor0 != 0) + armArmor0->compile(1.0f/16.0f); + if (armArmor1 != 0) + armArmor1->compile(1.0f/16.0f); + if (legging0 != 0) + legging0->compile(1.0f/16.0f); + if (legging1 != 0) + legging1->compile(1.0f/16.0f); + if (sock0 != 0) + sock0->compile(1.0f/16.0f); + if (sock1 != 0) + sock1->compile(1.0f/16.0f); + if (boot0 != 0) + boot0->compile(1.0f/16.0f); + if (boot1 != 0) + boot1->compile(1.0f/16.0f); holdingLeftHand=0; holdingRightHand=0; @@ -295,6 +401,28 @@ void HumanoidModel::render(shared_ptr entity, float time, float r, float pants0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); if (pants1 != 0) pants1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); + if (waist != 0) + waist->render(scale, usecompiled); + if (belt != 0) + belt->render(scale, usecompiled); + if (bodyArmor != 0) + bodyArmor->render(scale, usecompiled); + if (armArmor0 != 0) + armArmor0->render(scale, usecompiled); + if (armArmor1 != 0) + armArmor1->render(scale, usecompiled); + if (legging0 != 0) + legging0->render(scale, usecompiled); + if (legging1 != 0) + legging1->render(scale, usecompiled); + if (sock0 != 0) + sock0->render(scale, usecompiled); + if (sock1 != 0) + sock1->render(scale, usecompiled); + if (boot0 != 0) + boot0->render(scale, usecompiled); + if (boot1 != 0) + boot1->render(scale, usecompiled); } } @@ -603,6 +731,105 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float pants1->yRot = leg1->yRot; pants1->zRot = leg1->zRot; } + if (waist != 0) + { + waist->x = body->x; + waist->y = body->y; + waist->z = body->z; + waist->xRot = body->xRot; + waist->yRot = body->yRot; + waist->zRot = body->zRot; + } + if (belt != 0) + { + belt->x = body->x; + belt->y = body->y; + belt->z = body->z; + belt->xRot = body->xRot; + belt->yRot = body->yRot; + belt->zRot = body->zRot; + } + if (bodyArmor != 0) + { + bodyArmor->x = body->x; + bodyArmor->y = body->y; + bodyArmor->z = body->z; + bodyArmor->xRot = body->xRot; + bodyArmor->yRot = body->yRot; + bodyArmor->zRot = body->zRot; + } + if (armArmor0 != 0) + { + armArmor0->x = arm0->x; + armArmor0->y = arm0->y; + armArmor0->z = arm0->z; + armArmor0->xRot = arm0->xRot; + armArmor0->yRot = arm0->yRot; + armArmor0->zRot = arm0->zRot; + } + if (armArmor1 != 0) + { + armArmor1->x = arm1->x; + armArmor1->y = arm1->y; + armArmor1->z = arm1->z; + armArmor1->xRot = arm1->xRot; + armArmor1->yRot = arm1->yRot; + armArmor1->zRot = arm1->zRot; + } + if (legging0 != 0) + { + legging0->x = leg0->x; + legging0->y = leg0->y; + legging0->z = leg0->z; + legging0->xRot = leg0->xRot; + legging0->yRot = leg0->yRot; + legging0->zRot = leg0->zRot; + } + if (legging1 != 0) + { + legging1->x = leg1->x; + legging1->y = leg1->y; + legging1->z = leg1->z; + legging1->xRot = leg1->xRot; + legging1->yRot = leg1->yRot; + legging1->zRot = leg1->zRot; + } + if (sock0 != 0) + { + sock0->x = leg0->x; + sock0->y = leg0->y; + sock0->z = leg0->z; + sock0->xRot = leg0->xRot; + sock0->yRot = leg0->yRot; + sock0->zRot = leg0->zRot; + } + if (sock1 != 0) + { + sock1->x = leg1->x; + sock1->y = leg1->y; + sock1->z = leg1->z; + sock1->xRot = leg1->xRot; + sock1->yRot = leg1->yRot; + sock1->zRot = leg1->zRot; + } + if (boot0 != 0) + { + boot0->x = leg0->x; + boot0->y = leg0->y; + boot0->z = leg0->z; + boot0->xRot = leg0->xRot; + boot0->yRot = leg0->yRot; + boot0->zRot = leg0->zRot; + } + if (boot1 != 0) + { + boot1->x = leg1->x; + boot1->y = leg1->y; + boot1->z = leg1->z; + boot1->xRot = leg1->xRot; + boot1->yRot = leg1->yRot; + boot1->zRot = leg1->zRot; + } } } diff --git a/Minecraft.Client/HumanoidModel.h b/Minecraft.Client/HumanoidModel.h index 88a57adaf..504c1d182 100644 --- a/Minecraft.Client/HumanoidModel.h +++ b/Minecraft.Client/HumanoidModel.h @@ -1,10 +1,16 @@ #pragma once #include "Model.h" +#include "SkinOffset.h" class HumanoidModel : public Model { public: - ModelPart *head, *hair, *body, *jacket, *arm0, *sleeve0, *arm1, *sleeve1, *leg0, *pants0, *leg1, *pants1, *ear, *cloak; + // Base geometry + ModelPart *head, *hair, *body, *arm0, *arm1, *leg0, *leg1, *ear, *cloak; + // Second layer/64x64 skin geometry + ModelPart *jacket, *sleeve0, *sleeve1, *pants0, *pants1; + // Extra geometry for DLC skins + ModelPart *waist, *belt, *bodyArmor, *armArmor0, *armArmor1, *legging0, *legging1, *sock0, *sock1, *boot0, *boot1; //ModelPart *hat; int holdingLeftHand; diff --git a/Minecraft.Client/LivingEntityRenderer.cpp b/Minecraft.Client/LivingEntityRenderer.cpp index aa738ec77..ff218ea75 100644 --- a/Minecraft.Client/LivingEntityRenderer.cpp +++ b/Minecraft.Client/LivingEntityRenderer.cpp @@ -20,16 +20,14 @@ LivingEntityRenderer::LivingEntityRenderer(Model *model, float shadow) armor = nullptr; } -LivingEntityRenderer::LivingEntityRenderer(Model *model, float shadow, bool slimHands, bool is64x64) +LivingEntityRenderer::LivingEntityRenderer(Model *model, float shadow, bool is64x64) { this->model = model; if (is64x64) { this->modelClassic = new HumanoidModel(0, 0, 64, 64, false); - - if (slimHands == true) - this->modelSlim = new HumanoidModel(0, 0, 64, 64, true); + this->modelSlim = new HumanoidModel(0, 0, 64, 64, true); } shadowRadius = shadow; diff --git a/Minecraft.Client/LivingEntityRenderer.h b/Minecraft.Client/LivingEntityRenderer.h index 6ea76df39..fa187a468 100644 --- a/Minecraft.Client/LivingEntityRenderer.h +++ b/Minecraft.Client/LivingEntityRenderer.h @@ -20,7 +20,7 @@ protected: public: LivingEntityRenderer(Model *model, float shadow); - LivingEntityRenderer(Model *model, float shadow, bool slimHands, bool is64x64); + LivingEntityRenderer(Model *model, float shadow, bool is64x64); virtual void render(shared_ptr mob, double x, double y, double z, float rot, float a); virtual void setArmor(Model *armor); diff --git a/Minecraft.Client/PlayerRenderer.cpp b/Minecraft.Client/PlayerRenderer.cpp index 3a460ed79..e0973da95 100644 --- a/Minecraft.Client/PlayerRenderer.cpp +++ b/Minecraft.Client/PlayerRenderer.cpp @@ -55,7 +55,7 @@ static unsigned int nametagColorForIndex(int index) ResourceLocation PlayerRenderer::DEFAULT_LOCATION = ResourceLocation(TN_MOB_CHAR); -PlayerRenderer::PlayerRenderer() : LivingEntityRenderer( new HumanoidModel(0), 0.5f, true, true ) +PlayerRenderer::PlayerRenderer() : LivingEntityRenderer( new HumanoidModel(0), 0.5f, true ) { humanoidModel = static_cast(model); humanoidModelClassic = static_cast(modelClassic); @@ -557,7 +557,7 @@ void PlayerRenderer::renderHand() resModel->sleeve0->render(1 / 16.0f,true); //Render custom skin boxes on viewmodel - Botch - vector* additionalModelParts = Minecraft::GetInstance()->player->GetAdditionalModelParts(); + vector* additionalModelParts = player->GetAdditionalModelParts(); if (!additionalModelParts) return; //If there are no custom boxes, return. This fixes bug where the game will crash if you select a skin with no additional boxes. std::unordered_set additionalModelPartSet(additionalModelParts->begin(), additionalModelParts->end()); vector armchildren = resModel->arm0->children; diff --git a/Minecraft.Client/SkinBox.h b/Minecraft.Client/SkinBox.h index 907da411d..d82a790da 100644 --- a/Minecraft.Client/SkinBox.h +++ b/Minecraft.Client/SkinBox.h @@ -31,6 +31,6 @@ enum eBodyPart typedef struct { eBodyPart ePart; - float fX,fY,fZ,fW,fH,fD,fU,fV,fA,fM; + float fX,fY,fZ,fW,fH,fD,fU,fV,fA,fM,fS; } SKIN_BOX; diff --git a/Minecraft.World/TextureAndGeometryPacket.cpp b/Minecraft.World/TextureAndGeometryPacket.cpp index fee0a59ae..41fe933fe 100644 --- a/Minecraft.World/TextureAndGeometryPacket.cpp +++ b/Minecraft.World/TextureAndGeometryPacket.cpp @@ -179,6 +179,7 @@ void TextureAndGeometryPacket::read(DataInputStream *dis) //throws IOException this->BoxDataA[i].fV = dis->readFloat(); this->BoxDataA[i].fA = dis->readFloat(); this->BoxDataA[i].fM = dis->readFloat(); + this->BoxDataA[i].fS = dis->readFloat(); } } @@ -207,6 +208,7 @@ void TextureAndGeometryPacket::write(DataOutputStream *dos) //throws IOException dos->writeFloat(this->BoxDataA[i].fV); dos->writeFloat(this->BoxDataA[i].fA); dos->writeFloat(this->BoxDataA[i].fM); + dos->writeFloat(this->BoxDataA[i].fS); } }