From 69983c51adc8b8a42c02cf3c4db835b9cf2eb2d5 Mon Sep 17 00:00:00 2001 From: Langtanium <94726057+Langtanium@users.noreply.github.com> Date: Tue, 31 Mar 2026 19:16:43 -0700 Subject: [PATCH 1/4] Added code for 64x64 skins Added code for 64x64 classic and slim skins. Also added the remaining default skins. --- Minecraft.Client/Common/Consoles_App.cpp | 18 +- Minecraft.Client/Common/DLC/DLCManager.cpp | 1 + Minecraft.Client/Common/DLC/DLCManager.h | 1 + Minecraft.Client/Common/DLC/DLCSkinFile.cpp | 207 ++++++++++- Minecraft.Client/Common/DLC/DLCSkinFile.h | 5 + .../Common/UI/UIControl_PlayerSkinPreview.cpp | 10 +- .../Common/UI/UIScene_SkinSelectMenu.cpp | 40 ++ .../Common/res/1_2_2/mob/DevAlex.png | Bin 0 -> 3289 bytes .../Common/res/1_2_2/mob/DevSteve.png | Bin 0 -> 2561 bytes .../Common/res/1_2_2/mob/alex.png | Bin 0 -> 3420 bytes .../Common/res/1_2_2/mob/alex1.png | Bin 0 -> 2167 bytes .../Common/res/1_2_2/mob/alex2.png | Bin 0 -> 17576 bytes .../Common/res/1_2_2/mob/alex3.png | Bin 0 -> 1659 bytes .../Common/res/1_2_2/mob/alex4.png | Bin 0 -> 1976 bytes .../Common/res/1_2_2/mob/alex5.png | Bin 0 -> 2143 bytes .../Common/res/1_2_2/mob/alex6.png | Bin 0 -> 17619 bytes .../Common/res/1_2_2/mob/alex7.png | Bin 0 -> 2464 bytes Minecraft.Client/EntityRenderer.cpp | 2 + Minecraft.Client/EntityRenderer.h | 4 + Minecraft.Client/HumanoidModel.cpp | 347 ++++++++++++++---- Minecraft.Client/HumanoidModel.h | 31 +- Minecraft.Client/LivingEntityRenderer.cpp | 70 +++- Minecraft.Client/LivingEntityRenderer.h | 1 + Minecraft.Client/PlayerRenderer.cpp | 117 +++--- Minecraft.Client/PlayerRenderer.h | 3 + Minecraft.Client/SkinBox.h | 19 +- Minecraft.Client/SkinOffset.h | 40 ++ Minecraft.Client/Textures.cpp | 10 + Minecraft.Client/Textures.h | 10 + Minecraft.World/Definitions.h | 10 + Minecraft.World/Player.cpp | 20 + 31 files changed, 819 insertions(+), 147 deletions(-) create mode 100644 Minecraft.Client/Common/res/1_2_2/mob/DevAlex.png create mode 100644 Minecraft.Client/Common/res/1_2_2/mob/DevSteve.png create mode 100644 Minecraft.Client/Common/res/1_2_2/mob/alex.png create mode 100644 Minecraft.Client/Common/res/1_2_2/mob/alex1.png create mode 100644 Minecraft.Client/Common/res/1_2_2/mob/alex2.png create mode 100644 Minecraft.Client/Common/res/1_2_2/mob/alex3.png create mode 100644 Minecraft.Client/Common/res/1_2_2/mob/alex4.png create mode 100644 Minecraft.Client/Common/res/1_2_2/mob/alex5.png create mode 100644 Minecraft.Client/Common/res/1_2_2/mob/alex6.png create mode 100644 Minecraft.Client/Common/res/1_2_2/mob/alex7.png create mode 100644 Minecraft.Client/SkinOffset.h diff --git a/Minecraft.Client/Common/Consoles_App.cpp b/Minecraft.Client/Common/Consoles_App.cpp index 0a2fd159a4..2dd3882eb0 100644 --- a/Minecraft.Client/Common/Consoles_App.cpp +++ b/Minecraft.Client/Common/Consoles_App.cpp @@ -9201,7 +9201,14 @@ bool CMinecraftApp::DLCContentRetrieved(eDLCMarketplaceType eType) void CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, SKIN_BOX *SkinBoxA, DWORD dwSkinBoxC) { EntityRenderer *renderer = EntityRenderDispatcher::instance->getRenderer(eTYPE_PLAYER); - Model *pModel = renderer->getModel(); + unsigned int m_uiAnimOverrideBitmask = Player::getSkinAnimOverrideBitmask(dwSkinID); + Model *pModel; + if (m_uiAnimOverrideBitmask&(1<getModelClassic(); + else if (m_uiAnimOverrideBitmask&(1<getModelSlim(); + else + pModel = renderer->getModel(); vector *pvModelPart = new vector; vector *pvSkinBoxes = new vector; @@ -9233,7 +9240,14 @@ void CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, SKIN_BOX *SkinBoxA, D vector * CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, vector *pvSkinBoxA) { EntityRenderer *renderer = EntityRenderDispatcher::instance->getRenderer(eTYPE_PLAYER); - Model *pModel = renderer->getModel(); + unsigned int m_uiAnimOverrideBitmask = Player::getSkinAnimOverrideBitmask(dwSkinID); + Model *pModel; + if (m_uiAnimOverrideBitmask&(1<getModelClassic(); + else if (m_uiAnimOverrideBitmask&(1<getModelSlim(); + else + pModel = renderer->getModel(); vector *pvModelPart = new vector; EnterCriticalSection( &csAdditionalModelParts ); diff --git a/Minecraft.Client/Common/DLC/DLCManager.cpp b/Minecraft.Client/Common/DLC/DLCManager.cpp index c363becf43..f56b48b5fa 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 f114bd0756..a51160d777 100644 --- a/Minecraft.Client/Common/DLC/DLCManager.h +++ b/Minecraft.Client/Common/DLC/DLCManager.h @@ -45,6 +45,7 @@ class DLCManager 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 f7ef2ad005..ac0a86c768 100644 --- a/Minecraft.Client/Common/DLC/DLCSkinFile.cpp +++ b/Minecraft.Client/Common/DLC/DLCSkinFile.cpp @@ -113,12 +113,12 @@ void DLCSkinFile::addParameter(DLCManager::EDLCParameterType type, const wstring WCHAR wchBodyPart[10]; SKIN_BOX *pSkinBox = new SKIN_BOX; ZeroMemory(pSkinBox,sizeof(SKIN_BOX)); - + #ifdef __PS3__ // 4J Stu - The Xbox version used swscanf_s which isn't available in GCC. - swscanf(value.c_str(), L"%10ls%f%f%f%f%f%f%f%f", wchBodyPart, + swscanf(value.c_str(), L"%10ls%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", wchBodyPart,10, #endif &pSkinBox->fX, &pSkinBox->fY, @@ -127,7 +127,9 @@ void DLCSkinFile::addParameter(DLCManager::EDLCParameterType type, const wstring &pSkinBox->fH, &pSkinBox->fD, &pSkinBox->fU, - &pSkinBox->fV); + &pSkinBox->fV, + &pSkinBox->fA, + &pSkinBox->fM); if(wcscmp(wchBodyPart,L"HEAD")==0) { @@ -153,11 +155,199 @@ 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[4]; + 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%f%f%f%f", wchBodyPart, +#else + swscanf_s(value.c_str(), L"%9ls%f%f%f%f", wchBodyPart,4, +#endif + &pSkinOffset->fD, + &pSkinOffset->fO); + + 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"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. @@ -185,6 +375,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/DLC/DLCSkinFile.h b/Minecraft.Client/Common/DLC/DLCSkinFile.h index 15a50e7178..3b25861e8b 100644 --- a/Minecraft.Client/Common/DLC/DLCSkinFile.h +++ b/Minecraft.Client/Common/DLC/DLCSkinFile.h @@ -1,6 +1,8 @@ #pragma once #include "DLCFile.h" #include "..\..\..\Minecraft.Client\HumanoidModel.h" +// This is added to prevent a building failure, probably should move it to HumanoidModel.h later - Langtanium +#include "..\..\..\Minecraft.Client\SkinOffset.h" class DLCSkinFile : public DLCFile { @@ -12,6 +14,7 @@ class DLCSkinFile : public DLCFile unsigned int m_uiAnimOverrideBitmask; bool m_bIsFree; vector m_AdditionalBoxes; + vector m_Offsets; public: @@ -24,6 +27,8 @@ class DLCSkinFile : public DLCFile 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/UI/UIControl_PlayerSkinPreview.cpp b/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp index b8c439b1a5..be6169c3d6 100644 --- a/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp +++ b/Minecraft.Client/Common/UI/UIControl_PlayerSkinPreview.cpp @@ -257,7 +257,15 @@ void UIControl_PlayerSkinPreview::render(EntityRenderer *renderer, double x, dou glPushMatrix(); glDisable(GL_CULL_FACE); - HumanoidModel *model = static_cast(renderer->getModel()); + HumanoidModel *model; + Textures *t = Minecraft::GetInstance()->textures; + + if ((t->loadMemTexture(m_customTextureUrl, m_backupTexture) >= 45 && t->loadMemTexture(m_customTextureUrl, m_backupTexture) <= 53) || m_uiAnimOverrideBitmask&(1<(renderer->getModelSlim()); + else if (t->loadMemTexture(m_customTextureUrl, m_backupTexture) == 54 || m_uiAnimOverrideBitmask&(1<(renderer->getModelClassic()); + else + model = static_cast(renderer->getModel()); //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 a3482a24d1..2c179d9d74 100644 --- a/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_SkinSelectMenu.cpp @@ -24,6 +24,16 @@ const WCHAR *UIScene_SkinSelectMenu::wchDefaultNamesA[]= L"Prisoner Steve", L"Cyclist Steve", L"Boxer Steve", + L"Alex", + L"Tennis 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) @@ -993,6 +1003,36 @@ TEXTURE_NAME UIScene_SkinSelectMenu::getTextureId(int skinIndex) case eDefaultSkins_Skin7: texture = TN_MOB_CHAR7; break; + case eDefaultSkins_Skin8: + texture = TN_MOB_ALEX; + break; + case eDefaultSkins_Skin9: + texture = TN_MOB_ALEX1; + break; + case eDefaultSkins_Skin10: + texture = TN_MOB_ALEX2; + break; + case eDefaultSkins_Skin11: + texture = TN_MOB_ALEX3; + break; + case eDefaultSkins_Skin12: + texture = TN_MOB_ALEX4; + break; + case eDefaultSkins_Skin13: + texture = TN_MOB_ALEX5; + break; + case eDefaultSkins_Skin14: + texture = TN_MOB_ALEX6; + break; + case eDefaultSkins_Skin15: + texture = TN_MOB_ALEX7; + break; + case eDefaultSkins_Skin16: + texture = TN_MOB_DEVALEX; + break; + case eDefaultSkins_Skin17: + texture = TN_MOB_DEVSTEVE; + break; }; return texture; diff --git a/Minecraft.Client/Common/res/1_2_2/mob/DevAlex.png b/Minecraft.Client/Common/res/1_2_2/mob/DevAlex.png new file mode 100644 index 0000000000000000000000000000000000000000..9db32e3d858fafc54e5231d66f5c94d327833f66 GIT binary patch literal 3289 zcmV;~3?}o5P)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRZ|Ur9tkRCwCln`>-b$92blckbO6cbAmN}x5*^F3Yt^>m0*Qduu9e71P$zEU zI*x5XZCax#3Z!U&1}%bqN`$s(fujA;^nrYEQYTJP8;u<_fa3-Tk~U7F#zkd4Dp{tZ zhxsO#+Q)s*^uyhI_g-?jd|9N-0}QyFnZ0+;f6koOoYg)!UZfL!^RGXoI*tGDkAB|q z`zQb9oW>^Tqy(c+7bbsQH0q=Z+dGKu~V4B7~>HY3Mx?Pe!Qtb1lElWZ}1 zWh#SIB-(O7ZdMZOW`31Ep$Rmx@-dna2uu<9cD(JF^DY2DyYiKX5_aB5CowU)vMVG2h$O&kSc!hm z@e==AwazdY{YJu1C=B%jP=rEQt@ZVHO_(rKZaLfpf7MLwp|IXy{Ca68LD1g(yJJe%1)}NAnd6UAzU2U~zVh!J`IQIhDh5moJ*gjLQ*Ngw z{*TO?-&`T~Qc8SZV%8jlrXhs3Ov)8fDP&e@x{)GXXgyyyVE?CH-X00?Rj|--$4Vmy zn7KN^`#$gy(&;P`En?WcQp3Gci5)4Bjfj6K zB_V5`?c@7Rrf45kS7saJaynpR*A3D}YI~2s@{W%kIgnWC&t|>oct|O^a^*_L_`X~& zt4gK9e|_P;w&P!XX}aTrzIEzS$LHU9=bb8C%gbN+Q|9Lao$CSI z;2Mme+Y;eVz4x#J_=A6&0iakcB7`873Y4SgdHBAM>$=?g(a*LXlV^#gu7J!Ej5AxFKDF7b1dx+6;5h3(YkFWT`J%d^Lid|>~0KIbFOhksMR0<&k zJ>`L@zvuBkVd+2q7La%fd|&dwU!DQrxlfPN+uaJZ9{r~Y0J7OEzTX1Ib=?SrI4xIp z>s5Xc0DZ+QkK8>3KwmMprgG{nWa-YO(S$~qzw!j7QYpsA$GPqP-(=?e_W)@8$*24AFwB%+3-16Qgzf9`}Xal zeCR;{-umi8h?K!EeeM*QOeV2Qg+gJ~cMBo7eED*8tbE@`2!UZ3IF6G5Nh!tB(h`PY z;Cbu!qzu=KTo^KGBM6F`W+hyvAGZVw8jefa&~ZG!t@yog_UwumUHrrg6b>GwQmJeR z=uJ##(>S%%68n3Lb%YAkhmsQ0@vt0^ zOJ?$Dbaiz_JECb?#JHwuNGWlF!P(gs^Zor4L)+bEzEUdM<;WfOeUwrR?;B6VAx5E( zZqKBrJVs3~qM8;!L!*>W(c8Os^Jeh1YM#UU4@V0$O_Mh+pNh#sOXQZP#a2Xkj>E#p z2mrTEPct(x&~g51%FFj8u4|D>r&k=6NYo=Un8Iu{$Tc@;-T8pHv*Y`I6sw0jyu3d& zMR6@1r{#(CnSlXvYv~lF5-kd>n#{S56ARm0@dhy;z_Fb`avP0}OF$e1%d#ToLQ!08 z$COeDMI@!f269qTnw*U0&kYSl;vSzLe_p%(L3W=G*M{ddPDu zbRp1%z?Tx~xk#y)o;btXlha74xO#00DHRtlOrQ$`-`Ri_FpQQO7#kZSo6WXFIg?>z zWQ57sPR4EcYNGrb2M@L%Yh%Zyl#v3AOF`WJ`@V;+8_laW#lqE#lt*u;f8OHa8xxF; z4s-F+1os`>&*ao3rQW{v0}$F%0Nb{s9S_C7-GalNUrh&m_+U@l{uj^8t?gedlMLIj zfgr@yg^oxW6iXxcZY$Xmr+il)bD4X-p?ttbX}No<>pF3%YG)lf1zYWohHcxiDC;cr z^}&S;y!VM;XUPmUW40c+!!9d0Bk$ib`+iIKzA;Ke?u}tHw%6I z<8bgGgr4NY1k~&B`s2eSI)9)AXrlpi+TUD#_#)@|NOVbM`|JJP&F$n4S*pZeSH! ze*Esz0l)wDe{=hAP&2Uf-Pbt2Cn&qSbnYV0Tnq9JdBXq`@?58XHpgP!-aQg<-Cil) zmBocX@AYQs&u5TIP%P+JmV@Q`)JaDz=N|C!MFIr9cwW84Y6#{_ML(2Uwm* zrs)Lba;=1i-wcE6wcxMgdb<;VO3lOaJnWc~v#j8F?M+FU;1rdNW3WUkO_D!6>M ztC=YZ7|*6P9M8x0B-7RU?sA2zHK(nxR_zw^yVez6v>dvdTD|V*y!icB=`VIMTWwIW z9a1{fo5$W0I@gwJI}5;8>kDST@vyr8iz5o3?C;>vp5HMOUQZ-}cZ&G3y8pqyapn&;mgIC|`9KFR;Y$4K*Ju^vW zdK!Ct9842VpAIG*I|hdj!_lLw7b4vV0M?Vsj4!7lj@26=IDV*sp` zKVK_V9j_hGg+Kvbvu;2%nYUwCRkrJsHo)PEiQtg7#8P(`xwH&^Nv5D-JG@rSM{`WG zRY=unH2Cz9!zjXg0m1%5hsfr;z{t_Hrv-rYJ^K0sFK>RX{S8x3YU4lE+cE%g33^*~ zGhF^f>|8FAp3|X%T7^8XspK?4yB{t{DRCVqGKU+v`rZ~#Fsvg88D3sr5T6(Jg=Q|H z+?oneh4wPWJOp(DW}|_U631?@=pOm(C%Ny5Pf%Hy*nU?yWK1bVyOv#0mKy5^sL?(e&{48ZdG0n;?eWHK0rL9JFJUVq@a zZd6?o))>U^_urnJW_sdGP)_f;_)s-7vL0|74F1|5Af2oi1 z=|iwL`#zRsVObW9Mg!ZnaU3UV zp65j^el+6u{Cft+aIHF)S)*24!ZhpHj*V$q5wc+0|fw(bs*bOU`yIm zDG7Ld6cqj$Hqtcm$p`?@N}CFS{M+iV6X!>!90lOY762HD0EjkVI|V?bF#unE061_9 z0JZbkr@05={HqRj)+eHP-*~GoE&&>n^9yXN6UVSAXPVJjZyd;Uv2Xa~aC^z%$mdjd zy(C(tgtF_gERW-u^B?~>L@hbk;BO};k;bfh#`d%*JkCz^x+B$hFs~>n$Gx#`Oh zr<<80d7`&jH*daL=!hnc5#`&F1M~|=6t>j`SBs|}O>V_o5KiQ-%a4J-|6a%u>8&wqM_A@vm4ywu|Yo3X6$xhE( zpd`u}LHSbnLi?mKxS9?T=AdWz-3ewV4MT4<-Z%c5(^?W>yA-WGCyFbm5kP)qRIwk! zV1w%{$*?A)*H75G7kJS!;uux^Oq93nxOvd#iiUI$^4p6 zK99<^%Oy2$IsWK<5mYYizLrz6#XC9LI&cDFsGmv1%Q&rCo6Si6`F9nk#?r=>EXgTO-40Mi-AJ!HZ#S)9W5_7JEsemW_A3< z#Jiy2l&LsjWik8YX82>bbmxu;1{8@zPo~WH z))mKE_2M#BeOrg99y~J zU4AGkDykW=J#eTo66fIT+8C5~Ps))t_OO1Wka&V*elY zg-g#@2r>6xD>X*a^s`1L(IkI=ya|Eu9B7+5MIe*JNKOgIpwHumKE~?mjLIV_ds%9w zm10!ndX}2pyZIbX{-r?#XB1Dhx6OKDjvN^NHU2u^#l7}EmU8nqii^BKgIh)DfC(P) zRXE^_r*bBRl(M}(AA?QzYRDq28LsSPr&8O)hfy^iJ7MQN7AtR_nAz55mp=t5|1*Nd zwe(L(RIDQTm$ixAqn{=yYrIp3bymeO<;LM96vGonDsUb9cT*SM1=q$wV|0-Pz-&=x z9AqW9vh67pMWrXM==6i5kxe#t8HewG#|k45y5{DWm!LK&0uqCO#I@STx(fEI^Ub7~ z{KzIs*&>=R(rP*CaHDHY0RfFL@=jz|A_iRwMSFbD_^-xYozu+HRL-H72Dj$>we|^^nT? z_JxKg8ZPUHjCa!cWZ%W~ueEg6uC z<|A$%gS6RIOic+MeP$eZL!{+Lx!#C>OeBaAA$7dAW!T=^lndJL5x$Wb$jj;u8 zw+6E*5cB<>HF<#(8UKAN&cOoZzzc5+tJT}ZmK6@{YYV8AL|{te^TB9Xv{yL%Yzp1v zRuECNmrTLJeP!Je6%xkafwxB!Tt+d%${?tHh|58`pRFIWnTPIB%J_V<#Vc(s;m68O zc(*SQ=J>Mj!L(9-wPb|oEQWN}ilNhwfNt`~7r7Z`_ zrO0Vam2MpIbNB)b&YnHHm&@hW(Bi>)x2xOXb4WAHP$$K#J=)oIjo_{jP)}A+Mj=OJ zTp#n^-+-y$M%`?SU9?J3ty}BBjF|el8lNVXqLtR3*2?pQf6Mo`9{VBn{ke0yI{gW-jD>5^Q z$f?|3ZSv9I;r2m77;K6+3Ol#Z+8Q-)7On*?v^diwee_SaQKM7)U!-D7Uu$-;J|HCA`cN)wWju=M11qZsx5 zd16hu&#i@q6*$P(*SD$4my60rN>{{)==qsI2eK5~v4ipD%a=@m)+WVh>~IIn`4;iV zry8;MT>Ni~f#DHb4ifoTaEOpB0!{r>6MceFXZmiPB31yW3sq;4CRvlS#>_?J;PNKMP#Z1sT)qL!B9VJd(bp-_DOwtUq48gyp&Oxt>j z&EW4vnQtaIojVzmYm6En##^;lb@F?vB`MY7!hvUXGd~`y4qjSb@>-82;6r<97eBq* zS0A;{r;3&4ElZv&KfhWUA=~^`o{X00$BI*$qUBnYnya7BpncxErVE!26GO^NxZRrI zz2zk+MmFeI-96P+Oo_jnpk!UUxHn@ZRCAy#1rIFIM?xa)J=0y~unO~k2 zpvIAWX9EIc?5ZUZxLxcnQ@@Jduf4-tw>Jk_T`T+b;?|dkzWxZZaC0w-1l7f{=?PWF zh4cycw zwSMEmuLD+qoOb7&yw7!57#+SaNM59?s*x_q!pLb%(f3&Pd3;~YIsc*{ zC;~hCaeSooru~9^vu~v_L853ulKPa8|}4LI04**&%KVg3&|bD^dH literal 0 HcmV?d00001 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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 literal 0 HcmV?d00001 diff --git a/Minecraft.Client/Common/res/1_2_2/mob/alex3.png b/Minecraft.Client/Common/res/1_2_2/mob/alex3.png new file mode 100644 index 0000000000000000000000000000000000000000..a67a3c8234e2176b012cde67c965d5770108e846 GIT binary patch literal 1659 zcmV->288*EP)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRZ?0ZBwbRCwC#nomeuNgT(28(7m4w|ZDTNEf`c2!)~t%R(*&DhpLuD&$l(Y$1!J zhm!VYNTj7fh0sF|f}lAp!iESHwP}L1UW$caFD5kQkuE}zg0O-M@(!jjJtQ;vy~(^k z`D0>|eemNYGw&ty{mk$8o0&HcKT5WV**s zy}y)*5|v#T03?64Zp%Vh2vyY5f%&>@}!!F02MFAd@RY8J3kOz!}lsb z0^s8~8HH2nt>!fpLRA2;xZRaW^6mVbboQEw6!Q@&?kAnSX7cU)TnNF4M_^O9bU_U5 zWdMMu_pU=OmxE!?9VT+va|d#{96Y^uT`^t8!)Dn4Xd`!5CW#dHlMYK4kzzjb>9v=n zqdq2Hius5XdqzIJ&X>_}(8~d8VL^vEn$?e!Q8@kb9!{mVCB03{d9Pp)Q9h|S2~szg z;{KxG!g*2Qb5B2u_Lkaslv1!el1c1_lNcrZ;gp>**tBJ$UdR zx+?~dFqzqO7(>Wdx;3pFz*Ky4(?eV%gWwt&yj%ci&cHE$=>Q~5W+KZnb5|Y!9})?Z zSxdeb#qgxID-$=biCroCNyn0PxxUQuEP_ZHa^xRYcGL~*t0HW)uNRc%K zfXyE|6ea?MKZ~vxL7-)SnSNB*VfW9>_`2AYPG*JyX#IiSpTw?omNcA-5}Bxu2f|xw z%STdMK9YX(oTT48FRny)7FapGM%q~*Qru4twtU6`^jjT7mSxg!b&!6mgWR?+lHrFT zGW;+^Zrc}GIlYFj*9!qXkJ6h5P~lXpw6nm3(mGmC%cZ!#JOKSx2T7$;ssL!65deCt zy>bDhwtOTVeWnCZ5Q)8`VgQXgoK9zDHwFR#kqAH_0Ircipv&NzEr&1t5s3hN{0I<< z09^sLCxAeJiKZZG@;uuJKI74#>N0< zX7V;S2e7dL5Do)`Liz7=bIQ7n4S-;<#XJB52#1S8+Y&%1lo#199`NMuEm(5cV98;F zdAk)N-anbm+pREfx3YR#{&L3N+5nawKggd^dCLNDT5k#gEIoeEegLpY9smxHmIT1} zG6ulshnCC%JOG>nc<=B|jkgB?wNaqy0q~8)z3iPDhnF*U@J@|``?n$R{(grUEpI4* zYPZ+%9s=I}<`+A9i>0Op&|&E++5a~TAQEZpYLI^>SS|qkCJEmD<{x;pEC3t=7=YnM z*EeQ&2dzyNyosuHZ-=Feu!WDx^Ma-Xz`sbPbuR-jHdbs5T@ltZ1ZoLDZR<-D z!1S~dKsemy079Ym06=GbPww7gZK3Od{{gfU0H^h4djrUReg!9A6L9i10ol*5;3%^V z|NVQ=JOC=){}*`xT@lvR1FC($pk#*^?f>JgZ+`zDd%#g<8;&yDjq!kL-!H%~KZy4K z6)#7i?Qc;MY={Tw3Dg6m_LheNK;iuWH2|XL1x5jU9{{Zrr*gnB*v9|>002ovPDHLk FV1oMb-L?P# literal 0 HcmV?d00001 diff --git a/Minecraft.Client/Common/res/1_2_2/mob/alex4.png b/Minecraft.Client/Common/res/1_2_2/mob/alex4.png new file mode 100644 index 0000000000000000000000000000000000000000..a73a9314ab450928783037c566797b99387edad3 GIT binary patch literal 1976 zcmV;p2S@mcP)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRZ@K1oDDRCwCtn(u2N`7s|v} zj@mau5TZ!2eO2?q(U8T&E{n~GS|-aXl!Pv+>1`9MR*g;CCaps@1{pkiar2y>dvb4b zZxWj{z3^~z&$+qW@8>+vbMLw5AtcWhbhbj!*$Tl417!VHX`8V%(RQM90|1#N<8MH1 z%k+_4R`jMM76pb~!uByEoITbnxYPiOhJb=lEETE%L^k@F{z?E)6a*AS0WdBSPBmj)auuFg$TNAu|@*~)<^}_fM-^k2g|B|?~U;C$rq6DcS7v(euzEZ z4~x@{5cgYQGvtI7-#D!J#;GSH{GG5dXN0J?14L&F^$5`;$R43eVNnY4S|F$bV8t(a z+acl|l}35`V_2MSgcaX7q|<3QaXSs0At$85Q*h#T8q(=BtoX)Zak>%Kd;-M%R)}~< zVaeMrg^(xX6vKQBMre|X z-wZinbKV8(L8(9Pw^DDR05YDW6c(~$XRGXnN|Dvs$0mDSC40Y>1cIX#^>$DXK(Qzo z_gfELu=UVI;l%w`NQI{;gr%Q9lX*bY+aU?Qdss5}5m@^5O9;Dg_06aMAAp{8rn3 z30OOH=#b3vz1TE#TcF-(f@M#W%n-o4U~NvzcYW5iMYjp!ek+J>6P#{7Ku$Lw(ENh+ zK>;*$TVye~>}jG;ic$dh@87>a9DsMhT3DZzZf1S9wjcmXi3kDkfO*pc0L91sRv0{L zAcIE@l?4EE2Adm70RXKe0P2kXdIWpSCQ`iq+m&URv5z*sZ|P}}T3G?q8%?sCWkUc3vh8a=fr{rn0>z1hz2FD;ZG01F`*e?!G>%o(%J&leI}0O0Sk0KosF;S&HsG;~|2cm%_m9sq1| zWkGIuNQ!pBv_OO;HdHYhHi^y z04LAXU{w?x1JiGTyvLvC0Px#>(aB|f68tOgv~0n9v}2G(9JN2r^< zT8;qUf9s|h?pp7_UF#jVb<->p!+H+uL42E@5J2H5HYGlyLa`6~u{{-@(hdN{3Dcp-Zwc($jC^Qc>oK*X4@9JCjnS2lE}T{0T+*dLdN=z zk+HsG#MC1Y`_OmPOg#cI^$4^d+iwi?R5yUJ3umQ0(_Xaz`h|mv0LCty-FpC7kvsr4 zJgO1^KguisK0j1t4&VW>Ie_<$p>wD91^~6EKve=j8#;H2+!*K~L+4JB@4sp$LtlSR z4cp5KpxEVgt?U2!CQG{-fR^?DoYUoU&IXHJUe~(*U)2D#tp8U`2+*&$v&tVq-vw)B zpTqf&p!~uIyZ)DJ{hv;JRK6GNIsoi)Hw!>*{htEp>e{{;oDuG12$TWjq%4R2KlX9Dr|q7mt5J?*-=ryAFV!B#0hRaRAr?Nq%3b2jt2D2%uj$ zSXls+Y7B}2kS_#YFWw`m)mf5Soh7dq?~&LuH~A|W+C3q_uklCb1GEMp*ZRMb2jGlw zM?C;*3$Tu0!LeOefHeke4FX?ZkZXmPUHVQ09IzU2(Aogj17gqIB=*c*9uFwCzJM)$ zpal?_8UVH~fG>_vN`htafMV+lvZ_27k=Ty)0crr0z87c(@c#h*hQt8cFLNIN0000< KMNUMnLSTYA?13== literal 0 HcmV?d00001 diff --git a/Minecraft.Client/Common/res/1_2_2/mob/alex5.png b/Minecraft.Client/Common/res/1_2_2/mob/alex5.png new file mode 100644 index 0000000000000000000000000000000000000000..a81c05fcc1d298fe94794d50f8f547ea1e2d6f1c GIT binary patch literal 2143 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 literal 0 HcmV?d00001 diff --git a/Minecraft.Client/Common/res/1_2_2/mob/alex7.png b/Minecraft.Client/Common/res/1_2_2/mob/alex7.png new file mode 100644 index 0000000000000000000000000000000000000000..cb20ba3aab02410c3b8c95568448c337cd770dcf GIT binary patch literal 2464 zcmV;R319Y!P)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRZ_CP_p=RCwC#nr&=T*B!>6n>Z2T1L9?E7&dm^oWwSeR}v=<*f+8BMqrS!eVDef zYF!2?G`yv40LP@TRikK?@}Uyakfs(WLfep9@om~9v}xZ!rBYZ|p|U6}Flg0u9cBCS z?8E=wo9mk!+aU?0t1UgczV{qopa1VZ|8tIg4v^**bc5X$VEtOK-3tcYU{|@Eca(vR z?$k=CnA7XyGu@)ovFYzm$MAk4Xe*K#37G(BDFGYYV24+ZF)z4rtz2((gGa;Qp&Iao z4dBal;K6Dzp(X>!&CNCLnVXx7+}vC!iUI&|I2+h{B+VZHHyAAeH@d*BKCsavPd?}d zxB0;1D%f8Q9;#Hh+plm>KwpB?R5aUa&mH@D2m~Z z8B^eNOaPeDVeD)VMn_cK`t!Mk1<>RHW2NGN&N2beT>;iQ!7UnqeU)I}I)(ezE8M?9 zQea=DlpPHNIXO8=vU5YqPS6y%IseDb_BVr(g`Yxf{+K?;u8REr2?R% zT#lV((%UCg@OTS&q7^(677a-U$f1Y?o1dSLB} zrH{~u(5*f&sP!A0isZbx5FBm+ZoM8g0@Z`G=DcyV85Zs8WelLsCAr*L27aqT#`st% zxTQkI`u1|LwFK;|1y8n0uisY#hTJj?Zghz=y2|A}J-1H5}?RW%?JOj2oD|y~mBM@RRVL}Ce-U%L!fJa*t9#_Q~Kdb;(5a0k(NY=m^q<6`LQ#`PQlfsXHsrb& z0RY{Cy8cvDLtPi0ey&)tf~!`o;>wjPxop`o{`T9zyWa&a^#DUrW!mQlg5U?Y@A7a1 zc(?(4sS!NX0RHXnXFMDPf8z@9+!`OxukrDcGr)^Zf0EJ#HV_1LEvr0iXu$w1U%os^ z)-SRHFfsX%6uN5>!V?&n|f{=fgrBTe81r(Xa#eY{`^K2rb*bqc_a;qkcv zu)bysz^;K4lMi|G&L`Yo5ALrA|N4(ldH3@#`AQ@Bmea?#Ts~fO1^Bkh$MY_Kl4c8F zb@+|N31A>7^Mn(vk^*B7COOyyzU}h!*G?bLx%|9f2|iN*^O^$s7f(z+IKHwKQID(Ee(0f0Y0@R3qpEqAiRo^WAnqBaEkk&R11gD1ZSpyghnQoxT z&fexmBvkOjiTg>Kn0#o+9E`41_3dPZKJNgg1s7GAXkW@i`_dT!nDsOO*tyhzGg||eptmRhefn2|RC!>JObw8ZAKMjx-V5SauYyhdAh_x(L9dl5rg4gTn z^&c0&fl4{oQ+F_AO3kRkSr3D{%tPFHn{nD&#~RQ~5X@z>0nir!_XJ=ZcX`1*ntHu* z{d?Mb{rWENEF5t4+6`X4b|b9=%=PRny-)yFhu=t&dGeF0Y}O92g0KcY8wbp13anW7 ze3F(HZ8wyv?1`m-bzIlScDoV4uI}~Qcc#q&bX~uFXW<=So$0;f^d%`>`FWRr#+l@) zf|4XRS?lUk>r^raY7Wo}!FoMo0B0k~y1WzkL$5L~y1Y~FIWhUrkoEg6b}oz-6@XOA z0>}c$0>}c$0>}c$0>}c$0>}c$0>}c$0>}dRKLB7|JG3sYrUPL97ufs<$JYvg4#B+s z|Fs36|J{{MfyD|S-Tndd-UGY+2X@Qr=~ku>RD+8KK)U?{=6``x?Jt;V0n`dWFIzMK z=DNRNCIEI2^mV^Q1;BRyfMt)tV8{}Ln!L*+(-q*a4ghU`L8?s_cFWtT_5qjyB-BL& zV6OWM>;R;5z`O#O>z33^_YcfeW?tVP2+F$ui~vkqc;^kkTwm!HPt%q4dS!jTFED+L z-@GrN&$2gQ(EzYpR=0D2Ue8+gxU0XH;=Q;O@5N6-Wky@x+@<1DycfVza6qQ}3#<-! z-1UDQz}U^-Vf>@_F#ged#{06U!yoIdktbIG0000 literal 0 HcmV?d00001 diff --git a/Minecraft.Client/EntityRenderer.cpp b/Minecraft.Client/EntityRenderer.cpp index fa41dfa606..637b6315af 100644 --- a/Minecraft.Client/EntityRenderer.cpp +++ b/Minecraft.Client/EntityRenderer.cpp @@ -19,6 +19,8 @@ ResourceLocation EntityRenderer::SHADOW_LOCATION = ResourceLocation(TN__CLAMP__M EntityRenderer::EntityRenderer() { model = nullptr; + modelClassic = nullptr; + modelSlim = nullptr; tileRenderer = new TileRenderer(); shadowRadius = 0; shadowStrength = 1.0f; diff --git a/Minecraft.Client/EntityRenderer.h b/Minecraft.Client/EntityRenderer.h index ef3b63bdc2..a60b3a1452 100644 --- a/Minecraft.Client/EntityRenderer.h +++ b/Minecraft.Client/EntityRenderer.h @@ -30,6 +30,8 @@ class EntityRenderer 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 *modelClassic; + Model *modelSlim; protected: TileRenderer *tileRenderer; // 4J - changed to protected so derived classes can use instead of shadowing their own @@ -68,5 +70,7 @@ class EntityRenderer public: // 4J Added virtual Model *getModel() { return model; } + virtual Model *getModelClassic() { return modelClassic; } + virtual Model *getModelSlim() { return modelSlim; } virtual void SetItemFrame(bool bSet) {} }; diff --git a/Minecraft.Client/HumanoidModel.cpp b/Minecraft.Client/HumanoidModel.cpp index c6c6b9f4f4..8a425b8ba7 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) { @@ -30,6 +31,26 @@ ModelPart * HumanoidModel::AddOrRetrievePart(SKIN_BOX *pBox) case eBodyPart_Leg1: pAttachTo=leg1; 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; } // first check this box doesn't already exist @@ -49,7 +70,8 @@ ModelPart * HumanoidModel::AddOrRetrievePart(SKIN_BOX *pBox) pNewBox = new ModelPart(this, static_cast(pBox->fU), static_cast(pBox->fV)); pNewBox->visible=false; - pNewBox->addHumanoidBox(pBox->fX, pBox->fY, pBox->fZ, pBox->fW, pBox->fH, pBox->fD, 0); + if (pBox->fM > 0) pNewBox->bMirror = true; + 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); pAttachTo->addChild(pNewBox); @@ -58,47 +80,110 @@ ModelPart * HumanoidModel::AddOrRetrievePart(SKIN_BOX *pBox) return pNewBox; } -void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight) +void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight, bool slimHands, bool isArmor) { this->texWidth = texWidth; this->texHeight = texHeight; + jacket = nullptr; + sleeve0 = nullptr; + sleeve1 = nullptr; + pants0 = nullptr; + pants1 = nullptr; + m_fYOffset=yOffset; - cloak = new ModelPart(this, 0, 0); - cloak->addHumanoidBox(-5, -0, -1, 10, 16, 1, g); // Cloak - - ear = new ModelPart(this, 24, 0); - ear->addHumanoidBox(-3, -6, -1, 6, 6, 1, g); // Ear - - head = new ModelPart(this, 0, 0); - head->addHumanoidBox(-4, -8, -4, 8, 8, 8, g); // Head - head->setPos(0, 0 + yOffset, 0); - - hair = new ModelPart(this, 32, 0); - hair->addHumanoidBox(-4, -8, -4, 8, 8, 8, g + 0.5f); // Head - hair->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); - - arm0 = new ModelPart(this, 24 + 16, 16); - arm0->addHumanoidBox(-3, -2, -2, 4, 12, 4, g); // Arm0 - arm0->setPos(-5, 2 + yOffset, 0); - - arm1 = new ModelPart(this, 24 + 16, 16); - arm1->bMirror = true; - arm1->addHumanoidBox(-1, -2, -2, 4, 12, 4, g); // Arm1 - arm1->setPos(5, 2 + yOffset, 0); - - leg0 = new ModelPart(this, 0, 16); - leg0->addHumanoidBox(-2, 0, -2, 4, 12, 4, g); // Leg0 - leg0->setPos(-1.9, 12 + yOffset, 0); - - leg1 = new ModelPart(this, 0, 16); - leg1->bMirror = true; - leg1->addHumanoidBox(-2, 0, -2, 4, 12, 4, g); // Leg1 - leg1->setPos(1.9, 12 + yOffset, 0); + cloak = new ModelPart(this, 0, 0); + cloak->addHumanoidBox(-5, -0, -1, 10, 16, 1, g); // Cloak + + ear = new ModelPart(this, 24, 0); + ear->addHumanoidBox(-3, -6, -1, 6, 6, 1, g); // Ear + + head = new ModelPart(this, 0, 0); + head->addHumanoidBox(-4, -8, -4, 8, 8, 8, g); // Head + head->setPos(0, 0 + yOffset, 0); + + hair = new ModelPart(this, 32, 0); + hair->addHumanoidBox(-4, -8, -4, 8, 8, 8, g + 0.5f); // Head + hair->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 (texHeight == 64) + { + jacket = new ModelPart(this, 16, 32); + jacket->addHumanoidBox(-4, 0, -2, 8, 12, 4, g + 0.25); // Jacket + jacket->setPos(0, 0 + yOffset, 0); + } + + if (texHeight == 64) + { + arm0 = new ModelPart(this, 24 + 16, 16); + arm1 = new ModelPart(this, 16 + 16, 48); + + sleeve0 = new ModelPart(this, 24 + 16, 32); + sleeve1 = new ModelPart(this, 32 + 16, 48); + + if (slimHands == false) + { + 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) + { + 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->setPos(-5, 2 + yOffset, 0); + sleeve1->setPos(5, 2 + yOffset, 0); + } + else if (texHeight == 32) + { + arm0 = new ModelPart(this, 24 + 16, 16); + arm1 = new ModelPart(this, 24 + 16, 16); + arm1->bMirror = true; + } + + if (slimHands == false) + { + arm0->addHumanoidBox(-3, -2, -2, 4, 12, 4, g); // Arm0 + arm1->addHumanoidBox(-1, -2, -2, 4, 12, 4, g); // Arm1 + } + else if (slimHands == true) + { + 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) + { + 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->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->setPos(1.9, 12 + yOffset, 0); + } + else if (texHeight == 32) + { + leg1 = new ModelPart(this, 0, 16); + leg1->bMirror = true; + } + + leg0->addHumanoidBox(-2, 0, -2, 4, 12, 4, g); // Leg0 + leg0->setPos(-1.9, 12 + yOffset, 0); + + leg1->addHumanoidBox(-2, 0, -2, 4, 12, 4, g); // Leg1 + leg1->setPos(1.9, 12 + yOffset, 0); // 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 @@ -112,6 +197,17 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight) leg1->compile(1.0f/16.0f); hair->compile(1.0f/16.0f); + if (jacket != 0) + jacket->compile(1.0f/16.0f); + if (sleeve0 != 0) + sleeve0->compile(1.0f/16.0f); + if (sleeve1 != 0) + sleeve1->compile(1.0f/16.0f); + if (pants0 != 0) + pants0->compile(1.0f/16.0f); + if (pants1 != 0) + pants1->compile(1.0f/16.0f); + holdingLeftHand=0; holdingRightHand=0; sneaking=false; @@ -123,21 +219,33 @@ void HumanoidModel::_init(float g, float yOffset, int texWidth, int texHeight) eating_t = 0.0f; eating_swing = 0.0f; m_uiAnimOverrideBitmask = 0L; + m_isArmor = isArmor; } + HumanoidModel::HumanoidModel() : Model() { - _init(0, 0, 64, 32); + _init(0, 0, 64, 32, false, false); } HumanoidModel::HumanoidModel(float g) : Model() { - _init(g, 0, 64, 32); + _init(g, 0, 64, 32, false, false); +} + +HumanoidModel::HumanoidModel(float g, bool isArmor) : Model() +{ + _init(g, 0, 64, 32, false, isArmor); } HumanoidModel::HumanoidModel(float g, float yOffset, int texWidth, int texHeight) : Model() { - _init(g,yOffset,texWidth,texHeight); + _init(g,yOffset,texWidth,texHeight, false, false); +} + +HumanoidModel::HumanoidModel(float g, float yOffset, int texWidth, int texHeight, bool slimHands) : Model() +{ + _init(g,yOffset,texWidth,texHeight, slimHands, false); } void HumanoidModel::render(shared_ptr entity, float time, float r, float bob, float yRot, float xRot, float scale, bool usecompiled) @@ -170,13 +278,23 @@ 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 != 0) + 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); } } @@ -199,7 +317,6 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float arm1->xRot=0.0f; arm0->zRot = 0.0f; arm1->zRot = 0.0f; - } else if(uiBitmaskOverrideAnim&(1<zRot = 0.0f; arm1->zRot = 0.0f; } - // arm0.zRot = ((float) (util.Mth.cos(time * 0.2312f) + 1) * 1) * r; + // arm0.zRot = ((float) (util.Mth.cos(time * 0.2312f) + 1) * 1) * r; - // arm1.zRot = ((float) (util.Mth.cos(time * 0.2812f) - 1) * 1) * r; + // arm1.zRot = ((float) (util.Mth.cos(time * 0.2812f) - 1) * 1) * r; leg0->yRot = 0.0f; @@ -272,7 +389,7 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float leg1->xRot=0.0f; leg1->zRot=0.0f; leg0->yRot = 0.0f; - leg1->yRot = 0.0f; + leg1->yRot = 0.0f; } else if(uiBitmaskOverrideAnim&(1<yRot = 0.0f; arm1->yRot = 0.0f; + if (attackTime > -9990.0f) { float swing = attackTime; @@ -316,7 +434,7 @@ 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; + arm0->yRot += body->yRot * 2.0f; if((uiBitmaskOverrideAnim&(1<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 (sneaking) @@ -441,23 +558,68 @@ void HumanoidModel::setupAnim(float time, float r, float bob, float yRot, float arm0->xRot += ((float) (Mth::sin(bob * 0.067f)) * 0.05f); arm1->xRot -= ((float) (Mth::sin(bob * 0.067f)) * 0.05f); } + if (jacket != 0) + { + jacket->x = body->x; + jacket->y = body->y; + jacket->z = body->z; + jacket->xRot = body->xRot; + jacket->yRot = body->yRot; + jacket->zRot = body->zRot; + } + 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; + } } } void HumanoidModel::renderHair(float scale,bool usecompiled) { - hair->yRot = head->yRot; - hair->xRot = head->xRot; - hair->render(scale,usecompiled); + hair->yRot = head->yRot; + hair->xRot = head->xRot; + hair->render(scale,usecompiled); } void HumanoidModel::renderEars(float scale,bool usecompiled) { - ear->yRot = head->yRot; - ear->xRot = head->xRot; - ear->x=0; - ear->y=0; - ear->render(scale,usecompiled); + ear->yRot = head->yRot; + ear->xRot = head->xRot; + ear->x=0; + ear->y=0; + ear->render(scale,usecompiled); } void HumanoidModel::renderCloak(float scale,bool usecompiled) @@ -467,25 +629,42 @@ void HumanoidModel::renderCloak(float scale,bool usecompiled) void HumanoidModel::render(HumanoidModel *model, float scale, bool usecompiled) { - head->yRot = model->head->yRot; - head->y = model->head->y; - head->xRot = model->head->xRot; - hair->y = head->y; - hair->yRot = head->yRot; - hair->xRot = head->xRot; - - body->yRot = model->body->yRot; - - arm0->xRot = model->arm0->xRot; - arm0->yRot = model->arm0->yRot; - arm0->zRot = model->arm0->zRot; - - arm1->xRot = model->arm1->xRot; - arm1->yRot = model->arm1->yRot; - arm1->zRot = model->arm1->zRot; - - leg0->xRot = model->leg0->xRot; - leg1->xRot = model->leg1->xRot; + head->yRot = model->head->yRot; + head->y = model->head->y; + head->xRot = model->head->xRot; + hair->y = head->y; + hair->yRot = head->yRot; + hair->xRot = head->xRot; + + body->yRot = model->body->yRot; + + if (jacket != 0) + jacket->yRot = model->body->yRot; + + arm0->xRot = model->arm0->xRot; + arm0->yRot = model->arm0->yRot; + arm0->zRot = model->arm0->zRot; + + if (sleeve0 != 0) + sleeve0->xRot = model->arm0->xRot; + sleeve0->yRot = model->arm0->yRot; + sleeve0->zRot = model->arm0->zRot; + + arm1->xRot = model->arm1->xRot; + arm1->yRot = model->arm1->yRot; + arm1->zRot = model->arm1->zRot; + + if (sleeve1 != 0) + sleeve1->xRot = model->arm1->xRot; + sleeve1->yRot = model->arm1->yRot; + sleeve1->zRot = model->arm1->zRot; + + leg0->xRot = model->leg0->xRot; + if (pants0 != 0) + pants0->xRot = model->leg0->xRot; + leg1->xRot = model->leg1->xRot; + if (pants1 != 0) + pants1->xRot = model->leg1->xRot; head->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); body->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); @@ -494,4 +673,14 @@ void HumanoidModel::render(HumanoidModel *model, float scale, bool usecompiled) leg0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); leg1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); hair->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<0); + if (jacket != 0) + 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); } diff --git a/Minecraft.Client/HumanoidModel.h b/Minecraft.Client/HumanoidModel.h index 52f9d98e1a..88a57adafb 100644 --- a/Minecraft.Client/HumanoidModel.h +++ b/Minecraft.Client/HumanoidModel.h @@ -4,7 +4,7 @@ class HumanoidModel : public Model { public: - ModelPart *head, *hair, *body, *arm0, *arm1, *leg0, *leg1, *ear, *cloak; + ModelPart *head, *hair, *body, *jacket, *arm0, *sleeve0, *arm1, *sleeve1, *leg0, *pants0, *leg1, *pants1, *ear, *cloak; //ModelPart *hat; int holdingLeftHand; @@ -17,6 +17,7 @@ class HumanoidModel : public Model float eating_swing; // 4J added unsigned int m_uiAnimOverrideBitmask; // 4J added float m_fYOffset; // 4J added + bool m_isArmor; enum animbits { eAnim_ArmsDown =0, @@ -37,7 +38,22 @@ class HumanoidModel : public Model eAnim_DisableRenderLeg0, eAnim_DisableRenderLeg1, eAnim_DisableRenderHair, - eAnim_SmallModel // Maggie Simpson for riding horse, etc + eAnim_SmallModel, // Maggie Simpson for riding horse, etc + eAnim_ClassicModel, + eAnim_SlimModel, + // Hide overlay/second layer on 64x64 skins + eAnim_DisableRenderSleeve1, + eAnim_DisableRenderSleeve0, + eAnim_DisableRenderPants1, + eAnim_DisableRenderPants0, + eAnim_DisableRenderJacket, + eAnim_RenderArmorHead, + eAnim_RenderArmorArm0, + eAnim_RenderArmorArm1, + eAnim_RenderArmorTorso, + eAnim_RenderArmorLeg0, + eAnim_RenderArmorLeg1, + eAnim_Dinnerbone }; @@ -47,13 +63,20 @@ class HumanoidModel : public Model (1< 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); void renderHair(float scale, bool usecompiled); diff --git a/Minecraft.Client/LivingEntityRenderer.cpp b/Minecraft.Client/LivingEntityRenderer.cpp index b3478ba92c..aa738ec772 100644 --- a/Minecraft.Client/LivingEntityRenderer.cpp +++ b/Minecraft.Client/LivingEntityRenderer.cpp @@ -9,13 +9,29 @@ #include "..\Minecraft.World\Mth.h" #include "..\Minecraft.World\Player.h" - ResourceLocation LivingEntityRenderer::ENCHANT_GLINT_LOCATION = ResourceLocation(TN__BLUR__MISC_GLINT); int LivingEntityRenderer::MAX_ARMOR_LAYERS = 4; LivingEntityRenderer::LivingEntityRenderer(Model *model, float shadow) { this->model = model; + + shadowRadius = shadow; + armor = nullptr; +} + +LivingEntityRenderer::LivingEntityRenderer(Model *model, float shadow, bool slimHands, bool is64x64) +{ + this->model = model; + + if (is64x64) + { + this->modelClassic = new HumanoidModel(0, 0, 64, 64, false); + + if (slimHands == true) + this->modelSlim = new HumanoidModel(0, 0, 64, 64, true); + } + shadowRadius = shadow; armor = nullptr; } @@ -43,6 +59,8 @@ 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; if (mob == nullptr) { @@ -52,12 +70,16 @@ void LivingEntityRenderer::render(shared_ptr _mob, double x, double y, d glPushMatrix(); glDisable(GL_CULL_FACE); - model->attackTime = getAttackAnim(mob, a); - if (armor != nullptr) armor->attackTime = model->attackTime; - model->riding = mob->isRiding(); - if (armor != nullptr) armor->riding = model->riding; - model->young = mob->isBaby(); - if (armor != nullptr) armor->young = model->young; + if (player != nullptr && modelClassic != nullptr && (player->getCustomSkin() == 18 || player->getAnimOverrideBitmask()&(1<getCustomSkin() >= 8 && player->getCustomSkin() <= 17) || player->getAnimOverrideBitmask()&(1<attackTime = getAttackAnim(mob, a); + if (armor != nullptr) armor->attackTime = resModel->attackTime; + resModel->riding = mob->isRiding(); + if (armor != nullptr) armor->riding = resModel->riding; + resModel->young = mob->isBaby(); + if (armor != nullptr) armor->young = resModel->young; /*try*/ { @@ -103,7 +125,7 @@ void LivingEntityRenderer::render(shared_ptr _mob, double x, double y, d if (ws > 1) ws = 1; glEnable(GL_ALPHA_TEST); - model->prepareMobModel(mob, wp, ws, a); + resModel->prepareMobModel(mob, wp, ws, a); renderModel(mob, wp, ws, bob, headRot - bodyRot, headRotx, fScale); for (int i = 0; i < MAX_ARMOR_LAYERS; i++) @@ -187,7 +209,7 @@ void LivingEntityRenderer::render(shared_ptr _mob, double x, double y, d if (mob->hurtTime > 0 || mob->deathTime > 0) { glColor4f(br, 0, 0, 0.4f); - model->render(mob, wp, ws, bob, headRot - bodyRot, headRotx, fScale, false); + resModel->render(mob, wp, ws, bob, headRot - bodyRot, headRotx, fScale, false); for (int i = 0; i < MAX_ARMOR_LAYERS; i++) { if (prepareArmorOverlay(mob, i, a) >= 0) @@ -205,7 +227,7 @@ void LivingEntityRenderer::render(shared_ptr _mob, double x, double y, d float b = ((overlayColor) & 0xff) / 255.0f; float aa = ((overlayColor >> 24) & 0xff) / 255.0f; glColor4f(r, g, b, aa); - model->render(mob, wp, ws, bob, headRot - bodyRot, headRotx, fScale, false); + resModel->render(mob, wp, ws, bob, headRot - bodyRot, headRotx, fScale, false); for (int i = 0; i < MAX_ARMOR_LAYERS; i++) { if (prepareArmorOverlay(mob, i, a) >= 0) @@ -242,10 +264,17 @@ 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; + + if (player != nullptr && modelClassic != nullptr && (player->getCustomSkin() == 18 || player->getAnimOverrideBitmask()&(1<getCustomSkin() >= 8 && player->getCustomSkin() <= 17) || player->getAnimOverrideBitmask()&(1<isInvisible()) { - model->render(mob, wp, ws, bob, headRotMinusBodyRot, headRotx, scale, true); + resModel->render(mob, wp, ws, bob, headRotMinusBodyRot, headRotx, scale, true); } else if(!mob->isInvisibleTo(dynamic_pointer_cast(Minecraft::GetInstance()->player))) { @@ -255,7 +284,7 @@ void LivingEntityRenderer::renderModel(shared_ptr mob, float wp, f glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glAlphaFunc(GL_GREATER, 1.0f / 255.0f); - model->render(mob, wp, ws, bob, headRotMinusBodyRot, headRotx, scale, true); + resModel->render(mob, wp, ws, bob, headRotMinusBodyRot, headRotx, scale, true); glDisable(GL_BLEND); glAlphaFunc(GL_GREATER, .1f); glPopMatrix(); @@ -263,7 +292,7 @@ void LivingEntityRenderer::renderModel(shared_ptr mob, float wp, f } else { - model->setupAnim(wp, ws, bob, headRotMinusBodyRot, headRotx, scale, mob); + resModel->setupAnim(wp, ws, bob, headRotMinusBodyRot, headRotx, scale, mob); } } @@ -285,7 +314,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<instanceof(eTYPE_PLAYER) || !dynamic_pointer_cast(mob)->isCapeHidden() ) { @@ -313,7 +342,15 @@ void LivingEntityRenderer::additionalRendering(shared_ptr mob, flo void LivingEntityRenderer::renderArrows(shared_ptr mob, float a) { + shared_ptr player = dynamic_pointer_cast(mob); + Model *resModel; + + if (player != nullptr && modelClassic != nullptr && (player->getCustomSkin() == 18 || player->getAnimOverrideBitmask()&(1<getCustomSkin() >= 8 && player->getCustomSkin() <= 17) || player->getAnimOverrideBitmask()&(1<getArrowCount(); + if (arrowCount > 0) { shared_ptr arrow = std::make_shared(mob->level, mob->x, mob->y, mob->z); @@ -322,7 +359,10 @@ void LivingEntityRenderer::renderArrows(shared_ptr mob, float a) for (int i = 0; i < arrowCount; i++) { glPushMatrix(); - ModelPart *modelPart = model->getRandomModelPart(random); + + ModelPart *modelPart; + modelPart = resModel->getRandomModelPart(random); + Cube *cube = modelPart->cubes[random.nextInt(modelPart->cubes.size())]; modelPart->translateTo(1 / 16.0f); float xd = random.nextFloat(); diff --git a/Minecraft.Client/LivingEntityRenderer.h b/Minecraft.Client/LivingEntityRenderer.h index 2f77e1b54a..6ea76df39a 100644 --- a/Minecraft.Client/LivingEntityRenderer.h +++ b/Minecraft.Client/LivingEntityRenderer.h @@ -20,6 +20,7 @@ class LivingEntityRenderer : public EntityRenderer public: LivingEntityRenderer(Model *model, float shadow); + LivingEntityRenderer(Model *model, float shadow, bool slimHands, bool is64x64); virtual void render(shared_ptr mob, double x, double y, double z, float rot, float a); virtual void setArmor(Model *armor); diff --git a/Minecraft.Client/PlayerRenderer.cpp b/Minecraft.Client/PlayerRenderer.cpp index 23dff77f8e..534c6df368 100644 --- a/Minecraft.Client/PlayerRenderer.cpp +++ b/Minecraft.Client/PlayerRenderer.cpp @@ -55,12 +55,14 @@ static unsigned int nametagColorForIndex(int index) ResourceLocation PlayerRenderer::DEFAULT_LOCATION = ResourceLocation(TN_MOB_CHAR); -PlayerRenderer::PlayerRenderer() : LivingEntityRenderer( new HumanoidModel(0), 0.5f ) +PlayerRenderer::PlayerRenderer() : LivingEntityRenderer( new HumanoidModel(0), 0.5f, true, true ) { - humanoidModel = static_cast(model); + humanoidModel = static_cast(model); + humanoidModelClassic = static_cast(modelClassic); + humanoidModelSlim = static_cast(modelSlim); - armorParts1 = new HumanoidModel(1.0f); - armorParts2 = new HumanoidModel(0.5f); + armorParts1 = new HumanoidModel(1.0f, true); + armorParts2 = new HumanoidModel(0.5f, true); } unsigned int PlayerRenderer::getNametagColour(int index) @@ -160,12 +162,19 @@ 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; if(mob == nullptr) return; if(mob->hasInvisiblePrivilege()) return; + if (mob != nullptr && humanoidModelClassic != nullptr && (mob->getCustomSkin() == 18 || mob->getAnimOverrideBitmask()&(1<getCustomSkin() >= 8 && mob->getCustomSkin() <= 17) || mob->getAnimOverrideBitmask()&(1< item = mob->inventory->getSelected(); - armorParts1->holdingRightHand = armorParts2->holdingRightHand = humanoidModel->holdingRightHand = item != nullptr ? 1 : 0; + + armorParts1->holdingRightHand = armorParts2->holdingRightHand = resModel->holdingRightHand = item != nullptr ? 1 : 0; + if (item != nullptr) { if (mob->getUseItemDuration() > 0) @@ -173,11 +182,11 @@ void PlayerRenderer::render(shared_ptr _mob, double x, double y, double UseAnim anim = item->getUseAnimation(); if (anim == UseAnim_block) { - armorParts1->holdingRightHand = armorParts2->holdingRightHand = humanoidModel->holdingRightHand = 3; + armorParts1->holdingRightHand = armorParts2->holdingRightHand = resModel->holdingRightHand = 3; } else if (anim == UseAnim_bow) { - armorParts1->bowAndArrow = armorParts2->bowAndArrow = humanoidModel->bowAndArrow = true; + armorParts1->bowAndArrow = armorParts2->bowAndArrow = resModel->bowAndArrow = true; } } } @@ -187,17 +196,17 @@ void PlayerRenderer::render(shared_ptr _mob, double x, double y, double // These factors are largely lifted from ItemInHandRenderer to try and keep the 3rd person eating animation as similar as possible float t = (mob->getUseItemDuration() - a + 1); float swing = 1 - (t / item->getUseDuration()); - armorParts1->eating = armorParts2->eating = humanoidModel->eating = true; - armorParts1->eating_t = armorParts2->eating_t = humanoidModel->eating_t = t; - armorParts1->eating_swing = armorParts2->eating_swing = humanoidModel->eating_swing = swing; + + armorParts1->eating = armorParts2->eating = resModel->eating = true; + armorParts1->eating_t = armorParts2->eating_t = resModel->eating_t = t; + armorParts1->eating_swing = armorParts2->eating_swing = resModel->eating_swing = swing; } else { - armorParts1->eating = armorParts2->eating = humanoidModel->eating = false; + armorParts1->eating = armorParts2->eating = resModel->eating = false; } - armorParts1->sneaking = armorParts2->sneaking = humanoidModel->sneaking = mob->isSneaking(); - + armorParts1->sneaking = armorParts2->sneaking = resModel->sneaking = mob->isSneaking(); double yp = y - mob->heightOffset; if (mob->isSneaking() && !mob->instanceof(eTYPE_LOCALPLAYER)) { @@ -209,20 +218,20 @@ void PlayerRenderer::render(shared_ptr _mob, double x, double y, double { if(mob->isIdle()) { - humanoidModel->idle=true; + resModel->idle=true; armorParts1->idle=true; armorParts2->idle=true; } else { - humanoidModel->idle=false; + resModel->idle=false; armorParts1->idle=false; armorParts2->idle=false; } } else { - humanoidModel->idle=false; + resModel->idle=false; armorParts1->idle=false; armorParts2->idle=false; } @@ -248,10 +257,9 @@ void PlayerRenderer::render(shared_ptr _mob, double x, double y, double pModelPart->visible=false; } } - armorParts1->bowAndArrow = armorParts2->bowAndArrow = humanoidModel->bowAndArrow = false; - armorParts1->sneaking = armorParts2->sneaking = humanoidModel->sneaking = false; - armorParts1->holdingRightHand = armorParts2->holdingRightHand = humanoidModel->holdingRightHand = 0; - + armorParts1->bowAndArrow = armorParts2->bowAndArrow = resModel->bowAndArrow = false; + armorParts1->sneaking = armorParts2->sneaking = resModel->sneaking = false; + armorParts1->holdingRightHand = armorParts2->holdingRightHand = resModel->holdingRightHand = 0; } void PlayerRenderer::additionalRendering(shared_ptr _mob, float a) @@ -264,6 +272,11 @@ 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; + + if (mob != nullptr && humanoidModelClassic != nullptr && (mob->getCustomSkin() == 18 || mob->getAnimOverrideBitmask()&(1<getCustomSkin() >= 8 && mob->getCustomSkin() <= 17) || mob->getAnimOverrideBitmask()&(1< headGear = mob->inventory->getArmor(3); if (headGear != nullptr) @@ -274,7 +287,7 @@ void PlayerRenderer::additionalRendering(shared_ptr _mob, float a) if((uiAnimOverrideBitmask&(1<head->translateTo(1 / 16.0f); + resModel->head->translateTo(1 / 16.0f); if(headGear->getItem()->id < 256) { @@ -322,7 +335,7 @@ void PlayerRenderer::additionalRendering(shared_ptr _mob, float a) float s = 8 / 6.0f; glScalef(s, s, s); - humanoidModel->renderEars(1 / 16.0f,true); + resModel->renderEars(1 / 16.0f,true); glPopMatrix(); } } @@ -368,7 +381,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); - humanoidModel->renderCloak(1 / 16.0f,true); + resModel->renderCloak(1 / 16.0f,true); glPopMatrix(); } @@ -377,7 +390,7 @@ void PlayerRenderer::additionalRendering(shared_ptr _mob, float a) if (item != nullptr) { glPushMatrix(); - humanoidModel->arm0->translateTo(1 / 16.0f); + resModel->arm0->translateTo(1 / 16.0f); glTranslatef(-1 / 16.0f, 7 / 16.0f, 1 / 16.0f); if (mob->fishing != nullptr) @@ -507,30 +520,54 @@ void PlayerRenderer::scale(shared_ptr player, float a) void PlayerRenderer::renderHand() { + shared_ptr player = dynamic_pointer_cast(Minecraft::GetInstance()->player); + HumanoidModel *resModel; + + if (player != nullptr && humanoidModelClassic != nullptr && (player->getCustomSkin() == 18 || player->getAnimOverrideBitmask()&(1<getCustomSkin() >= 8 && player->getCustomSkin() <= 17) || player->getAnimOverrideBitmask()&(1<m_uiAnimOverrideBitmask = Minecraft::GetInstance()->player->getAnimOverrideBitmask(); - armorParts1->eating = armorParts2->eating = humanoidModel->eating = humanoidModel->idle = false; - humanoidModel->attackTime = 0; - humanoidModel->setupAnim(0, 0, 0, 0, 0, 1 / 16.0f, Minecraft::GetInstance()->player); + resModel->m_uiAnimOverrideBitmask = player->getAnimOverrideBitmask(); + armorParts1->eating = armorParts2->eating = resModel->eating = resModel->idle = false; + resModel->attackTime = 0; + resModel->setupAnim(0, 0, 0, 0, 0, 1 / 16.0f, Minecraft::GetInstance()->player); // 4J-PB - does this skin have its arm0 disabled? (Dalek, etc) - if((humanoidModel->m_uiAnimOverrideBitmask&(1<arm0->render(1 / 16.0f,true); - } - - + if((resModel->m_uiAnimOverrideBitmask&(1<arm0->render(1 / 16.0f,true); + // Does this skin have its sleeve0 disabled? + if((resModel->m_uiAnimOverrideBitmask&(1<sleeve0!=nullptr) + resModel->sleeve0->render(1 / 16.0f,true); + //Render custom skin boxes on viewmodel - Botch vector* additionalModelParts = Minecraft::GetInstance()->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 = humanoidModel->arm0->children; std::unordered_set additionalModelPartSet(additionalModelParts->begin(), additionalModelParts->end()); + vector armchildren = resModel->arm0->children; for (const auto& x : armchildren) { - if (x) { - if (additionalModelPartSet.find(x) != additionalModelPartSet.end()) { //This is to verify box is still actually on current skin - Botch + if (x && additionalModelPartSet.find(x) != additionalModelPartSet.end()) //This is to verify box is still actually on current skin - Botch + { + glPushMatrix(); + //We need to transform to match offset of arm - Botch + 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(); + } + } + //Render custom skin boxes on viewmodel for sleeve0 + if (resModel->sleeve0!=nullptr) + { + vector sleevechildren = resModel->sleeve0->children; + for (const auto& x : sleevechildren) { + if (x && 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 - Botch + //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; @@ -540,8 +577,6 @@ void PlayerRenderer::renderHand() } } } - - } void PlayerRenderer::setupPosition(shared_ptr _mob, double x, double y, double z) @@ -603,4 +638,4 @@ ResourceLocation *PlayerRenderer::getTextureLocation(shared_ptr entity) { shared_ptr player = dynamic_pointer_cast(entity); return new ResourceLocation(static_cast<_TEXTURE_NAME>(player->getTexture())); -} +} \ No newline at end of file diff --git a/Minecraft.Client/PlayerRenderer.h b/Minecraft.Client/PlayerRenderer.h index 494ff795f0..eafb7aaba2 100644 --- a/Minecraft.Client/PlayerRenderer.h +++ b/Minecraft.Client/PlayerRenderer.h @@ -14,6 +14,9 @@ class PlayerRenderer : public LivingEntityRenderer private: HumanoidModel *humanoidModel; + HumanoidModel *humanoidModelClassic; + HumanoidModel *humanoidModelSlim; + HumanoidModel *armorParts1; HumanoidModel *armorParts2; diff --git a/Minecraft.Client/SkinBox.h b/Minecraft.Client/SkinBox.h index 827e4447c3..907da411dc 100644 --- a/Minecraft.Client/SkinBox.h +++ b/Minecraft.Client/SkinBox.h @@ -9,11 +9,28 @@ 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 { eBodyPart ePart; - float fX,fY,fZ,fW,fH,fD,fU,fV; + float fX,fY,fZ,fW,fH,fD,fU,fV,fA,fM; } SKIN_BOX; diff --git a/Minecraft.Client/SkinOffset.h b/Minecraft.Client/SkinOffset.h new file mode 100644 index 0000000000..39f3780a0a --- /dev/null +++ b/Minecraft.Client/SkinOffset.h @@ -0,0 +1,40 @@ +#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_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 + +}; + +typedef struct +{ + eBodyOffset ePart; + string fD; + float fO; +} +SKIN_OFFSET; diff --git a/Minecraft.Client/Textures.cpp b/Minecraft.Client/Textures.cpp index ba7c028212..ba38dcf7f5 100644 --- a/Minecraft.Client/Textures.cpp +++ b/Minecraft.Client/Textures.cpp @@ -72,6 +72,16 @@ const wchar_t *Textures::preLoaded[TN_COUNT] = L"mob/char5", L"mob/char6", L"mob/char7", + 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", diff --git a/Minecraft.Client/Textures.h b/Minecraft.Client/Textures.h index 1fca56106a..5ac3182e2a 100644 --- a/Minecraft.Client/Textures.h +++ b/Minecraft.Client/Textures.h @@ -63,6 +63,16 @@ typedef enum _TEXTURE_NAME TN_MOB_CHAR5, TN_MOB_CHAR6, TN_MOB_CHAR7, + 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/Definitions.h b/Minecraft.World/Definitions.h index d338019dbe..f45252f5bc 100644 --- a/Minecraft.World/Definitions.h +++ b/Minecraft.World/Definitions.h @@ -35,6 +35,16 @@ enum EDefaultSkins eDefaultSkins_Skin5, eDefaultSkins_Skin6, eDefaultSkins_Skin7, + eDefaultSkins_Skin8, + eDefaultSkins_Skin9, + eDefaultSkins_Skin10, + eDefaultSkins_Skin11, + eDefaultSkins_Skin12, + eDefaultSkins_Skin13, + eDefaultSkins_Skin14, + eDefaultSkins_Skin15, + eDefaultSkins_Skin16, + eDefaultSkins_Skin17, eDefaultSkins_Count, }; \ No newline at end of file diff --git a/Minecraft.World/Player.cpp b/Minecraft.World/Player.cpp index 00c7148e41..0bc5154462 100644 --- a/Minecraft.World/Player.cpp +++ b/Minecraft.World/Player.cpp @@ -2702,6 +2702,26 @@ int Player::getTexture() return TN_MOB_CHAR6; // 4J - was L"/mob/char6.png"; case eDefaultSkins_Skin7: return TN_MOB_CHAR7; // 4J - was L"/mob/char7.png"; + case eDefaultSkins_Skin8: + return TN_MOB_ALEX; // 4J - was L"/mob/alex.png"; + case eDefaultSkins_Skin9: + return TN_MOB_ALEX1; // 4J - was L"/mob/alex1.png"; + case eDefaultSkins_Skin10: + return TN_MOB_ALEX2; // 4J - was L"/mob/alex2.png"; + case eDefaultSkins_Skin11: + return TN_MOB_ALEX3; // 4J - was L"/mob/alex3.png"; + case eDefaultSkins_Skin12: + return TN_MOB_ALEX4; // 4J - was L"/mob/alex4.png"; + case eDefaultSkins_Skin13: + return TN_MOB_ALEX5; // 4J - was L"/mob/alex5.png"; + case eDefaultSkins_Skin14: + return TN_MOB_ALEX6; // 4J - was L"/mob/alex6.png"; + case eDefaultSkins_Skin15: + return TN_MOB_ALEX7; // 4J - was L"/mob/alex7.png"; + case eDefaultSkins_Skin16: + return TN_MOB_DEVALEX; // 4J - was L"/mob/DevAlex.png"; + case eDefaultSkins_Skin17: + return TN_MOB_DEVSTEVE; // 4J - was L"/mob/DevSteve.png"; default: return TN_MOB_CHAR; // 4J - was L"/mob/char.png"; From e98c7a725b7120eba1af95eb57d3b48ff0b6b4d5 Mon Sep 17 00:00:00 2001 From: Langtanium <94726057+Langtanium@users.noreply.github.com> Date: Tue, 31 Mar 2026 21:14:10 -0700 Subject: [PATCH 2/4] Small correction Corrected some code in DLCSkinFile.cpp for getting the DLC skin offsets was getting too many parameters that don't exist. --- Minecraft.Client/Common/DLC/DLCSkinFile.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Minecraft.Client/Common/DLC/DLCSkinFile.cpp b/Minecraft.Client/Common/DLC/DLCSkinFile.cpp index ac0a86c768..3e36f36f64 100644 --- a/Minecraft.Client/Common/DLC/DLCSkinFile.cpp +++ b/Minecraft.Client/Common/DLC/DLCSkinFile.cpp @@ -230,15 +230,15 @@ void DLCSkinFile::addParameter(DLCManager::EDLCParameterType type, const wstring break; case DLCManager::e_DLCParamType_Offset: { - WCHAR wchBodyPart[4]; + WCHAR wchBodyPart[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%f%f%f%f", wchBodyPart, + swscanf(value.c_str(), L"%10ls%f%f", wchBodyPart, #else - swscanf_s(value.c_str(), L"%9ls%f%f%f%f", wchBodyPart,4, + swscanf_s(value.c_str(), L"%9ls%f%f", wchBodyPart,2, #endif &pSkinOffset->fD, &pSkinOffset->fO); From 48e84a9dc4ffd309d58a5dd048cb49566e8eb9d0 Mon Sep 17 00:00:00 2001 From: Langtanium <94726057+Langtanium@users.noreply.github.com> Date: Wed, 1 Apr 2026 16:22:26 -0700 Subject: [PATCH 3/4] Fixed cape rendering Fixed cape not rendering properly for 64x64 skin due to the renderer trying to using a 64x64 texture instead a of a 64x32 texture for the cape. --- Minecraft.Client/PlayerRenderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Minecraft.Client/PlayerRenderer.cpp b/Minecraft.Client/PlayerRenderer.cpp index 534c6df368..6dbe66231d 100644 --- a/Minecraft.Client/PlayerRenderer.cpp +++ b/Minecraft.Client/PlayerRenderer.cpp @@ -381,7 +381,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(); } From 0c963335a0c483c592da63d0e4dc06ca0ff22b42 Mon Sep 17 00:00:00 2001 From: Langtanium <94726057+Langtanium@users.noreply.github.com> Date: Sat, 4 Apr 2026 13:03:00 -0700 Subject: [PATCH 4/4] Small fix Fixed extra skin box data not being sent in multiplayer. Added another model type check in the XUI. --- .../Common/XUI/XUI_Ctrl_MinecraftSkinPreview.cpp | 10 +++++++++- Minecraft.World/TextureAndGeometryPacket.cpp | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Minecraft.Client/Common/XUI/XUI_Ctrl_MinecraftSkinPreview.cpp b/Minecraft.Client/Common/XUI/XUI_Ctrl_MinecraftSkinPreview.cpp index 1fa44d3f7d..120c640612 100644 --- a/Minecraft.Client/Common/XUI/XUI_Ctrl_MinecraftSkinPreview.cpp +++ b/Minecraft.Client/Common/XUI/XUI_Ctrl_MinecraftSkinPreview.cpp @@ -294,7 +294,15 @@ void CXuiCtrlMinecraftSkinPreview::render(EntityRenderer *renderer, double x, do glPushMatrix(); glDisable(GL_CULL_FACE); - HumanoidModel *model = static_cast(renderer->getModel()); + HumanoidModel *model; + Textures *t = Minecraft::GetInstance()->textures; + + if ((t->loadMemTexture(m_customTextureUrl, m_backupTexture) >= 45 && t->loadMemTexture(m_customTextureUrl, m_backupTexture) <= 53) || m_uiAnimOverrideBitmask&(1<(renderer->getModelSlim()); + else if (t->loadMemTexture(m_customTextureUrl, m_backupTexture) == 54 || m_uiAnimOverrideBitmask&(1<(renderer->getModelClassic()); + else + model = static_cast(renderer->getModel()); //getAttackAnim(mob, a); //if (armor != nullptr) armor->attackTime = model->attackTime; diff --git a/Minecraft.World/TextureAndGeometryPacket.cpp b/Minecraft.World/TextureAndGeometryPacket.cpp index 1c920ee7a4..fee0a59aef 100644 --- a/Minecraft.World/TextureAndGeometryPacket.cpp +++ b/Minecraft.World/TextureAndGeometryPacket.cpp @@ -177,6 +177,8 @@ 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(); } } @@ -203,6 +205,8 @@ 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); } }