Added skin offsets code

Added code to apply skin offsets if present on skin. Armor offsets defined in skin will also be applied.
This commit is contained in:
Langtanium 2026-05-20 13:32:44 -07:00
parent e048395679
commit ac3df25056
18 changed files with 852 additions and 68 deletions

View file

@ -2792,7 +2792,7 @@ void ClientConnection::handleTextureAndGeometry(shared_ptr<TextureAndGeometryPac
{
unsigned int uiAnimOverrideBitmask= app.GetAnimOverrideBitmask(packet->dwSkinID);
send(std::make_shared<TextureAndGeometryPacket>(packet->textureName, pbData, dwBytes, app.GetAdditionalSkinBoxes(packet->dwSkinID), uiAnimOverrideBitmask));
send(std::make_shared<TextureAndGeometryPacket>(packet->textureName, pbData, dwBytes, app.GetAdditionalSkinBoxes(packet->dwSkinID), app.GetSkinOffsets(packet->dwSkinID), uiAnimOverrideBitmask));
}
}
}
@ -2809,6 +2809,11 @@ void ClientConnection::handleTextureAndGeometry(shared_ptr<TextureAndGeometryPac
{
app.SetAdditionalSkinBoxes(packet->dwSkinID,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);

View file

@ -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<ModelPart *> * CMinecraftApp::SetAdditionalSkinBoxes(DWORD dwSkinID, vect
return pvModelPart;
}
void CMinecraftApp::SetSkinOffsets(DWORD dwSkinID, SKIN_OFFSET *SkinOffsetA, DWORD dwSkinOffsetC)
{
vector<SKIN_OFFSET *> *pvSkinOffset = new vector<SKIN_OFFSET *>;
EnterCriticalSection( &csSkinOffsets );
app.DebugPrintf("*** SetSkinOffsets - Adding skin offsets for skin %d from array of Skin Offsets\n",dwSkinID&0x0FFFFFFF);
for(unsigned int i=0;i<dwSkinOffsetC;i++)
{
pvSkinOffset->push_back(&SkinOffsetA[i]);
}
m_SkinOffsets.insert( std::pair<DWORD, vector<SKIN_OFFSET *> *>(dwSkinID, pvSkinOffset) );
LeaveCriticalSection( &csSkinOffsets );
}
vector<SKIN_OFFSET *> * CMinecraftApp::SetSkinOffsets(DWORD dwSkinID, vector<SKIN_OFFSET *> *pvSkinOffsetA)
{
vector<SKIN_OFFSET *> *pvSkinOffset = new vector<SKIN_OFFSET *>;
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<ModelPart *> *CMinecraftApp::GetAdditionalModelParts(DWORD dwSkinID)
{
@ -9722,6 +9759,23 @@ vector<SKIN_BOX *> *CMinecraftApp::GetAdditionalSkinBoxes(DWORD dwSkinID)
return pvSkinBoxes;
}
vector<SKIN_OFFSET *> *CMinecraftApp::GetSkinOffsets(DWORD dwSkinID)
{
EnterCriticalSection( &csSkinOffsets );
vector<SKIN_OFFSET *> *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 );

View file

@ -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<ModelPart *> * SetAdditionalSkinBoxes(DWORD dwSkinID, vector<SKIN_BOX *> *pvSkinBoxA);
vector<ModelPart *> *GetAdditionalModelParts(DWORD dwSkinID);
vector<SKIN_BOX *> *GetAdditionalSkinBoxes(DWORD dwSkinID);
void SetSkinOffsets(DWORD dwSkinID, SKIN_OFFSET *SkinOffsetA, DWORD dwSkinOffsetC);
vector<SKIN_OFFSET *> * SetSkinOffsets(DWORD dwSkinID, vector<SKIN_OFFSET *> *pvSkinOffsetA);
vector<SKIN_OFFSET *> *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<DWORD, vector<ModelPart *> *> m_AdditionalModelParts;
unordered_map<DWORD, vector<SKIN_BOX *> *> m_AdditionalSkinBoxes;
unordered_map<DWORD, vector<SKIN_OFFSET *> *> m_SkinOffsets;
unordered_map<DWORD, unsigned int> m_AnimOverrides;

View file

@ -397,6 +397,15 @@ vector<SKIN_BOX *> *DLCSkinFile::getAdditionalBoxes()
return &m_AdditionalBoxes;
}
int DLCSkinFile::getOffsetsCount()
{
return static_cast<int>(m_Offsets.size());
}
vector<SKIN_OFFSET *> *DLCSkinFile::getOffsets()
{
return &m_Offsets;
}
wstring DLCSkinFile::getParameterAsString(DLCManager::EDLCParameterType type)
{
switch(type)

View file

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

View file

@ -53,6 +53,7 @@ private:
ESkinPreviewAnimations m_currentAnimation;
//vector<Model::SKIN_BOX *> *m_pvAdditionalBoxes;
vector<ModelPart *> *m_pvAdditionalModelParts;
vector<SKIN_OFFSET *> *m_pvSkinOffsets;
public:
enum ESkinPreviewFacing
{

View file

@ -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<SKIN_OFFSET *> *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<SKIN_BOX *> *othervAdditionalSkinBoxes=nullptr;
vector<SKIN_OFFSET *> *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<SKIN_OFFSET *> *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<SKIN_OFFSET *> *pSkinOffsets = app.GetSkinOffsets(skinFile->getSkinID());
if(pSkinOffsets==nullptr)
{
pSkinOffsets = app.SetSkinOffsets(skinFile->getSkinID(),othervSkinOffsets);
}
}
// 4J-PB - anim override needs set before SetTexture
if(skinFile)
{

View file

@ -104,6 +104,7 @@ private:
DWORD m_originalSkinId;
wstring m_currentSkinPath, m_selectedSkinPath, m_selectedCapePath;
vector<SKIN_BOX *> *m_vAdditionalSkinBoxes;
vector<SKIN_OFFSET *> *m_vSkinOffsets;
bool m_bSlidingSkins, m_bAnimatingMove;
ESkinSelectNavigation m_currentNavigation;

View file

@ -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> entity, float time, float r, float bob, float yRot, float xRot, float scale, bool usecompiled)
{
{
vector<bool> hasArmorOffsets = {false, false, false, false, false, false};
vector<float> headOffsets = {0, 0, 0};
vector<float> bodyOffsets = {0, 0, 0};
vector<float> arm0Offsets = {0, 0, 0};
vector<float> arm1Offsets = {0, 0, 0};
vector<float> leg0Offsets = {0, 0, 0};
vector<float> leg1Offsets = {0, 0, 0};
if(entity != nullptr)
{
m_uiAnimOverrideBitmask=entity->getAnimOverrideBitmask();
shared_ptr<Player> player = dynamic_pointer_cast<Player>(entity);
vector<SKIN_OFFSET *>* 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> entity, float time, float r, float
glPopMatrix();
}
else
{
{
glPushMatrix();
glTranslatef(headOffsets[0], headOffsets[1], headOffsets[2]);
head->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderHead))>0&&(!(m_uiAnimOverrideBitmask&(1<<eAnim_RenderArmorHead))>0||!m_isArmor));
glPopMatrix();
glPushMatrix();
glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]);
body->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderTorso))>0&&(!(m_uiAnimOverrideBitmask&(1<<eAnim_RenderArmorTorso))>0||!m_isArmor));
glPopMatrix();
glPushMatrix();
glTranslatef(arm0Offsets[0], arm0Offsets[1], arm0Offsets[2]);
arm0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderArm0))>0&&(!(m_uiAnimOverrideBitmask&(1<<eAnim_RenderArmorArm0))>0||!m_isArmor));
glPopMatrix();
glPushMatrix();
glTranslatef(arm1Offsets[0], arm1Offsets[1], arm1Offsets[2]);
arm1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderArm1))>0&&(!(m_uiAnimOverrideBitmask&(1<<eAnim_RenderArmorArm1))>0||!m_isArmor));
glPopMatrix();
glPushMatrix();
glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]);
leg0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderLeg0))>0&&(!(m_uiAnimOverrideBitmask&(1<<eAnim_RenderArmorLeg0))>0||!m_isArmor));
glPopMatrix();
glPushMatrix();
glTranslatef(leg1Offsets[0], leg1Offsets[1], leg1Offsets[2]);
leg1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderLeg1))>0&&(!(m_uiAnimOverrideBitmask&(1<<eAnim_RenderArmorLeg1))>0||!m_isArmor));
glPopMatrix();
glPushMatrix();
glTranslatef(headOffsets[0], headOffsets[1], headOffsets[2]);
hair->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderHair))>0);
if (jacket)
glPopMatrix();
if (jacket != 0)
{
glPushMatrix();
glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]);
jacket->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderJacket))>0);
if (sleeve0)
glPopMatrix();
}
if (sleeve0 != 0)
{
glPushMatrix();
glTranslatef(arm0Offsets[0], arm0Offsets[1], arm0Offsets[2]);
sleeve0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderSleeve0))>0);
if (sleeve1)
glPopMatrix();
}
if (sleeve1 != 0)
{
glPushMatrix();
glTranslatef(arm1Offsets[0], arm1Offsets[1], arm1Offsets[2]);
sleeve1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderSleeve1))>0);
if (pants0)
glPopMatrix();
}
if (pants0 != 0)
{
glPushMatrix();
glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]);
pants0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderPants0))>0);
if (pants1)
glPopMatrix();
}
if (pants1 != 0)
{
glPushMatrix();
glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]);
pants1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderPants1))>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<SKIN_OFFSET *> *skinOffsets)
{
setupAnim(time, r, bob, yRot, xRot, scale, nullptr, m_uiAnimOverrideBitmask);
vector<float> headOffsets = {0, 0, 0};
vector<float> bodyOffsets = {0, 0, 0};
vector<float> arm0Offsets = {0, 0, 0};
vector<float> arm1Offsets = {0, 0, 0};
vector<float> leg0Offsets = {0, 0, 0};
vector<float> leg1Offsets = {0, 0, 0};
vector<SKIN_OFFSET *>* 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<<eAnim_DisableRenderHead))>0&&(!(m_uiAnimOverrideBitmask&(1<<eAnim_RenderArmorHead))>0||!m_isArmor));
glPopMatrix();
glPushMatrix();
glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]);
body->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderTorso))>0&&(!(m_uiAnimOverrideBitmask&(1<<eAnim_RenderArmorTorso))>0||!m_isArmor));
glPopMatrix();
glPushMatrix();
glTranslatef(arm0Offsets[0], arm0Offsets[1], arm0Offsets[2]);
arm0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderArm0))>0&&(!(m_uiAnimOverrideBitmask&(1<<eAnim_RenderArmorArm0))>0||!m_isArmor));
glPopMatrix();
glPushMatrix();
glTranslatef(arm1Offsets[0], arm1Offsets[1], arm1Offsets[2]);
arm1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderArm1))>0&&(!(m_uiAnimOverrideBitmask&(1<<eAnim_RenderArmorArm1))>0||!m_isArmor));
glPopMatrix();
glPushMatrix();
glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]);
leg0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderLeg0))>0&&(!(m_uiAnimOverrideBitmask&(1<<eAnim_RenderArmorLeg0))>0||!m_isArmor));
glPopMatrix();
glPushMatrix();
glTranslatef(leg1Offsets[0], leg1Offsets[1], leg1Offsets[2]);
leg1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderLeg1))>0&&(!(m_uiAnimOverrideBitmask&(1<<eAnim_RenderArmorLeg1))>0||!m_isArmor));
glPopMatrix();
glPushMatrix();
glTranslatef(headOffsets[0], headOffsets[1], headOffsets[2]);
hair->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderHair))>0);
glPopMatrix();
if (jacket != 0)
{
glPushMatrix();
glTranslatef(bodyOffsets[0], bodyOffsets[1], bodyOffsets[2]);
jacket->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderJacket))>0);
glPopMatrix();
}
if (sleeve0 != 0)
{
glPushMatrix();
glTranslatef(arm0Offsets[0], arm0Offsets[1], arm0Offsets[2]);
sleeve0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderSleeve0))>0);
glPopMatrix();
}
if (sleeve1 != 0)
{
glPushMatrix();
glTranslatef(arm1Offsets[0], arm1Offsets[1], arm1Offsets[2]);
sleeve1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderSleeve1))>0);
glPopMatrix();
}
if (pants0 != 0)
{
glPushMatrix();
glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]);
pants0->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderPants0))>0);
glPopMatrix();
}
if (pants1 != 0)
{
glPushMatrix();
glTranslatef(leg0Offsets[0], leg0Offsets[1], leg0Offsets[2]);
pants1->render(scale, usecompiled,(m_uiAnimOverrideBitmask&(1<<eAnim_DisableRenderPants1))>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();
}
}

