From e41b579603531d32a25ec8a388f0cf641abe8bac Mon Sep 17 00:00:00 2001 From: Langtanium <94726057+Langtanium@users.noreply.github.com> Date: Sat, 16 May 2026 23:34:29 -0700 Subject: [PATCH 1/9] Made changes to skin related code Renamed all Alex skins and Developer Steve skin to match the official file names, reordered default skin to match the order in the official release of LCE, modified model type logic to be more optimized, added more anim flags to HumanoidModel.h, added code to show armor if the corresponding part is hidden but the "show armor" part anim flag is present, added code to handle extra skin box values of "hide with armor", "mirror skin box", and "scale", corrected player model second/overlay layer scale from 0.5 to 0.25, and fixed skin boxes not rendering on 64x64 DLC skins. --- Minecraft.Client/Common/Consoles_App.cpp | 18 +- Minecraft.Client/Common/DLC/DLCSkinFile.cpp | 9 +- .../Common/UI/UIControl_PlayerSkinPreview.cpp | 21 +-- .../Common/UI/UIScene_SkinSelectMenu.cpp | 30 ++-- .../res/1_2_2/mob/{char17.png => DevAlex.png} | Bin .../res/1_2_2/mob/{char8.png => DevSteve.png} | Bin .../Common/res/1_2_2/mob/alex.png | Bin 0 -> 3420 bytes .../res/1_2_2/mob/{char13.png => alex1.png} | Bin .../res/1_2_2/mob/{char10.png => alex2.png} | Bin .../res/1_2_2/mob/{char15.png => alex3.png} | Bin .../res/1_2_2/mob/{char16.png => alex4.png} | Bin .../res/1_2_2/mob/{char12.png => alex5.png} | Bin .../res/1_2_2/mob/{char14.png => alex6.png} | Bin .../res/1_2_2/mob/{char11.png => alex7.png} | Bin .../Common/res/1_2_2/mob/char9.png | Bin 1615 -> 0 bytes .../res/mob/{char17.png => DevAlex.png} | Bin .../res/mob/{char8.png => DevSteve.png} | Bin Minecraft.Client/Common/res/mob/alex.png | Bin 0 -> 3420 bytes .../Common/res/mob/{char13.png => alex1.png} | Bin .../Common/res/mob/{char10.png => alex2.png} | Bin .../Common/res/mob/{char15.png => alex3.png} | Bin .../Common/res/mob/{char16.png => alex4.png} | Bin .../Common/res/mob/{char12.png => alex5.png} | Bin .../Common/res/mob/{char14.png => alex6.png} | Bin .../Common/res/mob/{char11.png => alex7.png} | Bin Minecraft.Client/Common/res/mob/char9.png | Bin 1615 -> 0 bytes Minecraft.Client/EntityRenderer.cpp | 10 +- Minecraft.Client/EntityRenderer.h | 8 +- Minecraft.Client/HumanoidModel.cpp | 57 +++--- Minecraft.Client/HumanoidModel.h | 23 ++- Minecraft.Client/LivingEntityRenderer.cpp | 103 ++--------- Minecraft.Client/LivingEntityRenderer.h | 4 +- Minecraft.Client/ModelPart.cpp | 1 + Minecraft.Client/ModelPart.h | 1 + Minecraft.Client/PlayerRenderer.cpp | 163 +++++++----------- Minecraft.Client/PlayerRenderer.h | 5 +- Minecraft.Client/SkinBox.h | 2 +- Minecraft.Client/Skins.h | 29 ---- Minecraft.Client/Textures.cpp | 40 ++--- Minecraft.Client/Textures.h | 20 +-- Minecraft.World/Player.cpp | 36 ++-- Minecraft.World/Player.h | 2 + Minecraft.World/TextureAndGeometryPacket.cpp | 6 + 43 files changed, 249 insertions(+), 339 deletions(-) rename Minecraft.Client/Common/res/1_2_2/mob/{char17.png => DevAlex.png} (100%) rename Minecraft.Client/Common/res/1_2_2/mob/{char8.png => DevSteve.png} (100%) create mode 100644 Minecraft.Client/Common/res/1_2_2/mob/alex.png rename Minecraft.Client/Common/res/1_2_2/mob/{char13.png => alex1.png} (100%) rename Minecraft.Client/Common/res/1_2_2/mob/{char10.png => alex2.png} (100%) rename Minecraft.Client/Common/res/1_2_2/mob/{char15.png => alex3.png} (100%) rename Minecraft.Client/Common/res/1_2_2/mob/{char16.png => alex4.png} (100%) rename Minecraft.Client/Common/res/1_2_2/mob/{char12.png => alex5.png} (100%) rename Minecraft.Client/Common/res/1_2_2/mob/{char14.png => alex6.png} (100%) rename Minecraft.Client/Common/res/1_2_2/mob/{char11.png => alex7.png} (100%) delete mode 100644 Minecraft.Client/Common/res/1_2_2/mob/char9.png rename Minecraft.Client/Common/res/mob/{char17.png => DevAlex.png} (100%) rename Minecraft.Client/Common/res/mob/{char8.png => DevSteve.png} (100%) create mode 100644 Minecraft.Client/Common/res/mob/alex.png rename Minecraft.Client/Common/res/mob/{char13.png => alex1.png} (100%) rename Minecraft.Client/Common/res/mob/{char10.png => alex2.png} (100%) rename Minecraft.Client/Common/res/mob/{char15.png => alex3.png} (100%) rename Minecraft.Client/Common/res/mob/{char16.png => alex4.png} (100%) rename Minecraft.Client/Common/res/mob/{char12.png => alex5.png} (100%) rename Minecraft.Client/Common/res/mob/{char14.png => alex6.png} (100%) rename Minecraft.Client/Common/res/mob/{char11.png => alex7.png} (100%) delete mode 100644 Minecraft.Client/Common/res/mob/char9.png delete mode 100644 Minecraft.Client/Skins.h diff --git a/Minecraft.Client/Common/Consoles_App.cpp b/Minecraft.Client/Common/Consoles_App.cpp index 82043249..0e2813df 100644 --- a/Minecraft.Client/Common/Consoles_App.cpp +++ b/Minecraft.Client/Common/Consoles_App.cpp @@ -9615,7 +9615,14 @@ void CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, SKIN_BOX *SkinBoxA, D { EntityRenderDispatcher *dispatcher = EntityRenderDispatcher::instance; EntityRenderer *renderer = dispatcher ? dispatcher->getRenderer(eTYPE_PLAYER) : nullptr; - Model *pModel = renderer ? renderer->getModel() : nullptr; + unsigned int m_uiAnimOverrideBitmask = GetAnimOverrideBitmask(dwSkinID); + Model *pModel; + if (m_uiAnimOverrideBitmask & (1 << HumanoidModel::eAnim_SlimModel)) + pModel = renderer ? renderer->getModel(2) : nullptr; + else if (m_uiAnimOverrideBitmask & (1 << HumanoidModel::eAnim_WideModel)) + pModel = renderer ? renderer->getModel(1) : nullptr; + else + pModel = renderer ? renderer->getModel(0) : nullptr; vector *pvModelPart = new vector; vector *pvSkinBoxes = new vector; @@ -9648,7 +9655,14 @@ vector * CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, vect { EntityRenderDispatcher *dispatcher = EntityRenderDispatcher::instance; EntityRenderer *renderer = dispatcher ? dispatcher->getRenderer(eTYPE_PLAYER) : nullptr; - Model *pModel = renderer ? renderer->getModel() : nullptr; + unsigned int m_uiAnimOverrideBitmask = GetAnimOverrideBitmask(dwSkinID); + Model *pModel; + if (m_uiAnimOverrideBitmask & (1 << HumanoidModel::eAnim_SlimModel)) + pModel = renderer ? renderer->getModel(2) : nullptr; + else if (m_uiAnimOverrideBitmask & (1 << HumanoidModel::eAnim_WideModel)) + pModel = renderer ? renderer->getModel(1) : nullptr; + else + pModel = renderer ? renderer->getModel(0) : nullptr; vector *pvModelPart = new vector; EnterCriticalSection( &csAdditionalModelParts ); diff --git a/Minecraft.Client/Common/DLC/DLCSkinFile.cpp b/Minecraft.Client/Common/DLC/DLCSkinFile.cpp index fb5282af..4723392e 100644 --- a/Minecraft.Client/Common/DLC/DLCSkinFile.cpp +++ b/Minecraft.Client/Common/DLC/DLCSkinFile.cpp @@ -120,9 +120,9 @@ void DLCSkinFile::addParameter(DLCManager::EDLCParameterType type, const wstring #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", 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", wchBodyPart,10, + swscanf_s(value.c_str(), L"%9ls%f%f%f%f%f%f%f%f%f%f%f", wchBodyPart,10, #endif &pSkinBox->fX, &pSkinBox->fY, @@ -131,7 +131,10 @@ void DLCSkinFile::addParameter(DLCManager::EDLCParameterType type, const wstring &pSkinBox->fH, &pSkinBox->fD, &pSkinBox->fU, - &pSkinBox->fV); + &pSkinBox->fV, + &pSkinBox->fA, + &pSkinBox->fM, + &pSkinBox->fS); if(wcscmp(wchBodyPart,L"HEAD")==0) { diff --git a/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp b/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp index 39432370..8a549637 100644 --- a/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp +++ b/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp @@ -8,7 +8,6 @@ #include "../../ModelPart.h" #include "../../Options.h" #include "../../../Minecraft.World/net.minecraft.world.entity.player.h" -#include "Skins.h" #include "UIControl_PlayerSkinPreview.h" #include @@ -309,24 +308,8 @@ void UIControl_PlayerSkinPreview::render(EntityRenderer *renderer, double x, dou glPushMatrix(); glDisable(GL_CULL_FACE); - HumanoidModel *model = static_cast(renderer->getModel()); - Textures *textures = Minecraft::GetInstance()->textures; - int skinId = textures->loadMemTexture(m_customTextureUrl, m_backupTexture) - 37; - - if (slim[skinId] == true) - { - if (textures->getHeight(m_customTextureUrl, m_backupTexture) == 64) - model = static_cast(renderer->getNewModelSlim()); - else - model = static_cast(renderer->getModelSlim()); - } - else - { - if (textures->getHeight(m_customTextureUrl, m_backupTexture) == 64) - model = static_cast(renderer->getNewModel()); - else - model = static_cast(renderer->getModel()); - } + Textures *t = Minecraft::GetInstance()->textures; + HumanoidModel *model = static_cast(renderer->getModel(Player::GetModelTypeFromTextureId(t->loadMemTexture(m_customTextureUrl, m_backupTexture))+Player::GetModelTypeFromAnimBitmask(m_uiAnimOverrideBitmask))); //getAttackAnim(mob, a); //if (armor != nullptr) armor->attackTime = model->attackTime; diff --git a/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.cpp index 590de54f..af3bead9 100644 --- a/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.cpp @@ -24,16 +24,16 @@ const WCHAR *UIScene_SkinSelectMenu::wchDefaultNamesA[]= L"Prisoner Steve", L"Cyclist Steve", L"Boxer Steve", - L"Developer Steve", L"Alex", - L"Tuxedo Alex", - L"Boxer Alex", - L"Prisoner Alex", L"Tennis Alex", - L"Cyclist Alex", + L"Tuxedo Alex", L"Athlete Alex", L"Swedish Alex", + L"Prisoner Alex", + L"Cyclist Alex", + L"Boxer Alex", L"Developer Alex", + L"Developer Steve", }; UIScene_SkinSelectMenu::UIScene_SkinSelectMenu(int iPad, void *initData, UILayer *parentLayer) : UIScene(iPad, parentLayer) @@ -1004,34 +1004,34 @@ TEXTURE_NAME UIScene_SkinSelectMenu::getTextureId(int skinIndex) texture = TN_MOB_CHAR7; break; case eDefaultSkins_Skin8: - texture = TN_MOB_CHAR8; + texture = TN_MOB_ALEX; break; case eDefaultSkins_Skin9: - texture = TN_MOB_CHAR9; + texture = TN_MOB_ALEX1; break; case eDefaultSkins_Skin10: - texture = TN_MOB_CHAR10; + texture = TN_MOB_ALEX2; break; case eDefaultSkins_Skin11: - texture = TN_MOB_CHAR11; + texture = TN_MOB_ALEX3; break; case eDefaultSkins_Skin12: - texture = TN_MOB_CHAR12; + texture = TN_MOB_ALEX4; break; case eDefaultSkins_Skin13: - texture = TN_MOB_CHAR13; + texture = TN_MOB_ALEX5; break; case eDefaultSkins_Skin14: - texture = TN_MOB_CHAR14; + texture = TN_MOB_ALEX6; break; case eDefaultSkins_Skin15: - texture = TN_MOB_CHAR15; + texture = TN_MOB_ALEX7; break; case eDefaultSkins_Skin16: - texture = TN_MOB_CHAR16; + texture = TN_MOB_DEVALEX; break; case eDefaultSkins_Skin17: - texture = TN_MOB_CHAR17; + texture = TN_MOB_DEVSTEVE; break; }; diff --git a/Minecraft.Client/Common/res/1_2_2/mob/char17.png b/Minecraft.Client/Common/res/1_2_2/mob/DevAlex.png similarity index 100% rename from Minecraft.Client/Common/res/1_2_2/mob/char17.png rename to Minecraft.Client/Common/res/1_2_2/mob/DevAlex.png diff --git a/Minecraft.Client/Common/res/1_2_2/mob/char8.png b/Minecraft.Client/Common/res/1_2_2/mob/DevSteve.png similarity index 100% rename from Minecraft.Client/Common/res/1_2_2/mob/char8.png rename to Minecraft.Client/Common/res/1_2_2/mob/DevSteve.png diff --git a/Minecraft.Client/Common/res/1_2_2/mob/alex.png b/Minecraft.Client/Common/res/1_2_2/mob/alex.png new file mode 100644 index 0000000000000000000000000000000000000000..b643fe2d083f64677a630087ba4c4004eac1ca06 GIT binary patch literal 3420 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 diff --git a/Minecraft.Client/Common/res/mob/char17.png b/Minecraft.Client/Common/res/mob/DevAlex.png similarity index 100% rename from Minecraft.Client/Common/res/mob/char17.png rename to Minecraft.Client/Common/res/mob/DevAlex.png diff --git a/Minecraft.Client/Common/res/mob/char8.png b/Minecraft.Client/Common/res/mob/DevSteve.png similarity index 100% rename from Minecraft.Client/Common/res/mob/char8.png rename to Minecraft.Client/Common/res/mob/DevSteve.png diff --git a/Minecraft.Client/Common/res/mob/alex.png b/Minecraft.Client/Common/res/mob/alex.png new file mode 100644 index 0000000000000000000000000000000000000000..b643fe2d083f64677a630087ba4c4004eac1ca06 GIT binary patch literal 3420 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 diff --git a/Minecraft.Client/EntityRenderer.cpp b/Minecraft.Client/EntityRenderer.cpp index 22698db3..46fc2687 100644 --- a/Minecraft.Client/EntityRenderer.cpp +++ b/Minecraft.Client/EntityRenderer.cpp @@ -19,9 +19,8 @@ ResourceLocation EntityRenderer::SHADOW_LOCATION = ResourceLocation(TN__CLAMP__M EntityRenderer::EntityRenderer() { model = nullptr; + modelWide = nullptr; modelSlim = nullptr; - newModel = nullptr; - newModelSlim = nullptr; tileRenderer = new TileRenderer(); shadowRadius = 0; shadowStrength = 1.0f; @@ -407,6 +406,13 @@ void EntityRenderer::registerTerrainTextures(IconRegister *iconRegister) { } +Model *EntityRenderer::getModel(int modelType) +{ + if (modelType == 2) return modelSlim; + else if (modelType == 1) return modelWide; + else return model; +} + ResourceLocation *EntityRenderer::getTextureLocation(shared_ptr mob) { diff --git a/Minecraft.Client/EntityRenderer.h b/Minecraft.Client/EntityRenderer.h index 6cdb1d86..c91f807c 100644 --- a/Minecraft.Client/EntityRenderer.h +++ b/Minecraft.Client/EntityRenderer.h @@ -31,9 +31,8 @@ private: protected: Model *model; // TODO 4J: Check why exactly this is here, it seems to get shadowed by classes inheriting from this by their own + Model *modelWide; Model *modelSlim; - Model *newModel; - Model *newModelSlim; protected: TileRenderer *tileRenderer; // 4J - changed to protected so derived classes can use instead of shadowing their own @@ -71,10 +70,7 @@ public: public: // 4J Added - virtual Model *getModel() { return model; } - virtual Model *getModelSlim() { return modelSlim; } - virtual Model *getNewModel() { return newModel; } - virtual Model *getNewModelSlim() { return newModelSlim; } + virtual Model *getModel(int modelType = 0); virtual void SetItemFrame(bool bSet) {} virtual bool shouldRender(shared_ptr entity, float camX, float camY, float camZ) { return true; } diff --git a/Minecraft.Client/HumanoidModel.cpp b/Minecraft.Client/HumanoidModel.cpp index c363f528..d6de0915 100644 --- a/Minecraft.Client/HumanoidModel.cpp +++ b/Minecraft.Client/HumanoidModel.cpp @@ -9,6 +9,7 @@ ModelPart * HumanoidModel::AddOrRetrievePart(SKIN_BOX *pBox) { ModelPart *pAttachTo=nullptr; + float scale=0; switch(pBox->ePart) { @@ -32,21 +33,29 @@ ModelPart * HumanoidModel::AddOrRetrievePart(SKIN_BOX *pBox) break; case eBodyPart_Jacket: pAttachTo=jacket; + scale=0.25; break; case eBodyPart_Sleeve0: pAttachTo=sleeve0; + scale=0.25; break; case eBodyPart_Sleeve1: pAttachTo=sleeve1; + scale=0.25; break; case eBodyPart_Pants0: pAttachTo=pants0; + scale=0.25; break; case eBodyPart_Pants1: pAttachTo=pants1; + scale=0.25; break; } + // check if this box has a declared scale then add it + if (pBox->fS != 0) scale = pBox->fS; + // first check this box doesn't already exist ModelPart *pNewBox = pAttachTo->retrieveChild(pBox); @@ -64,6 +73,8 @@ 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; // check if this box has the mirror flag + pNewBox->hideWithArmor = (unsigned int)pBox->fA; // add the "hide when armor is worn" bit flags pNewBox->addHumanoidBox(pBox->fX, pBox->fY, pBox->fZ, pBox->fW, pBox->fH, pBox->fD, 0); // 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); @@ -73,7 +84,7 @@ ModelPart * HumanoidModel::AddOrRetrievePart(SKIN_BOX *pBox) return pNewBox; } -void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, bool slimHands, bool mirror, bool force32) +void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, bool slimHands, bool mirror, bool force32, bool isArmor) { this->texWidth = texWidth; this->texHeight = texHeight; @@ -113,7 +124,7 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b if ((texWidth == 64 && texHeight == 64) && !force32) { jacket = new ModelPart(this, 16, 32); - jacket->addHumanoidBox(-4, 0, -2, 8, 12, 4, g + 0.5); + jacket->addHumanoidBox(-4, 0, -2, 8, 12, 4, g + 0.25); jacket->setPos(0, 0 + yOffset, 0); } @@ -131,13 +142,13 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b if (slimHands == false) { - sleeve0->addHumanoidBox(-3, -2, -2, 4, 12, 4, g + 0.5); - sleeve1->addHumanoidBox(-1, -2, -2, 4, 12, 4, g + 0.5); + sleeve0->addHumanoidBox(-3, -2, -2, 4, 12, 4, g + 0.25); + sleeve1->addHumanoidBox(-1, -2, -2, 4, 12, 4, g + 0.25); } else if (slimHands == true) { - sleeve0->addHumanoidBox(-2, -2, -2, 3, 12, 4, g + 0.5); - sleeve1->addHumanoidBox(-1, -2, -2, 3, 12, 4, g + 0.5); + sleeve0->addHumanoidBox(-2, -2, -2, 3, 12, 4, g + 0.25); + sleeve1->addHumanoidBox(-1, -2, -2, 3, 12, 4, g + 0.25); } sleeve0->setPos(-5, 2 + yOffset, 0); @@ -172,11 +183,11 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b leg1 = new ModelPart(this, 16, 48); pants0 = new ModelPart(this, 0, 32); - pants0->addHumanoidBox(-2, 0, -2, 4, 12, 4, g + 0.5); + pants0->addHumanoidBox(-2, 0, -2, 4, 12, 4, g + 0.25); pants0->setPos(-1.9, 12 + yOffset, 0); pants1 = new ModelPart(this, 0, 48); - pants1->addHumanoidBox(-2, 0, -2, 4, 12, 4, g + 0.5); + pants1->addHumanoidBox(-2, 0, -2, 4, 12, 4, g + 0.25); pants1->setPos(1.9, 12 + yOffset, 0); } else if ((texWidth == 64 && texHeight == 32) || force32) @@ -226,6 +237,7 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b bowAndArrow=false; elytraFlying = false; elytraCrouching = false; + m_isArmor = isArmor; // 4J added @@ -238,32 +250,37 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b HumanoidModel::HumanoidModel() : Model() { - _init(0, 0, 64, 32, false, true, false); + _init(0, 0, 64, 32, false, true, false, false); } HumanoidModel::HumanoidModel(float g) : Model() { - _init(g, 0, 64, 32, false, true, false); + _init(g, 0, 64, 32, false, true, false, false); +} + +HumanoidModel::HumanoidModel(float g, bool isArmor) : Model() +{ + _init(g, 0, 64, 32, false, true, false, isArmor); } HumanoidModel::HumanoidModel(float g, float yOffset, int texWidth, int texHeight) : Model() { - _init(g,yOffset,texWidth,texHeight, false, true, false); + _init(g,yOffset,texWidth,texHeight, false, true, false, false); } HumanoidModel::HumanoidModel(float g, float yOffset, int texWidth, int texHeight, bool slimHands) : Model() { - _init(g,yOffset,texWidth,texHeight, slimHands, true, false); + _init(g,yOffset,texWidth,texHeight, slimHands, true, false, false); } HumanoidModel::HumanoidModel(float g, float yOffset, int texWidth, int texHeight, bool slimHands, bool mirror) : Model() { - _init(g,yOffset,texWidth,texHeight, slimHands, mirror, false); + _init(g,yOffset,texWidth,texHeight, slimHands, mirror, false, false); } HumanoidModel::HumanoidModel(float g, float yOffset, int texWidth, int texHeight, bool slimHands, bool mirror, bool force32) : Model() { - _init(g,yOffset,texWidth,texHeight, slimHands, mirror, force32); + _init(g,yOffset,texWidth,texHeight, slimHands, mirror, force32, false); } void HumanoidModel::render(shared_ptr entity, float time, float r, float bob, float yRot, float xRot, float scale, bool usecompiled) @@ -308,12 +325,12 @@ void HumanoidModel::render(shared_ptr entity, float time, float r, float } else { - head->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - body->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - arm0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - arm1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - leg0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - leg1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); + head->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); + body->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); + arm0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); + arm1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); + leg0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); + leg1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); hair->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); if (jacket) diff --git a/Minecraft.Client/HumanoidModel.h b/Minecraft.Client/HumanoidModel.h index 4c7f95f5..525ae32e 100644 --- a/Minecraft.Client/HumanoidModel.h +++ b/Minecraft.Client/HumanoidModel.h @@ -15,6 +15,7 @@ public: float eating_swing; bool elytraFlying; bool elytraCrouching; + bool m_isArmor; unsigned int m_uiAnimOverrideBitmask; float m_fYOffset; enum animbits @@ -37,11 +38,20 @@ public: eAnim_DisableRenderLeg1, eAnim_DisableRenderHair, eAnim_SmallModel, - eAnim_DisableRenderJacket, - eAnim_DisableRenderSleeve0, - eAnim_DisableRenderSleeve1, - eAnim_DisableRenderPants0, - eAnim_DisableRenderPants1 + eAnim_WideModel, + eAnim_SlimModel, + eAnim_DisableRenderSleeve1, + eAnim_DisableRenderSleeve0, + eAnim_DisableRenderPants1, + eAnim_DisableRenderPants0, + eAnim_DisableRenderJacket, + eAnim_RenderArmorHead, + eAnim_RenderArmorArm0, + eAnim_RenderArmorArm1, + eAnim_RenderArmorTorso, + eAnim_RenderArmorLeg0, + eAnim_RenderArmorLeg1, + eAnim_Dinnerbone }; @@ -60,10 +70,11 @@ public: (1 << HumanoidModel::eAnim_DisableRenderPants1); void _init(float g, float yOffset, int texWidth, int texHeight, - bool slimHands, bool mirror, bool force32); + bool slimHands, bool mirror, bool force32, bool isArmor = false); HumanoidModel(); HumanoidModel(float g); + HumanoidModel(float g, bool isArmor); HumanoidModel(float g, float yOffset, int texWidth, int texHeight); HumanoidModel(float g, float yOffset, int texWidth, int texHeight, bool slimHands); HumanoidModel(float g, float yOffset, int texWidth, int texHeight, bool slimHands, bool mirror); diff --git a/Minecraft.Client/LivingEntityRenderer.cpp b/Minecraft.Client/LivingEntityRenderer.cpp index c6e7687e..8fe27fc7 100644 --- a/Minecraft.Client/LivingEntityRenderer.cpp +++ b/Minecraft.Client/LivingEntityRenderer.cpp @@ -8,29 +8,23 @@ #include "../Minecraft.World/Arrow.h" #include "../Minecraft.World/Mth.h" #include "../Minecraft.World/Player.h" -#include "Skins.h" - ResourceLocation LivingEntityRenderer::ENCHANT_GLINT_LOCATION = ResourceLocation(TN__BLUR__MISC_GLINT); int LivingEntityRenderer::MAX_ARMOR_LAYERS = 4; -LivingEntityRenderer::LivingEntityRenderer(Model *model, float shadow, bool slimHands, bool createNewVar) +LivingEntityRenderer::LivingEntityRenderer(Model *model, float shadow, bool isPlayer) { this->model = model; - if (slimHands == true) - this->modelSlim = new HumanoidModel(0, 0, 64, 32, true); - - if (createNewVar) + if (isPlayer) { - this->newModel = new HumanoidModel(0, 0, 64, 64, false, false); - - if (slimHands == true) - this->newModelSlim = new HumanoidModel(0, 0, 64, 64, true, false); + this->modelWide = new HumanoidModel(0, 0, 64, 64, false); + this->modelSlim = new HumanoidModel(0, 0, 64, 64, true); } shadowRadius = shadow; armor = nullptr; + resModel = model; } void LivingEntityRenderer::setArmor(Model *armor) @@ -38,6 +32,11 @@ void LivingEntityRenderer::setArmor(Model *armor) this->armor = armor; } +void LivingEntityRenderer::setPlayerModelType(Model *humanoidModel) +{ + resModel = humanoidModel; +} + float LivingEntityRenderer::rotlerp(float from, float to, float a) { float diff = to - from; @@ -56,8 +55,6 @@ void LivingEntityRenderer::render(shared_ptr _mob, double x, double y, d } shared_ptr mob = dynamic_pointer_cast(_mob); - shared_ptr player = dynamic_pointer_cast(_mob); - Model *resModel = static_cast(model); if (mob == nullptr) { @@ -67,30 +64,6 @@ void LivingEntityRenderer::render(shared_ptr _mob, double x, double y, d glPushMatrix(); glDisable(GL_CULL_FACE); - if (player != nullptr) - { - Textures *textures = Minecraft::GetInstance()->textures; - int skinId = player->getPlayerDefaultSkin() - 1; - int defaultSkin = player->getPlayerDefaultSkin() + 35; - - if (slim[skinId] == true) - { - if (textures->getHeight(player->customTextureUrl, defaultSkin) == 64) - resModel = static_cast(newModelSlim); - else - resModel = static_cast(modelSlim); - } - else - { - if (textures->getHeight(player->customTextureUrl, defaultSkin) == 64) - resModel = static_cast(newModel); - else - resModel = static_cast(model); - } - } - else - resModel = static_cast(model); - resModel->attackTime = getAttackAnim(mob, a); if (armor != nullptr) armor->attackTime = resModel->attackTime; resModel->riding = mob->isRiding(); @@ -281,33 +254,6 @@ void LivingEntityRenderer::render(shared_ptr _mob, double x, double y, d void LivingEntityRenderer::renderModel(shared_ptr mob, float wp, float ws, float bob, float headRotMinusBodyRot, float headRotx, float scale) { - shared_ptr player = dynamic_pointer_cast(mob); - Model *resModel = static_cast(model); - - if (player != nullptr) - { - Textures *textures = Minecraft::GetInstance()->textures; - int skinId = player->getPlayerDefaultSkin() - 1; - int defaultSkin = player->getPlayerDefaultSkin() + 35; - - if (slim[skinId] == true) - { - if (textures->getHeight(player->customTextureUrl, defaultSkin) == 64) - resModel = static_cast(newModelSlim); - else - resModel = static_cast(modelSlim); - } - else - { - if (textures->getHeight(player->customTextureUrl, defaultSkin) == 64) - resModel = static_cast(newModel); - else - resModel = static_cast(model); - } - } - else - resModel = static_cast(model); - bindTexture(mob); if (!mob->isInvisible()) { @@ -351,7 +297,7 @@ void LivingEntityRenderer::setupRotations(shared_ptr mob, float bo else { wstring name = mob->getAName(); - if (name == L"Dinnerbone" || name == L"Grumm") + if (name == L"Dinnerbone" || name == L"Grumm" || mob->getAnimOverrideBitmask() & (1 << HumanoidModel::eAnim_Dinnerbone)) { if ( !mob->instanceof(eTYPE_PLAYER) || !dynamic_pointer_cast(mob)->isCapeHidden() ) { @@ -379,33 +325,6 @@ void LivingEntityRenderer::additionalRendering(shared_ptr mob, flo void LivingEntityRenderer::renderArrows(shared_ptr mob, float a) { - shared_ptr player = dynamic_pointer_cast(mob); - Model *resModel = static_cast(model); - - if (player != nullptr) - { - Textures *textures = Minecraft::GetInstance()->textures; - int skinId = player->getPlayerDefaultSkin() - 1; - int defaultSkin = player->getPlayerDefaultSkin() + 35; - - if (slim[skinId] == true) - { - if (textures->getHeight(player->customTextureUrl, defaultSkin) == 64) - resModel = static_cast(newModelSlim); - else - resModel = static_cast(modelSlim); - } - else - { - if (textures->getHeight(player->customTextureUrl, defaultSkin) == 64) - resModel = static_cast(newModel); - else - resModel = static_cast(model); - } - } - else - resModel = static_cast(model); - int arrowCount = mob->getArrowCount(); if (arrowCount > 0) diff --git a/Minecraft.Client/LivingEntityRenderer.h b/Minecraft.Client/LivingEntityRenderer.h index ba2aa330..5c564e37 100644 --- a/Minecraft.Client/LivingEntityRenderer.h +++ b/Minecraft.Client/LivingEntityRenderer.h @@ -17,11 +17,13 @@ class LivingEntityRenderer : public EntityRenderer protected: //Model *model; // 4J Stu - This shadows the one in EntityRenderer Model *armor; + Model *resModel; public: - LivingEntityRenderer(Model *model, float shadow, bool slimHands = 0, bool createNewVar = 0); + LivingEntityRenderer(Model *model, float shadow, bool isPlayer = false); virtual void render(shared_ptr mob, double x, double y, double z, float rot, float a); virtual void setArmor(Model *armor); + virtual void setPlayerModelType(Model *humanoidModel); private: float rotlerp(float from, float to, float a); diff --git a/Minecraft.Client/ModelPart.cpp b/Minecraft.Client/ModelPart.cpp index 07d3bc17..152dc000 100644 --- a/Minecraft.Client/ModelPart.cpp +++ b/Minecraft.Client/ModelPart.cpp @@ -14,6 +14,7 @@ void ModelPart::_init() bMirror = false; visible = true; neverRender = false; + hideWithArmor = 0L; x=y=z = 0.0f; xRot=yRot=zRot = 0.0f; translateX = translateY = translateZ = 0.0f; diff --git a/Minecraft.Client/ModelPart.h b/Minecraft.Client/ModelPart.h index 61e26ab9..5e605aa9 100644 --- a/Minecraft.Client/ModelPart.h +++ b/Minecraft.Client/ModelPart.h @@ -17,6 +17,7 @@ public: bool bMirror; bool visible; bool neverRender; + unsigned int hideWithArmor; vector cubes; vector children; static const float RAD; diff --git a/Minecraft.Client/PlayerRenderer.cpp b/Minecraft.Client/PlayerRenderer.cpp index 8ff3bf85..5c033874 100644 --- a/Minecraft.Client/PlayerRenderer.cpp +++ b/Minecraft.Client/PlayerRenderer.cpp @@ -16,7 +16,6 @@ #include "../Minecraft.World/StringHelpers.h" #include "SkeletonHeadModel.h" #include "Textures.h" -#include "Skins.h" ResourceLocation PlayerRenderer::SKELETON_LOCATION = ResourceLocation(TN_MOB_SKELETON); ResourceLocation PlayerRenderer::WITHER_SKELETON_LOCATION = ResourceLocation(TN_MOB_WITHER_SKELETON); @@ -64,16 +63,22 @@ 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); - humanoidModelSlim = static_cast(modelSlim); - newHumanoidModel = static_cast(newModel); - newHumanoidModelSlim = static_cast(newModelSlim); + humanoidModel = static_cast(model); + humanoidModelWide = static_cast(modelWide); + humanoidModelSlim = static_cast(modelSlim); - armorParts1 = new HumanoidModel(1.0f); - armorParts2 = new HumanoidModel(0.5f); - armorParts3 = new HumanoidModel(0.5f); + armorParts1 = new HumanoidModel(1.0f, true); + armorParts2 = new HumanoidModel(0.5f, true); + armorParts3 = new HumanoidModel(0.5f, true); +} + +void PlayerRenderer::setModelType(shared_ptr player) +{ + if (Player::GetModelTypeFromTextureId(player->getCustomSkin()) == 1 || Player::GetModelTypeFromAnimBitmask(player->getAnimOverrideBitmask()) == 1) resModel = humanoidModelWide; + else if (Player::GetModelTypeFromTextureId(player->getCustomSkin()) == 2 || Player::GetModelTypeFromAnimBitmask(player->getAnimOverrideBitmask()) == 2) resModel = humanoidModelSlim; + else resModel = humanoidModel; } unsigned int PlayerRenderer::getNametagColour(int index) @@ -87,6 +92,7 @@ int PlayerRenderer::prepareArmor(shared_ptr _player, int layer, fl { // 4J - dynamic cast required because we aren't using templates/generics in our version shared_ptr player = dynamic_pointer_cast(_player); + setModelType(player); // 4J-PB - need to disable rendering armour for some special skins (Daleks) unsigned int uiAnimOverrideBitmask = player->getAnimOverrideBitmask(); @@ -116,9 +122,9 @@ int PlayerRenderer::prepareArmor(shared_ptr _player, int layer, fl armor->leg1->visible = layer == 2 || layer == 3; setArmor(armor); - if (armor != nullptr) armor->attackTime = model->attackTime; - if (armor != nullptr) armor->riding = model->riding; - if (armor != nullptr) armor->young = model->young; + if (armor != nullptr) armor->attackTime = resModel->attackTime; + if (armor != nullptr) armor->riding = resModel->riding; + if (armor != nullptr) armor->young = resModel->young; float brightness = SharedConstants::TEXTURE_LIGHTING ? 1 : player->getBrightness(a); if (armorItem->getMaterial() == ArmorItem::ArmorMaterial::CLOTH) @@ -221,38 +227,12 @@ void PlayerRenderer::render(shared_ptr _mob, double x, double y, double // 4J - dynamic cast required because we aren't using templates/generics in our version shared_ptr mob = dynamic_pointer_cast(_mob); - HumanoidModel* resModel = static_cast(model); if (mob == nullptr) return; if (mob->hasInvisiblePrivilege()) return; - if (mob != nullptr) - { - Textures* textures = Minecraft::GetInstance()->textures; - int skinId = mob->getPlayerDefaultSkin() - 1; - int defaultSkin = mob->getPlayerDefaultSkin() + 35; - - if (slim[skinId] == true) - { - if (textures->getHeight(mob->customTextureUrl, defaultSkin) == 64) - resModel = static_cast(newHumanoidModelSlim); - else - resModel = static_cast(humanoidModelSlim); - } - else - { - if (textures->getHeight(mob->customTextureUrl, defaultSkin) == 64) - resModel = static_cast(newHumanoidModel); - else - resModel = static_cast(humanoidModel); - } - } - else - resModel = static_cast(model); - - /*if (mob != nullptr && newHumanoidModelSlim != nullptr && (mob->getCustomSkin() >= 10 && mob->getCustomSkin() <= 18)) resModel = newHumanoidModelSlim; - else if (mob != nullptr && newHumanoidModel != nullptr && (mob->getCustomSkin() >= 2 && mob->getCustomSkin() <= 9)) resModel = newHumanoidModel; - else resModel = humanoidModel;*/ + setModelType(mob); + setPlayerModelType(resModel); shared_ptr item = mob->inventory->getSelected(); @@ -341,6 +321,12 @@ void PlayerRenderer::render(shared_ptr _mob, double x, double y, double armorParts2->idle = false; } + // Get armor in armor slot so we can hide the armor layer of the skin - Langtanium + shared_ptr itemHelmet = mob->inventory->getArmor(3); + shared_ptr itemChestplate = mob->inventory->getArmor(2); + shared_ptr itemLeggings = mob->inventory->getArmor(1); + shared_ptr itemBoots = mob->inventory->getArmor(0); + // 4J-PB - any additional parts to turn on for this player (skin dependent) vector* pAdditionalModelParts = mob->GetAdditionalModelParts(); //turn them on @@ -348,7 +334,16 @@ void PlayerRenderer::render(shared_ptr _mob, double x, double y, double { for (ModelPart* pModelPart : *pAdditionalModelParts) { - pModelPart->visible = true; + if (itemHelmet != nullptr && pModelPart->hideWithArmor & (1 << 0)) // Hide the skin boxes that have the "hide when helmet is worn" bit flag - Langtanium + pModelPart->visible = false; + else if (itemChestplate != nullptr && pModelPart->hideWithArmor & (1 << 1)) // Hide the skin boxes that have the "hide when chestplate is worn" bit flag - Langtanium + pModelPart->visible = false; + else if (itemLeggings != nullptr && pModelPart->hideWithArmor & (1 << 2)) // Hide the skin boxes that have the "hide when leggings are worn" bit flag - Langtanium + pModelPart->visible = false; + else if (itemBoots != nullptr && pModelPart->hideWithArmor & (1 << 3)) // Hide the skin boxes that have the "hide when boots are worn" bit flag - Langtanium + pModelPart->visible = false; + else + pModelPart->visible = true; } } @@ -379,35 +374,7 @@ void PlayerRenderer::additionalRendering(shared_ptr _mob, float a) // 4J - dynamic cast required because we aren't using templates/generics in our version shared_ptr mob = dynamic_pointer_cast(_mob); - HumanoidModel* resModel = static_cast(model); - - if (mob != nullptr) - { - Textures* textures = Minecraft::GetInstance()->textures; - int skinId = mob->getPlayerDefaultSkin() - 1; - int defaultSkin = mob->getPlayerDefaultSkin() + 35; - - if (slim[skinId] == true) - { - if (textures->getHeight(mob->customTextureUrl, defaultSkin) == 64) - resModel = static_cast(newHumanoidModelSlim); - else - resModel = static_cast(humanoidModelSlim); - } - else - { - if (textures->getHeight(mob->customTextureUrl, defaultSkin) == 64) - resModel = static_cast(newHumanoidModel); - else - resModel = static_cast(humanoidModel); - } - } - else - resModel = static_cast(model); - - /*if (mob != nullptr && newHumanoidModelSlim != nullptr && (mob->getCustomSkin() >= 10 && mob->getCustomSkin() <= 18)) resModel = newHumanoidModelSlim; - else if (mob != nullptr && newHumanoidModel != nullptr && (mob->getCustomSkin() >= 2 && mob->getCustomSkin() <= 9)) resModel = newHumanoidModel; - else resModel = humanoidModel;*/ + setModelType(mob); shared_ptr headGear = mob->inventory->getArmor(3); if (headGear != nullptr) @@ -741,35 +708,7 @@ void PlayerRenderer::scale(shared_ptr player, float a) void PlayerRenderer::renderHand() { shared_ptr player = dynamic_pointer_cast(Minecraft::GetInstance()->player); - HumanoidModel* resModel = static_cast(model); - - if (player != nullptr) - { - Textures* textures = Minecraft::GetInstance()->textures; - int skinId = player->getPlayerDefaultSkin() - 1; - int defaultSkin = player->getPlayerDefaultSkin() + 35; - - if (slim[skinId] == true) - { - if (textures->getHeight(player->customTextureUrl, defaultSkin) == 64) - resModel = static_cast(newHumanoidModelSlim); - else - resModel = static_cast(humanoidModelSlim); - } - else - { - if (textures->getHeight(player->customTextureUrl, defaultSkin) == 64) - resModel = static_cast(newHumanoidModel); - else - resModel = static_cast(humanoidModel); - } - } - else - resModel = static_cast(model); - - /*if (player != nullptr && newHumanoidModelSlim != nullptr && (player->getCustomSkin() >= 10 && player->getCustomSkin() <= 18)) resModel = newHumanoidModelSlim; - else if (player != nullptr && newHumanoidModel != nullptr && (player->getCustomSkin() >= 2 && player->getCustomSkin() <= 9)) resModel = newHumanoidModel; - else resModel = humanoidModel;*/ + setModelType(player); float brightness = 1; glColor3f(brightness, brightness, brightness); @@ -781,9 +720,12 @@ void PlayerRenderer::renderHand() // 4J-PB - does this skin have its arm0 disabled? (Dalek, etc) if ((resModel->m_uiAnimOverrideBitmask & (1 << HumanoidModel::eAnim_DisableRenderArm0)) == 0) resModel->arm0->render(1 / 16.0f, true); + // Does this skin have its sleeve0 disabled? + if ((resModel->m_uiAnimOverrideBitmask & (1 << HumanoidModel::eAnim_DisableRenderSleeve0)) == 0 && resModel->sleeve0 != nullptr) + 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. vector armchildren = resModel->arm0->children; std::unordered_set additionalModelPartSet(additionalModelParts->begin(), additionalModelParts->end()); @@ -801,6 +743,25 @@ void PlayerRenderer::renderHand() } } } + //Render custom skin boxes on viewmodel for sleeve0 + if (resModel->sleeve0!=nullptr) + { + vector sleevechildren = resModel->sleeve0->children; + for (const auto& x : sleevechildren) { + if (x) { + if (additionalModelPartSet.find(x) != additionalModelPartSet.end()) { //This is to verify box is still actually on current skin + glPushMatrix(); + //We need to transform to match offset of arm/sleeve + glTranslatef(-5 * 0.0625f, 2 * 0.0625f, 0); + glRotatef(0.1 * (180.0f / PI), 0, 0, 1); + x->visible = true; + x->render(1.0f / 16.0f, true); + x->visible = false; + glPopMatrix(); + } + } + } + } } void PlayerRenderer::setupPosition(shared_ptr _mob, double x, double y, double z) @@ -857,7 +818,7 @@ void PlayerRenderer::setupRotations(shared_ptr _mob, float bob, fl } } - else + else { LivingEntityRenderer::setupRotations(mob, bob, bodyRot, a); } diff --git a/Minecraft.Client/PlayerRenderer.h b/Minecraft.Client/PlayerRenderer.h index 8accdc7f..fb655ec7 100644 --- a/Minecraft.Client/PlayerRenderer.h +++ b/Minecraft.Client/PlayerRenderer.h @@ -14,9 +14,9 @@ public: private: HumanoidModel *humanoidModel; + HumanoidModel *humanoidModelWide; HumanoidModel *humanoidModelSlim; - HumanoidModel *newHumanoidModel; - HumanoidModel *newHumanoidModelSlim; + HumanoidModel *resModel; HumanoidModel *armorParts1; HumanoidModel *armorParts2; @@ -38,6 +38,7 @@ private: static const wstring MATERIAL_NAMES[5]; protected: + virtual void setModelType(shared_ptr player); virtual int prepareArmor(shared_ptr _player, int layer, float a); virtual void prepareSecondPassArmor(shared_ptr mob, int layer, float a); diff --git a/Minecraft.Client/SkinBox.h b/Minecraft.Client/SkinBox.h index b4600f1d..08b3073a 100644 --- a/Minecraft.Client/SkinBox.h +++ b/Minecraft.Client/SkinBox.h @@ -19,6 +19,6 @@ enum eBodyPart typedef struct { eBodyPart ePart; - float fX,fY,fZ,fW,fH,fD,fU,fV; + float fX,fY,fZ,fW,fH,fD,fU,fV,fA,fM,fS; } SKIN_BOX; diff --git a/Minecraft.Client/Skins.h b/Minecraft.Client/Skins.h deleted file mode 100644 index 7596fa7f..00000000 --- a/Minecraft.Client/Skins.h +++ /dev/null @@ -1,29 +0,0 @@ -#pragma once -#include -using namespace std; - -class AABB; -class Recipy; -class Object; - -static std::map slim = { - { 0, false }, - { 1, false }, - { 2, false }, - { 3, false }, - { 4, false }, - { 5, false }, - { 6, false }, - { 7, false }, - { 8, false }, - { 9, true }, - { 10, true }, - { 11, true }, - { 12, true }, - { 13, true }, - { 14, true }, - { 15, true }, - { 16, true }, - { 17, true }, - { 18, true }, -}; \ No newline at end of file diff --git a/Minecraft.Client/Textures.cpp b/Minecraft.Client/Textures.cpp index 627255b6..82cdf81e 100644 --- a/Minecraft.Client/Textures.cpp +++ b/Minecraft.Client/Textures.cpp @@ -72,16 +72,16 @@ const wchar_t *Textures::preLoaded[TN_COUNT] = L"mob/char5", L"mob/char6", L"mob/char7", - L"mob/char8", - L"mob/char9", - L"mob/char10", - L"mob/char11", - L"mob/char12", - L"mob/char13", - L"mob/char14", - L"mob/char15", - L"mob/char16", - L"mob/char17", + L"mob/alex", + L"mob/alex1", + L"mob/alex2", + L"mob/alex3", + L"mob/alex4", + L"mob/alex5", + L"mob/alex6", + L"mob/alex7", + L"mob/DevAlex", + L"mob/DevSteve", L"terrain/moon", L"terrain/sun", L"armor/power", @@ -1697,16 +1697,16 @@ TEXTURE_NAME OriginalImages[] = TN_MOB_CHAR5, TN_MOB_CHAR6, TN_MOB_CHAR7, - TN_MOB_CHAR8, - TN_MOB_CHAR9, - TN_MOB_CHAR10, - TN_MOB_CHAR11, - TN_MOB_CHAR12, - TN_MOB_CHAR13, - TN_MOB_CHAR14, - TN_MOB_CHAR15, - TN_MOB_CHAR16, - TN_MOB_CHAR17, + TN_MOB_ALEX, + TN_MOB_ALEX1, + TN_MOB_ALEX2, + TN_MOB_ALEX3, + TN_MOB_ALEX4, + TN_MOB_ALEX5, + TN_MOB_ALEX6, + TN_MOB_ALEX7, + TN_MOB_DEVALEX, + TN_MOB_DEVSTEVE, TN_MISC_MAPBG, diff --git a/Minecraft.Client/Textures.h b/Minecraft.Client/Textures.h index 5f08fe57..48eec6a4 100644 --- a/Minecraft.Client/Textures.h +++ b/Minecraft.Client/Textures.h @@ -63,16 +63,16 @@ typedef enum _TEXTURE_NAME TN_MOB_CHAR5, TN_MOB_CHAR6, TN_MOB_CHAR7, - TN_MOB_CHAR8, - TN_MOB_CHAR9, - TN_MOB_CHAR10, - TN_MOB_CHAR11, - TN_MOB_CHAR12, - TN_MOB_CHAR13, - TN_MOB_CHAR14, - TN_MOB_CHAR15, - TN_MOB_CHAR16, - TN_MOB_CHAR17, + TN_MOB_ALEX, + TN_MOB_ALEX1, + TN_MOB_ALEX2, + TN_MOB_ALEX3, + TN_MOB_ALEX4, + TN_MOB_ALEX5, + TN_MOB_ALEX6, + TN_MOB_ALEX7, + TN_MOB_DEVALEX, + TN_MOB_DEVSTEVE, TN_TERRAIN_MOON, TN_TERRAIN_SUN, TN_POWERED_CREEPER, diff --git a/Minecraft.World/Player.cpp b/Minecraft.World/Player.cpp index 8dd4930a..97d6e198 100644 --- a/Minecraft.World/Player.cpp +++ b/Minecraft.World/Player.cpp @@ -727,6 +727,22 @@ void Player::setCustomSkin(DWORD skinId) } +int Player::GetModelTypeFromAnimBitmask(unsigned int uiAnimOverrideBitmask) +{ + if (uiAnimOverrideBitmask&(1< 8 && textureId < 18) return 2; + else if (textureId == 18) return 1; + else if (textureId > 44 && textureId < 54) return 2; + else if (textureId == 54) return 1; + else return 0; +} + unsigned int Player::getSkinAnimOverrideBitmask(DWORD skinId) { unsigned long bitmask = 0L; @@ -2903,25 +2919,25 @@ int Player::getTexture() case eDefaultSkins_Skin7: return TN_MOB_CHAR7; // 4J - was L"/mob/char7.png"; case eDefaultSkins_Skin8: - return TN_MOB_CHAR8; // 4J - was L"/mob/char8.png"; + return TN_MOB_ALEX; // 4J - was L"/mob/alex.png"; case eDefaultSkins_Skin9: - return TN_MOB_CHAR9; // 4J - was L"/mob/char9.png"; + return TN_MOB_ALEX1; // 4J - was L"/mob/alex1.png"; case eDefaultSkins_Skin10: - return TN_MOB_CHAR10; // 4J - was L"/mob/char10.png"; + return TN_MOB_ALEX2; // 4J - was L"/mob/alex2.png"; case eDefaultSkins_Skin11: - return TN_MOB_CHAR11; // 4J - was L"/mob/char11.png"; + return TN_MOB_ALEX3; // 4J - was L"/mob/alex3.png"; case eDefaultSkins_Skin12: - return TN_MOB_CHAR12; // 4J - was L"/mob/char12.png"; + return TN_MOB_ALEX4; // 4J - was L"/mob/alex4.png"; case eDefaultSkins_Skin13: - return TN_MOB_CHAR13; // 4J - was L"/mob/char13.png"; + return TN_MOB_ALEX5; // 4J - was L"/mob/alex5.png"; case eDefaultSkins_Skin14: - return TN_MOB_CHAR14; // 4J - was L"/mob/char14.png"; + return TN_MOB_ALEX6; // 4J - was L"/mob/alex6.png"; case eDefaultSkins_Skin15: - return TN_MOB_CHAR15; // 4J - was L"/mob/char15.png"; + return TN_MOB_ALEX7; // 4J - was L"/mob/alex7.png"; case eDefaultSkins_Skin16: - return TN_MOB_CHAR16; // 4J - was L"/mob/char16.png"; + return TN_MOB_DEVALEX; // 4J - was L"/mob/DevAlex.png"; case eDefaultSkins_Skin17: - return TN_MOB_CHAR17; // 4J - was L"/mob/char17.png"; + return TN_MOB_DEVSTEVE; // 4J - was L"/mob/DevSteve.png"; default: return TN_MOB_CHAR; // 4J - was L"/mob/char.png"; diff --git a/Minecraft.World/Player.h b/Minecraft.World/Player.h index 61413adc..ecaddafa 100644 --- a/Minecraft.World/Player.h +++ b/Minecraft.World/Player.h @@ -442,6 +442,8 @@ public: static DWORD getCapeIdFromPath(const wstring &cape); static wstring getCapePathFromId(DWORD capeId); static unsigned int getSkinAnimOverrideBitmask(DWORD skinId); + static int GetModelTypeFromAnimBitmask(unsigned int uiAnimOverrideBitmask); + static int GetModelTypeFromTextureId(int textureId); // 4J Added void setXuid(PlayerUID xuid); diff --git a/Minecraft.World/TextureAndGeometryPacket.cpp b/Minecraft.World/TextureAndGeometryPacket.cpp index 1c920ee7..41fe933f 100644 --- a/Minecraft.World/TextureAndGeometryPacket.cpp +++ b/Minecraft.World/TextureAndGeometryPacket.cpp @@ -177,6 +177,9 @@ void TextureAndGeometryPacket::read(DataInputStream *dis) //throws IOException this->BoxDataA[i].fD = dis->readFloat(); this->BoxDataA[i].fU = dis->readFloat(); this->BoxDataA[i].fV = dis->readFloat(); + this->BoxDataA[i].fA = dis->readFloat(); + this->BoxDataA[i].fM = dis->readFloat(); + this->BoxDataA[i].fS = dis->readFloat(); } } @@ -203,6 +206,9 @@ void TextureAndGeometryPacket::write(DataOutputStream *dos) //throws IOException dos->writeFloat(this->BoxDataA[i].fD); dos->writeFloat(this->BoxDataA[i].fU); dos->writeFloat(this->BoxDataA[i].fV); + dos->writeFloat(this->BoxDataA[i].fA); + dos->writeFloat(this->BoxDataA[i].fM); + dos->writeFloat(this->BoxDataA[i].fS); } } From 7bc9a87027e2d0abae31d94df57e700d605ad377 Mon Sep 17 00:00:00 2001 From: Langtanium <94726057+Langtanium@users.noreply.github.com> Date: Mon, 18 May 2026 11:12:12 -0700 Subject: [PATCH 2/9] Small correction to modified skin code Adjusted modified code to work with default wide 64x64 skins. --- .../Common/UI/UIControl_PlayerSkinPreview.cpp | 2 +- Minecraft.Client/PlayerRenderer.cpp | 4 ++-- Minecraft.World/Player.cpp | 11 +++++------ 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp b/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp index 8a549637..d3d93319 100644 --- a/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp +++ b/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp @@ -309,7 +309,7 @@ void UIControl_PlayerSkinPreview::render(EntityRenderer *renderer, double x, dou glDisable(GL_CULL_FACE); Textures *t = Minecraft::GetInstance()->textures; - HumanoidModel *model = static_cast(renderer->getModel(Player::GetModelTypeFromTextureId(t->loadMemTexture(m_customTextureUrl, m_backupTexture))+Player::GetModelTypeFromAnimBitmask(m_uiAnimOverrideBitmask))); + HumanoidModel *model = static_cast(renderer->getModel(Player::GetModelTypeFromTextureId(t->loadMemTexture(m_customTextureUrl, m_backupTexture)-36)+Player::GetModelTypeFromAnimBitmask(m_uiAnimOverrideBitmask))); //getAttackAnim(mob, a); //if (armor != nullptr) armor->attackTime = model->attackTime; diff --git a/Minecraft.Client/PlayerRenderer.cpp b/Minecraft.Client/PlayerRenderer.cpp index 5c033874..68801625 100644 --- a/Minecraft.Client/PlayerRenderer.cpp +++ b/Minecraft.Client/PlayerRenderer.cpp @@ -76,8 +76,8 @@ PlayerRenderer::PlayerRenderer() : LivingEntityRenderer( new HumanoidModel(0), 0 void PlayerRenderer::setModelType(shared_ptr player) { - if (Player::GetModelTypeFromTextureId(player->getCustomSkin()) == 1 || Player::GetModelTypeFromAnimBitmask(player->getAnimOverrideBitmask()) == 1) resModel = humanoidModelWide; - else if (Player::GetModelTypeFromTextureId(player->getCustomSkin()) == 2 || Player::GetModelTypeFromAnimBitmask(player->getAnimOverrideBitmask()) == 2) resModel = humanoidModelSlim; + if (Player::GetModelTypeFromTextureId(player->getCustomSkin()) == 2 || Player::GetModelTypeFromAnimBitmask(player->getAnimOverrideBitmask()) == 2) resModel = humanoidModelSlim; + else if (Player::GetModelTypeFromTextureId(player->getCustomSkin()) == 1 || Player::GetModelTypeFromAnimBitmask(player->getAnimOverrideBitmask()) == 1) resModel = humanoidModelWide; else resModel = humanoidModel; } diff --git a/Minecraft.World/Player.cpp b/Minecraft.World/Player.cpp index 97d6e198..e8756ea7 100644 --- a/Minecraft.World/Player.cpp +++ b/Minecraft.World/Player.cpp @@ -727,19 +727,18 @@ void Player::setCustomSkin(DWORD skinId) } -int Player::GetModelTypeFromAnimBitmask(unsigned int uiAnimOverrideBitmask) +int Player::GetModelTypeFromAnimBitmask(unsigned int animBitmask) { - if (uiAnimOverrideBitmask&(1< 8 && textureId < 18) return 2; else if (textureId == 18) return 1; - else if (textureId > 44 && textureId < 54) return 2; - else if (textureId == 54) return 1; + else if (textureId >= 0 && textureId < 9) return 1; else return 0; } From b5847b1ae7f3752d712e4bf8ad81452d63358f45 Mon Sep 17 00:00:00 2001 From: Langtanium <94726057+Langtanium@users.noreply.github.com> Date: Mon, 18 May 2026 12:01:41 -0700 Subject: [PATCH 3/9] Small correction Removed some spaces and added resModel default value to not break a previous fix for skins on servers. --- Minecraft.Client/PlayerRenderer.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Minecraft.Client/PlayerRenderer.cpp b/Minecraft.Client/PlayerRenderer.cpp index 68801625..3a4fe742 100644 --- a/Minecraft.Client/PlayerRenderer.cpp +++ b/Minecraft.Client/PlayerRenderer.cpp @@ -63,11 +63,12 @@ static unsigned int nametagColorForIndex(int index) ResourceLocation PlayerRenderer::DEFAULT_LOCATION = ResourceLocation(TN_MOB_CHAR); -PlayerRenderer::PlayerRenderer() : LivingEntityRenderer( new HumanoidModel(0), 0.5f, true ) +PlayerRenderer::PlayerRenderer() : LivingEntityRenderer(new HumanoidModel(0), 0.5f, true) { - humanoidModel = static_cast(model); - humanoidModelWide = static_cast(modelWide); - humanoidModelSlim = static_cast(modelSlim); + humanoidModel = static_cast(model); + humanoidModelWide = static_cast(modelWide); + humanoidModelSlim = static_cast(modelSlim); + resModel = humanoidModel; armorParts1 = new HumanoidModel(1.0f, true); armorParts2 = new HumanoidModel(0.5f, true); From 131db508b5542efa2c939669336488e67f617e85 Mon Sep 17 00:00:00 2001 From: Langtanium <94726057+Langtanium@users.noreply.github.com> Date: Tue, 19 May 2026 16:49:28 -0700 Subject: [PATCH 4/9] More skin changes Added armor skin layer to HumanoidModel.cpp and HumanoidModel.h and adjusted skin box code to handle new armor layer. Added SkinOffsets.h with SKIN_OFFSET type. Added code to DLCManager.cpp, DLCManager.h, DLCSkinFile.cpp, and DLCSkinFile.h to read skin offsets from DLC skin packs (Does not affect skin yet). Changed Steve skins back to their original 64x32 size for parity with official LCE. Removed some redundant code. --- Minecraft.Client/Common/DLC/DLCManager.cpp | 1 + Minecraft.Client/Common/DLC/DLCManager.h | 1 + Minecraft.Client/Common/DLC/DLCSkinFile.cpp | 205 +++++ Minecraft.Client/Common/DLC/DLCSkinFile.h | 3 + .../Common/res/1_2_2/mob/char.png | Bin 1643 -> 1360 bytes .../Common/res/1_2_2/mob/char1.png | Bin 2483 -> 1755 bytes .../Common/res/1_2_2/mob/char2.png | Bin 4220 -> 4339 bytes .../Common/res/1_2_2/mob/char3.png | Bin 4148 -> 4234 bytes .../Common/res/1_2_2/mob/char4.png | Bin 4419 -> 4647 bytes .../Common/res/1_2_2/mob/char5.png | Bin 4166 -> 4251 bytes .../Common/res/1_2_2/mob/char6.png | Bin 4630 -> 4541 bytes .../Common/res/1_2_2/mob/char7.png | Bin 3428 -> 5068 bytes Minecraft.Client/Common/res/mob/char.png | Bin 1643 -> 1360 bytes Minecraft.Client/Common/res/mob/char1.png | Bin 2483 -> 1755 bytes Minecraft.Client/Common/res/mob/char2.png | Bin 4220 -> 4339 bytes Minecraft.Client/Common/res/mob/char3.png | Bin 4148 -> 4234 bytes Minecraft.Client/Common/res/mob/char4.png | Bin 4419 -> 4647 bytes Minecraft.Client/Common/res/mob/char5.png | Bin 4166 -> 4251 bytes Minecraft.Client/Common/res/mob/char6.png | Bin 4630 -> 4541 bytes Minecraft.Client/Common/res/mob/char7.png | Bin 3428 -> 5068 bytes Minecraft.Client/HumanoidModel.cpp | 764 ++++++++---------- Minecraft.Client/HumanoidModel.h | 9 +- Minecraft.Client/LivingEntityRenderer.cpp | 2 +- Minecraft.Client/PlayerRenderer.cpp | 13 +- Minecraft.Client/SkinBox.h | 12 + Minecraft.Client/SkinOffset.h | 48 ++ Minecraft.Client/VillagerZombieModel.cpp | 4 +- Minecraft.World/Player.cpp | 1 - 28 files changed, 630 insertions(+), 433 deletions(-) create mode 100644 Minecraft.Client/SkinOffset.h diff --git a/Minecraft.Client/Common/DLC/DLCManager.cpp b/Minecraft.Client/Common/DLC/DLCManager.cpp index 8f35b1d1..01196b25 100644 --- a/Minecraft.Client/Common/DLC/DLCManager.cpp +++ b/Minecraft.Client/Common/DLC/DLCManager.cpp @@ -24,6 +24,7 @@ const WCHAR *DLCManager::wchTypeNamesA[]= L"ENCHANTTEXTFOCUSCOLOUR", L"DATAPATH", L"PACKVERSION", + L"OFFSET", }; DLCManager::DLCManager() diff --git a/Minecraft.Client/Common/DLC/DLCManager.h b/Minecraft.Client/Common/DLC/DLCManager.h index f114bd07..a51160d7 100644 --- a/Minecraft.Client/Common/DLC/DLCManager.h +++ b/Minecraft.Client/Common/DLC/DLCManager.h @@ -45,6 +45,7 @@ public: e_DLCParamType_EnchantmentTextFocusColour, e_DLCParamType_DataPath, e_DLCParamType_PackVersion, + e_DLCParamType_Offset, e_DLCParamType_Max, diff --git a/Minecraft.Client/Common/DLC/DLCSkinFile.cpp b/Minecraft.Client/Common/DLC/DLCSkinFile.cpp index 4723392e..17004313 100644 --- a/Minecraft.Client/Common/DLC/DLCSkinFile.cpp +++ b/Minecraft.Client/Common/DLC/DLCSkinFile.cpp @@ -160,11 +160,216 @@ void DLCSkinFile::addParameter(DLCManager::EDLCParameterType type, const wstring { pSkinBox->ePart=eBodyPart_Leg1; } + else if(wcscmp(wchBodyPart,L"HEADWEAR")==0) + { + pSkinBox->ePart=eBodyPart_Headwear; + } + else if(wcscmp(wchBodyPart,L"JACKET")==0) + { + pSkinBox->ePart=eBodyPart_Jacket; + } + else if(wcscmp(wchBodyPart,L"SLEEVE0")==0) + { + pSkinBox->ePart=eBodyPart_Sleeve0; + } + else if(wcscmp(wchBodyPart,L"SLEEVE1")==0) + { + pSkinBox->ePart=eBodyPart_Sleeve1; + } + else if(wcscmp(wchBodyPart,L"PANTS0")==0) + { + pSkinBox->ePart=eBodyPart_Pants0; + } + else if(wcscmp(wchBodyPart,L"PANTS1")==0) + { + pSkinBox->ePart=eBodyPart_Pants1; + } + else if(wcscmp(wchBodyPart,L"WAIST")==0) + { + pSkinBox->ePart=eBodyPart_Waist; + } + else if(wcscmp(wchBodyPart,L"LEGGING0")==0) + { + pSkinBox->ePart=eBodyPart_Legging0; + } + else if(wcscmp(wchBodyPart,L"LEGGING1")==0) + { + pSkinBox->ePart=eBodyPart_Legging1; + } + else if(wcscmp(wchBodyPart,L"SOCK0")==0) + { + pSkinBox->ePart=eBodyPart_Sock0; + } + else if(wcscmp(wchBodyPart,L"SOCK1")==0) + { + pSkinBox->ePart=eBodyPart_Sock1; + } + else if(wcscmp(wchBodyPart,L"BOOT0")==0) + { + pSkinBox->ePart=eBodyPart_Boot0; + } + else if(wcscmp(wchBodyPart,L"BOOT1")==0) + { + pSkinBox->ePart=eBodyPart_Boot1; + } + else if(wcscmp(wchBodyPart,L"ARMARMOR0")==0) + { + pSkinBox->ePart=eBodyPart_ArmArmor0; + } + else if(wcscmp(wchBodyPart,L"ARMARMOR1")==0) + { + pSkinBox->ePart=eBodyPart_ArmArmor1; + } + else if(wcscmp(wchBodyPart,L"BODYARMOR")==0) + { + pSkinBox->ePart=eBodyPart_BodyArmor; + } + else if(wcscmp(wchBodyPart,L"BELT")==0) + { + pSkinBox->ePart=eBodyPart_Belt; + } // add this to the skin's vector of parts m_AdditionalBoxes.push_back(pSkinBox); } break; + case DLCManager::e_DLCParamType_Offset: + { + WCHAR wchBodyPart[10]; + wchar_t wchDirection[2]; + SKIN_OFFSET *pSkinOffset = new SKIN_OFFSET; + ZeroMemory(pSkinOffset,sizeof(SKIN_OFFSET)); + +#ifdef __PS3__ + // 4J Stu - The Xbox version used swscanf_s which isn't available in GCC. + swscanf(value.c_str(), L"%10ls%2ls%f", wchBodyPart, +#else + swscanf_s(value.c_str(), L"%9ls%2ls%f", wchBodyPart,10, wchDirection,2, +#endif + &pSkinOffset->fO); + + if(wcscmp(wchDirection,L"X")==0) + { + pSkinOffset->fD=eOffsetDirection_X; + } + else if (wcscmp(wchDirection,L"Y")==0) + { + pSkinOffset->fD=eOffsetDirection_Y; + } + else if(wcscmp(wchDirection,L"Z")==0) + { + pSkinOffset->fD=eOffsetDirection_Z; + } + + if(wcscmp(wchBodyPart,L"HEAD")==0) + { + pSkinOffset->ePart=eBodyOffset_Head; + } + else if(wcscmp(wchBodyPart,L"BODY")==0) + { + pSkinOffset->ePart=eBodyOffset_Body; + } + else if(wcscmp(wchBodyPart,L"ARM0")==0) + { + pSkinOffset->ePart=eBodyOffset_Arm0; + } + else if(wcscmp(wchBodyPart,L"ARM1")==0) + { + pSkinOffset->ePart=eBodyOffset_Arm1; + } + else if(wcscmp(wchBodyPart,L"LEG0")==0) + { + pSkinOffset->ePart=eBodyOffset_Leg0; + } + else if(wcscmp(wchBodyPart,L"LEG1")==0) + { + pSkinOffset->ePart=eBodyOffset_Leg1; + } + else if(wcscmp(wchBodyPart,L"HEADWEAR")==0) + { + pSkinOffset->ePart=eBodyOffset_Headwear; + } + else if(wcscmp(wchBodyPart,L"JACKET")==0) + { + pSkinOffset->ePart=eBodyOffset_Jacket; + } + else if(wcscmp(wchBodyPart,L"SLEEVE0")==0) + { + pSkinOffset->ePart=eBodyOffset_Sleeve0; + } + else if(wcscmp(wchBodyPart,L"SLEEVE1")==0) + { + pSkinOffset->ePart=eBodyOffset_Sleeve1; + } + else if(wcscmp(wchBodyPart,L"PANTS0")==0) + { + pSkinOffset->ePart=eBodyOffset_Pants0; + } + else if(wcscmp(wchBodyPart,L"PANTS1")==0) + { + pSkinOffset->ePart=eBodyOffset_Pants1; + } + else if(wcscmp(wchBodyPart,L"HELMET")==0) + { + pSkinOffset->ePart=eBodyOffset_Helmet; + } + else if(wcscmp(wchBodyPart,L"WAIST")==0) + { + pSkinOffset->ePart=eBodyOffset_Waist; + } + else if(wcscmp(wchBodyPart,L"LEGGING0")==0) + { + pSkinOffset->ePart=eBodyOffset_Legging0; + } + else if(wcscmp(wchBodyPart,L"LEGGING1")==0) + { + pSkinOffset->ePart=eBodyOffset_Legging1; + } + else if(wcscmp(wchBodyPart,L"SOCK0")==0) + { + pSkinOffset->ePart=eBodyOffset_Sock0; + } + else if(wcscmp(wchBodyPart,L"SOCK1")==0) + { + pSkinOffset->ePart=eBodyOffset_Sock1; + } + else if(wcscmp(wchBodyPart,L"BOOT0")==0) + { + pSkinOffset->ePart=eBodyOffset_Boot0; + } + else if(wcscmp(wchBodyPart,L"BOOT1")==0) + { + pSkinOffset->ePart=eBodyOffset_Boot1; + } + else if(wcscmp(wchBodyPart,L"ARMARMOR1")==0) + { + pSkinOffset->ePart=eBodyOffset_ArmArmor1; + } + else if(wcscmp(wchBodyPart,L"ARMARMOR0")==0) + { + pSkinOffset->ePart=eBodyOffset_ArmArmor0; + } + else if(wcscmp(wchBodyPart,L"BODYARMOR")==0) + { + pSkinOffset->ePart=eBodyOffset_BodyArmor; + } + else if(wcscmp(wchBodyPart,L"BELT")==0) + { + pSkinOffset->ePart=eBodyOffset_Belt; + } + else if(wcscmp(wchBodyPart,L"TOOL0")==0) + { + pSkinOffset->ePart=eBodyOffset_Tool0; + } + else if(wcscmp(wchBodyPart,L"TOOL1")==0) + { + pSkinOffset->ePart=eBodyOffset_Tool1; + } + + // add this to the skin's vector of offsets + m_Offsets.push_back(pSkinOffset); + } + break; case DLCManager::e_DLCParamType_Anim: #ifdef __PS3__ // 4J Stu - The Xbox version used swscanf_s which isn't available in GCC. diff --git a/Minecraft.Client/Common/DLC/DLCSkinFile.h b/Minecraft.Client/Common/DLC/DLCSkinFile.h index eb9f70be..810e883f 100644 --- a/Minecraft.Client/Common/DLC/DLCSkinFile.h +++ b/Minecraft.Client/Common/DLC/DLCSkinFile.h @@ -13,6 +13,7 @@ private: unsigned int m_uiAnimOverrideBitmask; bool m_bIsFree; vector m_AdditionalBoxes; + vector m_Offsets; _SkinAdjustments m_skinAdjustments; public: @@ -26,6 +27,8 @@ public: bool getParameterAsBool(DLCManager::EDLCParameterType type) override; vector *getAdditionalBoxes(); int getAdditionalBoxesCount(); + vector *getOffsets(); + int getOffsetsCount(); unsigned int getAnimOverrideBitmask() { return m_uiAnimOverrideBitmask;} bool isFree() {return m_bIsFree;} }; \ No newline at end of file diff --git a/Minecraft.Client/Common/res/1_2_2/mob/char.png b/Minecraft.Client/Common/res/1_2_2/mob/char.png index e05dbe6976d2482c8a0d4e65ace90ac6c9f95a9e..7cfa08a869366adf395cc443c14a5f59ecfb92d3 100644 GIT binary patch delta 1354 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 diff --git a/Minecraft.Client/Common/res/1_2_2/mob/char1.png b/Minecraft.Client/Common/res/1_2_2/mob/char1.png index 32257c5bf8eb4e30e9a2531e86d9ac80adf2c414..41576e6333bbbdf77a7e50c8ca3f8f8bc386b44a 100644 GIT binary patch delta 1752 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 HuZRBy;dpdF diff --git a/Minecraft.Client/Common/res/1_2_2/mob/char2.png b/Minecraft.Client/Common/res/1_2_2/mob/char2.png index 9c320cbc2c790c1cf2d39f0ab389f80fd977495a..b921f856e549603e96f28f02e77d087b9b71a6f6 100644 GIT binary patch literal 4339 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 diff --git a/Minecraft.Client/Common/res/1_2_2/mob/char3.png b/Minecraft.Client/Common/res/1_2_2/mob/char3.png index d45682fc9dd4c686913818348e87de66c231eee8..c7a39868be4faac00a0394ffcae3e7d9efae6ffa 100644 GIT binary patch literal 4234 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 literal 4148 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 diff --git a/Minecraft.Client/Common/res/1_2_2/mob/char4.png b/Minecraft.Client/Common/res/1_2_2/mob/char4.png index 00dad3d5e1f07285ea99324a392f34b7620f2bfc..25dcfec4a20c5fa65894c1fa9b3cc5d3ea764897 100644 GIT binary patch literal 4647 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 literal 4419 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 xfup#s=^TJpo}rLwrB|sV01rHVxF;37Ht3k literal 4166 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 E3wI{sVgLXD diff --git a/Minecraft.Client/Common/res/1_2_2/mob/char6.png b/Minecraft.Client/Common/res/1_2_2/mob/char6.png index d28abf783c546bf6800a64e6b0ca8c3896907aea..74a71c4f480fff730235859225a2f5a018f91e8e 100644 GIT binary patch literal 4541 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 b_MZU&_-;1=V3U&P00000NkvXXu0mjffVrCr literal 4630 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 Peb;(qqYI7aon!wC;H)xl diff --git a/Minecraft.Client/Common/res/1_2_2/mob/char7.png b/Minecraft.Client/Common/res/1_2_2/mob/char7.png index 974403c24a5aabd66c58774689dc81def93915aa..216cc6d148634a491f258bb8faab290daca298b2 100644 GIT binary patch literal 5068 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 N(A6~1C|9$K`X841X;J_H diff --git a/Minecraft.Client/Common/res/mob/char.png b/Minecraft.Client/Common/res/mob/char.png index e05dbe6976d2482c8a0d4e65ace90ac6c9f95a9e..7cfa08a869366adf395cc443c14a5f59ecfb92d3 100644 GIT binary patch delta 1354 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 diff --git a/Minecraft.Client/Common/res/mob/char1.png b/Minecraft.Client/Common/res/mob/char1.png index 32257c5bf8eb4e30e9a2531e86d9ac80adf2c414..41576e6333bbbdf77a7e50c8ca3f8f8bc386b44a 100644 GIT binary patch delta 1752 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 HuZRBy;dpdF diff --git a/Minecraft.Client/Common/res/mob/char2.png b/Minecraft.Client/Common/res/mob/char2.png index 9c320cbc2c790c1cf2d39f0ab389f80fd977495a..b921f856e549603e96f28f02e77d087b9b71a6f6 100644 GIT binary patch literal 4339 zcmVKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z000IaNklmu1zcLh z1;nM?5LDs_QZI-@g@k(J0BRvEMFNf>Ar2Iok_d&mij%milj7j@#_Qdk_m9KwjAz#C zjU5~u=Si!Xo!{^Gc7Ff9zwcYY9oEODMm#{GHBlIn-UH}Xz%%F0477jo4{r&MaCz?s z%H@7GNwlUC$Aq$|9+oTsjkaK7ILxjS!y(6Isr@Kb;uwIY)~F!ptMl^TH##?~oy${G zBUEC4-v>bMC;I@}Ih=CYdX8p#E z?FR<~jJ1@*ki=S=TGQSZjE@yfpPCx!hrtg<00Jp#cCi2;9`fie9&|v`AKMlXkDeOx z0M3ID0x1OLSfOp&BNpR82}#=;jIl^52~~ji5Ok+P7(laaaNgs+M~W0T0tWGjYqiEb z#0DPk-VSORWswXxn(R*F_)Xc|u-CDxcdc|?jQ zy*%PbTR;VhB(Wen4)|^$+KIzCkCcKJzx^z67*Q^b(rnZrkZjy|j~`w5J&k69HVzdC ze79Y!b2uxAq5$XpzIeouO#x#KQcB`Lbza^YJWz@hQ55onXTOTmf?FF~ti6AWm9_VA z+EKe*=bN8?oG1z@MG6mCYY4h~bw;MS?|DRL3<`^OhQv6u@jUm$V?6)lIVw@WP#p8w z@Bf6K{_=N}bi(NqALNHGzrr_OdV|sGhp0pW&p&yN=bm^BZG2}BXF%9v!6Pyd#0NO% zh@yzEd~$||M#ib@7S-|yCmx(WSM$Hv$eI&#BfM;e4HSz@aKPB<*#qApq)Vl3g>-+M_A`F9&tYeKz;4(BLGy# z$62q{@V1RH78S*Kp;=kGiF1zX#25f=oluTTY&9)yo!|wiC?*U;tZj3C_7snwIf*ld z^;!*pjV;aV7nch>;xmuVFfknRz1265wgq}0%*=kc5VBHS1gguIFAvPv?EFXlm*=9s zvRAJpY}GdhzRWpUR$;ILMseebGT z8L&zynxg2$Z5!Di;)5t!5?z z3UXsKDk|-awIrcbF7w7~zXIUm&%Vpb%{rfZ;Uxf`{=%2Awn%@2AV7#6ULb@h^sX_w zuf7lh@BJ=$7#8v8+LgD(9RrZ^_k#wYGw1{I_G|B6V`}CMzq#;ALGANje1_{Q%bc7% zT{thqrE=zUKk#a|nmf)bMHohS?-4@aoW)vO`2B+hK;}2Uo7H>xnVy|z_3AqSEG{mx zxVQ+w^_69&XXkh6_j5k~y!X9Q=kp}%NI}p!*I|C$7RYB{X=!PozRR5qowG<8;JwFt zx2JR7JA?=_oBzvSVu4aw=8VyWkCYOZJLouPnLIt0Wj?KhSLf!k7tZSsn$`I#$X7zD zpJGR^{C^HW>fBys-kZ_kPWC$r6=aDGjmo-2&F zUj2Nj`+ZV}!^Qx$ZzuQLQ+t3{KPU71=I!$LfBVZHGd*hz*4oT*DFcEaD9E)=4ii$QSg$wu){lR_zY5sP!AqA02d1^Xl@TRt43*)LzMxvJj23M2 z#482d($J1=vr+GhMVaGWC)2>B*LyMs4}=GMfNHZ*-{pK>u2e{C`*x?4b+XI()VcL~ hqY#8%`9arz2LJ8FboYNA)tbEHzM7F5(6qRB1lOoNQ@WMe_DVK3)TX9jqW}PaT31KY6wj*vfQ%5Yi(fw2 z#S;-i?XDUCw5CR0m}KI89#xWX4bPz8XfFaX$j3;@bs0f2QZNI4+{ z04OAp8XCsB8X7#tf&LyyA9n!I!4>C(n48ZtB~D;N!plEM5tu$)?s*MNM`Sv{o%2|o zgb8V2vaP%o1Q57p0iTZXAZE%~z*4gn%wXO^DnKSI%>p+U_t%JE_T9}8OW%X%*`dy2c^BIKa5i@+JU5-pmqTah|38h0vK3obvw31kby@=KO~g! z1`;?Dfeyp1dkF$QPQoyTq}Qd-Y<40aZ07-x!gfVgaR_sgf}nmHv~%K79$T)s2aBLb zpRgKaG+EI(o%;5Lcw1%Or&{ICq#?!XcC$||`;0$34S2N&lbVw#VO>SykQKUCtw&PX zV(aqj3+6O1LV!WnhdIDHnNJQPoy<+Q$+!L$Sk)nSyuV~6zUoFfm>a08Kd}}>Pe+X6 z%z=KH`COp(d(*8dfQVoK5E9EDL435IHvO32%KOrS-n0Wey~FK!%R_g!alPvA?{z4S4d^0+~1`IXS4%BKP}5;xi|wLW7o1No3TIhdACJ#5mWhD9{4t~|Vk^$(X4d2wQsYTTr~Cso12=)~nW zWCpRdEp!dU>;qKzc@H#JEdmI7NyZZ>S2+U&mjLdBTdT*1H_zmhDelC517pAtwu(nA zd{l$PKea2;LgSw{Xg^A$cm_hkyVGxP3duYgn==mxY_io4D54%xKH9HYUw!FP32^A=^YKrf#tP13&ebm68?yl{Y4vrCF$`D^ptE zhPv=c>*jUj(T&|UVBg~K0K-!A2V7c@tfLw@=eS1)DOwU1M0ZVgZFa$Ef(sJu!P?ca zfc;m(9JIMl>tA!eDSkt}CUl=NRHRpEndIOpVk79V>P#zA{;yIrLBDF6kSF~v8E?G6 zTOoD9^6Y^0L(E}@jzArxG5LWe^ge%UM(C5!d!3JVUv91 zM+VF^R766AS>*Xlcr9CPrYXN^&@=mXyzC*XeKW+7_+O0*#R>n`pC!ZicPKMcS zScD8-ysqwSB4@^iFQhl8vMBrxzgxj%)?Z0ujBs~%%N=<*;xRh+t|W)EidR;mfLS8J zQty@_`*ZBQiWh@Oa>U4~V59!SoUu`f?4YcTcZ?$)BVTeNZW!f;WE$nH2(E}+8-uFK zs=+mBRV|Kd6>rB(znd;rHB`a%pGsn@$;7^kkcc!{DAz1BD^x#g*euU#GOt3ZA+_?K z@75GOvuldf3bRe9aA|&PA!4Oif0PB)52>i06x+d`*jT_Vj4aB%u-`G?V+%TMYi#>$ z3qNZF$0}*4IAHCt+EJDo@Bt%!qe}QjiI78Pd45foRl8A;gZ@1+JMVhS>bb1WqRw1& z6Z-KfA!l1^+&Eh?N%6gI7W;>OZTq*su!pylBsf$!q$~$VS+AIu*7qC5Oai`6zOP}P zQY_K}tV*mNY@IBrtW!@SQ;t%UQcBppS+rRXWcFcyJzbnLT&6t(SImcJ7G+mnES`kG zRA4zaDW4>Q+PZqqNsgh%%%dl{_jC3f(YRQbHAL%d1#UgADqC=+Z8q?;-hk*_-JDmv znmdt{9!qZH)ZF+SdxMcpe@E*J$O6a9^AB^Aa-U9<_GSY2z7~B=8O80*?B=0=p({^O z7uFYqrl!$rP(F=rF%;V6>;Uc@SU9>jnDaP4sef&lOk0q}`i)Q#-Vm*vpWMJ5-Z2*7S$2JVH`DEkcL7X-H!SV@D}L z1)(#Y!yn*pY13&J$TpIKA@h8Ud|m1GCJQw!HP36h zvi-z6s>g!)OSf{C})1p*vh=hq!o)hlOk_WDXAF)Yk4T8n7K;+=sgtckTVk6H8~W@w>^@r7TlZkm z(cBR$lhL@V#$dhRq2L3W0NSP6-!%uGlU_9nNs4)4hq|uTt}8E}_!ky36g(=t&9TnO zrow@G_3~3)*Ll)<`ZUuk_<~H7?4RwF1H1koUN?Oj{VO{dxe0OcxRPk@i>t%?r5h?Y zSZ>(HOkS3E7Ee3OfPyzsV`w3CDjJTaE;+gV>7(!Bm%o)$PZJGmOX?IQBDzng)(qa{ z8zF)w#*6ju$OqkCy9_lln7E>ZF#G)?Ii;~X=?Xp1xTvCxGK@kD%d3w{~xtg_!O4y~+*qU;8^ux=jkFt>Us&HjSJ)Y~P>ot<0&c#@XTiaFgEYyED!f zbE-cqd2oZGB(2okpw2+fDF1G80lKvBC+h3RWW>${lLtji_TP@vuJL2;=%CBS7&#a8 zI`Q>T^@_g3`+nsUuTS+QU6?NIW-~|0F=lLfOwgIchVM$xVMr#W%|Yvd*q!a@?Z4Z{ zKi^c(7?u7dCd@m&^cPyfe=9*ZjSbAFNV$_UV@i89<4Wfo+i662y3W~bt3p?s0- z*OQ7G%!%!JjOs~6*P-oTg7m^{G~%4JP(HevD9^Td|9XsHVW2}-GO7S+D9A?5&rFeE ztz6)$ttiZReSNJa#MK^w6z8IgHI>bB)OcuntH4#KHNveUHmEnrugps?#!SvxL#oir zB+peV)d7xHmrHR_#hBeHKw4(wiUMSKhZtZ3 z5d$E+rH2Rm|Jna6C&D1Yf8zvrTN*?FK=5pf2Qrc9-?$In{zsTtLBKYChxvd0@_ z?~q0c5aDyBWMERDvj6RSef@7aFi&gsVyv878vqD3bv4z@t+n@ZkY|bA#7iUZG=)HQIIF1VKZ`j?A68A-WFkgwp zr#(n>UJ_-i%{zBEmCvQY`ya%U?BchUX4E>lkQt+1=8s! zSlT6YDol+c1WcmS&jc<7b9iw~_roQB5Bx~&#xtEtJ!GMJNV!*_N0Z34`m(rmg{ zhf?50>Mdo{U^{jIZof@p|Bkbxxb-J_b@=b)D^gl+6|~SWjw52mBDkC##jC9NbsZG) zIbvNU>hyBxF){?`G0U``P4JsckQ$bB#6};Vj*RX0d~1g-FUmJNVh363yC$YC9p=l-E-)LqIoFF9A%14pNT?XVH(ZhES)mTV%0+6u6t2Madg~ z5@h(AtR)E43YIonBNEB=9#?Qy#QbbG1k1(=KjMSnq+O92&-!gRaIGlV_{2LkaJ&hF zIurooTHk@NWB9hfXUqi*7Km6)OhPdHP0urvlS7rBzEA5a^IpW@N1Ao;ej>G0lom-r`JFMPxKO zti&jlCBZ{7_OSk{%_TK6)RS8Yqu+S^5jadtUfg)t8XX3&UUaF}QkG3n26AD#$|QQ) xs}Bx9+djXe7yTnXSpa=2<1&(BTXE3Wj=z6J-+bNhy7r&fr3*LIY*KfM{U3_AtKR?s diff --git a/Minecraft.Client/Common/res/mob/char3.png b/Minecraft.Client/Common/res/mob/char3.png index d45682fc9dd4c686913818348e87de66c231eee8..c7a39868be4faac00a0394ffcae3e7d9efae6ffa 100644 GIT binary patch literal 4234 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 literal 4148 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 diff --git a/Minecraft.Client/Common/res/mob/char4.png b/Minecraft.Client/Common/res/mob/char4.png index 00dad3d5e1f07285ea99324a392f34b7620f2bfc..25dcfec4a20c5fa65894c1fa9b3cc5d3ea764897 100644 GIT binary patch literal 4647 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 literal 4419 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 xfup#s=^TJpo}rLwrB|sV01rHVxF;37Ht3k literal 4166 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 E3wI{sVgLXD diff --git a/Minecraft.Client/Common/res/mob/char6.png b/Minecraft.Client/Common/res/mob/char6.png index d28abf783c546bf6800a64e6b0ca8c3896907aea..74a71c4f480fff730235859225a2f5a018f91e8e 100644 GIT binary patch literal 4541 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 b_MZU&_-;1=V3U&P00000NkvXXu0mjffVrCr literal 4630 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 Peb;(qqYI7aon!wC;H)xl diff --git a/Minecraft.Client/Common/res/mob/char7.png b/Minecraft.Client/Common/res/mob/char7.png index 974403c24a5aabd66c58774689dc81def93915aa..216cc6d148634a491f258bb8faab290daca298b2 100644 GIT binary patch literal 5068 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 N(A6~1C|9$K`X841X;J_H diff --git a/Minecraft.Client/HumanoidModel.cpp b/Minecraft.Client/HumanoidModel.cpp index d6de0915..57bbc646 100644 --- a/Minecraft.Client/HumanoidModel.cpp +++ b/Minecraft.Client/HumanoidModel.cpp @@ -51,6 +51,42 @@ ModelPart * HumanoidModel::AddOrRetrievePart(SKIN_BOX *pBox) pAttachTo=pants1; scale=0.25; break; + case eBodyPart_Headwear: + pAttachTo=hair; + 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 then add it @@ -84,7 +120,7 @@ ModelPart * HumanoidModel::AddOrRetrievePart(SKIN_BOX *pBox) return pNewBox; } -void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, bool slimHands, bool mirror, bool force32, bool isArmor) +void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, bool slim, bool isArmor) { this->texWidth = texWidth; this->texHeight = texHeight; @@ -95,6 +131,18 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b 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); cloak->addHumanoidBox(-5, -0, -1, 10, 16, 1, g); // Cloak @@ -121,18 +169,11 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b hair->addHumanoidBox(-4, -8, -4, 8, 8, 8, g + 0.5f); // Head hair->setPos(0, 0 + yOffset, 0); - if ((texWidth == 64 && texHeight == 64) && !force32) - { - jacket = new ModelPart(this, 16, 32); - jacket->addHumanoidBox(-4, 0, -2, 8, 12, 4, g + 0.25); - jacket->setPos(0, 0 + yOffset, 0); - } - body = new ModelPart(this, 16, 16); body->addHumanoidBox(-4, 0, -2, 8, 12, 4, g); // Body body->setPos(0, 0 + yOffset, 0); - if ((texWidth == 64 && texHeight == 64) && !force32) + if (texHeight == 64) { arm0 = new ModelPart(this, 24 + 16, 16); arm1 = new ModelPart(this, 16 + 16, 48); @@ -140,60 +181,96 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b sleeve0 = new ModelPart(this, 24 + 16, 32); sleeve1 = new ModelPart(this, 32 + 16, 48); - if (slimHands == false) + if (!slim) { - sleeve0->addHumanoidBox(-3, -2, -2, 4, 12, 4, g + 0.25); - sleeve1->addHumanoidBox(-1, -2, -2, 4, 12, 4, g + 0.25); + sleeve0->addHumanoidBox(-3, -2, -2, 4, 12, 4, g + 0.25); // Sleeve0 + sleeve1->addHumanoidBox(-1, -2, -2, 4, 12, 4, g + 0.25); // Sleeve1 } - else if (slimHands == true) + else if (slim) { - sleeve0->addHumanoidBox(-2, -2, -2, 3, 12, 4, g + 0.25); - sleeve1->addHumanoidBox(-1, -2, -2, 3, 12, 4, g + 0.25); + sleeve0->addHumanoidBox(-2, -2, -2, 3, 12, 4, g + 0.25); // Sleeve0 Slim + sleeve1->addHumanoidBox(-1, -2, -2, 3, 12, 4, g + 0.25); // Sleeve1 Slim } + jacket = new ModelPart(this, 16, 32); + jacket->addHumanoidBox(-4, 0, -2, 8, 12, 4, g + 0.25); + jacket->setPos(0, 0 + yOffset, 0); + sleeve0->setPos(-5, 2 + yOffset, 0); sleeve1->setPos(5, 2 + 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); } - else if ((texWidth == 64 && texHeight == 32) || force32) + else if (texHeight == 32) { arm0 = new ModelPart(this, 24 + 16, 16); arm1 = new ModelPart(this, 24 + 16, 16); - } - - if (slimHands == false) - { - arm0->addHumanoidBox(-3, -2, -2, 4, 12, 4, g); - arm1->addHumanoidBox(-1, -2, -2, 4, 12, 4, g); - } - else if (slimHands == true) - { - arm0->addHumanoidBox(-2, -2, -2, 3, 12, 4, g); - arm1->addHumanoidBox(-1, -2, -2, 3, 12, 4, g); - } - - arm0->setPos(-5, 2 + yOffset, 0); - arm1->setPos(5, 2 + yOffset, 0); - - if (mirror == true) arm1->bMirror = true; + } - if ((texWidth == 64 && texHeight == 64) && !force32) + if (!slim) + { + arm0->addHumanoidBox(-3, -2, -2, 4, 12, 4, g); // Arm0 + arm1->addHumanoidBox(-1, -2, -2, 4, 12, 4, g); // Arm1 + } + else if (slim) + { + arm0->addHumanoidBox(-2, -2, -2, 3, 12, 4, g); // Arm0 Slim + arm1->addHumanoidBox(-1, -2, -2, 3, 12, 4, g); // Arm1 Slim + } + + arm0->setPos(-5, 2 + yOffset, 0); + arm1->setPos(5, 2 + yOffset, 0); + + leg0 = new ModelPart(this, 0, 16); + if (texHeight == 64) { - leg0 = new ModelPart(this, 0, 16); leg1 = new ModelPart(this, 16, 48); pants0 = new ModelPart(this, 0, 32); - pants0->addHumanoidBox(-2, 0, -2, 4, 12, 4, g + 0.25); + pants0->addHumanoidBox(-2, 0, -2, 4, 12, 4, g + 0.25); // Pants0 pants0->setPos(-1.9, 12 + yOffset, 0); pants1 = new ModelPart(this, 0, 48); - pants1->addHumanoidBox(-2, 0, -2, 4, 12, 4, g + 0.25); + pants1->addHumanoidBox(-2, 0, -2, 4, 12, 4, g + 0.25); // Pants1 pants1->setPos(1.9, 12 + yOffset, 0); } - else if ((texWidth == 64 && texHeight == 32) || force32) + else if (texHeight == 32) { - leg0 = new ModelPart(this, 0, 16); leg1 = new ModelPart(this, 0, 16); + leg1->bMirror = true; } leg0->addHumanoidBox(-2, 0, -2, 4, 12, 4, g); // Leg0 @@ -202,9 +279,6 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b leg1->addHumanoidBox(-2, 0, -2, 4, 12, 4, g); // Leg1 leg1->setPos(1.9, 12 + yOffset, 0); - if (mirror == true) - leg1->bMirror = true; - // 4J added - compile now to avoid random performance hit first time cubes are rendered // 4J Stu - Not just performance, but alpha+depth tests don't work right unless we compile here cloak->compile(1.0f/16.0f); @@ -219,7 +293,7 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b leg1->compile(1.0f/16.0f); hair->compile(1.0f/16.0f); - if (jacket != 0) + if (jacket) jacket->compile(1.0f/16.0f); if (sleeve0 != 0) sleeve0->compile(1.0f/16.0f); @@ -229,6 +303,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; @@ -239,7 +335,6 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b elytraCrouching = false; m_isArmor = isArmor; - // 4J added eating = false; eating_t = 0.0f; @@ -250,37 +345,27 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b HumanoidModel::HumanoidModel() : Model() { - _init(0, 0, 64, 32, false, true, false, false); + _init(0, 0, 64, 32, false, false); } HumanoidModel::HumanoidModel(float g) : Model() { - _init(g, 0, 64, 32, false, true, false, false); + _init(g, 0, 64, 32, false, false); } HumanoidModel::HumanoidModel(float g, bool isArmor) : Model() { - _init(g, 0, 64, 32, false, true, false, isArmor); + _init(g, 0, 64, 32, false, isArmor); } HumanoidModel::HumanoidModel(float g, float yOffset, int texWidth, int texHeight) : Model() { - _init(g,yOffset,texWidth,texHeight, false, true, false, false); + _init(g, yOffset, texWidth, texHeight, false, false); } -HumanoidModel::HumanoidModel(float g, float yOffset, int texWidth, int texHeight, bool slimHands) : Model() +HumanoidModel::HumanoidModel(float g, float yOffset, int texWidth, int texHeight, bool slim) : Model() { - _init(g,yOffset,texWidth,texHeight, slimHands, true, false, false); -} - -HumanoidModel::HumanoidModel(float g, float yOffset, int texWidth, int texHeight, bool slimHands, bool mirror) : Model() -{ - _init(g,yOffset,texWidth,texHeight, slimHands, mirror, false, false); -} - -HumanoidModel::HumanoidModel(float g, float yOffset, int texWidth, int texHeight, bool slimHands, bool mirror, bool force32) : Model() -{ - _init(g,yOffset,texWidth,texHeight, slimHands, mirror, force32, false); + _init(g, yOffset, texWidth, texHeight, slim, false); } void HumanoidModel::render(shared_ptr entity, float time, float r, float bob, float yRot, float xRot, float scale, bool usecompiled) @@ -343,6 +428,28 @@ void HumanoidModel::render(shared_ptr entity, float time, float r, float pants0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); if (pants1) pants1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); + if (waist != 0) + waist->render(scale, usecompiled); + if (belt) + belt->render(scale, usecompiled); + if (bodyArmor) + bodyArmor->render(scale, usecompiled); + if (armArmor0) + armArmor0->render(scale, usecompiled); + if (armArmor1) + armArmor1->render(scale, usecompiled); + if (legging0) + legging0->render(scale, usecompiled); + if (legging1) + legging1->render(scale, usecompiled); + if (sock0) + sock0->render(scale, usecompiled); + if (sock1) + sock1->render(scale, usecompiled); + if (boot0) + boot0->render(scale, usecompiled); + if (boot1) + boot1->render(scale, usecompiled); } } @@ -357,9 +464,6 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float hair->xRot = head->xRot; body->z = 0.0f; - if (jacket) - jacket->z = 0.0f; - // Does the skin have an override for anim? if(uiBitmaskOverrideAnim&(1<xRot=0.0f; arm0->zRot = 0.0f; arm1->zRot = 0.0f; - - if (sleeve0) - { - sleeve0->xRot=0.0f; - sleeve0->zRot=0.0f; - } - - if (sleeve1) - { - sleeve1->xRot=0.0f; - sleeve1->zRot=0.0f; - } } else if(uiBitmaskOverrideAnim&(1<xRot=-HALF_PI; arm0->zRot = 0.0f; arm1->zRot = 0.0f; - - if (sleeve0) - { - sleeve0->xRot=-HALF_PI; - sleeve0->zRot=0.0f; - } - - if (sleeve1) - { - sleeve1->xRot=-HALF_PI; - sleeve1->zRot=0.0f; - } } else if(uiBitmaskOverrideAnim&(1<xRot = (Mth::cos(time * 0.6662f + PI) * 2.0f) * r * 0.5f; arm0->zRot = 0.0f; arm1->zRot = 0.0f; - - if (sleeve0) - { - sleeve0->xRot=(Mth::cos(time * 0.6662f + PI) * 2.0f) * r * 0.5f; - sleeve0->zRot=0.0f; - } - - if (sleeve1) - { - sleeve1->xRot=(Mth::cos(time * 0.6662f + PI) * 2.0f) * r * 0.5f; - sleeve1->zRot=0.0f; - } } // 4J-PB - Weeping Angel - does't look good holding something in the arm that's up else if((uiBitmaskOverrideAnim&(1<zRot = -0.3f; arm1->xRot = ( Mth::cos(time * 0.6662f) * 2.0f) * r * 0.5f; arm1->zRot = 0.0f; - - if (sleeve0) - { - sleeve0->xRot=-PI; - sleeve0->zRot=-0.3f; - } - - if (sleeve1) - { - sleeve1->xRot=( Mth::cos(time * 0.6662f) * 2.0f) * r * 0.5f; - sleeve1->zRot=0.0f; - } } else { @@ -445,18 +501,6 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float arm1->xRot = ( Mth::cos(time * 0.6662f) * 2.0f) * r * 0.5f; arm0->zRot = 0.0f; arm1->zRot = 0.0f; - - if (sleeve0) - { - sleeve0->xRot=(Mth::cos(time * 0.6662f + PI) * 2.0f) * r * 0.5f; - sleeve0->zRot=0.0f; - } - - if (sleeve1) - { - sleeve1->xRot=( Mth::cos(time * 0.6662f) * 2.0f) * r * 0.5f; - sleeve1->zRot=0.0f; - } } // arm0.zRot = ((float) (util.Mth.cos(time * 0.2312f) + 1) * 1) * r; @@ -467,12 +511,6 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float leg0->yRot = 0.0f; leg1->yRot = 0.0f; - if (pants0) - pants0->yRot=0.0f; - - if (pants1) - pants1->yRot=0.0f; - if (riding) { if ((uiBitmaskOverrideAnim&(1<xRot = -HALF_PI * 0.8f; leg0->yRot = HALF_PI * 0.2f; leg1->yRot = -HALF_PI * 0.2f; - - if (sleeve0) - sleeve0->xRot+=-HALF_PI * 0.4f; - - if (sleeve1) - sleeve1->xRot+=-HALF_PI * 0.4f; - - if (pants0) - { - pants0->xRot=-HALF_PI * 0.8f; - pants0->yRot=HALF_PI * 0.2f; - } - - if (pants1) - { - pants1->xRot=-HALF_PI * 0.8f; - pants1->yRot=-HALF_PI * 0.2f; - } } else { @@ -508,18 +528,6 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float arm1->xRot += -HALF_PI * 0.4f; leg0->xRot = -HALF_PI * 0.4f; leg1->xRot = -HALF_PI * 0.4f; - - if (sleeve0) - sleeve0->xRot+=-HALF_PI * 0.4f; - - if (sleeve1) - sleeve1->xRot+=-HALF_PI * 0.4f; - - if (pants0) - pants0->xRot=-HALF_PI * 0.4f; - - if (pants1) - pants1->xRot=-HALF_PI * 0.4f; } } else if(idle && !sneaking ) @@ -528,18 +536,6 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float leg1->xRot = -HALF_PI; leg0->yRot = HALF_PI * 0.2f; leg1->yRot = -HALF_PI * 0.2f; - - if (pants0) - { - pants0->xRot=-HALF_PI; - pants0->yRot=HALF_PI * 0.2f; - } - - if (pants1) - { - pants1->xRot=-HALF_PI; - pants1->yRot=-HALF_PI * 0.2f; - } } else if(uiBitmaskOverrideAnim&(1<xRot=0.0f; leg1->zRot=0.0f; leg0->yRot = 0.0f; - leg1->yRot = 0.0f; - - if (pants0) - { - pants0->xRot=0.0f; - pants0->zRot=0.0f; - pants0->yRot=0.0f; - } - - if (pants1) - { - pants1->xRot=0.0f; - pants1->zRot=0.0f; - pants1->yRot=0.0f; - } + leg1->yRot = 0.0f; } else if(uiBitmaskOverrideAnim&(1<xRot = ( Mth::cos(time * 0.6662f) * 1.4f) * r; leg1->xRot = ( Mth::cos(time * 0.6662f) * 1.4f) * r; - - if (pants0) - pants0->xRot=( Mth::cos(time * 0.6662f) * 1.4f) * r; - - if (pants1) - pants1->xRot=( Mth::cos(time * 0.6662f) * 1.4f) * r; } else { leg0->xRot = ( Mth::cos(time * 0.6662f) * 1.4f) * r; leg1->xRot = ( Mth::cos(time * 0.6662f + PI) * 1.4f) * r; - - if (pants0) - pants0->xRot=( Mth::cos(time * 0.6662f) * 1.4f) * r; - - if (pants1) - pants1->xRot=( Mth::cos(time * 0.6662f + PI) * 1.4f) * r; } if (holdingLeftHand != 0) { arm1->xRot = arm1->xRot * 0.5f - HALF_PI * 0.2f * holdingLeftHand; - - if (sleeve1) - sleeve1->xRot=sleeve1->xRot * 0.5f - HALF_PI * 0.2f * holdingLeftHand; } if (holdingRightHand != 0) { arm0->xRot = arm0->xRot * 0.5f - HALF_PI * 0.2f * holdingRightHand; - - if (sleeve0) - sleeve0->xRot=sleeve0->xRot * 0.5f - HALF_PI * 0.2f * holdingRightHand; } arm0->yRot = 0.0f; arm1->yRot = 0.0f; - if (sleeve0) - sleeve0->yRot=0.0f; - if (sleeve1) - sleeve1->yRot=0.0f; - if (attackTime > -9990.0f) { float swing = attackTime; @@ -622,20 +581,6 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float arm1->yRot += body->yRot; arm1->xRot += body->yRot; - if (sleeve0) - { - sleeve0->z=Mth::sin(body->yRot) * 5.0f; - sleeve0->x=-Mth::cos(body->yRot) * 5.0f; - sleeve0->yRot+=body->yRot; - } - if (sleeve1) - { - sleeve1->z=-Mth::sin(body->yRot) * 5.0f; - sleeve1->x=Mth::cos(body->yRot) * 5.0f; - sleeve1->yRot+=body->yRot; - sleeve1->xRot+=body->yRot; - } - swing = 1.0f - attackTime; swing *= swing; swing *= swing; @@ -643,27 +588,15 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float float aa = Mth::sin(swing * PI); float bb = Mth::sin(attackTime * PI) * -(head->xRot - 0.7f) * 0.75f; arm0->xRot -= aa * 1.2f + bb; // 4J - changed 1.2 -> 1.2f - arm0->yRot += body->yRot * 2.0f; - - if (sleeve0) - { - sleeve0->xRot -= aa * 1.2f + bb; - sleeve0->yRot += body->yRot * 2.0f; - } + arm0->yRot += body->yRot * 2.0f; if((uiBitmaskOverrideAnim&(1<zRot -= Mth::sin(attackTime * PI) * -0.4f; - - if (sleeve0) - sleeve0->zRot -= Mth::sin(attackTime * PI) * -0.4f; } else { arm0->zRot = Mth::sin(attackTime * PI) * -0.4f; - - if (sleeve0) - sleeve0->zRot = Mth::sin(attackTime * PI) * -0.4f; } } @@ -679,13 +612,6 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float arm0->xRot = - Mth::abs(Mth::cos(eating_t / 4.0f * PI) * 0.1f) * (eating_swing > 0.2 ? 1.0f : 0.0f) * 2.0f; // This factor is the chomping bit (conditional factor is so that he doesn't eat whilst the food is being pulled away at the end) arm0->yRot -= iss * 0.5f; // This factor and the following to the general arm movement through the life of the swing arm0->xRot -= iss * 1.2f; - - if (sleeve0) - { - sleeve0->xRot = -Mth::abs(Mth::cos(eating_t / 4.0f * PI) * 0.1f) * (eating_swing > 0.2 ? 1.0f : 0.0f) * 2.0f; - sleeve0->yRot -= iss * 0.5f; - sleeve0->xRot -= iss * 1.2f; - } } if (sneaking) @@ -709,39 +635,6 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float hair->y = +1.0f; ear->y = +1.0f; cloak->y = 0.0f; - - if (jacket) - { - jacket->xRot = -0.5f; - jacket->z = 2.0f; - jacket->y = 0.0f; - } - - if (sleeve0) - { - sleeve0->xRot += 0.4f; - sleeve0->y = 2.0f; - } - - if (sleeve1) - { - sleeve1->xRot += 0.4f; - sleeve1->y = 2.0f; - } - - if (pants0) - { - pants0->xRot -= 0.0f; - pants0->z = -4.0f; - pants0->y = +9.0f; - } - - if (pants1) - { - pants1->xRot -= 0.0f; - pants1->z = -4.0f; - pants1->y = +9.0f; - } } else { @@ -761,38 +654,6 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float hair->y = +1.0f; ear->y = +1.0f; cloak->y = 0.0f; - - if (jacket) - { - jacket->xRot = 0.5f; - jacket->y = 0.0f; - } - - if (sleeve0) - { - sleeve0->xRot += 0.4f; - sleeve0->y = 2.0f; - } - - if (sleeve1) - { - sleeve1->xRot += 0.4f; - sleeve1->y = 2.0f; - } - - if (pants0) - { - pants0->xRot -= 0.0f; - pants0->z = +4.0f; - pants0->y = +9.0f; - } - - if (pants1) - { - pants1->xRot -= 0.0f; - pants1->z = +4.0f; - pants1->y = +9.0f; - } } } else @@ -801,15 +662,6 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float leg0->z = 0.1f; leg1->z = 0.1f; - if (jacket) - jacket->xRot = 0.0f; - - if (pants0) - pants0->z = 0.1f; - - if (pants1) - pants1->z = 0.1f; - if(!riding && idle) { leg0->y = 22.0f; @@ -821,17 +673,6 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float hair->y = 10.0f; ear->y = 11.0f; cloak->y = 10.0f; - - if (jacket) - jacket->y = 10.0f; - if (sleeve0) - sleeve0->y = 12.0f; - if (sleeve1) - sleeve1->y = 12.0f; - if (pants0) - pants0->y = 22.0f; - if (pants1) - pants1->y = 22.0f; } else { @@ -844,17 +685,6 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float hair->y = 0.0f; ear->y = 1.0f; cloak->y = 0.0f; - - if (jacket) - jacket->y = 0.0f; - if (sleeve0) - sleeve0->y = 2.0f; - if (sleeve1) - sleeve1->y = 2.0f; - if (pants0) - pants0->y = 12.0f; - if (pants1) - pants1->y = 12.0f; } } @@ -863,18 +693,6 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float arm0->xRot += ((Mth::sin(bob * 0.067f)) * 0.05f); arm1->xRot -= ((Mth::sin(bob * 0.067f)) * 0.05f); - if (sleeve0) - { - sleeve0->xRot += ((Mth::sin(bob * 0.067f)) * 0.05f); - sleeve0->zRot += ((Mth::cos(bob * 0.09f)) * 0.05f + 0.05f); - } - - if (sleeve1) - { - sleeve1->xRot -= ((Mth::sin(bob * 0.067f)) * 0.05f); - sleeve1->zRot -= ((Mth::cos(bob * 0.09f)) * 0.05f + 0.05f); - } - if (bowAndArrow) { float attack2 = 0.0f; @@ -892,79 +710,189 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float arm1->zRot -= ((float) (Mth::cos(bob * 0.09f)) * 0.05f + 0.05f); arm0->xRot += ((float) (Mth::sin(bob * 0.067f)) * 0.05f); arm1->xRot -= ((float) (Mth::sin(bob * 0.067f)) * 0.05f); + } - if (sleeve0) + if (elytraFlying) + { + if (elytraCrouching) { - sleeve0->zRot = 0.0f; - sleeve0->yRot = -(0.1f - attack2 * 0.6f) + head->yRot; - sleeve0->xRot = -HALF_PI + head->xRot; - sleeve0->xRot -= attack2 * 1.2f - attack * 0.4f; - sleeve0->zRot += ((float) (Mth::cos(bob * 0.09f)) * 0.05f + 0.05f); - sleeve0->xRot += ((float) (Mth::sin(bob * 0.067f)) * 0.05f); + arm0->xRot = PI; arm0->yRot = 0.0f; arm0->zRot = 0.0f; arm0->y = 2.0f; + arm1->xRot = 0.0f; arm1->yRot = 0.0f; arm1->zRot = 0.0f; arm1->y = 2.0f; + leg0->xRot = 0.0f; leg0->yRot = 0.0f; leg0->zRot = 0.0f; + leg1->xRot = 0.0f; leg1->yRot = 0.0f; leg1->zRot = 0.0f; + } + else + { + float elytraTime = (float)(entity->tickCount) * 0.3f; + float spd2 = (float)(entity->xd * entity->xd + entity->yd * entity->yd + entity->zd * entity->zd); + float fDamp = spd2 / 0.2f; + fDamp = fDamp * fDamp * fDamp; + if (fDamp < 1.0f) fDamp = 1.0f; + + float armAmp = 2.0f * r * 0.5f / fDamp; + float legAmp = 1.4f * r / fDamp; + + arm0->xRot = Mth::cos(elytraTime + PI) * armAmp; + arm0->yRot = 0.0f; arm0->zRot = 0.0f; arm0->y = 2.0f; + + arm1->xRot = Mth::cos(elytraTime) * armAmp; + arm1->yRot = 0.0f; arm1->zRot = 0.0f; arm1->y = 2.0f; + + leg0->xRot = Mth::cos(elytraTime) * legAmp; + leg0->yRot = 0.0f; leg0->zRot = 0.0f; + leg1->xRot = Mth::cos(elytraTime + PI) * legAmp; + leg1->yRot = 0.0f; leg1->zRot = 0.0f; } - if (sleeve1) - { - sleeve1->zRot = 0.0f; - sleeve1->yRot = +(0.1f - attack2 * 0.6f) + head->yRot + 0.4f; - sleeve1->xRot = -HALF_PI + head->xRot; - sleeve1->xRot -= attack2 * 1.2f - attack * 0.4f; - sleeve1->zRot -= ((float) (Mth::cos(bob * 0.09f)) * 0.05f + 0.05f); - sleeve1->xRot -= ((float) (Mth::sin(bob * 0.067f)) * 0.05f); - } + body->xRot = 0.0f; + body->z = 0.0f; + + + head->xRot = -(float)(PI / 4.0f); + hair->xRot = head->xRot; + } + + if (jacket != 0) + { + jacket->x = body->x; + jacket->y = body->y; + jacket->z = body->z; + jacket->xRot = body->xRot; + jacket->yRot = body->yRot; + } + if (sleeve0 != 0) + { + sleeve0->x = arm0->x; + sleeve0->y = arm0->y; + sleeve0->z = arm0->z; + sleeve0->xRot = arm0->xRot; + sleeve0->yRot = arm0->yRot; + sleeve0->zRot = arm0->zRot; + } + if (sleeve1 != 0) + { + sleeve1->x = arm1->x; + sleeve1->y = arm1->y; + sleeve1->z = arm1->z; + sleeve1->xRot = arm1->xRot; + sleeve1->yRot = arm1->yRot; + sleeve1->zRot = arm1->zRot; + } + if (pants0 != 0) + { + pants0->x = leg0->x; + pants0->y = leg0->y; + pants0->z = leg0->z; + pants0->xRot = leg0->xRot; + pants0->yRot = leg0->yRot; + pants0->zRot = leg0->zRot; + } + if (pants1 != 0) + { + pants1->x = leg1->x; + pants1->y = leg1->y; + pants1->z = leg1->z; + pants1->xRot = leg1->xRot; + 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; + } + if (belt != 0) + { + belt->x = body->x; + belt->y = body->y; + belt->z = body->z; + belt->xRot = body->xRot; + belt->yRot = body->yRot; + } + if (bodyArmor != 0) + { + bodyArmor->x = body->x; + bodyArmor->y = body->y; + bodyArmor->z = body->z; + bodyArmor->xRot = body->xRot; + bodyArmor->yRot = body->yRot; + } + 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; } } - - if (elytraFlying) - { - if (elytraCrouching) - { - arm0->xRot = PI; arm0->yRot = 0.0f; arm0->zRot = 0.0f; arm0->y = 2.0f; - if (sleeve0) { sleeve0->xRot = PI; sleeve0->yRot = 0.0f; sleeve0->zRot = 0.0f; sleeve0->y = 2.0f; } - - arm1->xRot = 0.0f; arm1->yRot = 0.0f; arm1->zRot = 0.0f; arm1->y = 2.0f; - if (sleeve1) { sleeve1->xRot = 0.0f; sleeve1->yRot = 0.0f; sleeve1->zRot = 0.0f; sleeve1->y = 2.0f; } - - leg0->xRot = 0.0f; leg0->yRot = 0.0f; leg0->zRot = 0.0f; - leg1->xRot = 0.0f; leg1->yRot = 0.0f; leg1->zRot = 0.0f; - if (pants0) { pants0->xRot = 0.0f; pants0->yRot = 0.0f; pants0->zRot = 0.0f; } - if (pants1) { pants1->xRot = 0.0f; pants1->yRot = 0.0f; pants1->zRot = 0.0f; } - } - else - { - float elytraTime = (float)(entity->tickCount) * 0.3f; - float spd2 = (float)(entity->xd * entity->xd + entity->yd * entity->yd + entity->zd * entity->zd); - float fDamp = spd2 / 0.2f; - fDamp = fDamp * fDamp * fDamp; - if (fDamp < 1.0f) fDamp = 1.0f; - - float armAmp = 2.0f * r * 0.5f / fDamp; - float legAmp = 1.4f * r / fDamp; - - arm0->xRot = Mth::cos(elytraTime + PI) * armAmp; - arm0->yRot = 0.0f; arm0->zRot = 0.0f; arm0->y = 2.0f; - if (sleeve0) { sleeve0->xRot = arm0->xRot; sleeve0->yRot = 0.0f; sleeve0->zRot = 0.0f; sleeve0->y = 2.0f; } - - arm1->xRot = Mth::cos(elytraTime) * armAmp; - arm1->yRot = 0.0f; arm1->zRot = 0.0f; arm1->y = 2.0f; - if (sleeve1) { sleeve1->xRot = arm1->xRot; sleeve1->yRot = 0.0f; sleeve1->zRot = 0.0f; sleeve1->y = 2.0f; } - - leg0->xRot = Mth::cos(elytraTime) * legAmp; - leg0->yRot = 0.0f; leg0->zRot = 0.0f; - leg1->xRot = Mth::cos(elytraTime + PI) * legAmp; - leg1->yRot = 0.0f; leg1->zRot = 0.0f; - if (pants0) { pants0->xRot = leg0->xRot; pants0->yRot = 0.0f; pants0->zRot = 0.0f; } - if (pants1) { pants1->xRot = leg1->xRot; pants1->yRot = 0.0f; pants1->zRot = 0.0f; } - } - - body->xRot = 0.0f; - body->z = 0.0f; - - - head->xRot = -(float)(PI / 4.0f); - hair->xRot = head->xRot; - } - } void HumanoidModel::renderHair(float scale,bool usecompiled) diff --git a/Minecraft.Client/HumanoidModel.h b/Minecraft.Client/HumanoidModel.h index 525ae32e..072e77ea 100644 --- a/Minecraft.Client/HumanoidModel.h +++ b/Minecraft.Client/HumanoidModel.h @@ -1,9 +1,11 @@ #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; + ModelPart* waist, * belt, * bodyArmor, * armArmor0, * armArmor1, * legging0, * legging1, * sock0, * sock1, * boot0, * boot1; ModelPart* elytraLeft, * elytraRight; int holdingLeftHand; int holdingRightHand; @@ -69,16 +71,13 @@ public: (1 << HumanoidModel::eAnim_DisableRenderPants0) | (1 << HumanoidModel::eAnim_DisableRenderPants1); - void _init(float g, float yOffset, int texWidth, int texHeight, - bool slimHands, bool mirror, bool force32, bool isArmor = false); + void _init(float g, float yOffset, int texWidth, int texHeight, bool slim, bool isArmor); HumanoidModel(); HumanoidModel(float g); HumanoidModel(float g, bool isArmor); HumanoidModel(float g, float yOffset, int texWidth, int texHeight); - HumanoidModel(float g, float yOffset, int texWidth, int texHeight, bool slimHands); - HumanoidModel(float g, float yOffset, int texWidth, int texHeight, bool slimHands, bool mirror); - HumanoidModel(float g, float yOffset, int texWidth, int texHeight, bool slimHands, bool mirror, bool force32); + HumanoidModel(float g, float yOffset, int texWidth, int texHeight, bool slim); virtual void render(shared_ptr entity, float time, float r, float bob, float yRot, float xRot, float scale, bool usecompiled); diff --git a/Minecraft.Client/LivingEntityRenderer.cpp b/Minecraft.Client/LivingEntityRenderer.cpp index 8fe27fc7..bc5deb77 100644 --- a/Minecraft.Client/LivingEntityRenderer.cpp +++ b/Minecraft.Client/LivingEntityRenderer.cpp @@ -18,7 +18,7 @@ LivingEntityRenderer::LivingEntityRenderer(Model *model, float shadow, bool isPl if (isPlayer) { - this->modelWide = new HumanoidModel(0, 0, 64, 64, false); + this->modelWide = new HumanoidModel(0, 0, 64, 64); this->modelSlim = new HumanoidModel(0, 0, 64, 64, true); } diff --git a/Minecraft.Client/PlayerRenderer.cpp b/Minecraft.Client/PlayerRenderer.cpp index 3a4fe742..ba8169ff 100644 --- a/Minecraft.Client/PlayerRenderer.cpp +++ b/Minecraft.Client/PlayerRenderer.cpp @@ -77,9 +77,12 @@ PlayerRenderer::PlayerRenderer() : LivingEntityRenderer(new HumanoidModel(0), 0. void PlayerRenderer::setModelType(shared_ptr player) { - if (Player::GetModelTypeFromTextureId(player->getCustomSkin()) == 2 || Player::GetModelTypeFromAnimBitmask(player->getAnimOverrideBitmask()) == 2) resModel = humanoidModelSlim; - else if (Player::GetModelTypeFromTextureId(player->getCustomSkin()) == 1 || Player::GetModelTypeFromAnimBitmask(player->getAnimOverrideBitmask()) == 1) resModel = humanoidModelWide; - else resModel = humanoidModel; + if (Player::GetModelTypeFromTextureId(player->getCustomSkin()) == 2 || Player::GetModelTypeFromAnimBitmask(player->getAnimOverrideBitmask()) == 2) + resModel = humanoidModelSlim; + else if (Player::GetModelTypeFromTextureId(player->getCustomSkin()) == 1 || Player::GetModelTypeFromAnimBitmask(player->getAnimOverrideBitmask()) == 1) + resModel = humanoidModelWide; + else + resModel = humanoidModel; } unsigned int PlayerRenderer::getNametagColour(int index) @@ -93,7 +96,6 @@ int PlayerRenderer::prepareArmor(shared_ptr _player, int layer, fl { // 4J - dynamic cast required because we aren't using templates/generics in our version shared_ptr player = dynamic_pointer_cast(_player); - setModelType(player); // 4J-PB - need to disable rendering armour for some special skins (Daleks) unsigned int uiAnimOverrideBitmask = player->getAnimOverrideBitmask(); @@ -375,7 +377,6 @@ void PlayerRenderer::additionalRendering(shared_ptr _mob, float a) // 4J - dynamic cast required because we aren't using templates/generics in our version shared_ptr mob = dynamic_pointer_cast(_mob); - setModelType(mob); shared_ptr headGear = mob->inventory->getArmor(3); if (headGear != nullptr) @@ -478,7 +479,7 @@ void PlayerRenderer::additionalRendering(shared_ptr _mob, float a) glRotatef(lean2 / 2, 0, 0, 1); glRotatef(-lean2 / 2, 0, 1, 0); glRotatef(180, 0, 1, 0); - resModel->renderCloak(1 / 16.0f, true); + humanoidModel->renderCloak(1 / 16.0f, true); glPopMatrix(); } diff --git a/Minecraft.Client/SkinBox.h b/Minecraft.Client/SkinBox.h index 08b3073a..d82a790d 100644 --- a/Minecraft.Client/SkinBox.h +++ b/Minecraft.Client/SkinBox.h @@ -9,11 +9,23 @@ enum eBodyPart eBodyPart_Arm1, eBodyPart_Leg0, eBodyPart_Leg1, + eBodyPart_Headwear, eBodyPart_Jacket, eBodyPart_Sleeve0, eBodyPart_Sleeve1, eBodyPart_Pants0, eBodyPart_Pants1, + eBodyPart_Waist, + eBodyPart_Legging0, + eBodyPart_Legging1, + eBodyPart_Sock0, + eBodyPart_Sock1, + eBodyPart_Boot0, + eBodyPart_Boot1, + eBodyPart_ArmArmor0, + eBodyPart_ArmArmor1, + eBodyPart_BodyArmor, + eBodyPart_Belt }; typedef struct diff --git a/Minecraft.Client/SkinOffset.h b/Minecraft.Client/SkinOffset.h new file mode 100644 index 00000000..79d39cac --- /dev/null +++ b/Minecraft.Client/SkinOffset.h @@ -0,0 +1,48 @@ +#pragma once + +enum eBodyOffset +{ + eBodyOffset_Unknown=0, + eBodyOffset_Head, + eBodyOffset_Body, + eBodyOffset_Arm0, + eBodyOffset_Arm1, + eBodyOffset_Leg0, + eBodyOffset_Leg1, + eBodyOffset_Headwear, + eBodyOffset_Jacket, + eBodyOffset_Sleeve0, + eBodyOffset_Sleeve1, + eBodyOffset_Pants0, + eBodyOffset_Pants1, + eBodyOffset_Helmet, + eBodyOffset_Waist, + eBodyOffset_Legging0, + eBodyOffset_Legging1, + eBodyOffset_Sock0, + eBodyOffset_Sock1, + eBodyOffset_Boot0, + eBodyOffset_Boot1, + eBodyOffset_ArmArmor1, + eBodyOffset_ArmArmor0, + eBodyOffset_BodyArmor, + eBodyOffset_Belt, + eBodyOffset_Tool0, + eBodyOffset_Tool1 + +}; + +enum eOffsetDirection +{ + eOffsetDirection_Unknown=0, + eOffsetDirection_X, + eOffsetDirection_Y, + eOffsetDirection_Z +}; + +typedef struct +{ + eBodyOffset ePart; + float fD, fO; +} +SKIN_OFFSET; diff --git a/Minecraft.Client/VillagerZombieModel.cpp b/Minecraft.Client/VillagerZombieModel.cpp index b8a607f3..707a5d63 100644 --- a/Minecraft.Client/VillagerZombieModel.cpp +++ b/Minecraft.Client/VillagerZombieModel.cpp @@ -25,12 +25,12 @@ void VillagerZombieModel::_init(float g, float yOffset, bool isArmor) head->compile(1.0f/16.0f); } -VillagerZombieModel::VillagerZombieModel() : HumanoidModel(0, 0, 64, 64, false, true, true) +VillagerZombieModel::VillagerZombieModel() : HumanoidModel(0, 0, 64, 64) { _init(0, 0, false); } -VillagerZombieModel::VillagerZombieModel(float g, float yOffset, bool isArmor) : HumanoidModel(g, 0, 64, isArmor ? 32 : 64 , false, true, isArmor ? true : false) +VillagerZombieModel::VillagerZombieModel(float g, float yOffset, bool isArmor) : HumanoidModel(g, 0, 64, isArmor ? 32 : 64) { _init(g, yOffset, isArmor); } diff --git a/Minecraft.World/Player.cpp b/Minecraft.World/Player.cpp index e8756ea7..b4820390 100644 --- a/Minecraft.World/Player.cpp +++ b/Minecraft.World/Player.cpp @@ -738,7 +738,6 @@ int Player::GetModelTypeFromTextureId(int textureId) { if (textureId > 8 && textureId < 18) return 2; else if (textureId == 18) return 1; - else if (textureId >= 0 && textureId < 9) return 1; else return 0; } From ac3df250562b21e69c19302a97d522af5f37d8c2 Mon Sep 17 00:00:00 2001 From: Langtanium <94726057+Langtanium@users.noreply.github.com> Date: Wed, 20 May 2026 13:32:44 -0700 Subject: [PATCH 5/9] Added skin offsets code Added code to apply skin offsets if present on skin. Armor offsets defined in skin will also be applied. --- Minecraft.Client/ClientConnection.cpp | 7 +- Minecraft.Client/Common/Consoles_App.cpp | 62 +- Minecraft.Client/Common/Consoles_App.h | 6 + Minecraft.Client/Common/DLC/DLCSkinFile.cpp | 9 + .../Common/UI/UIControl_PlayerSkinPreview.cpp | 4 +- .../Common/UI/UIControl_PlayerSkinPreview.h | 1 + .../Common/UI/UIScene_SkinSelectMenu.cpp | 38 ++ .../Common/UI/UIScene_SkinSelectMenu.h | 1 + Minecraft.Client/HumanoidModel.cpp | 601 ++++++++++++++++-- Minecraft.Client/HumanoidModel.h | 9 +- Minecraft.Client/ModelPart.cpp | 1 + Minecraft.Client/ModelPart.h | 1 + Minecraft.Client/PlayerConnection.cpp | 13 +- Minecraft.Client/PlayerRenderer.cpp | 4 + Minecraft.World/Player.cpp | 82 ++- Minecraft.World/Player.h | 5 + Minecraft.World/TextureAndGeometryPacket.cpp | 71 ++- Minecraft.World/TextureAndGeometryPacket.h | 5 +- 18 files changed, 852 insertions(+), 68 deletions(-) diff --git a/Minecraft.Client/ClientConnection.cpp b/Minecraft.Client/ClientConnection.cpp index d13356f9..141947be 100644 --- a/Minecraft.Client/ClientConnection.cpp +++ b/Minecraft.Client/ClientConnection.cpp @@ -2792,7 +2792,7 @@ void ClientConnection::handleTextureAndGeometry(shared_ptrdwSkinID); - send(std::make_shared(packet->textureName, pbData, dwBytes, app.GetAdditionalSkinBoxes(packet->dwSkinID), uiAnimOverrideBitmask)); + send(std::make_shared(packet->textureName, pbData, dwBytes, app.GetAdditionalSkinBoxes(packet->dwSkinID), app.GetSkinOffsets(packet->dwSkinID), uiAnimOverrideBitmask)); } } } @@ -2809,6 +2809,11 @@ void ClientConnection::handleTextureAndGeometry(shared_ptrdwSkinID,packet->BoxDataA,packet->dwBoxC); } + // Add the offet data + if(packet->dwOffsetC!=0) + { + app.SetSkinOffsets(packet->dwSkinID,packet->OffsetDataA,packet->dwOffsetC); + } // Add the anim override app.SetAnimOverrideBitmask(packet->dwSkinID,packet->uiAnimOverrideBitmask); diff --git a/Minecraft.Client/Common/Consoles_App.cpp b/Minecraft.Client/Common/Consoles_App.cpp index 0e2813df..93435aeb 100644 --- a/Minecraft.Client/Common/Consoles_App.cpp +++ b/Minecraft.Client/Common/Consoles_App.cpp @@ -198,6 +198,7 @@ CMinecraftApp::CMinecraftApp() InitializeCriticalSection(&csTMSPPDownloadQueue); InitializeCriticalSection(&csAdditionalModelParts); InitializeCriticalSection(&csAdditionalSkinBoxes); + InitializeCriticalSection(&csSkinOffsets); InitializeCriticalSection(&csAnimOverrideBitmask); InitializeCriticalSection(&csMemFilesLock); InitializeCriticalSection(&csMemTPDLock); @@ -242,8 +243,7 @@ CMinecraftApp::CMinecraftApp() } -void CMinecraftApp::GetSkinAdjustments(_SkinAdjustments* out, - unsigned int skinId) +void CMinecraftApp::GetSkinAdjustments(_SkinAdjustments* out, unsigned int skinId) { _SkinAdjustments adj; @@ -261,8 +261,7 @@ void CMinecraftApp::GetSkinAdjustments(_SkinAdjustments* out, *out = adj; } -void CMinecraftApp::SetSkinAdjustments(unsigned int skinId, - const _SkinAdjustments& adj) +void CMinecraftApp::SetSkinAdjustments(unsigned int skinId, const _SkinAdjustments& adj) { EnterCriticalSection(&csAdditionalSkinBoxes); @@ -9687,6 +9686,44 @@ vector * CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, vect return pvModelPart; } +void CMinecraftApp::SetSkinOffsets(DWORD dwSkinID, SKIN_OFFSET *SkinOffsetA, DWORD dwSkinOffsetC) +{ + vector *pvSkinOffset = new vector; + + EnterCriticalSection( &csSkinOffsets ); + + app.DebugPrintf("*** SetSkinOffsets - Adding skin offsets for skin %d from array of Skin Offsets\n",dwSkinID&0x0FFFFFFF); + + for(unsigned int i=0;ipush_back(&SkinOffsetA[i]); + } + + + m_SkinOffsets.insert( std::pair *>(dwSkinID, pvSkinOffset) ); + + LeaveCriticalSection( &csSkinOffsets ); + +} + +vector * CMinecraftApp::SetSkinOffsets(DWORD dwSkinID, vector *pvSkinOffsetA) +{ + vector *pvSkinOffset = new vector; + + EnterCriticalSection( &csSkinOffsets ); + app.DebugPrintf("*** SetSkinOffsets - Inserting skin offsets for skin %d from array of Skin Offsets\n",dwSkinID&0x0FFFFFFF); + + for( auto& it : *pvSkinOffsetA ) + { + pvSkinOffset->push_back(it); + } + + m_SkinOffsets.emplace(dwSkinID, pvSkinOffsetA); + + LeaveCriticalSection( &csSkinOffsets ); + return pvSkinOffset; +} + vector *CMinecraftApp::GetAdditionalModelParts(DWORD dwSkinID) { @@ -9722,6 +9759,23 @@ vector *CMinecraftApp::GetAdditionalSkinBoxes(DWORD dwSkinID) return pvSkinBoxes; } +vector *CMinecraftApp::GetSkinOffsets(DWORD dwSkinID) +{ + EnterCriticalSection( &csSkinOffsets ); + vector *pvSkinOffsets=nullptr; + if(m_SkinOffsets.size()>0) + { + auto it = m_SkinOffsets.find(dwSkinID); + if(it!=m_SkinOffsets.end()) + { + pvSkinOffsets = (*it).second; + } + } + + LeaveCriticalSection( &csSkinOffsets ); + return pvSkinOffsets; +} + unsigned int CMinecraftApp::GetAnimOverrideBitmask(DWORD dwSkinID) { EnterCriticalSection( &csAnimOverrideBitmask ); diff --git a/Minecraft.Client/Common/Consoles_App.h b/Minecraft.Client/Common/Consoles_App.h index 52f4c043..b6fd23d2 100644 --- a/Minecraft.Client/Common/Consoles_App.h +++ b/Minecraft.Client/Common/Consoles_App.h @@ -21,6 +21,7 @@ using namespace std; #include "./GameRules/ConsoleGameRulesConstants.h" #include "./GameRules/GameRuleManager.h" #include "../SkinBox.h" +#include "../SkinOffset.h" #include "../ArchiveFile.h" #include "lce_filesystem/FolderFile.h" @@ -848,6 +849,7 @@ private: CRITICAL_SECTION csTMSPPDownloadQueue; CRITICAL_SECTION csAdditionalModelParts; CRITICAL_SECTION csAdditionalSkinBoxes; + CRITICAL_SECTION csSkinOffsets; CRITICAL_SECTION csAnimOverrideBitmask; bool m_bCorruptSaveDeleted; wstring m_currentSaveFolderName; // 4J Added: for hardcore world deletion on Win64 @@ -870,6 +872,9 @@ public: vector * SetAdditionalSkinBoxes(DWORD dwSkinID, vector *pvSkinBoxA); vector *GetAdditionalModelParts(DWORD dwSkinID); vector *GetAdditionalSkinBoxes(DWORD dwSkinID); + void SetSkinOffsets(DWORD dwSkinID, SKIN_OFFSET *SkinOffsetA, DWORD dwSkinOffsetC); + vector * SetSkinOffsets(DWORD dwSkinID, vector *pvSkinOffsetA); + vector *GetSkinOffsets(DWORD dwSkinID); void SetAnimOverrideBitmask(DWORD dwSkinID,unsigned int uiAnimOverrideBitmask); unsigned int GetAnimOverrideBitmask(DWORD dwSkinID); @@ -900,6 +905,7 @@ private: // vector of additional skin model parts, indexed by the skin texture id unordered_map *> m_AdditionalModelParts; unordered_map *> m_AdditionalSkinBoxes; + unordered_map *> m_SkinOffsets; unordered_map m_AnimOverrides; diff --git a/Minecraft.Client/Common/DLC/DLCSkinFile.cpp b/Minecraft.Client/Common/DLC/DLCSkinFile.cpp index 17004313..e309da78 100644 --- a/Minecraft.Client/Common/DLC/DLCSkinFile.cpp +++ b/Minecraft.Client/Common/DLC/DLCSkinFile.cpp @@ -397,6 +397,15 @@ vector *DLCSkinFile::getAdditionalBoxes() return &m_AdditionalBoxes; } +int DLCSkinFile::getOffsetsCount() +{ + return static_cast(m_Offsets.size()); +} +vector *DLCSkinFile::getOffsets() +{ + return &m_Offsets; +} + wstring DLCSkinFile::getParameterAsString(DLCManager::EDLCParameterType type) { switch(type) diff --git a/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp b/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp index d3d93319..653b98cd 100644 --- a/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp +++ b/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp @@ -107,6 +107,7 @@ UIControl_PlayerSkinPreview::UIControl_PlayerSkinPreview() m_framesAnimatingRotation = 0; m_bAnimatingToFacing = false; m_pvAdditionalModelParts=nullptr; + m_pvSkinOffsets=nullptr; m_uiAnimOverrideBitmask=0L; } @@ -183,6 +184,7 @@ void UIControl_PlayerSkinPreview::SetTexture(const wstring &url, TEXTURE_NAME ba } m_pvAdditionalModelParts=app.GetAdditionalModelParts(app.getSkinIdFromPath(m_customTextureUrl)); + m_pvSkinOffsets=app.GetSkinOffsets(app.getSkinIdFromPath(m_customTextureUrl)); } void UIControl_PlayerSkinPreview::SetFacing(ESkinPreviewFacing facing, bool bAnimate /*= false*/) @@ -421,7 +423,7 @@ void UIControl_PlayerSkinPreview::render(EntityRenderer *renderer, double x, dou glEnable(GL_ALPHA_TEST); //model->prepareMobModel(mob, wp, ws, a); - model->render(nullptr, wp, ws, bob, headRot - bodyRot, headRotx, _scale, true); + model->renderUI(wp, ws, bob, headRot - bodyRot, headRotx, _scale, true, m_pvSkinOffsets); /*for (int i = 0; i < MAX_ARMOR_LAYERS; i++) { if (prepareArmor(mob, i, a)) diff --git a/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.h b/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.h index 974e5924..91430ab9 100644 --- a/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.h +++ b/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.h @@ -53,6 +53,7 @@ private: ESkinPreviewAnimations m_currentAnimation; //vector *m_pvAdditionalBoxes; vector *m_pvAdditionalModelParts; + vector *m_pvSkinOffsets; public: enum ESkinPreviewFacing { diff --git a/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.cpp index af3bead9..05996f55 100644 --- a/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.cpp @@ -59,6 +59,7 @@ UIScene_SkinSelectMenu::UIScene_SkinSelectMenu(int iPad, void *initData, UILayer m_selectedSkinPath = L""; m_selectedCapePath = L""; m_vAdditionalSkinBoxes = nullptr; + m_vSkinOffsets = nullptr; m_bSlidingSkins = false; m_bAnimatingMove = false; @@ -662,6 +663,7 @@ void UIScene_SkinSelectMenu::handleSkinIndexChanged() m_selectedSkinPath = skinFile->getPath(); m_selectedCapePath = skinFile->getParameterAsString(DLCManager::e_DLCParamType_Cape); m_vAdditionalSkinBoxes = skinFile->getAdditionalBoxes(); + m_vSkinOffsets = skinFile->getOffsets(); skinName = skinFile->getParameterAsString( DLCManager::e_DLCParamType_DisplayName ); skinOrigin = skinFile->getParameterAsString( DLCManager::e_DLCParamType_ThemeName ); @@ -684,6 +686,7 @@ void UIScene_SkinSelectMenu::handleSkinIndexChanged() m_selectedSkinPath = L""; m_selectedCapePath = L""; m_vAdditionalSkinBoxes = nullptr; + m_vSkinOffsets = nullptr; switch(m_packIndex) { @@ -726,6 +729,7 @@ void UIScene_SkinSelectMenu::handleSkinIndexChanged() m_selectedSkinPath = skinFile->getPath(); m_selectedCapePath = skinFile->getParameterAsString(DLCManager::e_DLCParamType_Cape); m_vAdditionalSkinBoxes = skinFile->getAdditionalBoxes(); + m_vSkinOffsets = skinFile->getOffsets(); skinName = skinFile->getParameterAsString( DLCManager::e_DLCParamType_DisplayName ); skinOrigin = skinFile->getParameterAsString( DLCManager::e_DLCParamType_ThemeName ); @@ -773,6 +777,17 @@ void UIScene_SkinSelectMenu::handleSkinIndexChanged() pAdditionalModelParts = app.SetAdditionalSkinBoxes(skinFile->getSkinID(),m_vAdditionalSkinBoxes); } } + + if(m_vSkinOffsets && m_vSkinOffsets->size()!=0) + { + // add the skin Offsets to the humanoid model, but only if we've not done this already + + vector *pSkinOffsets = app.GetSkinOffsets(skinFile->getSkinID()); + if(pSkinOffsets==nullptr) + { + pSkinOffsets = app.SetSkinOffsets(skinFile->getSkinID(),m_vSkinOffsets); + } + } if(skinFile!=nullptr) { @@ -790,6 +805,7 @@ void UIScene_SkinSelectMenu::handleSkinIndexChanged() wstring otherSkinPath = L""; wstring otherCapePath = L""; vector *othervAdditionalSkinBoxes=nullptr; + vector *othervSkinOffsets=nullptr; wchar_t chars[256]; // turn off all displays @@ -844,6 +860,7 @@ void UIScene_SkinSelectMenu::handleSkinIndexChanged() otherSkinPath = skinFile->getPath(); otherCapePath = skinFile->getParameterAsString(DLCManager::e_DLCParamType_Cape); othervAdditionalSkinBoxes = skinFile->getAdditionalBoxes(); + othervSkinOffsets = skinFile->getOffsets(); backupTexture = TN_MOB_CHAR; } else @@ -851,6 +868,7 @@ void UIScene_SkinSelectMenu::handleSkinIndexChanged() otherSkinPath = L""; otherCapePath = L""; othervAdditionalSkinBoxes=nullptr; + othervSkinOffsets=nullptr; switch(m_packIndex) { case SKIN_SELECT_PACK_DEFAULT: @@ -870,6 +888,7 @@ void UIScene_SkinSelectMenu::handleSkinIndexChanged() otherSkinPath = skinFile->getPath(); otherCapePath = skinFile->getParameterAsString(DLCManager::e_DLCParamType_Cape); othervAdditionalSkinBoxes = skinFile->getAdditionalBoxes(); + othervSkinOffsets = skinFile->getOffsets(); backupTexture = TN_MOB_CHAR; } } @@ -887,6 +906,14 @@ void UIScene_SkinSelectMenu::handleSkinIndexChanged() pAdditionalModelParts = app.SetAdditionalSkinBoxes(skinFile->getSkinID(),othervAdditionalSkinBoxes); } } + if(othervSkinOffsets && othervSkinOffsets->size()!=0) + { + vector *pSkinOffsets = app.GetSkinOffsets(skinFile->getSkinID()); + if(pSkinOffsets==nullptr) + { + pSkinOffsets = app.SetSkinOffsets(skinFile->getSkinID(),othervSkinOffsets); + } + } // 4J-PB - anim override needs set before SetTexture if(skinFile!=nullptr) { @@ -915,6 +942,7 @@ void UIScene_SkinSelectMenu::handleSkinIndexChanged() otherSkinPath = skinFile->getPath(); otherCapePath = skinFile->getParameterAsString(DLCManager::e_DLCParamType_Cape); othervAdditionalSkinBoxes = skinFile->getAdditionalBoxes(); + othervSkinOffsets = skinFile->getOffsets(); backupTexture = TN_MOB_CHAR; } else @@ -922,6 +950,7 @@ void UIScene_SkinSelectMenu::handleSkinIndexChanged() otherSkinPath = L""; otherCapePath = L""; othervAdditionalSkinBoxes=nullptr; + othervSkinOffsets=nullptr; switch(m_packIndex) { case SKIN_SELECT_PACK_DEFAULT: @@ -941,6 +970,7 @@ void UIScene_SkinSelectMenu::handleSkinIndexChanged() otherSkinPath = skinFile->getPath(); otherCapePath = skinFile->getParameterAsString(DLCManager::e_DLCParamType_Cape); othervAdditionalSkinBoxes = skinFile->getAdditionalBoxes(); + othervSkinOffsets = skinFile->getOffsets(); backupTexture = TN_MOB_CHAR; } } @@ -958,6 +988,14 @@ void UIScene_SkinSelectMenu::handleSkinIndexChanged() pAdditionalModelParts = app.SetAdditionalSkinBoxes(skinFile->getSkinID(),othervAdditionalSkinBoxes); } } + if(othervSkinOffsets && othervSkinOffsets->size()!=0) + { + vector *pSkinOffsets = app.GetSkinOffsets(skinFile->getSkinID()); + if(pSkinOffsets==nullptr) + { + pSkinOffsets = app.SetSkinOffsets(skinFile->getSkinID(),othervSkinOffsets); + } + } // 4J-PB - anim override needs set before SetTexture if(skinFile) { diff --git a/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.h b/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.h index f75494a8..bef2d4fc 100644 --- a/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.h +++ b/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.h @@ -104,6 +104,7 @@ private: DWORD m_originalSkinId; wstring m_currentSkinPath, m_selectedSkinPath, m_selectedCapePath; vector *m_vAdditionalSkinBoxes; + vector *m_vSkinOffsets; bool m_bSlidingSkins, m_bAnimatingMove; ESkinSelectNavigation m_currentNavigation; diff --git a/Minecraft.Client/HumanoidModel.cpp b/Minecraft.Client/HumanoidModel.cpp index 57bbc646..eb8840c2 100644 --- a/Minecraft.Client/HumanoidModel.cpp +++ b/Minecraft.Client/HumanoidModel.cpp @@ -1,8 +1,9 @@ #include "stdafx.h" #include "HumanoidModel.h" #include "../Minecraft.World/Mth.h" -#include "../Minecraft.World/Entity.h" +#include "../Minecraft.World/Player.h" #include "ModelPart.h" +#include "Cube.h" // 4J added @@ -156,8 +157,6 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b elytraLeft->addHumanoidBox(0.0f, 0.0f, 0.0f, 10, 20, 2, 0.0f); elytraLeft->setPos(-5.0f, 0.0f + yOffset, 0.0f); // Wing Right - - ear = new ModelPart(this, 24, 0); ear->addHumanoidBox(-3, -6, -1, 6, 6, 1, g); // Ear @@ -295,35 +294,35 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b if (jacket) jacket->compile(1.0f/16.0f); - if (sleeve0 != 0) + if (sleeve0) sleeve0->compile(1.0f/16.0f); - if (sleeve1 != 0) + if (sleeve1) sleeve1->compile(1.0f/16.0f); - if (pants0 != 0) + if (pants0) pants0->compile(1.0f/16.0f); - if (pants1 != 0) + if (pants1) pants1->compile(1.0f/16.0f); - if (waist != 0) + if (waist) waist->compile(1.0f/16.0f); - if (belt != 0) + if (belt) belt->compile(1.0f/16.0f); - if (bodyArmor != 0) + if (bodyArmor) bodyArmor->compile(1.0f/16.0f); - if (armArmor0 != 0) + if (armArmor0) armArmor0->compile(1.0f/16.0f); - if (armArmor1 != 0) + if (armArmor1) armArmor1->compile(1.0f/16.0f); - if (legging0 != 0) + if (legging0) legging0->compile(1.0f/16.0f); - if (legging1 != 0) + if (legging1) legging1->compile(1.0f/16.0f); - if (sock0 != 0) + if (sock0) sock0->compile(1.0f/16.0f); - if (sock1 != 0) + if (sock1) sock1->compile(1.0f/16.0f); - if (boot0 != 0) + if (boot0) boot0->compile(1.0f/16.0f); - if (boot1 != 0) + if (boot1) boot1->compile(1.0f/16.0f); holdingLeftHand=0; @@ -369,10 +368,256 @@ HumanoidModel::HumanoidModel(float g, float yOffset, int texWidth, int texHeight } void HumanoidModel::render(shared_ptr entity, float time, float r, float bob, float yRot, float xRot, float scale, bool usecompiled) -{ +{ + vector hasArmorOffsets = {false, false, false, false, false, false}; + vector headOffsets = {0, 0, 0}; + vector bodyOffsets = {0, 0, 0}; + vector arm0Offsets = {0, 0, 0}; + vector arm1Offsets = {0, 0, 0}; + vector leg0Offsets = {0, 0, 0}; + vector leg1Offsets = {0, 0, 0}; + if(entity != nullptr) { m_uiAnimOverrideBitmask=entity->getAnimOverrideBitmask(); + + shared_ptr player = dynamic_pointer_cast(entity); + vector* pSkinOffsets = nullptr; + if (player != nullptr) + pSkinOffsets = player->GetSkinOffsets(); + if (pSkinOffsets != nullptr) + { + for( SKIN_OFFSET *pSkinOffset : *pSkinOffsets ) + { + switch (pSkinOffset->ePart) + { + case eBodyOffset_Head: + if (pSkinOffset->fD == 1) + headOffsets[0] += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 2) + headOffsets[1] += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 3) + headOffsets[2] += pSkinOffset->fO / 16.0f; + break; + case eBodyOffset_Body: + if (pSkinOffset->fD == 1) + bodyOffsets[0] += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 2) + bodyOffsets[1] += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 3) + bodyOffsets[2] += pSkinOffset->fO / 16.0f; + break; + case eBodyOffset_Arm0: + if (pSkinOffset->fD == 1) + arm0Offsets[0] += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 2) + arm0Offsets[1] += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 3) + arm0Offsets[2] += pSkinOffset->fO / 16.0f; + break; + case eBodyOffset_Arm1: + if (pSkinOffset->fD == 1) + arm1Offsets[0] += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 2) + arm1Offsets[1] += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 3) + arm1Offsets[2] += pSkinOffset->fO / 16.0f; + break; + case eBodyOffset_Leg0: + if (pSkinOffset->fD == 1) + leg0Offsets[0] += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 2) + leg0Offsets[1] += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 3) + leg0Offsets[2] += pSkinOffset->fO / 16.0f; + break; + case eBodyOffset_Leg1: + if (pSkinOffset->fD == 1) + leg1Offsets[0] += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 2) + leg1Offsets[1] += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 3) + leg1Offsets[2] += pSkinOffset->fO / 16.0f; + break; + case eBodyOffset_Helmet: + if (m_isArmor && !head->isArmorPart2 && head->visible) + { + hasArmorOffsets[0] = true; + delete head; + head = new ModelPart(this, 0, 0); + head->addHumanoidBox(-4, -8 + pSkinOffset->fO, -4, 8, 8, 8, 1.0f); // Head + head->setPos(0, 0 + m_fYOffset, 0); + head->compile(1.0f/16.0f); + } + break; + case eBodyOffset_BodyArmor: + if (m_isArmor && !body->isArmorPart2 && body->visible) + { + hasArmorOffsets[1] = true; + delete body; + body = new ModelPart(this, 16, 16); + body->addHumanoidBox(-4, 0 + pSkinOffset->fO, -2, 8, 12, 4, 1.0f); // Body + body->setPos(0, 0 + m_fYOffset, 0); + body->compile(1.0f/16.0f); + } + break; + case eBodyOffset_ArmArmor0: + if (m_isArmor && !arm0->isArmorPart2 && arm0->visible) + { + hasArmorOffsets[2] = true; + delete arm0; + arm0 = new ModelPart(this, 24 + 16, 16); + arm0->addHumanoidBox(-3, -2 + pSkinOffset->fO, -2, 4, 12, 4, 1.0f); // Arm0 + arm0->setPos(-5, 2 + m_fYOffset, 0); + arm0->compile(1.0f/16.0f); + } + break; + case eBodyOffset_ArmArmor1: + if (m_isArmor && !arm1->isArmorPart2 && arm1->visible) + { + hasArmorOffsets[3] = true; + delete arm1; + arm1 = new ModelPart(this, 24 + 16, 16); + arm1->bMirror = true; + arm1->addHumanoidBox(-1, -2 + pSkinOffset->fO, -2, 4, 12, 4, 1.0f); // Arm1 + arm1->setPos(5, 2 + m_fYOffset, 0); + arm1->compile(1.0f/16.0f); + } + break; + case eBodyOffset_Belt: + if (m_isArmor && body->isArmorPart2 && body->visible) + { + hasArmorOffsets[1] = true; + delete body; + body = new ModelPart(this, 16, 16); + body->addHumanoidBox(-4, 0 + pSkinOffset->fO, -2, 8, 12, 4, 0.5f); // Body + body->setPos(0, 0 + m_fYOffset, 0); + body->compile(1.0f/16.0f); + body->isArmorPart2 = true; + } + break; + case eBodyOffset_Legging0: + if (m_isArmor && leg0->isArmorPart2 && leg0->visible) + { + hasArmorOffsets[4] = true; + delete leg0; + leg0 = new ModelPart(this, 0, 16); + leg0->addHumanoidBox(-2, 0 + pSkinOffset->fO, -2, 4, 12, 4, 0.5f); // Leg0 + leg0->setPos(-1.9, 12 + m_fYOffset, 0); + leg0->compile(1.0f/16.0f); + leg0->isArmorPart2 = true; + } + break; + case eBodyOffset_Legging1: + if (m_isArmor && leg1->isArmorPart2 && leg1->visible) + { + hasArmorOffsets[5] = true; + delete leg1; + leg1 = new ModelPart(this, 0, 16); + leg1->bMirror = true; + leg1->addHumanoidBox(-2, 0 + pSkinOffset->fO, -2, 4, 12, 4, 0.5f); // Leg1 + leg1->setPos(1.9, 12 + m_fYOffset, 0); + leg1->compile(1.0f/16.0f); + leg1->isArmorPart2 = true; + } + break; + case eBodyOffset_Boot0: + if (m_isArmor && !leg0->isArmorPart2 && leg0->visible) + { + hasArmorOffsets[4] = true; + delete leg0; + leg0 = new ModelPart(this, 0, 16); + leg0->addHumanoidBox(-2, 0 + pSkinOffset->fO, -2, 4, 12, 4, 1.0f); // Leg0 + leg0->setPos(-1.9, 12 + m_fYOffset, 0); + leg0->compile(1.0f/16.0f); + } + break; + case eBodyOffset_Boot1: + if (m_isArmor && !leg1->isArmorPart2 && leg1->visible) + { + hasArmorOffsets[5] = true; + delete leg1; + leg1 = new ModelPart(this, 0, 16); + leg1->bMirror = true; + leg1->addHumanoidBox(-2, 0 + pSkinOffset->fO, -2, 4, 12, 4, 1.0f); // Leg1 + leg1->setPos(1.9, 12 + m_fYOffset, 0); + leg1->compile(1.0f/16.0f); + } + break; + } + } + } + + if (m_isArmor) + { + if (!hasArmorOffsets[0] && head->cubes[0]->y0 != -8 && head->visible) + { + delete head; + head = new ModelPart(this, 0, 0); + head->addHumanoidBox(-4, -8, -4, 8, 8, 8, 1.0f); // Head + head->setPos(0, 0 + m_fYOffset, 0); + head->compile(1.0f/16.0f); + } + if (!hasArmorOffsets[1] && body->cubes[0]->y0 != 0 && body->visible) + { + delete body; + body = new ModelPart(this, 16, 16); + if (body->isArmorPart2) + { + body->addHumanoidBox(-4, 0, -2, 8, 12, 4, 0.5f); // Body + body->isArmorPart2 = true; + } + else + body->addHumanoidBox(-4, 0, -2, 8, 12, 4, 1.0f); // Body + body->setPos(0, 0 + m_fYOffset, 0); + body->compile(1.0f/16.0f); + } + if (!hasArmorOffsets[2] && arm0->cubes[0]->y0 != -2 && arm0->visible) + { + delete arm0; + arm0 = new ModelPart(this, 24 + 16, 16); + arm0->addHumanoidBox(-3, -2, -2, 4, 12, 4, 1.0f); // Arm0 + arm0->setPos(-5, 2 + m_fYOffset, 0); + arm0->compile(1.0f/16.0f); + } + if (!hasArmorOffsets[3] && arm1->cubes[0]->y0 != -2 && arm1->visible) + { + delete arm1; + arm1 = new ModelPart(this, 24 + 16, 16); + arm1->bMirror = true; + arm1->addHumanoidBox(-1, -2, -2, 4, 12, 4, 1.0f); // Arm1 + arm1->setPos(5, 2 + m_fYOffset, 0); + arm1->compile(1.0f/16.0f); + } + if (!hasArmorOffsets[4] && leg0->cubes[0]->y0 != 0 && leg0->visible) + { + delete leg0; + leg0 = new ModelPart(this, 0, 16); + if (leg0->isArmorPart2) + { + leg0->addHumanoidBox(-2, 0, -2, 4, 12, 4, 0.5f); // Leg0 + leg0->isArmorPart2 = true; + } + else + leg0->addHumanoidBox(-2, 0, -2, 4, 12, 4, 1.0f); // Leg0 + leg0->setPos(-1.9, 12 + m_fYOffset, 0); + leg0->compile(1.0f/16.0f); + } + if (!hasArmorOffsets[5] && leg1->cubes[0]->y0 != 0 && leg1->visible) + { + delete leg1; + leg1 = new ModelPart(this, 0, 16); + if (leg1->isArmorPart2) + { + leg1->addHumanoidBox(-2, 0, -2, 4, 12, 4, 0.5f); // Leg1 + leg1->isArmorPart2 = true; + } + else + leg1->addHumanoidBox(-2, 0, -2, 4, 12, 4, 1.0f); // Leg1 + leg1->setPos(1.9, 12 + m_fYOffset, 0); + leg1->compile(1.0f/16.0f); + } + } } setupAnim(time, r, bob, yRot, xRot, scale, entity, m_uiAnimOverrideBitmask); @@ -409,47 +654,331 @@ void HumanoidModel::render(shared_ptr entity, float time, float r, float glPopMatrix(); } else - { + { + glPushMatrix(); + glTranslatef(headOffsets[0], headOffsets[1], headOffsets[2]); head->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); + glPopMatrix(); + glPushMatrix(); + glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]); body->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); + glPopMatrix(); + glPushMatrix(); + glTranslatef(arm0Offsets[0], arm0Offsets[1], arm0Offsets[2]); arm0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); + glPopMatrix(); + glPushMatrix(); + glTranslatef(arm1Offsets[0], arm1Offsets[1], arm1Offsets[2]); arm1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); + glPopMatrix(); + glPushMatrix(); + glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); leg0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); + glPopMatrix(); + glPushMatrix(); + glTranslatef(leg1Offsets[0], leg1Offsets[1], leg1Offsets[2]); leg1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); + glPopMatrix(); + glPushMatrix(); + glTranslatef(headOffsets[0], headOffsets[1], headOffsets[2]); hair->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - - if (jacket) + glPopMatrix(); + if (jacket != 0) + { + glPushMatrix(); + glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]); jacket->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - if (sleeve0) + glPopMatrix(); + } + if (sleeve0 != 0) + { + glPushMatrix(); + glTranslatef(arm0Offsets[0], arm0Offsets[1], arm0Offsets[2]); sleeve0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - if (sleeve1) + glPopMatrix(); + } + if (sleeve1 != 0) + { + glPushMatrix(); + glTranslatef(arm1Offsets[0], arm1Offsets[1], arm1Offsets[2]); sleeve1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - if (pants0) + glPopMatrix(); + } + if (pants0 != 0) + { + glPushMatrix(); + glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); pants0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - if (pants1) + glPopMatrix(); + } + if (pants1 != 0) + { + glPushMatrix(); + glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); pants1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); + glPopMatrix(); + } if (waist != 0) waist->render(scale, usecompiled); - if (belt) + if (belt != 0) + { + glPushMatrix(); + glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]); belt->render(scale, usecompiled); - if (bodyArmor) + glPopMatrix(); + } + if (bodyArmor != 0) + { + glPushMatrix(); + glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]); bodyArmor->render(scale, usecompiled); - if (armArmor0) + glPopMatrix(); + } + if (armArmor0 != 0) + { + glPushMatrix(); + glTranslatef(arm0Offsets[0], arm0Offsets[1], arm0Offsets[2]); armArmor0->render(scale, usecompiled); - if (armArmor1) + glPopMatrix(); + } + if (armArmor1 != 0) + { + glPushMatrix(); + glTranslatef(arm1Offsets[0], arm1Offsets[1], arm1Offsets[2]); armArmor1->render(scale, usecompiled); - if (legging0) + glPopMatrix(); + } + if (legging0 != 0) + { + glPushMatrix(); + glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); legging0->render(scale, usecompiled); - if (legging1) + glPopMatrix(); + } + if (legging1 != 0) + { + glPushMatrix(); + glTranslatef(leg1Offsets[0], leg1Offsets[1], leg1Offsets[2]); legging1->render(scale, usecompiled); - if (sock0) + glPopMatrix(); + } + if (sock0 != 0) sock0->render(scale, usecompiled); - if (sock1) + if (sock1 != 0) sock1->render(scale, usecompiled); - if (boot0) + if (boot0 != 0) + { + glPushMatrix(); + glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); boot0->render(scale, usecompiled); - if (boot1) + glPopMatrix(); + } + if (boot1 != 0) + { + glPushMatrix(); + glTranslatef(leg1Offsets[0], leg1Offsets[1], leg1Offsets[2]); boot1->render(scale, usecompiled); + glPopMatrix(); + } + } +} + +// This code is similar to what's above, but allows skin offsets to work in the skin select menu - Langtanium +void HumanoidModel::renderUI(float time, float r, float bob, float yRot, float xRot, float scale, bool usecompiled, vector *skinOffsets) +{ + setupAnim(time, r, bob, yRot, xRot, scale, nullptr, m_uiAnimOverrideBitmask); + + vector headOffsets = {0, 0, 0}; + vector bodyOffsets = {0, 0, 0}; + vector arm0Offsets = {0, 0, 0}; + vector arm1Offsets = {0, 0, 0}; + vector leg0Offsets = {0, 0, 0}; + vector leg1Offsets = {0, 0, 0}; + vector* pSkinOffsets = nullptr; + if (skinOffsets != nullptr) + pSkinOffsets = skinOffsets; + if (pSkinOffsets != nullptr) + { + for( SKIN_OFFSET *pSkinOffset : *pSkinOffsets ) + { + switch (pSkinOffset->ePart) + { + case eBodyOffset_Head: + if(pSkinOffset->fD == 1) + headOffsets[0] = pSkinOffset->fO / 16.0f; + else if(pSkinOffset->fD == 2) + headOffsets[1] = pSkinOffset->fO / 16.0f; + else if(pSkinOffset->fD == 3) + headOffsets[2] = pSkinOffset->fO / 16.0f; + break; + case eBodyOffset_Body: + if(pSkinOffset->fD == 1) + bodyOffsets[0] = pSkinOffset->fO / 16.0f; + else if(pSkinOffset->fD == 2) + bodyOffsets[1] = pSkinOffset->fO / 16.0f; + else if(pSkinOffset->fD == 3) + bodyOffsets[2] = pSkinOffset->fO / 16.0f; + break; + case eBodyOffset_Arm0: + if(pSkinOffset->fD == 1) + arm0Offsets[0] = pSkinOffset->fO / 16.0f; + else if(pSkinOffset->fD == 2) + arm0Offsets[1] = pSkinOffset->fO / 16.0f; + else if(pSkinOffset->fD == 3) + arm0Offsets[2] = pSkinOffset->fO / 16.0f; + break; + case eBodyOffset_Arm1: + if(pSkinOffset->fD == 1) + arm1Offsets[0] = pSkinOffset->fO / 16.0f; + else if(pSkinOffset->fD == 2) + arm1Offsets[1] = pSkinOffset->fO / 16.0f; + else if(pSkinOffset->fD == 3) + arm1Offsets[2] = pSkinOffset->fO / 16.0f; + break; + case eBodyOffset_Leg0: + if(pSkinOffset->fD == 1) + leg0Offsets[0] = pSkinOffset->fO / 16.0f; + else if(pSkinOffset->fD == 2) + leg0Offsets[1] = pSkinOffset->fO / 16.0f; + else if(pSkinOffset->fD == 3) + leg0Offsets[2] = pSkinOffset->fO / 16.0f; + break; + case eBodyOffset_Leg1: + if(pSkinOffset->fD == 1) + leg1Offsets[0] = pSkinOffset->fO / 16.0f; + else if(pSkinOffset->fD == 2) + leg1Offsets[1] = pSkinOffset->fO / 16.0f; + else if(pSkinOffset->fD == 3) + leg1Offsets[2] = pSkinOffset->fO / 16.0f; + break; + } + } + } + + glPushMatrix(); + glTranslatef(headOffsets[0], headOffsets[1], headOffsets[2]); + head->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); + glPopMatrix(); + glPushMatrix(); + glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]); + body->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); + glPopMatrix(); + glPushMatrix(); + glTranslatef(arm0Offsets[0], arm0Offsets[1], arm0Offsets[2]); + arm0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); + glPopMatrix(); + glPushMatrix(); + glTranslatef(arm1Offsets[0], arm1Offsets[1], arm1Offsets[2]); + arm1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); + glPopMatrix(); + glPushMatrix(); + glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); + leg0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); + glPopMatrix(); + glPushMatrix(); + glTranslatef(leg1Offsets[0], leg1Offsets[1], leg1Offsets[2]); + leg1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); + glPopMatrix(); + glPushMatrix(); + glTranslatef(headOffsets[0], headOffsets[1], headOffsets[2]); + hair->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); + glPopMatrix(); + if (jacket != 0) + { + glPushMatrix(); + glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]); + jacket->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); + glPopMatrix(); + } + if (sleeve0 != 0) + { + glPushMatrix(); + glTranslatef(arm0Offsets[0], arm0Offsets[1], arm0Offsets[2]); + sleeve0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); + glPopMatrix(); + } + if (sleeve1 != 0) + { + glPushMatrix(); + glTranslatef(arm1Offsets[0], arm1Offsets[1], arm1Offsets[2]); + sleeve1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); + glPopMatrix(); + } + if (pants0 != 0) + { + glPushMatrix(); + glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); + pants0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); + glPopMatrix(); + } + if (pants1 != 0) + { + glPushMatrix(); + glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); + pants1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); + glPopMatrix(); + } + if (waist != 0) + waist->render(scale, usecompiled); + if (belt != 0) + { + glPushMatrix(); + glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]); + belt->render(scale, usecompiled); + glPopMatrix(); + } + if (bodyArmor != 0) + { + glPushMatrix(); + glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]); + bodyArmor->render(scale, usecompiled); + glPopMatrix(); + } + if (armArmor0 != 0) + { + glPushMatrix(); + glTranslatef(arm0Offsets[0], arm0Offsets[1], arm0Offsets[2]); + armArmor0->render(scale, usecompiled); + glPopMatrix(); + } + if (armArmor1 != 0) + { + glPushMatrix(); + glTranslatef(arm1Offsets[0], arm1Offsets[1], arm1Offsets[2]); + armArmor1->render(scale, usecompiled); + glPopMatrix(); + } + if (legging0 != 0) + { + glPushMatrix(); + glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); + legging0->render(scale, usecompiled); + glPopMatrix(); + } + if (legging1 != 0) + { + glPushMatrix(); + glTranslatef(leg1Offsets[0], leg1Offsets[1], leg1Offsets[2]); + legging1->render(scale, usecompiled); + glPopMatrix(); + } + if (sock0 != 0) + sock0->render(scale, usecompiled); + if (sock1 != 0) + sock1->render(scale, usecompiled); + if (boot0 != 0) + { + glPushMatrix(); + glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); + boot0->render(scale, usecompiled); + glPopMatrix(); + } + if (boot1 != 0) + { + glPushMatrix(); + glTranslatef(leg1Offsets[0], leg1Offsets[1], leg1Offsets[2]); + boot1->render(scale, usecompiled); + glPopMatrix(); } } diff --git a/Minecraft.Client/HumanoidModel.h b/Minecraft.Client/HumanoidModel.h index 072e77ea..424509a7 100644 --- a/Minecraft.Client/HumanoidModel.h +++ b/Minecraft.Client/HumanoidModel.h @@ -79,12 +79,9 @@ public: HumanoidModel(float g, float yOffset, int texWidth, int texHeight); HumanoidModel(float g, float yOffset, int texWidth, int texHeight, bool slim); - virtual void render(shared_ptr entity, float time, float r, float bob, - float yRot, float xRot, float scale, bool usecompiled); - virtual void setupAnim(float time, float r, float bob, float yRot, float xRot, - float scale, shared_ptr entity, - unsigned int uiBitmaskOverrideAnim = 0); - + virtual void render(shared_ptr entity, float time, float r, float bob, float yRot, float xRot, float scale, bool usecompiled); + virtual void renderUI(float time, float r, float bob, float yRot, float xRot, float scale, bool usecompiled, vector *skinOffsets); + virtual void setupAnim(float time, float r, float bob, float yRot, float xRot, float scale, shared_ptr entity, unsigned int uiBitmaskOverrideAnim = 0); void renderHair(float scale, bool usecompiled); void renderEars(float scale, bool usecompiled); void renderCloak(float scale, bool usecompiled); diff --git a/Minecraft.Client/ModelPart.cpp b/Minecraft.Client/ModelPart.cpp index 152dc000..6a85df5c 100644 --- a/Minecraft.Client/ModelPart.cpp +++ b/Minecraft.Client/ModelPart.cpp @@ -15,6 +15,7 @@ void ModelPart::_init() visible = true; neverRender = false; hideWithArmor = 0L; + isArmorPart2 = false; x=y=z = 0.0f; xRot=yRot=zRot = 0.0f; translateX = translateY = translateZ = 0.0f; diff --git a/Minecraft.Client/ModelPart.h b/Minecraft.Client/ModelPart.h index 5e605aa9..0633e443 100644 --- a/Minecraft.Client/ModelPart.h +++ b/Minecraft.Client/ModelPart.h @@ -18,6 +18,7 @@ public: bool visible; bool neverRender; unsigned int hideWithArmor; + bool isArmorPart2; vector cubes; vector children; static const float RAD; diff --git a/Minecraft.Client/PlayerConnection.cpp b/Minecraft.Client/PlayerConnection.cpp index 166e03dc..aa4174c6 100644 --- a/Minecraft.Client/PlayerConnection.cpp +++ b/Minecraft.Client/PlayerConnection.cpp @@ -1593,9 +1593,10 @@ void PlayerConnection::handleTextureAndGeometry(shared_ptr *pvSkinBoxes = app.GetAdditionalSkinBoxes(packet->dwSkinID); + vector *pvSkinOffsets = app.GetSkinOffsets(packet->dwSkinID); unsigned int uiAnimOverrideBitmask= app.GetAnimOverrideBitmask(packet->dwSkinID); - send(std::make_shared(packet->textureName, pbData, dwTextureBytes, pvSkinBoxes, uiAnimOverrideBitmask)); + send(std::make_shared(packet->textureName, pbData, dwTextureBytes, pvSkinBoxes, pvSkinOffsets, uiAnimOverrideBitmask)); } } else @@ -1618,6 +1619,13 @@ void PlayerConnection::handleTextureAndGeometry(shared_ptrdwSkinID,packet->dwBoxC); #endif app.SetAdditionalSkinBoxes(packet->dwSkinID,packet->BoxDataA,packet->dwBoxC); + }// add the offsets to the app list + if(packet->dwOffsetC!=0) + { +#ifndef _CONTENT_PACKAGE + wprintf(L"Adding skin offsets for skin id %X, offset count %d\n",packet->dwSkinID,packet->dwOffsetC); +#endif + app.SetSkinOffsets(packet->dwSkinID,packet->OffsetDataA,packet->dwOffsetC); } // Add the anim override app.SetAnimOverrideBitmask(packet->dwSkinID,packet->uiAnimOverrideBitmask); @@ -1668,9 +1676,10 @@ void PlayerConnection::handleTextureAndGeometryReceived(const wstring &textureNa // get the data from the app DWORD dwSkinID = app.getSkinIdFromPath(textureName); vector *pvSkinBoxes = app.GetAdditionalSkinBoxes(dwSkinID); + vector *pvSkinOffsets = app.GetSkinOffsets(dwSkinID); unsigned int uiAnimOverrideBitmask= app.GetAnimOverrideBitmask(dwSkinID); - send(std::make_shared(textureName, pbData, dwTextureBytes, pvSkinBoxes, uiAnimOverrideBitmask)); + send(std::make_shared(textureName, pbData, dwTextureBytes, pvSkinBoxes, pvSkinOffsets, uiAnimOverrideBitmask)); } m_texturesRequested.erase(it); } diff --git a/Minecraft.Client/PlayerRenderer.cpp b/Minecraft.Client/PlayerRenderer.cpp index ba8169ff..dfd041fd 100644 --- a/Minecraft.Client/PlayerRenderer.cpp +++ b/Minecraft.Client/PlayerRenderer.cpp @@ -124,6 +124,10 @@ int PlayerRenderer::prepareArmor(shared_ptr _player, int layer, fl armor->leg0->visible = layer == 2 || layer == 3; armor->leg1->visible = layer == 2 || layer == 3; + armor->body->isArmorPart2 = layer == 2; + armor->leg0->isArmorPart2 = layer == 2; + armor->leg1->isArmorPart2 = layer == 2; + setArmor(armor); if (armor != nullptr) armor->attackTime = resModel->attackTime; if (armor != nullptr) armor->riding = resModel->riding; diff --git a/Minecraft.World/Player.cpp b/Minecraft.World/Player.cpp index b4820390..01d45328 100644 --- a/Minecraft.World/Player.cpp +++ b/Minecraft.World/Player.cpp @@ -110,6 +110,10 @@ void Player::_init() m_bCheckedForModelParts=false; m_bCheckedDLCForModelParts=false; + m_ppSkinOffsets=nullptr; + m_bCheckedForSkinOffsets=false; + m_bCheckedDLCForSkinOffsets=false; + #if defined(__PS3__) || defined(__ORBIS__) m_ePlayerNameValidState=ePlayerNameValid_NotSet; #endif @@ -724,21 +728,9 @@ void Player::setCustomSkin(DWORD skinId) m_bCheckedDLCForModelParts=false; this->SetAdditionalModelParts(nullptr); - -} - -int Player::GetModelTypeFromAnimBitmask(unsigned int animBitmask) -{ - if (animBitmask&(1< 8 && textureId < 18) return 2; - else if (textureId == 18) return 1; - else return 0; + m_bCheckedForSkinOffsets=false; + m_bCheckedDLCForSkinOffsets=false; + this->SetSkinOffsets(nullptr); } unsigned int Player::getSkinAnimOverrideBitmask(DWORD skinId) @@ -3403,11 +3395,71 @@ vector *Player::GetAdditionalModelParts() return m_ppAdditionalModelParts; } +vector *Player::GetSkinOffsets() +{ + if(m_ppSkinOffsets==nullptr && !m_bCheckedForSkinOffsets) + { + bool hasCustomTexture = !customTextureUrl.empty(); + bool customTextureIsDefaultSkin = customTextureUrl.substr(0,3).compare(L"def") == 0; + + // see if we can find the parts + m_ppSkinOffsets=app.GetSkinOffsets(m_dwSkinId); + + // If it's a default texture (which has no parts), we have the parts, or we already have the texture (in which case we should have parts if there are any) then we are done + if(!hasCustomTexture || customTextureIsDefaultSkin || m_ppSkinOffsets != nullptr || app.IsFileInMemoryTextures(customTextureUrl)) + { + m_bCheckedForSkinOffsets=true; + } + if(m_ppSkinOffsets == nullptr && !m_bCheckedDLCForSkinOffsets) + { + m_bCheckedDLCForSkinOffsets = true; + + // we don't have the data from the dlc skin yet + app.DebugPrintf("m_bCheckedForModelOffsets Couldn't get skin offsets for skin %X\n",m_dwSkinId); + + // do we have it from the DLC pack? + DLCSkinFile *pDLCSkinFile = app.m_dlcManager.getSkinFile(this->customTextureUrl); + + if(pDLCSkinFile!=nullptr) + { + DWORD dwOffsetC=pDLCSkinFile->getOffsetsCount(); + if(dwOffsetC!=0) + { + app.DebugPrintf("m_bCheckedForSkinOffsets Got skin offsets from DLCskin for skin %X\n",m_dwSkinId); + m_ppSkinOffsets=app.SetSkinOffsets(m_dwSkinId,pDLCSkinFile->getOffsets()); + } + + m_bCheckedForSkinOffsets=true; + } + } + } + return m_ppSkinOffsets; +} + +int Player::GetModelTypeFromAnimBitmask(unsigned int animBitmask) +{ + if (animBitmask&(1< 8 && textureId < 18) return 2; + else if (textureId == 18) return 1; + else return 0; +} + void Player::SetAdditionalModelParts(vector *ppAdditionalModelParts) { m_ppAdditionalModelParts=ppAdditionalModelParts; } +void Player::SetSkinOffsets(vector *ppSkinOffsets) +{ + m_ppSkinOffsets=ppSkinOffsets; +} + #if defined(__PS3__) || defined(__ORBIS__) Player::ePlayerNameValidState Player::GetPlayerNameValidState(void) diff --git a/Minecraft.World/Player.h b/Minecraft.World/Player.h index ecaddafa..6b25bc2d 100644 --- a/Minecraft.World/Player.h +++ b/Minecraft.World/Player.h @@ -555,6 +555,8 @@ public: vector *GetAdditionalModelParts(); void SetAdditionalModelParts(vector *ppAdditionalModelParts); + vector *GetSkinOffsets(); + void SetSkinOffsets(vector *ppSkinOffsets); #if defined(__PS3__) || defined(__ORBIS__) enum ePlayerNameValidState @@ -571,6 +573,9 @@ private: vector *m_ppAdditionalModelParts; bool m_bCheckedForModelParts; bool m_bCheckedDLCForModelParts; + vector *m_ppSkinOffsets; + bool m_bCheckedForSkinOffsets; + bool m_bCheckedDLCForSkinOffsets; #if defined(__PS3__) || defined(__ORBIS__) ePlayerNameValidState m_ePlayerNameValidState; // 4J-PB - to ensure we have the characters for this name in our font, or display a player number instead diff --git a/Minecraft.World/TextureAndGeometryPacket.cpp b/Minecraft.World/TextureAndGeometryPacket.cpp index 41fe933f..44309caa 100644 --- a/Minecraft.World/TextureAndGeometryPacket.cpp +++ b/Minecraft.World/TextureAndGeometryPacket.cpp @@ -12,7 +12,9 @@ TextureAndGeometryPacket::TextureAndGeometryPacket() this->dwTextureBytes = 0; this->pbData = nullptr; this->dwBoxC = 0; + this->dwOffsetC = 0; this->BoxDataA = nullptr; + this->OffsetDataA = nullptr; uiAnimOverrideBitmask=0; } @@ -43,7 +45,9 @@ TextureAndGeometryPacket::TextureAndGeometryPacket(const wstring &textureName, P this->pbData = pbData; this->dwTextureBytes = dwBytes; this->dwBoxC = 0; + this->dwOffsetC = 0; this->BoxDataA=nullptr; + this->OffsetDataA=nullptr; this->uiAnimOverrideBitmask=0; } @@ -62,6 +66,7 @@ TextureAndGeometryPacket::TextureAndGeometryPacket(const wstring &textureName, P this->dwTextureBytes = dwBytes; this->uiAnimOverrideBitmask = pDLCSkinFile->getAnimOverrideBitmask(); this->dwBoxC = pDLCSkinFile->getAdditionalBoxesCount(); + this->dwOffsetC = pDLCSkinFile->getOffsetsCount(); if(this->dwBoxC!=0) { this->BoxDataA= new SKIN_BOX [this->dwBoxC]; @@ -77,9 +82,24 @@ TextureAndGeometryPacket::TextureAndGeometryPacket(const wstring &textureName, P { this->BoxDataA=nullptr; } + if(this->dwOffsetC!=0) + { + this->OffsetDataA= new SKIN_OFFSET [this->dwOffsetC]; + vector *pSkinOffsets=pDLCSkinFile->getOffsets(); + int iCount=0; + + for(auto& pSkinOffset : *pSkinOffsets) + { + this->OffsetDataA[iCount++]=*pSkinOffset; + } + } + else + { + this->OffsetDataA=nullptr; + } } -TextureAndGeometryPacket::TextureAndGeometryPacket(const wstring &textureName, PBYTE pbData, DWORD dwBytes,vector *pvSkinBoxes, unsigned int uiAnimOverrideBitmask) +TextureAndGeometryPacket::TextureAndGeometryPacket(const wstring &textureName, PBYTE pbData, DWORD dwBytes, vector *pvSkinBoxes, vector *pvSkinOffsets, unsigned int uiAnimOverrideBitmask) { this->textureName = textureName; @@ -109,6 +129,22 @@ TextureAndGeometryPacket::TextureAndGeometryPacket(const wstring &textureName, P this->BoxDataA[iCount++]=*pSkinBox; } } + if(pvSkinOffsets==nullptr) + { + this->dwOffsetC=0; + this->OffsetDataA=nullptr; + } + else + { + this->dwOffsetC = static_cast(pvSkinOffsets->size()); + this->OffsetDataA= new SKIN_OFFSET [this->dwOffsetC]; + int iCount=0; + + for(auto& pSkinOffset : *pvSkinOffsets) + { + this->OffsetDataA[iCount++]=*pSkinOffset; + } + } } @@ -148,6 +184,7 @@ void TextureAndGeometryPacket::read(DataInputStream *dis) //throws IOException uiAnimOverrideBitmask = dis->readInt(); short rawBoxC = dis->readShort(); + short rawOffsetC = dis->readShort(); if (rawBoxC <= 0) { dwBoxC = 0; @@ -160,11 +197,27 @@ void TextureAndGeometryPacket::read(DataInputStream *dis) //throws IOException dwBoxC = 0; // sane limit for skin boxes } } + if (rawOffsetC <= 0) + { + dwOffsetC = 0; + } + else + { + dwOffsetC = (DWORD)(unsigned short)rawOffsetC; + if (dwOffsetC > 256) + { + dwOffsetC = 0; // sane limit for skin offsets + } + } if(dwBoxC>0) { this->BoxDataA= new SKIN_BOX [dwBoxC]; } + if(dwOffsetC>0) + { + this->OffsetDataA= new SKIN_OFFSET [dwOffsetC]; + } for(DWORD i=0;iBoxDataA[i].fM = dis->readFloat(); this->BoxDataA[i].fS = dis->readFloat(); } + for(DWORD i=0;iOffsetDataA[i].ePart = static_cast(dis->readShort()); + this->OffsetDataA[i].fD = dis->readFloat(); + this->OffsetDataA[i].fO = dis->readFloat(); + } } -void TextureAndGeometryPacket::write(DataOutputStream *dos) //throws IOException +void __fastcall TextureAndGeometryPacket::write(DataOutputStream *dos) //throws IOException { dos->writeUTF(textureName); dos->writeInt(dwSkinID); @@ -210,6 +269,14 @@ void TextureAndGeometryPacket::write(DataOutputStream *dos) //throws IOException dos->writeFloat(this->BoxDataA[i].fM); dos->writeFloat(this->BoxDataA[i].fS); } + + dos->writeShort(static_cast(dwOffsetC)); + for(DWORD i=0;iwriteShort(static_cast(this->OffsetDataA[i].ePart)); + dos->writeFloat(this->OffsetDataA[i].fD); + dos->writeFloat(this->OffsetDataA[i].fO); + } } int TextureAndGeometryPacket::getEstimatedSize() diff --git a/Minecraft.World/TextureAndGeometryPacket.h b/Minecraft.World/TextureAndGeometryPacket.h index fa0a5837..245edd2a 100644 --- a/Minecraft.World/TextureAndGeometryPacket.h +++ b/Minecraft.World/TextureAndGeometryPacket.h @@ -4,6 +4,7 @@ using namespace std; #include "Packet.h" #include "../Minecraft.Client/Model.h" #include "../Minecraft.Client/SkinBox.h" +#include "../Minecraft.Client/SkinOffset.h" class DLCSkinFile; @@ -15,14 +16,16 @@ public: PBYTE pbData; DWORD dwTextureBytes; SKIN_BOX *BoxDataA; + SKIN_OFFSET *OffsetDataA; DWORD dwBoxC; + DWORD dwOffsetC; unsigned int uiAnimOverrideBitmask; TextureAndGeometryPacket(); ~TextureAndGeometryPacket(); TextureAndGeometryPacket(const wstring &textureName, PBYTE pbData, DWORD dwBytes); TextureAndGeometryPacket(const wstring &textureName, PBYTE pbData, DWORD dwBytes, DLCSkinFile *pDLCSkinFile); - TextureAndGeometryPacket(const wstring &textureName, PBYTE pbData, DWORD dwBytes, vector *pvSkinBoxes, unsigned int uiAnimOverrideBitmask); + TextureAndGeometryPacket(const wstring &textureName, PBYTE pbData, DWORD dwBytes, vector *pvSkinBoxes, vector *pvSkinOffsets, unsigned int uiAnimOverrideBitmask); virtual void handle(PacketListener *listener); virtual void read(DataInputStream *dis); From 809bb109307195825a35d0e13704d11f9d509dc9 Mon Sep 17 00:00:00 2001 From: Langtanium <94726057+Langtanium@users.noreply.github.com> Date: Tue, 26 May 2026 12:23:31 -0700 Subject: [PATCH 6/9] Removed armor offsets Removed armor offsets as they would call the compile() function so many times overflowing memory triggering a safeguard which terminates the process. --- Minecraft.Client/HumanoidModel.cpp | 176 ----------------------------- 1 file changed, 176 deletions(-) diff --git a/Minecraft.Client/HumanoidModel.cpp b/Minecraft.Client/HumanoidModel.cpp index eb8840c2..9a5be78c 100644 --- a/Minecraft.Client/HumanoidModel.cpp +++ b/Minecraft.Client/HumanoidModel.cpp @@ -439,185 +439,9 @@ void HumanoidModel::render(shared_ptr entity, float time, float r, float else if (pSkinOffset->fD == 3) leg1Offsets[2] += pSkinOffset->fO / 16.0f; break; - case eBodyOffset_Helmet: - if (m_isArmor && !head->isArmorPart2 && head->visible) - { - hasArmorOffsets[0] = true; - delete head; - head = new ModelPart(this, 0, 0); - head->addHumanoidBox(-4, -8 + pSkinOffset->fO, -4, 8, 8, 8, 1.0f); // Head - head->setPos(0, 0 + m_fYOffset, 0); - head->compile(1.0f/16.0f); - } - break; - case eBodyOffset_BodyArmor: - if (m_isArmor && !body->isArmorPart2 && body->visible) - { - hasArmorOffsets[1] = true; - delete body; - body = new ModelPart(this, 16, 16); - body->addHumanoidBox(-4, 0 + pSkinOffset->fO, -2, 8, 12, 4, 1.0f); // Body - body->setPos(0, 0 + m_fYOffset, 0); - body->compile(1.0f/16.0f); - } - break; - case eBodyOffset_ArmArmor0: - if (m_isArmor && !arm0->isArmorPart2 && arm0->visible) - { - hasArmorOffsets[2] = true; - delete arm0; - arm0 = new ModelPart(this, 24 + 16, 16); - arm0->addHumanoidBox(-3, -2 + pSkinOffset->fO, -2, 4, 12, 4, 1.0f); // Arm0 - arm0->setPos(-5, 2 + m_fYOffset, 0); - arm0->compile(1.0f/16.0f); - } - break; - case eBodyOffset_ArmArmor1: - if (m_isArmor && !arm1->isArmorPart2 && arm1->visible) - { - hasArmorOffsets[3] = true; - delete arm1; - arm1 = new ModelPart(this, 24 + 16, 16); - arm1->bMirror = true; - arm1->addHumanoidBox(-1, -2 + pSkinOffset->fO, -2, 4, 12, 4, 1.0f); // Arm1 - arm1->setPos(5, 2 + m_fYOffset, 0); - arm1->compile(1.0f/16.0f); - } - break; - case eBodyOffset_Belt: - if (m_isArmor && body->isArmorPart2 && body->visible) - { - hasArmorOffsets[1] = true; - delete body; - body = new ModelPart(this, 16, 16); - body->addHumanoidBox(-4, 0 + pSkinOffset->fO, -2, 8, 12, 4, 0.5f); // Body - body->setPos(0, 0 + m_fYOffset, 0); - body->compile(1.0f/16.0f); - body->isArmorPart2 = true; - } - break; - case eBodyOffset_Legging0: - if (m_isArmor && leg0->isArmorPart2 && leg0->visible) - { - hasArmorOffsets[4] = true; - delete leg0; - leg0 = new ModelPart(this, 0, 16); - leg0->addHumanoidBox(-2, 0 + pSkinOffset->fO, -2, 4, 12, 4, 0.5f); // Leg0 - leg0->setPos(-1.9, 12 + m_fYOffset, 0); - leg0->compile(1.0f/16.0f); - leg0->isArmorPart2 = true; - } - break; - case eBodyOffset_Legging1: - if (m_isArmor && leg1->isArmorPart2 && leg1->visible) - { - hasArmorOffsets[5] = true; - delete leg1; - leg1 = new ModelPart(this, 0, 16); - leg1->bMirror = true; - leg1->addHumanoidBox(-2, 0 + pSkinOffset->fO, -2, 4, 12, 4, 0.5f); // Leg1 - leg1->setPos(1.9, 12 + m_fYOffset, 0); - leg1->compile(1.0f/16.0f); - leg1->isArmorPart2 = true; - } - break; - case eBodyOffset_Boot0: - if (m_isArmor && !leg0->isArmorPart2 && leg0->visible) - { - hasArmorOffsets[4] = true; - delete leg0; - leg0 = new ModelPart(this, 0, 16); - leg0->addHumanoidBox(-2, 0 + pSkinOffset->fO, -2, 4, 12, 4, 1.0f); // Leg0 - leg0->setPos(-1.9, 12 + m_fYOffset, 0); - leg0->compile(1.0f/16.0f); - } - break; - case eBodyOffset_Boot1: - if (m_isArmor && !leg1->isArmorPart2 && leg1->visible) - { - hasArmorOffsets[5] = true; - delete leg1; - leg1 = new ModelPart(this, 0, 16); - leg1->bMirror = true; - leg1->addHumanoidBox(-2, 0 + pSkinOffset->fO, -2, 4, 12, 4, 1.0f); // Leg1 - leg1->setPos(1.9, 12 + m_fYOffset, 0); - leg1->compile(1.0f/16.0f); - } - break; } } } - - if (m_isArmor) - { - if (!hasArmorOffsets[0] && head->cubes[0]->y0 != -8 && head->visible) - { - delete head; - head = new ModelPart(this, 0, 0); - head->addHumanoidBox(-4, -8, -4, 8, 8, 8, 1.0f); // Head - head->setPos(0, 0 + m_fYOffset, 0); - head->compile(1.0f/16.0f); - } - if (!hasArmorOffsets[1] && body->cubes[0]->y0 != 0 && body->visible) - { - delete body; - body = new ModelPart(this, 16, 16); - if (body->isArmorPart2) - { - body->addHumanoidBox(-4, 0, -2, 8, 12, 4, 0.5f); // Body - body->isArmorPart2 = true; - } - else - body->addHumanoidBox(-4, 0, -2, 8, 12, 4, 1.0f); // Body - body->setPos(0, 0 + m_fYOffset, 0); - body->compile(1.0f/16.0f); - } - if (!hasArmorOffsets[2] && arm0->cubes[0]->y0 != -2 && arm0->visible) - { - delete arm0; - arm0 = new ModelPart(this, 24 + 16, 16); - arm0->addHumanoidBox(-3, -2, -2, 4, 12, 4, 1.0f); // Arm0 - arm0->setPos(-5, 2 + m_fYOffset, 0); - arm0->compile(1.0f/16.0f); - } - if (!hasArmorOffsets[3] && arm1->cubes[0]->y0 != -2 && arm1->visible) - { - delete arm1; - arm1 = new ModelPart(this, 24 + 16, 16); - arm1->bMirror = true; - arm1->addHumanoidBox(-1, -2, -2, 4, 12, 4, 1.0f); // Arm1 - arm1->setPos(5, 2 + m_fYOffset, 0); - arm1->compile(1.0f/16.0f); - } - if (!hasArmorOffsets[4] && leg0->cubes[0]->y0 != 0 && leg0->visible) - { - delete leg0; - leg0 = new ModelPart(this, 0, 16); - if (leg0->isArmorPart2) - { - leg0->addHumanoidBox(-2, 0, -2, 4, 12, 4, 0.5f); // Leg0 - leg0->isArmorPart2 = true; - } - else - leg0->addHumanoidBox(-2, 0, -2, 4, 12, 4, 1.0f); // Leg0 - leg0->setPos(-1.9, 12 + m_fYOffset, 0); - leg0->compile(1.0f/16.0f); - } - if (!hasArmorOffsets[5] && leg1->cubes[0]->y0 != 0 && leg1->visible) - { - delete leg1; - leg1 = new ModelPart(this, 0, 16); - if (leg1->isArmorPart2) - { - leg1->addHumanoidBox(-2, 0, -2, 4, 12, 4, 0.5f); // Leg1 - leg1->isArmorPart2 = true; - } - else - leg1->addHumanoidBox(-2, 0, -2, 4, 12, 4, 1.0f); // Leg1 - leg1->setPos(1.9, 12 + m_fYOffset, 0); - leg1->compile(1.0f/16.0f); - } - } } setupAnim(time, r, bob, yRot, xRot, scale, entity, m_uiAnimOverrideBitmask); From 6880b6505fddc12615b48dc5e2e4fa693c18fea8 Mon Sep 17 00:00:00 2001 From: Langtanium <94726057+Langtanium@users.noreply.github.com> Date: Wed, 27 May 2026 18:39:27 -0700 Subject: [PATCH 7/9] Reworked skin offset code in HumanoidModel.cpp Changed skin offsets to use ModelPart values of translateX, translateY, and translateZ. Implemented armor offsets again (rotation origin is not correct). Fixed DLC skin box scale not being applied. --- Minecraft.Client/HumanoidModel.cpp | 438 ++++++++++++++++++++--------- 1 file changed, 306 insertions(+), 132 deletions(-) diff --git a/Minecraft.Client/HumanoidModel.cpp b/Minecraft.Client/HumanoidModel.cpp index 9a5be78c..29866d2a 100644 --- a/Minecraft.Client/HumanoidModel.cpp +++ b/Minecraft.Client/HumanoidModel.cpp @@ -112,9 +112,9 @@ ModelPart * HumanoidModel::AddOrRetrievePart(SKIN_BOX *pBox) pNewBox->visible=false; if (pBox->fM > 0) pNewBox->bMirror = true; // check if this box has the mirror flag pNewBox->hideWithArmor = (unsigned int)pBox->fA; // add the "hide when armor is worn" bit flags - pNewBox->addHumanoidBox(pBox->fX, pBox->fY, pBox->fZ, pBox->fW, pBox->fH, pBox->fD, 0); + 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); + //pNewBox->compile(1.0f/16.0f); pAttachTo->addChild(pNewBox); } @@ -369,13 +369,12 @@ HumanoidModel::HumanoidModel(float g, float yOffset, int texWidth, int texHeight void HumanoidModel::render(shared_ptr entity, float time, float r, float bob, float yRot, float xRot, float scale, bool usecompiled) { - vector hasArmorOffsets = {false, false, false, false, false, false}; - vector headOffsets = {0, 0, 0}; - vector bodyOffsets = {0, 0, 0}; - vector arm0Offsets = {0, 0, 0}; - vector arm1Offsets = {0, 0, 0}; - vector leg0Offsets = {0, 0, 0}; - vector leg1Offsets = {0, 0, 0}; + float headOffsets[3] = {0}; + float bodyOffsets[3] = {0}; + float arm0Offsets[3] = {0}; + float arm1Offsets[3] = {0}; + float leg0Offsets[3] = {0}; + float leg1Offsets[3] = {0}; if(entity != nullptr) { @@ -392,52 +391,313 @@ void HumanoidModel::render(shared_ptr entity, float time, float r, float switch (pSkinOffset->ePart) { case eBodyOffset_Head: - if (pSkinOffset->fD == 1) - headOffsets[0] += pSkinOffset->fO / 16.0f; - else if (pSkinOffset->fD == 2) - headOffsets[1] += pSkinOffset->fO / 16.0f; - else if (pSkinOffset->fD == 3) - headOffsets[2] += pSkinOffset->fO / 16.0f; + if (pSkinOffset->fD == 1 && head->translateX == 0) + { + head->translateX = pSkinOffset->fO / 16.0f; + hair->translateX = pSkinOffset->fO / 16.0f; + headOffsets[0] = pSkinOffset->fO / 16.0f; + } + else if (pSkinOffset->fD == 2 && head->translateY == 0) + { + head->translateY = pSkinOffset->fO / 16.0f; + hair->translateY = pSkinOffset->fO / 16.0f; + headOffsets[1] = pSkinOffset->fO / 16.0f; + } + else if (pSkinOffset->fD == 3 && head->translateZ == 0) + { + head->translateZ = pSkinOffset->fO / 16.0f; + hair->translateZ = pSkinOffset->fO / 16.0f; + headOffsets[2] = pSkinOffset->fO / 16.0f; + } break; case eBodyOffset_Body: - if (pSkinOffset->fD == 1) - bodyOffsets[0] += pSkinOffset->fO / 16.0f; - else if (pSkinOffset->fD == 2) - bodyOffsets[1] += pSkinOffset->fO / 16.0f; - else if (pSkinOffset->fD == 3) - bodyOffsets[2] += pSkinOffset->fO / 16.0f; + if (pSkinOffset->fD == 1 && body->translateX == 0) + { + body->translateX = pSkinOffset->fO / 16.0f; + if (jacket) + jacket->translateX = pSkinOffset->fO / 16.0f; + if (bodyArmor) + bodyArmor->translateX = pSkinOffset->fO / 16.0f; + if (waist) + waist->translateX = pSkinOffset->fO / 16.0f; + if (belt) + belt->translateX = pSkinOffset->fO / 16.0f; + bodyOffsets[0] = pSkinOffset->fO / 16.0f; + } + else if (pSkinOffset->fD == 2 && body->translateY == 0) + { + body->translateY = pSkinOffset->fO / 16.0f; + if (jacket) + jacket->translateY = pSkinOffset->fO / 16.0f; + if (bodyArmor) + bodyArmor->translateY = pSkinOffset->fO / 16.0f; + if (waist) + waist->translateY = pSkinOffset->fO / 16.0f; + if (belt) + belt->translateY = pSkinOffset->fO / 16.0f; + bodyOffsets[1] = pSkinOffset->fO / 16.0f; + } + else if (pSkinOffset->fD == 3 && body->translateZ == 0) + { + body->translateZ = pSkinOffset->fO / 16.0f; + if (jacket) + jacket->translateZ = pSkinOffset->fO / 16.0f; + if (bodyArmor) + bodyArmor->translateZ = pSkinOffset->fO / 16.0f; + if (waist) + waist->translateZ = pSkinOffset->fO / 16.0f; + if (belt) + belt->translateZ = pSkinOffset->fO / 16.0f; + bodyOffsets[2] = pSkinOffset->fO / 16.0f; + } break; case eBodyOffset_Arm0: - if (pSkinOffset->fD == 1) - arm0Offsets[0] += pSkinOffset->fO / 16.0f; - else if (pSkinOffset->fD == 2) - arm0Offsets[1] += pSkinOffset->fO / 16.0f; - else if (pSkinOffset->fD == 3) - arm0Offsets[2] += pSkinOffset->fO / 16.0f; + if (pSkinOffset->fD == 1 && arm0->translateX == 0) + { + arm0->translateX = pSkinOffset->fO / 16.0f; + if (sleeve0) + sleeve0->translateX = pSkinOffset->fO / 16.0f; + if (armArmor0) + armArmor0->translateX = pSkinOffset->fO / 16.0f; + arm0Offsets[0] = pSkinOffset->fO / 16.0f; + } + else if (pSkinOffset->fD == 2 && arm0->translateY == 0) + { + arm0->translateY = pSkinOffset->fO / 16.0f; + if (sleeve0) + sleeve0->translateY = pSkinOffset->fO / 16.0f; + if (armArmor0) + armArmor0->translateY = pSkinOffset->fO / 16.0f; + arm0Offsets[1] = pSkinOffset->fO / 16.0f; + } + else if (pSkinOffset->fD == 3 && arm0->translateZ == 0) + { + arm0->translateZ = pSkinOffset->fO / 16.0f; + if (sleeve0) + sleeve0->translateZ = pSkinOffset->fO / 16.0f; + if (armArmor0) + armArmor0->translateZ = pSkinOffset->fO / 16.0f; + arm0Offsets[2] = pSkinOffset->fO / 16.0f; + } break; case eBodyOffset_Arm1: - if (pSkinOffset->fD == 1) - arm1Offsets[0] += pSkinOffset->fO / 16.0f; - else if (pSkinOffset->fD == 2) - arm1Offsets[1] += pSkinOffset->fO / 16.0f; - else if (pSkinOffset->fD == 3) - arm1Offsets[2] += pSkinOffset->fO / 16.0f; + if (pSkinOffset->fD == 1 && arm1->translateX == 0) + { + arm1->translateX = pSkinOffset->fO / 16.0f; + if (sleeve1) + sleeve1->translateX = pSkinOffset->fO / 16.0f; + if (armArmor1) + armArmor1->translateX = pSkinOffset->fO / 16.0f; + arm1Offsets[0] = pSkinOffset->fO / 16.0f; + } + else if (pSkinOffset->fD == 2 && arm1->translateY == 0) + { + arm1->translateY = pSkinOffset->fO / 16.0f; + if (sleeve1) + sleeve1->translateY = pSkinOffset->fO / 16.0f; + if (armArmor1) + armArmor1->translateY = pSkinOffset->fO / 16.0f; + arm1Offsets[1] = pSkinOffset->fO / 16.0f; + } + else if (pSkinOffset->fD == 3 && arm1->translateZ == 0) + { + arm1->translateZ = pSkinOffset->fO / 16.0f; + if (sleeve1) + sleeve1->translateZ = pSkinOffset->fO / 16.0f; + if (armArmor1) + armArmor1->translateZ = pSkinOffset->fO / 16.0f; + arm1Offsets[2] = pSkinOffset->fO / 16.0f; + } break; case eBodyOffset_Leg0: - if (pSkinOffset->fD == 1) - leg0Offsets[0] += pSkinOffset->fO / 16.0f; - else if (pSkinOffset->fD == 2) - leg0Offsets[1] += pSkinOffset->fO / 16.0f; - else if (pSkinOffset->fD == 3) - leg0Offsets[2] += pSkinOffset->fO / 16.0f; + if (pSkinOffset->fD == 1 && leg0->translateX == 0) + { + leg0->translateX = pSkinOffset->fO / 16.0f; + if (pants0) + pants0->translateX = pSkinOffset->fO / 16.0f; + if (legging0) + legging0->translateX = pSkinOffset->fO / 16.0f; + if (sock0) + sock0->translateX = pSkinOffset->fO / 16.0f; + if (boot0) + boot0->translateX = pSkinOffset->fO / 16.0f; + leg0Offsets[0] = pSkinOffset->fO / 16.0f; + } + else if (pSkinOffset->fD == 2 && leg0->translateY == 0) + { + leg0->translateY = pSkinOffset->fO / 16.0f; + if (pants0) + pants0->translateY = pSkinOffset->fO / 16.0f; + if (legging0) + legging0->translateY = pSkinOffset->fO / 16.0f; + if (sock0) + sock0->translateY = pSkinOffset->fO / 16.0f; + if (boot0) + boot0->translateY = pSkinOffset->fO / 16.0f; + leg0Offsets[1] = pSkinOffset->fO / 16.0f; + } + else if (pSkinOffset->fD == 3 && leg0->translateZ == 0) + { + leg0->translateZ = pSkinOffset->fO / 16.0f; + if (pants0) + pants0->translateZ = pSkinOffset->fO / 16.0f; + if (legging0) + legging0->translateZ = pSkinOffset->fO / 16.0f; + if (sock0) + sock0->translateZ = pSkinOffset->fO / 16.0f; + if (boot0) + boot0->translateZ = pSkinOffset->fO / 16.0f; + leg0Offsets[2] = pSkinOffset->fO / 16.0f; + } break; case eBodyOffset_Leg1: - if (pSkinOffset->fD == 1) - leg1Offsets[0] += pSkinOffset->fO / 16.0f; - else if (pSkinOffset->fD == 2) - leg1Offsets[1] += pSkinOffset->fO / 16.0f; - else if (pSkinOffset->fD == 3) - leg1Offsets[2] += pSkinOffset->fO / 16.0f; + if (pSkinOffset->fD == 1 && leg1->translateX == 0) + { + leg1->translateX = pSkinOffset->fO / 16.0f; + if (pants1) + pants1->translateX = pSkinOffset->fO / 16.0f; + if (legging1) + legging1->translateX = pSkinOffset->fO / 16.0f; + if (sock1) + sock1->translateX = pSkinOffset->fO / 16.0f; + if (boot1) + boot1->translateX = pSkinOffset->fO / 16.0f; + leg1Offsets[0] = pSkinOffset->fO / 16.0f; + } + else if (pSkinOffset->fD == 2 && leg1->translateY == 0) + { + leg1->translateY = pSkinOffset->fO / 16.0f; + if (pants1) + pants1->translateY = pSkinOffset->fO / 16.0f; + if (legging1) + legging1->translateY = pSkinOffset->fO / 16.0f; + if (sock1) + sock1->translateY = pSkinOffset->fO / 16.0f; + if (boot1) + boot1->translateY = pSkinOffset->fO / 16.0f; + leg1Offsets[1] = pSkinOffset->fO / 16.0f; + } + else if (pSkinOffset->fD == 3 && leg1->translateZ == 0) + { + leg1->translateZ = pSkinOffset->fO / 16.0f; + if (pants1) + pants1->translateZ = pSkinOffset->fO / 16.0f; + if (legging1) + legging1->translateZ = pSkinOffset->fO / 16.0f; + if (sock1) + sock1->translateZ = pSkinOffset->fO / 16.0f; + if (boot1) + boot1->translateZ = pSkinOffset->fO / 16.0f; + leg1Offsets[2] = pSkinOffset->fO / 16.0f; + } + break; + case eBodyOffset_Helmet: + if (m_isArmor) + { + if (pSkinOffset->fD == 1 && head->translateX == headOffsets[0]) + { + head->translateX += pSkinOffset->fO / 16.0f; + hair->translateX += pSkinOffset->fO / 16.0f; + } + else if (pSkinOffset->fD == 2 && head->translateY == headOffsets[1]) + { + head->translateY += pSkinOffset->fO / 16.0f; + hair->translateY += pSkinOffset->fO / 16.0f; + } + else if (pSkinOffset->fD == 3 && head->translateZ == headOffsets[2]) + { + head->translateZ += pSkinOffset->fO / 16.0f; + hair->translateZ += pSkinOffset->fO / 16.0f; + } + } + break; + case eBodyOffset_BodyArmor: + if (m_isArmor && !body->isArmorPart2) + { + if (pSkinOffset->fD == 1 && body->translateX == bodyOffsets[0]) + body->translateX += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 2 && body->translateY == bodyOffsets[1]) + body->translateY += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 3 && body->translateZ == bodyOffsets[2]) + body->translateZ += pSkinOffset->fO / 16.0f; + } + break; + case eBodyOffset_ArmArmor0: + if (m_isArmor) + { + if (pSkinOffset->fD == 1 && arm0->translateX == arm0Offsets[0]) + arm0->translateX += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 2 && arm0->translateY == arm0Offsets[1]) + arm0->translateY += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 3 && arm0->translateZ == arm0Offsets[2]) + arm0->translateZ += pSkinOffset->fO / 16.0f; + } + break; + case eBodyOffset_ArmArmor1: + if (m_isArmor) + { + if (pSkinOffset->fD == 1 && arm1->translateX == arm1Offsets[0]) + arm1->translateX += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 2 && arm1->translateY == arm1Offsets[1]) + arm1->translateY += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 3 && arm1->translateZ == arm1Offsets[2]) + arm1->translateZ += pSkinOffset->fO / 16.0f; + } + break; + case eBodyOffset_Waist: + if (m_isArmor && body->isArmorPart2) + { + if (pSkinOffset->fD == 1 && body->translateX == bodyOffsets[0]) + body->translateX += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 2 && body->translateY == bodyOffsets[1]) + body->translateY += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 3 && body->translateZ == bodyOffsets[2]) + body->translateZ += pSkinOffset->fO / 16.0f; + } + break; + case eBodyOffset_Legging0: + if (m_isArmor && leg0->isArmorPart2) + { + if (pSkinOffset->fD == 1 && leg0->translateX == leg0Offsets[0]) + leg0->translateX += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 2 && leg0->translateY == leg0Offsets[1]) + leg0->translateY += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 3 && leg0->translateZ == leg0Offsets[2]) + leg0->translateZ += pSkinOffset->fO / 16.0f; + } + break; + case eBodyOffset_Legging1: + if (m_isArmor && leg1->isArmorPart2) + { + if (pSkinOffset->fD == 1 && leg1->translateX == leg1Offsets[0]) + leg1->translateX += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 2 && leg1->translateY == leg1Offsets[1]) + leg1->translateY += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 3 && leg1->translateZ == leg1Offsets[2]) + leg1->translateZ += pSkinOffset->fO / 16.0f; + } + break; + case eBodyOffset_Boot0: + if (m_isArmor && !leg0->isArmorPart2) + { + if (pSkinOffset->fD == 1 && leg0->translateX == leg0Offsets[0]) + leg0->translateX += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 2 && leg0->translateY == leg0Offsets[1]) + leg0->translateY += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 3 && leg0->translateZ == leg0Offsets[2]) + leg0->translateZ += pSkinOffset->fO / 16.0f; + } + break; + case eBodyOffset_Boot1: + if (m_isArmor && !leg1->isArmorPart2) + { + if (pSkinOffset->fD == 1 && leg1->translateX == leg1Offsets[0]) + leg1->translateX += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 2 && leg1->translateY == leg1Offsets[1]) + leg1->translateY += pSkinOffset->fO / 16.0f; + else if (pSkinOffset->fD == 3 && leg1->translateZ == leg1Offsets[2]) + leg1->translateZ += pSkinOffset->fO / 16.0f; + } break; } } @@ -478,132 +738,46 @@ void HumanoidModel::render(shared_ptr entity, float time, float r, float glPopMatrix(); } else - { - glPushMatrix(); - glTranslatef(headOffsets[0], headOffsets[1], headOffsets[2]); + { head->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); - glPopMatrix(); - glPushMatrix(); - glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]); body->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); - glPopMatrix(); - glPushMatrix(); - glTranslatef(arm0Offsets[0], arm0Offsets[1], arm0Offsets[2]); arm0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); - glPopMatrix(); - glPushMatrix(); - glTranslatef(arm1Offsets[0], arm1Offsets[1], arm1Offsets[2]); arm1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); - glPopMatrix(); - glPushMatrix(); - glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); leg0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); - glPopMatrix(); - glPushMatrix(); - glTranslatef(leg1Offsets[0], leg1Offsets[1], leg1Offsets[2]); leg1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); - glPopMatrix(); - glPushMatrix(); - glTranslatef(headOffsets[0], headOffsets[1], headOffsets[2]); hair->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - glPopMatrix(); if (jacket != 0) - { - glPushMatrix(); - glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]); jacket->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - glPopMatrix(); - } if (sleeve0 != 0) - { - glPushMatrix(); - glTranslatef(arm0Offsets[0], arm0Offsets[1], arm0Offsets[2]); sleeve0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - glPopMatrix(); - } if (sleeve1 != 0) - { - glPushMatrix(); - glTranslatef(arm1Offsets[0], arm1Offsets[1], arm1Offsets[2]); sleeve1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - glPopMatrix(); - } if (pants0 != 0) - { - glPushMatrix(); - glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); pants0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - glPopMatrix(); - } if (pants1 != 0) - { - glPushMatrix(); - glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); pants1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - glPopMatrix(); - } if (waist != 0) waist->render(scale, usecompiled); if (belt != 0) - { - glPushMatrix(); - glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]); belt->render(scale, usecompiled); - glPopMatrix(); - } if (bodyArmor != 0) - { - glPushMatrix(); - glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]); bodyArmor->render(scale, usecompiled); - glPopMatrix(); - } if (armArmor0 != 0) - { - glPushMatrix(); - glTranslatef(arm0Offsets[0], arm0Offsets[1], arm0Offsets[2]); armArmor0->render(scale, usecompiled); - glPopMatrix(); - } if (armArmor1 != 0) - { - glPushMatrix(); - glTranslatef(arm1Offsets[0], arm1Offsets[1], arm1Offsets[2]); armArmor1->render(scale, usecompiled); - glPopMatrix(); - } if (legging0 != 0) - { - glPushMatrix(); - glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); legging0->render(scale, usecompiled); - glPopMatrix(); - } if (legging1 != 0) - { - glPushMatrix(); - glTranslatef(leg1Offsets[0], leg1Offsets[1], leg1Offsets[2]); legging1->render(scale, usecompiled); - glPopMatrix(); - } if (sock0 != 0) sock0->render(scale, usecompiled); if (sock1 != 0) sock1->render(scale, usecompiled); if (boot0 != 0) - { - glPushMatrix(); - glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); boot0->render(scale, usecompiled); - glPopMatrix(); - } if (boot1 != 0) - { - glPushMatrix(); - glTranslatef(leg1Offsets[0], leg1Offsets[1], leg1Offsets[2]); boot1->render(scale, usecompiled); - glPopMatrix(); - } } } From 7c632c72f0ca8fd69ff84ed711feaa1b69c56e74 Mon Sep 17 00:00:00 2001 From: Langtanium <94726057+Langtanium@users.noreply.github.com> Date: Thu, 28 May 2026 18:01:56 -0700 Subject: [PATCH 8/9] Added item offsets for DLC skins Added item offsets for DLC skins and changed some more code in HumanoidModel.cpp --- Minecraft.Client/HumanoidModel.cpp | 311 ++++++++++++++---------- Minecraft.Client/ItemInHandRenderer.cpp | 28 ++- 2 files changed, 212 insertions(+), 127 deletions(-) diff --git a/Minecraft.Client/HumanoidModel.cpp b/Minecraft.Client/HumanoidModel.cpp index 29866d2a..75d4a7c8 100644 --- a/Minecraft.Client/HumanoidModel.cpp +++ b/Minecraft.Client/HumanoidModel.cpp @@ -182,17 +182,17 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b if (!slim) { - sleeve0->addHumanoidBox(-3, -2, -2, 4, 12, 4, g + 0.25); // Sleeve0 - sleeve1->addHumanoidBox(-1, -2, -2, 4, 12, 4, g + 0.25); // Sleeve1 + sleeve0->addHumanoidBox(-3, -2, -2, 4, 12, 4, g + 0.25f); // Sleeve0 + sleeve1->addHumanoidBox(-1, -2, -2, 4, 12, 4, g + 0.25f); // Sleeve1 } else if (slim) { - sleeve0->addHumanoidBox(-2, -2, -2, 3, 12, 4, g + 0.25); // Sleeve0 Slim - sleeve1->addHumanoidBox(-1, -2, -2, 3, 12, 4, g + 0.25); // Sleeve1 Slim + sleeve0->addHumanoidBox(-2, -2, -2, 3, 12, 4, g + 0.25f); // Sleeve0 Slim + sleeve1->addHumanoidBox(-1, -2, -2, 3, 12, 4, g + 0.25f); // Sleeve1 Slim } jacket = new ModelPart(this, 16, 32); - jacket->addHumanoidBox(-4, 0, -2, 8, 12, 4, g + 0.25); + jacket->addHumanoidBox(-4, 0, -2, 8, 12, 4, g + 0.25f); jacket->setPos(0, 0 + yOffset, 0); sleeve0->setPos(-5, 2 + yOffset, 0); @@ -259,11 +259,11 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b leg1 = new ModelPart(this, 16, 48); pants0 = new ModelPart(this, 0, 32); - pants0->addHumanoidBox(-2, 0, -2, 4, 12, 4, g + 0.25); // Pants0 + pants0->addHumanoidBox(-2, 0, -2, 4, 12, 4, g + 0.25f); // Pants0 pants0->setPos(-1.9, 12 + yOffset, 0); pants1 = new ModelPart(this, 0, 48); - pants1->addHumanoidBox(-2, 0, -2, 4, 12, 4, g + 0.25); // Pants1 + pants1->addHumanoidBox(-2, 0, -2, 4, 12, 4, g + 0.25f); // Pants1 pants1->setPos(1.9, 12 + yOffset, 0); } else if (texHeight == 32) @@ -784,200 +784,265 @@ void HumanoidModel::render(shared_ptr entity, float time, float r, float // This code is similar to what's above, but allows skin offsets to work in the skin select menu - Langtanium void HumanoidModel::renderUI(float time, float r, float bob, float yRot, float xRot, float scale, bool usecompiled, vector *skinOffsets) { - setupAnim(time, r, bob, yRot, xRot, scale, nullptr, m_uiAnimOverrideBitmask); + float headOffsets[3] = {0}; + float bodyOffsets[3] = {0}; + float arm0Offsets[3] = {0}; + float arm1Offsets[3] = {0}; + float leg0Offsets[3] = {0}; + float leg1Offsets[3] = {0}; - vector headOffsets = {0, 0, 0}; - vector bodyOffsets = {0, 0, 0}; - vector arm0Offsets = {0, 0, 0}; - vector arm1Offsets = {0, 0, 0}; - vector leg0Offsets = {0, 0, 0}; - vector leg1Offsets = {0, 0, 0}; - vector* pSkinOffsets = nullptr; if (skinOffsets != nullptr) - pSkinOffsets = skinOffsets; - if (pSkinOffsets != nullptr) { - for( SKIN_OFFSET *pSkinOffset : *pSkinOffsets ) + for( SKIN_OFFSET *pSkinOffset : *skinOffsets ) { switch (pSkinOffset->ePart) { case eBodyOffset_Head: - if(pSkinOffset->fD == 1) + if (pSkinOffset->fD == 1 && head->translateX == 0) + { + head->translateX = pSkinOffset->fO / 16.0f; + hair->translateX = pSkinOffset->fO / 16.0f; headOffsets[0] = pSkinOffset->fO / 16.0f; - else if(pSkinOffset->fD == 2) + } + else if (pSkinOffset->fD == 2 && head->translateY == 0) + { + head->translateY = pSkinOffset->fO / 16.0f; + hair->translateY = pSkinOffset->fO / 16.0f; headOffsets[1] = pSkinOffset->fO / 16.0f; - else if(pSkinOffset->fD == 3) + } + else if (pSkinOffset->fD == 3 && head->translateZ == 0) + { + head->translateZ = pSkinOffset->fO / 16.0f; + hair->translateZ = pSkinOffset->fO / 16.0f; headOffsets[2] = pSkinOffset->fO / 16.0f; + } break; case eBodyOffset_Body: - if(pSkinOffset->fD == 1) + if (pSkinOffset->fD == 1 && body->translateX == 0) + { + body->translateX = pSkinOffset->fO / 16.0f; + if (jacket) + jacket->translateX = pSkinOffset->fO / 16.0f; + if (bodyArmor) + bodyArmor->translateX = pSkinOffset->fO / 16.0f; + if (waist) + waist->translateX = pSkinOffset->fO / 16.0f; + if (belt) + belt->translateX = pSkinOffset->fO / 16.0f; bodyOffsets[0] = pSkinOffset->fO / 16.0f; - else if(pSkinOffset->fD == 2) + } + else if (pSkinOffset->fD == 2 && body->translateY == 0) + { + body->translateY = pSkinOffset->fO / 16.0f; + if (jacket) + jacket->translateY = pSkinOffset->fO / 16.0f; + if (bodyArmor) + bodyArmor->translateY = pSkinOffset->fO / 16.0f; + if (waist) + waist->translateY = pSkinOffset->fO / 16.0f; + if (belt) + belt->translateY = pSkinOffset->fO / 16.0f; bodyOffsets[1] = pSkinOffset->fO / 16.0f; - else if(pSkinOffset->fD == 3) + } + else if (pSkinOffset->fD == 3 && body->translateZ == 0) + { + body->translateZ = pSkinOffset->fO / 16.0f; + if (jacket) + jacket->translateZ = pSkinOffset->fO / 16.0f; + if (bodyArmor) + bodyArmor->translateZ = pSkinOffset->fO / 16.0f; + if (waist) + waist->translateZ = pSkinOffset->fO / 16.0f; + if (belt) + belt->translateZ = pSkinOffset->fO / 16.0f; bodyOffsets[2] = pSkinOffset->fO / 16.0f; + } break; case eBodyOffset_Arm0: - if(pSkinOffset->fD == 1) + if (pSkinOffset->fD == 1 && arm0->translateX == 0) + { + arm0->translateX = pSkinOffset->fO / 16.0f; + if (sleeve0) + sleeve0->translateX = pSkinOffset->fO / 16.0f; + if (armArmor0) + armArmor0->translateX = pSkinOffset->fO / 16.0f; arm0Offsets[0] = pSkinOffset->fO / 16.0f; - else if(pSkinOffset->fD == 2) + } + else if (pSkinOffset->fD == 2 && arm0->translateY == 0) + { + arm0->translateY = pSkinOffset->fO / 16.0f; + if (sleeve0) + sleeve0->translateY = pSkinOffset->fO / 16.0f; + if (armArmor0) + armArmor0->translateY = pSkinOffset->fO / 16.0f; arm0Offsets[1] = pSkinOffset->fO / 16.0f; - else if(pSkinOffset->fD == 3) + } + else if (pSkinOffset->fD == 3 && arm0->translateZ == 0) + { + arm0->translateZ = pSkinOffset->fO / 16.0f; + if (sleeve0) + sleeve0->translateZ = pSkinOffset->fO / 16.0f; + if (armArmor0) + armArmor0->translateZ = pSkinOffset->fO / 16.0f; arm0Offsets[2] = pSkinOffset->fO / 16.0f; + } break; case eBodyOffset_Arm1: - if(pSkinOffset->fD == 1) + if (pSkinOffset->fD == 1 && arm1->translateX == 0) + { + arm1->translateX = pSkinOffset->fO / 16.0f; + if (sleeve1) + sleeve1->translateX = pSkinOffset->fO / 16.0f; + if (armArmor1) + armArmor1->translateX = pSkinOffset->fO / 16.0f; arm1Offsets[0] = pSkinOffset->fO / 16.0f; - else if(pSkinOffset->fD == 2) + } + else if (pSkinOffset->fD == 2 && arm1->translateY == 0) + { + arm1->translateY = pSkinOffset->fO / 16.0f; + if (sleeve1) + sleeve1->translateY = pSkinOffset->fO / 16.0f; + if (armArmor1) + armArmor1->translateY = pSkinOffset->fO / 16.0f; arm1Offsets[1] = pSkinOffset->fO / 16.0f; - else if(pSkinOffset->fD == 3) + } + else if (pSkinOffset->fD == 3 && arm1->translateZ == 0) + { + arm1->translateZ = pSkinOffset->fO / 16.0f; + if (sleeve1) + sleeve1->translateZ = pSkinOffset->fO / 16.0f; + if (armArmor1) + armArmor1->translateZ = pSkinOffset->fO / 16.0f; arm1Offsets[2] = pSkinOffset->fO / 16.0f; + } break; case eBodyOffset_Leg0: - if(pSkinOffset->fD == 1) + if (pSkinOffset->fD == 1 && leg0->translateX == 0) + { + leg0->translateX = pSkinOffset->fO / 16.0f; + if (pants0) + pants0->translateX = pSkinOffset->fO / 16.0f; + if (legging0) + legging0->translateX = pSkinOffset->fO / 16.0f; + if (sock0) + sock0->translateX = pSkinOffset->fO / 16.0f; + if (boot0) + boot0->translateX = pSkinOffset->fO / 16.0f; leg0Offsets[0] = pSkinOffset->fO / 16.0f; - else if(pSkinOffset->fD == 2) + } + else if (pSkinOffset->fD == 2 && leg0->translateY == 0) + { + leg0->translateY = pSkinOffset->fO / 16.0f; + if (pants0) + pants0->translateY = pSkinOffset->fO / 16.0f; + if (legging0) + legging0->translateY = pSkinOffset->fO / 16.0f; + if (sock0) + sock0->translateY = pSkinOffset->fO / 16.0f; + if (boot0) + boot0->translateY = pSkinOffset->fO / 16.0f; leg0Offsets[1] = pSkinOffset->fO / 16.0f; - else if(pSkinOffset->fD == 3) + } + else if (pSkinOffset->fD == 3 && leg0->translateZ == 0) + { + leg0->translateZ = pSkinOffset->fO / 16.0f; + if (pants0) + pants0->translateZ = pSkinOffset->fO / 16.0f; + if (legging0) + legging0->translateZ = pSkinOffset->fO / 16.0f; + if (sock0) + sock0->translateZ = pSkinOffset->fO / 16.0f; + if (boot0) + boot0->translateZ = pSkinOffset->fO / 16.0f; leg0Offsets[2] = pSkinOffset->fO / 16.0f; + } break; case eBodyOffset_Leg1: - if(pSkinOffset->fD == 1) + if (pSkinOffset->fD == 1 && leg1->translateX == 0) + { + leg1->translateX = pSkinOffset->fO / 16.0f; + if (pants1) + pants1->translateX = pSkinOffset->fO / 16.0f; + if (legging1) + legging1->translateX = pSkinOffset->fO / 16.0f; + if (sock1) + sock1->translateX = pSkinOffset->fO / 16.0f; + if (boot1) + boot1->translateX = pSkinOffset->fO / 16.0f; leg1Offsets[0] = pSkinOffset->fO / 16.0f; - else if(pSkinOffset->fD == 2) + } + else if (pSkinOffset->fD == 2 && leg1->translateY == 0) + { + leg1->translateY = pSkinOffset->fO / 16.0f; + if (pants1) + pants1->translateY = pSkinOffset->fO / 16.0f; + if (legging1) + legging1->translateY = pSkinOffset->fO / 16.0f; + if (sock1) + sock1->translateY = pSkinOffset->fO / 16.0f; + if (boot1) + boot1->translateY = pSkinOffset->fO / 16.0f; leg1Offsets[1] = pSkinOffset->fO / 16.0f; - else if(pSkinOffset->fD == 3) + } + else if (pSkinOffset->fD == 3 && leg1->translateZ == 0) + { + leg1->translateZ = pSkinOffset->fO / 16.0f; + if (pants1) + pants1->translateZ = pSkinOffset->fO / 16.0f; + if (legging1) + legging1->translateZ = pSkinOffset->fO / 16.0f; + if (sock1) + sock1->translateZ = pSkinOffset->fO / 16.0f; + if (boot1) + boot1->translateZ = pSkinOffset->fO / 16.0f; leg1Offsets[2] = pSkinOffset->fO / 16.0f; + } break; } } } - - glPushMatrix(); - glTranslatef(headOffsets[0], headOffsets[1], headOffsets[2]); + + setupAnim(time, r, bob, yRot, xRot, scale, nullptr, m_uiAnimOverrideBitmask); + head->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); - glPopMatrix(); - glPushMatrix(); - glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]); body->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); - glPopMatrix(); - glPushMatrix(); - glTranslatef(arm0Offsets[0], arm0Offsets[1], arm0Offsets[2]); arm0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); - glPopMatrix(); - glPushMatrix(); - glTranslatef(arm1Offsets[0], arm1Offsets[1], arm1Offsets[2]); arm1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); - glPopMatrix(); - glPushMatrix(); - glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); leg0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); - glPopMatrix(); - glPushMatrix(); - glTranslatef(leg1Offsets[0], leg1Offsets[1], leg1Offsets[2]); leg1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); - glPopMatrix(); - glPushMatrix(); - glTranslatef(headOffsets[0], headOffsets[1], headOffsets[2]); hair->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - glPopMatrix(); if (jacket != 0) - { - glPushMatrix(); - glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]); jacket->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - glPopMatrix(); - } if (sleeve0 != 0) - { - glPushMatrix(); - glTranslatef(arm0Offsets[0], arm0Offsets[1], arm0Offsets[2]); sleeve0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - glPopMatrix(); - } if (sleeve1 != 0) - { - glPushMatrix(); - glTranslatef(arm1Offsets[0], arm1Offsets[1], arm1Offsets[2]); sleeve1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - glPopMatrix(); - } if (pants0 != 0) - { - glPushMatrix(); - glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); pants0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - glPopMatrix(); - } if (pants1 != 0) - { - glPushMatrix(); - glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); pants1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - glPopMatrix(); - } if (waist != 0) waist->render(scale, usecompiled); if (belt != 0) - { - glPushMatrix(); - glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]); belt->render(scale, usecompiled); - glPopMatrix(); - } if (bodyArmor != 0) - { - glPushMatrix(); - glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]); bodyArmor->render(scale, usecompiled); - glPopMatrix(); - } if (armArmor0 != 0) - { - glPushMatrix(); - glTranslatef(arm0Offsets[0], arm0Offsets[1], arm0Offsets[2]); armArmor0->render(scale, usecompiled); - glPopMatrix(); - } if (armArmor1 != 0) - { - glPushMatrix(); - glTranslatef(arm1Offsets[0], arm1Offsets[1], arm1Offsets[2]); armArmor1->render(scale, usecompiled); - glPopMatrix(); - } if (legging0 != 0) - { - glPushMatrix(); - glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); legging0->render(scale, usecompiled); - glPopMatrix(); - } if (legging1 != 0) - { - glPushMatrix(); - glTranslatef(leg1Offsets[0], leg1Offsets[1], leg1Offsets[2]); legging1->render(scale, usecompiled); - glPopMatrix(); - } if (sock0 != 0) sock0->render(scale, usecompiled); if (sock1 != 0) sock1->render(scale, usecompiled); if (boot0 != 0) - { - glPushMatrix(); - glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]); boot0->render(scale, usecompiled); - glPopMatrix(); - } if (boot1 != 0) - { - glPushMatrix(); - glTranslatef(leg1Offsets[0], leg1Offsets[1], leg1Offsets[2]); boot1->render(scale, usecompiled); - glPopMatrix(); - } } void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float xRot, float scale, shared_ptr entity, unsigned int uiBitmaskOverrideAnim) diff --git a/Minecraft.Client/ItemInHandRenderer.cpp b/Minecraft.Client/ItemInHandRenderer.cpp index 9faebffd..e04945c5 100644 --- a/Minecraft.Client/ItemInHandRenderer.cpp +++ b/Minecraft.Client/ItemInHandRenderer.cpp @@ -399,14 +399,34 @@ void ItemInHandRenderer::renderItem3D(Tesselator *t, float u0, float v0, float u void ItemInHandRenderer::render(float a) { - float h = oHeight + (height - oHeight) * a; - shared_ptr player = minecraft->player; + float h = oHeight + (height - oHeight) * a; + shared_ptr player = minecraft->player; if (player == nullptr) { return; } + vector* pSkinOffsets = nullptr; + pSkinOffsets = player->GetSkinOffsets(); + if (pSkinOffsets != nullptr) + { + for( SKIN_OFFSET *pSkinOffset : *pSkinOffsets ) + { + switch (pSkinOffset->ePart) + { + case eBodyOffset_Arm0: + if (pSkinOffset->fD == 2) + h += pSkinOffset->fO / 16.0f; + break; + case eBodyOffset_Tool0: + if (pSkinOffset->fD == 2) + h += pSkinOffset->fO / 16.0f; + break; + } + } + } + // 4J - added so we can adjust the position of the hands for horizontal & vertical split screens float fudgeX = 0.0f; float fudgeY = 0.0f; @@ -900,8 +920,8 @@ void ItemInHandRenderer::renderFire(float a) unsigned int col = Minecraft::GetInstance()->getColourTable()->getColor( eMinecraftColour_Fire_Overlay ); float aCol = ( (col>>24)&0xFF )/255.0f; float rCol = ( (col>>16)&0xFF )/255.0f; - float gCol = ( (col>>8)&0xFF )/255.0; - float bCol = ( col&0xFF )/255.0; + float gCol = ( (col>>8)&0xFF )/255.0f; + float bCol = ( col&0xFF )/255.0f; glColor4f(rCol, gCol, bCol, aCol); glEnable(GL_BLEND); From 253b460676f4270e4cc1cf84b2ed2e6193c65675 Mon Sep 17 00:00:00 2001 From: Langtanium <94726057+Langtanium@users.noreply.github.com> Date: Tue, 2 Jun 2026 11:42:13 -0700 Subject: [PATCH 9/9] Fixed skin offset leak and removed skin item offset Fixed DLC skin offset leak causing offsets from one skin to leak onto another skin. Removed skin item offset as the location it was previously added to did not have the desired result. --- Minecraft.Client/HumanoidModel.cpp | 432 ++++++++++++++---------- Minecraft.Client/HumanoidModel.h | 1 + Minecraft.Client/ItemInHandRenderer.cpp | 20 -- 3 files changed, 256 insertions(+), 197 deletions(-) diff --git a/Minecraft.Client/HumanoidModel.cpp b/Minecraft.Client/HumanoidModel.cpp index 75d4a7c8..bd362789 100644 --- a/Minecraft.Client/HumanoidModel.cpp +++ b/Minecraft.Client/HumanoidModel.cpp @@ -126,6 +126,8 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b this->texWidth = texWidth; this->texHeight = texHeight; + m_is64x64 = texHeight == 64; + jacket = nullptr; sleeve0 = nullptr; sleeve1 = nullptr; @@ -172,7 +174,7 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b body->addHumanoidBox(-4, 0, -2, 8, 12, 4, g); // Body body->setPos(0, 0 + yOffset, 0); - if (texHeight == 64) + if (m_is64x64) { arm0 = new ModelPart(this, 24 + 16, 16); arm1 = new ModelPart(this, 16 + 16, 48); @@ -232,7 +234,7 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b boot1->addHumanoidBox(0, 0, 0, 0, 0, 0, g); // Boot1 boot1->setPos(1.9, 12 + yOffset, 0); } - else if (texHeight == 32) + else if (!m_is64x64) { arm0 = new ModelPart(this, 24 + 16, 16); arm1 = new ModelPart(this, 24 + 16, 16); @@ -254,7 +256,7 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b arm1->setPos(5, 2 + yOffset, 0); leg0 = new ModelPart(this, 0, 16); - if (texHeight == 64) + if (m_is64x64) { leg1 = new ModelPart(this, 16, 48); @@ -266,7 +268,7 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b pants1->addHumanoidBox(-2, 0, -2, 4, 12, 4, g + 0.25f); // Pants1 pants1->setPos(1.9, 12 + yOffset, 0); } - else if (texHeight == 32) + else if (!m_is64x64) { leg1 = new ModelPart(this, 0, 16); leg1->bMirror = true; @@ -292,38 +294,25 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, b leg1->compile(1.0f/16.0f); hair->compile(1.0f/16.0f); - if (jacket) + if (m_is64x64) + { jacket->compile(1.0f/16.0f); - if (sleeve0) sleeve0->compile(1.0f/16.0f); - if (sleeve1) sleeve1->compile(1.0f/16.0f); - if (pants0) pants0->compile(1.0f/16.0f); - if (pants1) pants1->compile(1.0f/16.0f); - if (waist) waist->compile(1.0f/16.0f); - if (belt) belt->compile(1.0f/16.0f); - if (bodyArmor) bodyArmor->compile(1.0f/16.0f); - if (armArmor0) armArmor0->compile(1.0f/16.0f); - if (armArmor1) armArmor1->compile(1.0f/16.0f); - if (legging0) legging0->compile(1.0f/16.0f); - if (legging1) legging1->compile(1.0f/16.0f); - if (sock0) sock0->compile(1.0f/16.0f); - if (sock1) sock1->compile(1.0f/16.0f); - if (boot0) boot0->compile(1.0f/16.0f); - if (boot1) boot1->compile(1.0f/16.0f); + } holdingLeftHand=0; holdingRightHand=0; @@ -380,6 +369,80 @@ void HumanoidModel::render(shared_ptr entity, float time, float r, float { m_uiAnimOverrideBitmask=entity->getAnimOverrideBitmask(); + // Reset offsets so they don't leak onto other skins - Langtanium + head->translateX = 0; + head->translateY = 0; + head->translateZ = 0; + hair->translateX = 0; + hair->translateY = 0; + hair->translateZ = 0; + body->translateX = 0; + body->translateY = 0; + body->translateZ = 0; + arm0->translateX = 0; + arm0->translateY = 0; + arm0->translateZ = 0; + arm1->translateX = 0; + arm1->translateY = 0; + arm1->translateZ = 0; + leg0->translateX = 0; + leg0->translateY = 0; + leg0->translateZ = 0; + leg1->translateX = 0; + leg1->translateY = 0; + leg1->translateZ = 0; + if (m_is64x64) + { + jacket->translateX = 0; + jacket->translateY = 0; + jacket->translateZ = 0; + sleeve0->translateX = 0; + sleeve0->translateY = 0; + sleeve0->translateZ = 0; + sleeve1->translateX = 0; + sleeve1->translateY = 0; + sleeve1->translateZ = 0; + pants0->translateX = 0; + pants0->translateY = 0; + pants0->translateZ = 0; + pants1->translateX = 0; + pants1->translateY = 0; + pants1->translateZ = 0; + bodyArmor->translateX = 0; + bodyArmor->translateY = 0; + bodyArmor->translateZ = 0; + waist->translateX = 0; + waist->translateY = 0; + waist->translateZ = 0; + belt->translateX = 0; + belt->translateY = 0; + belt->translateZ = 0; + armArmor0->translateX = 0; + armArmor0->translateY = 0; + armArmor0->translateZ = 0; + armArmor1->translateX = 0; + armArmor1->translateY = 0; + armArmor1->translateZ = 0; + legging0->translateX = 0; + legging0->translateY = 0; + legging0->translateZ = 0; + legging1->translateX = 0; + legging1->translateY = 0; + legging1->translateZ = 0; + sock0->translateX = 0; + sock0->translateY = 0; + sock0->translateZ = 0; + sock1->translateX = 0; + sock1->translateY = 0; + sock1->translateZ = 0; + boot0->translateX = 0; + boot0->translateY = 0; + boot0->translateZ = 0; + boot1->translateX = 0; + boot1->translateY = 0; + boot1->translateZ = 0; + } + shared_ptr player = dynamic_pointer_cast(entity); vector* pSkinOffsets = nullptr; if (player != nullptr) @@ -414,40 +477,37 @@ void HumanoidModel::render(shared_ptr entity, float time, float r, float if (pSkinOffset->fD == 1 && body->translateX == 0) { body->translateX = pSkinOffset->fO / 16.0f; - if (jacket) + if (m_is64x64) + { jacket->translateX = pSkinOffset->fO / 16.0f; - if (bodyArmor) bodyArmor->translateX = pSkinOffset->fO / 16.0f; - if (waist) waist->translateX = pSkinOffset->fO / 16.0f; - if (belt) belt->translateX = pSkinOffset->fO / 16.0f; + } bodyOffsets[0] = pSkinOffset->fO / 16.0f; } else if (pSkinOffset->fD == 2 && body->translateY == 0) { body->translateY = pSkinOffset->fO / 16.0f; - if (jacket) + if (m_is64x64) + { jacket->translateY = pSkinOffset->fO / 16.0f; - if (bodyArmor) bodyArmor->translateY = pSkinOffset->fO / 16.0f; - if (waist) waist->translateY = pSkinOffset->fO / 16.0f; - if (belt) belt->translateY = pSkinOffset->fO / 16.0f; + } bodyOffsets[1] = pSkinOffset->fO / 16.0f; } else if (pSkinOffset->fD == 3 && body->translateZ == 0) { body->translateZ = pSkinOffset->fO / 16.0f; - if (jacket) + if (m_is64x64) + { jacket->translateZ = pSkinOffset->fO / 16.0f; - if (bodyArmor) bodyArmor->translateZ = pSkinOffset->fO / 16.0f; - if (waist) waist->translateZ = pSkinOffset->fO / 16.0f; - if (belt) belt->translateZ = pSkinOffset->fO / 16.0f; + } bodyOffsets[2] = pSkinOffset->fO / 16.0f; } break; @@ -455,28 +515,31 @@ void HumanoidModel::render(shared_ptr entity, float time, float r, float if (pSkinOffset->fD == 1 && arm0->translateX == 0) { arm0->translateX = pSkinOffset->fO / 16.0f; - if (sleeve0) + if (m_is64x64) + { sleeve0->translateX = pSkinOffset->fO / 16.0f; - if (armArmor0) armArmor0->translateX = pSkinOffset->fO / 16.0f; + } arm0Offsets[0] = pSkinOffset->fO / 16.0f; } else if (pSkinOffset->fD == 2 && arm0->translateY == 0) { arm0->translateY = pSkinOffset->fO / 16.0f; - if (sleeve0) + if (m_is64x64) + { sleeve0->translateY = pSkinOffset->fO / 16.0f; - if (armArmor0) armArmor0->translateY = pSkinOffset->fO / 16.0f; + } arm0Offsets[1] = pSkinOffset->fO / 16.0f; } else if (pSkinOffset->fD == 3 && arm0->translateZ == 0) { arm0->translateZ = pSkinOffset->fO / 16.0f; - if (sleeve0) + if (m_is64x64) + { sleeve0->translateZ = pSkinOffset->fO / 16.0f; - if (armArmor0) armArmor0->translateZ = pSkinOffset->fO / 16.0f; + } arm0Offsets[2] = pSkinOffset->fO / 16.0f; } break; @@ -484,28 +547,31 @@ void HumanoidModel::render(shared_ptr entity, float time, float r, float if (pSkinOffset->fD == 1 && arm1->translateX == 0) { arm1->translateX = pSkinOffset->fO / 16.0f; - if (sleeve1) + if (m_is64x64) + { sleeve1->translateX = pSkinOffset->fO / 16.0f; - if (armArmor1) armArmor1->translateX = pSkinOffset->fO / 16.0f; + } arm1Offsets[0] = pSkinOffset->fO / 16.0f; } else if (pSkinOffset->fD == 2 && arm1->translateY == 0) { arm1->translateY = pSkinOffset->fO / 16.0f; - if (sleeve1) + if (m_is64x64) + { sleeve1->translateY = pSkinOffset->fO / 16.0f; - if (armArmor1) armArmor1->translateY = pSkinOffset->fO / 16.0f; + } arm1Offsets[1] = pSkinOffset->fO / 16.0f; } else if (pSkinOffset->fD == 3 && arm1->translateZ == 0) { arm1->translateZ = pSkinOffset->fO / 16.0f; - if (sleeve1) + if (m_is64x64) + { sleeve1->translateZ = pSkinOffset->fO / 16.0f; - if (armArmor1) armArmor1->translateZ = pSkinOffset->fO / 16.0f; + } arm1Offsets[2] = pSkinOffset->fO / 16.0f; } break; @@ -513,40 +579,37 @@ void HumanoidModel::render(shared_ptr entity, float time, float r, float if (pSkinOffset->fD == 1 && leg0->translateX == 0) { leg0->translateX = pSkinOffset->fO / 16.0f; - if (pants0) + if (m_is64x64) + { pants0->translateX = pSkinOffset->fO / 16.0f; - if (legging0) legging0->translateX = pSkinOffset->fO / 16.0f; - if (sock0) sock0->translateX = pSkinOffset->fO / 16.0f; - if (boot0) boot0->translateX = pSkinOffset->fO / 16.0f; + } leg0Offsets[0] = pSkinOffset->fO / 16.0f; } else if (pSkinOffset->fD == 2 && leg0->translateY == 0) { leg0->translateY = pSkinOffset->fO / 16.0f; - if (pants0) + if (m_is64x64) + { pants0->translateY = pSkinOffset->fO / 16.0f; - if (legging0) legging0->translateY = pSkinOffset->fO / 16.0f; - if (sock0) sock0->translateY = pSkinOffset->fO / 16.0f; - if (boot0) boot0->translateY = pSkinOffset->fO / 16.0f; + } leg0Offsets[1] = pSkinOffset->fO / 16.0f; } else if (pSkinOffset->fD == 3 && leg0->translateZ == 0) { leg0->translateZ = pSkinOffset->fO / 16.0f; - if (pants0) + if (m_is64x64) + { pants0->translateZ = pSkinOffset->fO / 16.0f; - if (legging0) legging0->translateZ = pSkinOffset->fO / 16.0f; - if (sock0) sock0->translateZ = pSkinOffset->fO / 16.0f; - if (boot0) boot0->translateZ = pSkinOffset->fO / 16.0f; + } leg0Offsets[2] = pSkinOffset->fO / 16.0f; } break; @@ -554,40 +617,37 @@ void HumanoidModel::render(shared_ptr entity, float time, float r, float if (pSkinOffset->fD == 1 && leg1->translateX == 0) { leg1->translateX = pSkinOffset->fO / 16.0f; - if (pants1) + if (m_is64x64) + { pants1->translateX = pSkinOffset->fO / 16.0f; - if (legging1) legging1->translateX = pSkinOffset->fO / 16.0f; - if (sock1) sock1->translateX = pSkinOffset->fO / 16.0f; - if (boot1) boot1->translateX = pSkinOffset->fO / 16.0f; + } leg1Offsets[0] = pSkinOffset->fO / 16.0f; } else if (pSkinOffset->fD == 2 && leg1->translateY == 0) { leg1->translateY = pSkinOffset->fO / 16.0f; - if (pants1) + if (m_is64x64) + { pants1->translateY = pSkinOffset->fO / 16.0f; - if (legging1) legging1->translateY = pSkinOffset->fO / 16.0f; - if (sock1) sock1->translateY = pSkinOffset->fO / 16.0f; - if (boot1) boot1->translateY = pSkinOffset->fO / 16.0f; + } leg1Offsets[1] = pSkinOffset->fO / 16.0f; } else if (pSkinOffset->fD == 3 && leg1->translateZ == 0) { leg1->translateZ = pSkinOffset->fO / 16.0f; - if (pants1) + if (m_is64x64) + { pants1->translateZ = pSkinOffset->fO / 16.0f; - if (legging1) legging1->translateZ = pSkinOffset->fO / 16.0f; - if (sock1) sock1->translateZ = pSkinOffset->fO / 16.0f; - if (boot1) boot1->translateZ = pSkinOffset->fO / 16.0f; + } leg1Offsets[2] = pSkinOffset->fO / 16.0f; } break; @@ -724,16 +784,14 @@ void HumanoidModel::render(shared_ptr entity, float time, float r, float leg1->render(scale, usecompiled); hair->render(scale, usecompiled); - if (jacket) + if (m_is64x64) + { jacket->render(scale, usecompiled); - if (sleeve0) sleeve0->render(scale, usecompiled); - if (sleeve1) sleeve1->render(scale, usecompiled); - if (pants0) pants0->render(scale, usecompiled); - if (pants1) pants1->render(scale, usecompiled); + } glPopMatrix(); } @@ -746,50 +804,104 @@ void HumanoidModel::render(shared_ptr entity, float time, float r, float leg0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); leg1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); hair->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - if (jacket != 0) + if (m_is64x64) + { jacket->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - if (sleeve0 != 0) sleeve0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - if (sleeve1 != 0) sleeve1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - if (pants0 != 0) 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); + } } } // This code is similar to what's above, but allows skin offsets to work in the skin select menu - Langtanium void HumanoidModel::renderUI(float time, float r, float bob, float yRot, float xRot, float scale, bool usecompiled, vector *skinOffsets) { - float headOffsets[3] = {0}; - float bodyOffsets[3] = {0}; - float arm0Offsets[3] = {0}; - float arm1Offsets[3] = {0}; - float leg0Offsets[3] = {0}; - float leg1Offsets[3] = {0}; + // Reset offsets so they don't leak onto other skins - Langtanium + head->translateX = 0; + head->translateY = 0; + head->translateZ = 0; + hair->translateX = 0; + hair->translateY = 0; + hair->translateZ = 0; + body->translateX = 0; + body->translateY = 0; + body->translateZ = 0; + arm0->translateX = 0; + arm0->translateY = 0; + arm0->translateZ = 0; + arm1->translateX = 0; + arm1->translateY = 0; + arm1->translateZ = 0; + leg0->translateX = 0; + leg0->translateY = 0; + leg0->translateZ = 0; + leg1->translateX = 0; + leg1->translateY = 0; + leg1->translateZ = 0; + if (m_is64x64) + { + jacket->translateX = 0; + jacket->translateY = 0; + jacket->translateZ = 0; + sleeve0->translateX = 0; + sleeve0->translateY = 0; + sleeve0->translateZ = 0; + sleeve1->translateX = 0; + sleeve1->translateY = 0; + sleeve1->translateZ = 0; + pants0->translateX = 0; + pants0->translateY = 0; + pants0->translateZ = 0; + pants1->translateX = 0; + pants1->translateY = 0; + pants1->translateZ = 0; + bodyArmor->translateX = 0; + bodyArmor->translateY = 0; + bodyArmor->translateZ = 0; + waist->translateX = 0; + waist->translateY = 0; + waist->translateZ = 0; + belt->translateX = 0; + belt->translateY = 0; + belt->translateZ = 0; + armArmor0->translateX = 0; + armArmor0->translateY = 0; + armArmor0->translateZ = 0; + armArmor1->translateX = 0; + armArmor1->translateY = 0; + armArmor1->translateZ = 0; + legging0->translateX = 0; + legging0->translateY = 0; + legging0->translateZ = 0; + legging1->translateX = 0; + legging1->translateY = 0; + legging1->translateZ = 0; + sock0->translateX = 0; + sock0->translateY = 0; + sock0->translateZ = 0; + sock1->translateX = 0; + sock1->translateY = 0; + sock1->translateZ = 0; + boot0->translateX = 0; + boot0->translateY = 0; + boot0->translateZ = 0; + boot1->translateX = 0; + boot1->translateY = 0; + boot1->translateZ = 0; + } if (skinOffsets != nullptr) { @@ -802,200 +914,179 @@ void HumanoidModel::renderUI(float time, float r, float bob, float yRot, float x { head->translateX = pSkinOffset->fO / 16.0f; hair->translateX = pSkinOffset->fO / 16.0f; - headOffsets[0] = pSkinOffset->fO / 16.0f; } else if (pSkinOffset->fD == 2 && head->translateY == 0) { head->translateY = pSkinOffset->fO / 16.0f; hair->translateY = pSkinOffset->fO / 16.0f; - headOffsets[1] = pSkinOffset->fO / 16.0f; } else if (pSkinOffset->fD == 3 && head->translateZ == 0) { head->translateZ = pSkinOffset->fO / 16.0f; hair->translateZ = pSkinOffset->fO / 16.0f; - headOffsets[2] = pSkinOffset->fO / 16.0f; } break; case eBodyOffset_Body: if (pSkinOffset->fD == 1 && body->translateX == 0) { body->translateX = pSkinOffset->fO / 16.0f; - if (jacket) + if (m_is64x64) + { jacket->translateX = pSkinOffset->fO / 16.0f; - if (bodyArmor) bodyArmor->translateX = pSkinOffset->fO / 16.0f; - if (waist) waist->translateX = pSkinOffset->fO / 16.0f; - if (belt) belt->translateX = pSkinOffset->fO / 16.0f; - bodyOffsets[0] = pSkinOffset->fO / 16.0f; + } } else if (pSkinOffset->fD == 2 && body->translateY == 0) { body->translateY = pSkinOffset->fO / 16.0f; - if (jacket) + if (m_is64x64) + { jacket->translateY = pSkinOffset->fO / 16.0f; - if (bodyArmor) bodyArmor->translateY = pSkinOffset->fO / 16.0f; - if (waist) waist->translateY = pSkinOffset->fO / 16.0f; - if (belt) belt->translateY = pSkinOffset->fO / 16.0f; - bodyOffsets[1] = pSkinOffset->fO / 16.0f; + } } else if (pSkinOffset->fD == 3 && body->translateZ == 0) { body->translateZ = pSkinOffset->fO / 16.0f; - if (jacket) + if (m_is64x64) + { jacket->translateZ = pSkinOffset->fO / 16.0f; - if (bodyArmor) bodyArmor->translateZ = pSkinOffset->fO / 16.0f; - if (waist) waist->translateZ = pSkinOffset->fO / 16.0f; - if (belt) belt->translateZ = pSkinOffset->fO / 16.0f; - bodyOffsets[2] = pSkinOffset->fO / 16.0f; + } } break; case eBodyOffset_Arm0: if (pSkinOffset->fD == 1 && arm0->translateX == 0) { arm0->translateX = pSkinOffset->fO / 16.0f; - if (sleeve0) + if (m_is64x64) + { sleeve0->translateX = pSkinOffset->fO / 16.0f; - if (armArmor0) armArmor0->translateX = pSkinOffset->fO / 16.0f; - arm0Offsets[0] = pSkinOffset->fO / 16.0f; + } } else if (pSkinOffset->fD == 2 && arm0->translateY == 0) { arm0->translateY = pSkinOffset->fO / 16.0f; - if (sleeve0) + if (m_is64x64) + { sleeve0->translateY = pSkinOffset->fO / 16.0f; - if (armArmor0) armArmor0->translateY = pSkinOffset->fO / 16.0f; - arm0Offsets[1] = pSkinOffset->fO / 16.0f; + } } else if (pSkinOffset->fD == 3 && arm0->translateZ == 0) { arm0->translateZ = pSkinOffset->fO / 16.0f; - if (sleeve0) + if (m_is64x64) + { sleeve0->translateZ = pSkinOffset->fO / 16.0f; - if (armArmor0) armArmor0->translateZ = pSkinOffset->fO / 16.0f; - arm0Offsets[2] = pSkinOffset->fO / 16.0f; + } } break; case eBodyOffset_Arm1: if (pSkinOffset->fD == 1 && arm1->translateX == 0) { arm1->translateX = pSkinOffset->fO / 16.0f; - if (sleeve1) + if (m_is64x64) + { sleeve1->translateX = pSkinOffset->fO / 16.0f; - if (armArmor1) armArmor1->translateX = pSkinOffset->fO / 16.0f; - arm1Offsets[0] = pSkinOffset->fO / 16.0f; + } } else if (pSkinOffset->fD == 2 && arm1->translateY == 0) { arm1->translateY = pSkinOffset->fO / 16.0f; - if (sleeve1) + if (m_is64x64) + { sleeve1->translateY = pSkinOffset->fO / 16.0f; - if (armArmor1) armArmor1->translateY = pSkinOffset->fO / 16.0f; - arm1Offsets[1] = pSkinOffset->fO / 16.0f; + } } else if (pSkinOffset->fD == 3 && arm1->translateZ == 0) { arm1->translateZ = pSkinOffset->fO / 16.0f; - if (sleeve1) + if (m_is64x64) + { sleeve1->translateZ = pSkinOffset->fO / 16.0f; - if (armArmor1) armArmor1->translateZ = pSkinOffset->fO / 16.0f; - arm1Offsets[2] = pSkinOffset->fO / 16.0f; + } } break; case eBodyOffset_Leg0: if (pSkinOffset->fD == 1 && leg0->translateX == 0) { leg0->translateX = pSkinOffset->fO / 16.0f; - if (pants0) + if (m_is64x64) + { pants0->translateX = pSkinOffset->fO / 16.0f; - if (legging0) legging0->translateX = pSkinOffset->fO / 16.0f; - if (sock0) sock0->translateX = pSkinOffset->fO / 16.0f; - if (boot0) boot0->translateX = pSkinOffset->fO / 16.0f; - leg0Offsets[0] = pSkinOffset->fO / 16.0f; + } } else if (pSkinOffset->fD == 2 && leg0->translateY == 0) { leg0->translateY = pSkinOffset->fO / 16.0f; - if (pants0) + if (m_is64x64) + { pants0->translateY = pSkinOffset->fO / 16.0f; - if (legging0) legging0->translateY = pSkinOffset->fO / 16.0f; - if (sock0) sock0->translateY = pSkinOffset->fO / 16.0f; - if (boot0) boot0->translateY = pSkinOffset->fO / 16.0f; - leg0Offsets[1] = pSkinOffset->fO / 16.0f; + } } else if (pSkinOffset->fD == 3 && leg0->translateZ == 0) { leg0->translateZ = pSkinOffset->fO / 16.0f; - if (pants0) + if (m_is64x64) + { pants0->translateZ = pSkinOffset->fO / 16.0f; - if (legging0) legging0->translateZ = pSkinOffset->fO / 16.0f; - if (sock0) sock0->translateZ = pSkinOffset->fO / 16.0f; - if (boot0) boot0->translateZ = pSkinOffset->fO / 16.0f; - leg0Offsets[2] = pSkinOffset->fO / 16.0f; + } } break; case eBodyOffset_Leg1: if (pSkinOffset->fD == 1 && leg1->translateX == 0) { leg1->translateX = pSkinOffset->fO / 16.0f; - if (pants1) + if (m_is64x64) + { pants1->translateX = pSkinOffset->fO / 16.0f; - if (legging1) legging1->translateX = pSkinOffset->fO / 16.0f; - if (sock1) sock1->translateX = pSkinOffset->fO / 16.0f; - if (boot1) boot1->translateX = pSkinOffset->fO / 16.0f; - leg1Offsets[0] = pSkinOffset->fO / 16.0f; + } } else if (pSkinOffset->fD == 2 && leg1->translateY == 0) { leg1->translateY = pSkinOffset->fO / 16.0f; - if (pants1) + if (m_is64x64) + { pants1->translateY = pSkinOffset->fO / 16.0f; - if (legging1) legging1->translateY = pSkinOffset->fO / 16.0f; - if (sock1) sock1->translateY = pSkinOffset->fO / 16.0f; - if (boot1) boot1->translateY = pSkinOffset->fO / 16.0f; - leg1Offsets[1] = pSkinOffset->fO / 16.0f; + } } else if (pSkinOffset->fD == 3 && leg1->translateZ == 0) { leg1->translateZ = pSkinOffset->fO / 16.0f; - if (pants1) + if (m_is64x64) + { pants1->translateZ = pSkinOffset->fO / 16.0f; - if (legging1) legging1->translateZ = pSkinOffset->fO / 16.0f; - if (sock1) sock1->translateZ = pSkinOffset->fO / 16.0f; - if (boot1) boot1->translateZ = pSkinOffset->fO / 16.0f; - leg1Offsets[2] = pSkinOffset->fO / 16.0f; + } } break; } @@ -1011,38 +1102,25 @@ void HumanoidModel::renderUI(float time, float r, float bob, float yRot, float x leg0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); leg1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0&&(!(m_uiAnimOverrideBitmask&(1<0||!m_isArmor)); hair->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - if (jacket != 0) + if (m_is64x64) + { jacket->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - if (sleeve0 != 0) sleeve0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - if (sleeve1 != 0) sleeve1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); - if (pants0 != 0) 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); + } } void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float xRot, float scale, shared_ptr entity, unsigned int uiBitmaskOverrideAnim) diff --git a/Minecraft.Client/HumanoidModel.h b/Minecraft.Client/HumanoidModel.h index 424509a7..8980be15 100644 --- a/Minecraft.Client/HumanoidModel.h +++ b/Minecraft.Client/HumanoidModel.h @@ -18,6 +18,7 @@ public: bool elytraFlying; bool elytraCrouching; bool m_isArmor; + bool m_is64x64; unsigned int m_uiAnimOverrideBitmask; float m_fYOffset; enum animbits diff --git a/Minecraft.Client/ItemInHandRenderer.cpp b/Minecraft.Client/ItemInHandRenderer.cpp index e04945c5..4d91b4f0 100644 --- a/Minecraft.Client/ItemInHandRenderer.cpp +++ b/Minecraft.Client/ItemInHandRenderer.cpp @@ -407,26 +407,6 @@ void ItemInHandRenderer::render(float a) return; } - vector* pSkinOffsets = nullptr; - pSkinOffsets = player->GetSkinOffsets(); - if (pSkinOffsets != nullptr) - { - for( SKIN_OFFSET *pSkinOffset : *pSkinOffsets ) - { - switch (pSkinOffset->ePart) - { - case eBodyOffset_Arm0: - if (pSkinOffset->fD == 2) - h += pSkinOffset->fO / 16.0f; - break; - case eBodyOffset_Tool0: - if (pSkinOffset->fD == 2) - h += pSkinOffset->fO / 16.0f; - break; - } - } - } - // 4J - added so we can adjust the position of the hands for horizontal & vertical split screens float fudgeX = 0.0f; float fudgeY = 0.0f;