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);