View file

@ -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> 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> entity,
unsigned int uiBitmaskOverrideAnim = 0);
virtual void render(shared_ptr<Entity> 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<SKIN_OFFSET *> *skinOffsets);
virtual void setupAnim(float time, float r, float bob, float yRot, float xRot, float scale, shared_ptr<Entity> entity, unsigned int uiBitmaskOverrideAnim = 0);
void renderHair(float scale, bool usecompiled);
void renderEars(float scale, bool usecompiled);
void renderCloak(float scale, bool usecompiled);

View file

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

View file

@ -18,6 +18,7 @@ public:
bool visible;
bool neverRender;
unsigned int hideWithArmor;
bool isArmorPart2;
vector <Cube *> cubes;
vector <ModelPart *> children;
static const float RAD;

View file

@ -1593,9 +1593,10 @@ void PlayerConnection::handleTextureAndGeometry(shared_ptr<TextureAndGeometryPac
{
// we don't have the dlc skin, so retrieve the data from the app store
vector<SKIN_BOX *> *pvSkinBoxes = app.GetAdditionalSkinBoxes(packet->dwSkinID);
vector<SKIN_OFFSET *> *pvSkinOffsets = app.GetSkinOffsets(packet->dwSkinID);
unsigned int uiAnimOverrideBitmask= app.GetAnimOverrideBitmask(packet->dwSkinID);
send(std::make_shared<TextureAndGeometryPacket>(packet->textureName, pbData, dwTextureBytes, pvSkinBoxes, uiAnimOverrideBitmask));
send(std::make_shared<TextureAndGeometryPacket>(packet->textureName, pbData, dwTextureBytes, pvSkinBoxes, pvSkinOffsets, uiAnimOverrideBitmask));
}
}
else
@ -1618,6 +1619,13 @@ void PlayerConnection::handleTextureAndGeometry(shared_ptr<TextureAndGeometryPac
wprintf(L"Adding skin boxes for skin id %X, box count %d\n",packet->dwSkinID,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<SKIN_BOX *> *pvSkinBoxes = app.GetAdditionalSkinBoxes(dwSkinID);
vector<SKIN_OFFSET *> *pvSkinOffsets = app.GetSkinOffsets(dwSkinID);
unsigned int uiAnimOverrideBitmask= app.GetAnimOverrideBitmask(dwSkinID);
send(std::make_shared<TextureAndGeometryPacket>(textureName, pbData, dwTextureBytes, pvSkinBoxes, uiAnimOverrideBitmask));
send(std::make_shared<TextureAndGeometryPacket>(textureName, pbData, dwTextureBytes, pvSkinBoxes, pvSkinOffsets, uiAnimOverrideBitmask));
}
m_texturesRequested.erase(it);
}

