From b3feddfef372618c8a9d7a0abcaf18cfad866c18 Mon Sep 17 00:00:00 2001 From: daoge <3523206925@qq.com> Date: Tue, 3 Mar 2026 03:04:10 +0800 Subject: feat: TU19 (Dec 2014) Features & Content (#155) * try to resolve merge conflict * feat: TU19 (Dec 2014) Features & Content (#32) * December 2014 files * Working release build * Fix compilation issues * Add sound to Windows64Media * Add DLC content and force Tutorial DLC * Revert "Add DLC content and force Tutorial DLC" This reverts commit 97a43994725008e35fceb984d5549df9c8cea470. * Disable broken light packing * Disable breakpoint during DLC texture map load Allows DLC loading but the DLC textures are still broken * Fix post build not working * ... * fix vs2022 build * fix cmake build --------- Co-authored-by: Loki --- Minecraft.Client/MobRenderer.cpp | 568 +++++++-------------------------------- 1 file changed, 90 insertions(+), 478 deletions(-) (limited to 'Minecraft.Client/MobRenderer.cpp') diff --git a/Minecraft.Client/MobRenderer.cpp b/Minecraft.Client/MobRenderer.cpp index 8874ab9c..ee512530 100644 --- a/Minecraft.Client/MobRenderer.cpp +++ b/Minecraft.Client/MobRenderer.cpp @@ -1,5 +1,6 @@ #include "stdafx.h" #include "MobRenderer.h" +#include "LivingEntityRenderer.h" #include "MultiPlayerLocalPlayer.h" #include "..\Minecraft.World\net.minecraft.world.entity.h" #include "..\Minecraft.World\net.minecraft.world.entity.player.h" @@ -8,508 +9,119 @@ #include "..\Minecraft.World\Mth.h" #include "entityRenderDispatcher.h" -MobRenderer::MobRenderer(Model *model, float shadow) : EntityRenderer() +MobRenderer::MobRenderer(Model *model, float shadow) : LivingEntityRenderer(model, shadow) { - this->model = model; - this->shadowRadius = shadow; - - this->armor = NULL; } -void MobRenderer::setArmor(Model *armor) +void MobRenderer::render(shared_ptr _mob, double x, double y, double z, float rot, float a) { - this->armor = armor; + shared_ptr mob = dynamic_pointer_cast(_mob); + + LivingEntityRenderer::render(mob, x, y, z, rot, a); + renderLeash(mob, x, y, z, rot, a); } -float MobRenderer::rotlerp(float from, float to, float a) +bool MobRenderer::shouldShowName(shared_ptr mob) { - float diff = to - from; - while (diff < -180) - diff += 360; - while (diff >= 180) - diff -= 360; - return from + a * diff; + return LivingEntityRenderer::shouldShowName(mob) && (mob->shouldShowName() || dynamic_pointer_cast(mob)->hasCustomName() && mob == entityRenderDispatcher->crosshairPickMob); } -void MobRenderer::render(shared_ptr _mob, double x, double y, double z, float rot, float a) +void MobRenderer::renderLeash(shared_ptr entity, double x, double y, double z, float rot, float a) { - // 4J - added - this used to use generics so the input parameter could be a mob (or derived type), but we aren't - // able to do that so dynamically casting to get the more specific type here. - shared_ptr mob = dynamic_pointer_cast(_mob); - glPushMatrix(); - glDisable(GL_CULL_FACE); - - model->attackTime = getAttackAnim(mob, a); - if (armor != NULL) armor->attackTime = model->attackTime; - model->riding = mob->isRiding(); - if (armor != NULL) armor->riding = model->riding; - model->young = mob->isBaby(); - if (armor != NULL) armor->young = model->young; - - // 4J - removed try/catch -// try -// { - float bodyRot = rotlerp(mob->yBodyRotO, mob->yBodyRot, a); - float headRot = rotlerp(mob->yHeadRotO, mob->yHeadRot, a); - - if (mob->isRiding() && dynamic_pointer_cast(mob->riding)) - { - shared_ptr riding = dynamic_pointer_cast(mob->riding); - bodyRot = rotlerp(riding->yBodyRotO, riding->yBodyRot, a); - - float headDiff = Mth::wrapDegrees(headRot - bodyRot); - if (headDiff < -85) headDiff = -85; - if (headDiff >= 85) headDiff = +85; - bodyRot = headRot - headDiff; - if (headDiff * headDiff > 50 * 50) - { - bodyRot += headDiff * 0.2f; - } - } - - float headRotx = (mob->xRotO + (mob->xRot - mob->xRotO) * a); - - setupPosition(mob, x, y, z); - - float bob = getBob(mob, a); - setupRotations(mob, bob, bodyRot, a); - - float _scale = 1 / 16.0f; - glEnable(GL_RESCALE_NORMAL); - glScalef(-1, -1, 1); - - scale(mob, a); - glTranslatef(0, -24 * _scale - 0.125f / 16.0f, 0); - - - float ws = mob->walkAnimSpeedO + (mob->walkAnimSpeed - mob->walkAnimSpeedO) * a; - float wp = mob->walkAnimPos - mob->walkAnimSpeed * (1 - a); - if (mob->isBaby()) + shared_ptr roper = entity->getLeashHolder(); + // roper = entityRenderDispatcher.cameraEntity; + if (roper != NULL) + { + glColor4f(1.0f, 1.0f, 1.0f, 1.0f); + + y -= (1.6 - entity->bbHeight) * .5; + Tesselator *tessellator = Tesselator::getInstance(); + double roperYRot = lerp(roper->yRotO, roper->yRot, a * .5f) * Mth::RAD_TO_GRAD; + double roperXRot = lerp(roper->xRotO, roper->xRot, a * .5f) * Mth::RAD_TO_GRAD; + double rotOffCos = cos(roperYRot); + double rotOffSin = sin(roperYRot); + double yOff = sin(roperXRot); + if (roper->instanceof(eTYPE_HANGING_ENTITY)) { - wp *= 3.0f; - } - - if (ws > 1) ws = 1; - - MemSect(31); - bindTexture(mob->customTextureUrl, mob->getTexture()); - MemSect(0); - glEnable(GL_ALPHA_TEST); - - model->prepareMobModel(mob, wp, ws, a); - renderModel(mob, wp, ws, bob, headRot - bodyRot, headRotx, _scale); - for (int i = 0; i < MAX_ARMOR_LAYERS; i++) + rotOffCos = 0; + rotOffSin = 0; + yOff = -1; + } + double swingOff = cos(roperXRot); + double endX = lerp(roper->xo, roper->x, a) - (rotOffCos * 0.7) - (rotOffSin * 0.5 * swingOff); + double endY = lerp(roper->yo + roper->getHeadHeight() * .7, roper->y + roper->getHeadHeight() * .7, a) - (yOff * 0.5) - .25; + double endZ = lerp(roper->zo, roper->z, a) - (rotOffSin * 0.7) + (rotOffCos * 0.5 * swingOff); + + double entityYRot = lerp(entity->yBodyRotO, entity->yBodyRot, a) * Mth::RAD_TO_GRAD + PI * .5; + rotOffCos = cos(entityYRot) * entity->bbWidth * .4; + rotOffSin = sin(entityYRot) * entity->bbWidth * .4; + double startX = lerp(entity->xo, entity->x, a) + rotOffCos; + double startY = lerp(entity->yo, entity->y, a); + double startZ = lerp(entity->zo, entity->z, a) + rotOffSin; + x += rotOffCos; + z += rotOffSin; + + double dx = (float) (endX - startX); + double dy = (float) (endY - startY); + double dz = (float) (endZ - startZ); + + glDisable(GL_TEXTURE_2D); + glDisable(GL_LIGHTING); + glDisable(GL_CULL_FACE); + + unsigned int lightCol = Minecraft::GetInstance()->getColourTable()->getColor( eMinecraftColour_Leash_Light_Colour ); + float rLightCol = ( (lightCol>>16)&0xFF )/255.0f; + float gLightCol = ( (lightCol>>8)&0xFF )/255.0; + float bLightCol = ( lightCol&0xFF )/255.0; + + unsigned int darkCol = Minecraft::GetInstance()->getColourTable()->getColor( eMinecraftColour_Leash_Dark_Colour ); + float rDarkCol = ( (darkCol>>16)&0xFF )/255.0f; + float gDarkCol = ( (darkCol>>8)&0xFF )/255.0; + float bDarkCol = ( darkCol&0xFF )/255.0; + + int steps = 24; + double width = .025; + tessellator->begin(GL_TRIANGLE_STRIP); + for (int k = 0; k <= steps; k++) { - int armorType = prepareArmor(mob, i, a); - if (armorType > 0) + if (k % 2 == 0) { - armor->prepareMobModel(mob, wp, ws, a); - armor->render(mob, wp, ws, bob, headRot - bodyRot, headRotx, _scale, true); - if ((armorType & 0xf0) == 16) - { - prepareSecondPassArmor(mob, i, a); - armor->render(mob, wp, ws, bob, headRot - bodyRot, headRotx, _scale, true); - } - // 4J - added condition here for rendering player as part of the gui. Avoiding rendering the glint here as it involves using its own blending, and for gui rendering - // we are globally blending to be able to offer user configurable gui opacity. Note that I really don't know why GL_BLEND is turned off at the end of the first - // armour layer anyway, or why alpha testing is turned on... but we definitely don't want to be turning blending off during the gui render. - if( !entityRenderDispatcher->isGuiRender ) - { - if ((armorType & 0xf) == 0xf) //MGH - fix for missing enchantment glow - { - float time = mob->tickCount + a; - bindTexture(TN__BLUR__MISC_GLINT); // 4J was "%blur%/misc/glint.png" - glEnable(GL_BLEND); - float br = 0.5f; - glColor4f(br, br, br, 1); - glDepthFunc(GL_EQUAL); - glDepthMask(false); - - for (int j = 0; j < 2; j++) - { - glDisable(GL_LIGHTING); - float brr = 0.76f; - glColor4f(0.5f * brr, 0.25f * brr, 0.8f * brr, 1); - glBlendFunc(GL_SRC_COLOR, GL_ONE); - glMatrixMode(GL_TEXTURE); - glLoadIdentity(); - float uo = time * (0.001f + j * 0.003f) * 20; - float ss = 1 / 3.0f; - glScalef(ss, ss, ss); - glRotatef(30 - (j) * 60.0f, 0, 0, 1); - glTranslatef(0, uo, 0); - glMatrixMode(GL_MODELVIEW); - armor->render(mob, wp, ws, bob, headRot - bodyRot, headRotx, _scale, false); - } - - glColor4f(1, 1, 1, 1); - glMatrixMode(GL_TEXTURE); - glDepthMask(true); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glEnable(GL_LIGHTING); - glDisable(GL_BLEND); - glDepthFunc(GL_LEQUAL); - - } - glDisable(GL_BLEND); - } - glEnable(GL_ALPHA_TEST); + tessellator->color(rLightCol, gLightCol, bLightCol, 1.0F); } + else + { + tessellator->color(rDarkCol, gDarkCol, bDarkCol, 1.0F); + } + float aa = (float) k / (float) steps; + tessellator->vertex(x + (dx * aa) + 0, y + (dy * ((aa * aa) + aa) * 0.5) + ((((float) steps - (float) k) / (steps * 0.75F)) + 0.125F), z + (dz * aa)); + tessellator->vertex(x + (dx * aa) + width, y + (dy * ((aa * aa) + aa) * 0.5) + ((((float) steps - (float) k) / (steps * 0.75F)) + 0.125F) + width, z + (dz * aa)); } + tessellator->end(); - glDepthMask(true); - - additionalRendering(mob, a); - float br = mob->getBrightness(a); - int overlayColor = getOverlayColor(mob, br, a); - glActiveTexture(GL_TEXTURE1); - glDisable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE0); - - if (((overlayColor >> 24) & 0xff) > 0 || mob->hurtTime > 0 || mob->deathTime > 0) + tessellator->begin(GL_TRIANGLE_STRIP); + for (int k = 0; k <= steps; k++) { - glDisable(GL_TEXTURE_2D); - glDisable(GL_ALPHA_TEST); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDepthFunc(GL_EQUAL); - - // 4J - changed these renders to not use the compiled version of their models, because otherwise the render states set - // about (in particular the depth & alpha test) don't work with our command buffer versions - if (mob->hurtTime > 0 || mob->deathTime > 0) + if (k % 2 == 0) { - glColor4f(br, 0, 0, 0.4f); - model->render(mob, wp, ws, bob, headRot - bodyRot, headRotx, _scale, false); - for (int i = 0; i < MAX_ARMOR_LAYERS; i++) - { - if (prepareArmorOverlay(mob, i, a) >= 0) - { - glColor4f(br, 0, 0, 0.4f); - armor->render(mob, wp, ws, bob, headRot - bodyRot, headRotx, _scale, false); - } - } + tessellator->color(rLightCol, gLightCol, bLightCol, 1.0F); } - - if (((overlayColor >> 24) & 0xff) > 0) + else { - float r = ((overlayColor >> 16) & 0xff) / 255.0f; - float g = ((overlayColor >> 8) & 0xff) / 255.0f; - float b = ((overlayColor) & 0xff) / 255.0f; - float aa = ((overlayColor >> 24) & 0xff) / 255.0f; - glColor4f(r, g, b, aa); - model->render(mob, wp, ws, bob, headRot - bodyRot, headRotx, _scale, false); - for (int i = 0; i < MAX_ARMOR_LAYERS; i++) - { - if (prepareArmorOverlay(mob, i, a) >= 0) - { - glColor4f(r, g, b, aa); - armor->render(mob, wp, ws, bob, headRot - bodyRot, headRotx, _scale, false); - } - } + tessellator->color(rDarkCol, gDarkCol, bDarkCol, 1.0F); } - - glDepthFunc(GL_LEQUAL); - glDisable(GL_BLEND); - glEnable(GL_ALPHA_TEST); - glEnable(GL_TEXTURE_2D); + float aa = (float) k / (float) steps; + tessellator->vertex(x + (dx * aa) + 0, y + (dy * ((aa * aa) + aa) * 0.5) + ((((float) steps - (float) k) / (steps * 0.75F)) + 0.125F) + width, z + (dz * aa)); + tessellator->vertex(x + (dx * aa) + width, y + (dy * ((aa * aa) + aa) * 0.5) + ((((float) steps - (float) k) / (steps * 0.75F)) + 0.125F), z + (dz * aa) + width); } - glDisable(GL_RESCALE_NORMAL); -// } -//catch (Exception e) { - // // System.out.println("Failed: " + modelNames[model]); - // e.printStackTrace(); - // } - glActiveTexture(GL_TEXTURE1); - glEnable(GL_TEXTURE_2D); - glActiveTexture(GL_TEXTURE0); - - glEnable(GL_CULL_FACE); - - glPopMatrix(); - - MemSect(31); - renderName(mob, x, y, z); - MemSect(0); -} - -void MobRenderer::renderModel(shared_ptr mob, float wp, float ws, float bob, float headRotMinusBodyRot, float headRotx, float scale) -{ - shared_ptr player = dynamic_pointer_cast(Minecraft::GetInstance()->player); - - bindTexture(mob->customTextureUrl, mob->getTexture()); - if (!mob->isInvisible()) - { - model->render(mob, wp, ws, bob, headRotMinusBodyRot, headRotx, scale, true); - } - else if ( !mob->isInvisibleTo(player) ) - { - glPushMatrix(); - glColor4f(1, 1, 1, 0.15f); - glDepthMask(false); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glAlphaFunc(GL_GREATER, 1.0f / 255.0f); - model->render(mob, wp, ws, bob, headRotMinusBodyRot, headRotx, scale, true); - glDisable(GL_BLEND); - glAlphaFunc(GL_GREATER, .1f); - glPopMatrix(); - glDepthMask(true); - } - else - { - model->setupAnim(wp, ws, bob, headRotMinusBodyRot, headRotx, scale);//, mob); - } -} - -void MobRenderer::setupPosition(shared_ptr mob, double x, double y, double z) -{ - glTranslatef((float) x, (float) y, (float) z); -} + tessellator->end(); -void MobRenderer::setupRotations(shared_ptr mob, float bob, float bodyRot, float a) -{ - glRotatef(180 - bodyRot, 0, 1, 0); - if (mob->deathTime > 0) - { - float fall = (mob->deathTime + a - 1) / 20.0f * 1.6f; - fall = (float)sqrt(fall); - if (fall > 1) fall = 1; - glRotatef(fall * getFlipDegrees(mob), 0, 0, 1); + glEnable(GL_LIGHTING); + glEnable(GL_TEXTURE_2D); + glEnable(GL_CULL_FACE); } } -float MobRenderer::getAttackAnim(shared_ptr mob, float a) -{ - return mob->getAttackAnim(a); -} - -float MobRenderer::getBob(shared_ptr mob, float a) -{ - return (mob->tickCount + a); -} - -void MobRenderer::additionalRendering(shared_ptr mob, float a) -{ -} - -int MobRenderer::prepareArmorOverlay(shared_ptr mob, int layer, float a) +double MobRenderer::lerp(double prev, double next, double a) { - return prepareArmor(mob, layer, a); -} - -int MobRenderer::prepareArmor(shared_ptr mob, int layer, float a) -{ - return -1; -} - -void MobRenderer::prepareSecondPassArmor(shared_ptr mob, int layer, float a) -{ -} - -float MobRenderer::getFlipDegrees(shared_ptr mob) -{ - return 90; -} - -int MobRenderer::getOverlayColor(shared_ptr mob, float br, float a) -{ - return 0; -} - -void MobRenderer::scale(shared_ptr mob, float a) -{ -} - -void MobRenderer::renderName(shared_ptr mob, double x, double y, double z) -{ - if (Minecraft::renderDebug()) - { - //renderNameTag(mob, _toString(mob->entityId), x, y, z, 64); - } -} - -// 4J Added parameter for color here so that we can colour players names -void MobRenderer::renderNameTag(shared_ptr mob, const wstring& OriginalName, double x, double y, double z, int maxDist, int color /*= 0xffffffff*/) -{ - - if ( app.GetGameSettings(eGameSetting_DisplayHUD)==0 ) - { - // 4J-PB - turn off gamertag render - return; - } - - if(app.GetGameHostOption(eGameHostOption_Gamertags)==0) - { - // turn off gamertags if the host has set them off - return; - } - - float dist = mob->distanceTo(entityRenderDispatcher->cameraEntity); - - if (dist > maxDist) - { - return; - } - - Font *font = getFont(); - - float size = 1.60f; - float s = 1 / 60.0f * size; - - glPushMatrix(); - glTranslatef((float) x + 0, (float) y + 2.3f, (float) z); - glNormal3f(0, 1, 0); - - glRotatef(-this->entityRenderDispatcher->playerRotY, 0, 1, 0); - glRotatef(this->entityRenderDispatcher->playerRotX, 1, 0, 0); - - glScalef(-s, -s, s); - glDisable(GL_LIGHTING); - - // 4J Stu - If it's beyond readable distance, then just render a coloured box - int readableDist = PLAYER_NAME_READABLE_FULLSCREEN; - if( !RenderManager.IsHiDef() ) - { - readableDist = PLAYER_NAME_READABLE_DISTANCE_SD; - } - else if ( app.GetLocalPlayerCount() > 2 ) - { - readableDist = PLAYER_NAME_READABLE_DISTANCE_SPLITSCREEN; - } - - float textOpacity = 1.0f; - if( dist >= readableDist ) - { - int diff = dist - readableDist; - - textOpacity /= (diff/2); - - if( diff > readableDist ) textOpacity = 0.0f; - } - - if( textOpacity < 0.0f ) textOpacity = 0.0f; - if( textOpacity > 1.0f ) textOpacity = 1.0f; - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - Tesselator *t = Tesselator::getInstance(); - - int offs = 0; - shared_ptr player = dynamic_pointer_cast(mob); - if (player != NULL && app.isXuidDeadmau5( player->getXuid() ) ) offs = -10; - - wstring playerName; - WCHAR wchName[2]; - -#if defined(__PS3__) || defined(__ORBIS__) - // Check we have all the font characters for this player name - switch(player->GetPlayerNameValidState()) - { - case Player::ePlayerNameValid_NotSet: - if(font->AllCharactersValid(OriginalName)) - { - playerName=OriginalName; - player->SetPlayerNameValidState(true); - } - else - { - memset(wchName,0,sizeof(WCHAR)*2); - swprintf(wchName, 2, L"%d",player->getPlayerIndex()+1); - playerName=wchName; - player->SetPlayerNameValidState(false); - } - break; - case Player::ePlayerNameValid_True: - playerName=OriginalName; - break; - case Player::ePlayerNameValid_False: - memset(wchName,0,sizeof(WCHAR)*2); - swprintf(wchName, 2, L"%d",player->getPlayerIndex()+1); - playerName=wchName; - break; - } - -#else - playerName=OriginalName; -#endif - - if( textOpacity > 0.0f ) - { - glColor4f(1.0f,1.0f,1.0f,textOpacity); - - glDepthMask(false); - glDisable(GL_DEPTH_TEST); - - glDisable(GL_TEXTURE_2D); - - t->begin(); - int w = font->width(playerName) / 2; - - if( textOpacity < 1.0f ) - { - t->color(color, 255 * textOpacity); - } - else - { - t->color(0.0f, 0.0f, 0.0f, 0.25f); - } - t->vertex((float)(-w - 1), (float)( -1 + offs), (float)( 0)); - t->vertex((float)(-w - 1), (float)( +8 + offs + 1), (float)( 0)); - t->vertex((float)(+w + 1), (float)( +8 + offs + 1), (float)( 0)); - t->vertex((float)(+w + 1), (float)( -1 + offs), (float)( 0)); - t->end(); - - glEnable(GL_DEPTH_TEST); - glDepthMask(true); - glDepthFunc(GL_ALWAYS); - glLineWidth(2.0f); - t->begin(GL_LINE_STRIP); - t->color(color, 255 * textOpacity); - t->vertex((float)(-w - 1), (float)( -1 + offs), (float)( 0)); - t->vertex((float)(-w - 1), (float)( +8 + offs + 1), (float)( 0)); - t->vertex((float)(+w + 1), (float)( +8 + offs + 1), (float)( 0)); - t->vertex((float)(+w + 1), (float)( -1 + offs), (float)( 0)); - t->vertex((float)(-w - 1), (float)( -1 + offs), (float)( 0)); - t->end(); - glDepthFunc(GL_LEQUAL); - glDepthMask(false); - glDisable(GL_DEPTH_TEST); - - glEnable(GL_TEXTURE_2D); - font->draw(playerName, -font->width(playerName) / 2, offs, 0x20ffffff); - glEnable(GL_DEPTH_TEST); - - glDepthMask(true); - } - - if( textOpacity < 1.0f ) - { - glColor4f(1.0f,1.0f,1.0f,1.0f); - glDisable(GL_TEXTURE_2D); - glDepthFunc(GL_ALWAYS); - t->begin(); - int w = font->width(playerName) / 2; - t->color(color, 255); - t->vertex((float)(-w - 1), (float)( -1 + offs), (float)( 0)); - t->vertex((float)(-w - 1), (float)( +8 + offs), (float)( 0)); - t->vertex((float)(+w + 1), (float)( +8 + offs), (float)( 0)); - t->vertex((float)(+w + 1), (float)( -1 + offs), (float)( 0)); - t->end(); - glDepthFunc(GL_LEQUAL); - glEnable(GL_TEXTURE_2D); - - glTranslatef(0.0f, 0.0f, -0.04f); - } - - if( textOpacity > 0.0f ) - { - int textColor = ( ( (int)(textOpacity*255) << 24 ) | 0xffffff ); - font->draw(playerName, -font->width(playerName) / 2, offs, textColor); - } - - glEnable(GL_LIGHTING); - glDisable(GL_BLEND); - glColor4f(1, 1, 1, 1); - glPopMatrix(); -} + return prev + (next - prev) * a; +} \ No newline at end of file -- cgit v1.2.3