View file

@ -124,6 +124,10 @@ int PlayerRenderer::prepareArmor(shared_ptr<LivingEntity> _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;

View file

@ -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<<HumanoidModel::eAnim_SlimModel)) return 2;
else if (animBitmask&(1<<HumanoidModel::eAnim_WideModel)) return 1;
else return 0;
}
int Player::GetModelTypeFromTextureId(int textureId)
{
if (textureId > 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<ModelPart *> *Player::GetAdditionalModelParts()
return m_ppAdditionalModelParts;
}
vector<SKIN_OFFSET *> *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<<HumanoidModel::eAnim_SlimModel)) return 2;
else if (animBitmask&(1<<HumanoidModel::eAnim_WideModel)) return 1;
else return 0;
}
int Player::GetModelTypeFromTextureId(int textureId)
{
if (textureId > 8 && textureId < 18) return 2;
else if (textureId == 18) return 1;
else return 0;
}
void Player::SetAdditionalModelParts(vector<ModelPart *> *ppAdditionalModelParts)
{
m_ppAdditionalModelParts=ppAdditionalModelParts;
}
void Player::SetSkinOffsets(vector<SKIN_OFFSET *> *ppSkinOffsets)
{
m_ppSkinOffsets=ppSkinOffsets;
}
#if defined(__PS3__) || defined(__ORBIS__)
Player::ePlayerNameValidState Player::GetPlayerNameValidState(void)

View file

@ -555,6 +555,8 @@ public:
vector<ModelPart *> *GetAdditionalModelParts();
void SetAdditionalModelParts(vector<ModelPart *> *ppAdditionalModelParts);
vector<SKIN_OFFSET *> *GetSkinOffsets();
void SetSkinOffsets(vector<SKIN_OFFSET *> *ppSkinOffsets);
#if defined(__PS3__) || defined(__ORBIS__)
enum ePlayerNameValidState
@ -571,6 +573,9 @@ private:
vector<ModelPart *> *m_ppAdditionalModelParts;
bool m_bCheckedForModelParts;
bool m_bCheckedDLCForModelParts;
vector<SKIN_OFFSET *> *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

View file

@ -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<SKIN_OFFSET *> *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<SKIN_BOX *> *pvSkinBoxes, unsigned int uiAnimOverrideBitmask)
TextureAndGeometryPacket::TextureAndGeometryPacket(const wstring &textureName, PBYTE pbData, DWORD dwBytes, vector<SKIN_BOX *> *pvSkinBoxes, vector<SKIN_OFFSET *> *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<DWORD>(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;i<dwBoxC;i++)
{
@ -181,9 +234,15 @@ void TextureAndGeometryPacket::read(DataInputStream *dis) //throws IOException
this->BoxDataA[i].fM = dis->readFloat();
this->BoxDataA[i].fS = dis->readFloat();
}
for(DWORD i=0;i<dwOffsetC;i++)
{
this->OffsetDataA[i].ePart = static_cast<eBodyOffset>(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<short>(dwOffsetC));
for(DWORD i=0;i<dwOffsetC;i++)
{
dos->writeShort(static_cast<short>(this->OffsetDataA[i].ePart));
dos->writeFloat(this->OffsetDataA[i].fD);
dos->writeFloat(this->OffsetDataA[i].fO);
}
}
int TextureAndGeometryPacket::getEstimatedSize()

View file

@ -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<SKIN_BOX *> *pvSkinBoxes, unsigned int uiAnimOverrideBitmask);
TextureAndGeometryPacket(const wstring &textureName, PBYTE pbData, DWORD dwBytes, vector<SKIN_BOX *> *pvSkinBoxes, vector<SKIN_OFFSET *> *pvSkinOffsets, unsigned int uiAnimOverrideBitmask);
virtual void handle(PacketListener *listener);
virtual void read(DataInputStream *dis);