Files
mcpe/source/client/renderer/GameRenderer.cpp
Brent f12a3c1c61 Visual Studio Project Overhaul + Cleanup (#80)
* Visual Studio Project Overhaul + Cleanup
* SDL2 project for Windows
* Re-added game client icon to SDL2 code
* Renamed "AppPlatform_windows" to "AppPlatform_win32" (this is the name of the Windows API and is not representative of the architecture type)
* Renamed "LoggerWindows" to "LoggerWin32"
* Renamed "SoundSystemWindows to "SoundSystemDS" (DirectSound). This may be used for the 360, so it wouldn't really be Windows-specific then.
* Moved "ClientSideNetworkHandler" from "network" to "client/network". We don't need it being compiled for the server if the client's the only thing that needs it.
* I wonder if this still works on macOS...

* Bugfixes & Fixed for macOS

* Options::savePropertiesToFile Logging Bugfix

* Silence Winsock Deprecation Warnings in RakNet

* VS Project Improvements
- Replaced 50 billion relative paths with $(MC_ROOT)
- Added $(RAKNET_PATH) variable to override RakNet location
- Re-added gitignore for .vcxproj.user files
- Added debugging config to Directory.Builds.props
- Slimmed down project configurations for SDL2

* VS Project Config Bugfixes
- Fixed RakNet header path for additional includes

* RakNet Target for XCode

* XCode Project Config Fixes

* Packet logging

* Network VS Project Filter Fix

* Fix RakNet Packet ID Length
We previously didn't have consistency between old and new C++ regarding PacketType enum length. Now we do. This is required or else it completely breaks networking between the versions.

* Additional RakNet Error Handling

* Disable packet logging

* * Fix CMakeLists.txt

This reflects the relocation of ClientSideNetworkHandler.cpp.

* * Also add renderer/GL/GL.cpp to the CMakeLists.txt

* * Replace libpng with stb_image

* * Fix buggy water behavior.

* * Put the CMakeLists of the SDL project in debug mode

* Visual Studio 2010 Support

* * Change the SdlIoCallbacks from an array to a single member.

This fixes compilation of the sdl2 target on VS.

* * Fix missing _error label.

* Revert "* Fix missing _error label."

This reverts commit 99a057fc84049a16c864bd840fb439a008af5c74.

* Revert "* Replace libpng with stb_image"

* info_updateGame Tiles

---------

Co-authored-by: Brent Da Mage <BrentDaMage@users.noreply.github.com>
Co-authored-by: iProgramInCpp <iprogramincpp@gmail.com>
2023-10-22 10:08:59 +03:00

898 lines
21 KiB
C++

/********************************************************************
Minecraft: Pocket Edition - Decompilation Project
Copyright (C) 2023 iProgramInCpp
The following code is licensed under the BSD 1 clause license.
SPDX-License-Identifier: BSD-1-Clause
********************************************************************/
#include "thirdparty/GL/GL.hpp"
#include "GameRenderer.hpp"
#include "client/app/Minecraft.hpp"
#include "Frustum.hpp"
int t_keepPic;
void GameRenderer::_init()
{
//ItemInHandRenderer* m_pItemInHandRenderer = nullptr;
field_8 = 0.0f;
field_C = 0;
field_10 = nullptr;
field_14 = 0.0f;
field_18 = 0.0f;
field_1C = 0.0f;
field_20 = 0.0f;
field_24 = 0.0f;
field_28 = 0.0f;
field_2C = 4.0f;
field_30 = 4.0f;
field_34 = 0.0f;
field_38 = 0.0f;
field_3C = 0.0f;
field_40 = 0.0f;
field_44 = 1.0f;
field_48 = 0.0f;
field_4C = 0.0f;
field_50 = 0.0f;
field_54 = 0.0f;
field_58 = 0.0f;
field_5C = 0.0f;
field_60 = 0.0f;
field_64 = 0.0f;
field_68 = 0.0f;
field_6C = 0.0f;
field_70 = 0.0f;
field_74 = 0.0f;
field_78 = 0.0f;
field_7C = 0.0f;
field_80 = 0.0f;
field_84 = 0.0f;
m_lastUpdatedMS = 0;
m_shownFPS = 0;
m_shownChunkUpdates = 0;
}
GameRenderer::GameRenderer(Minecraft* pMinecraft) :
m_pMinecraft(pMinecraft)
{
_init();
saveMatrices();
m_pItemInHandRenderer = new ItemInHandRenderer(pMinecraft);
EntityRenderDispatcher::getInstance()->m_pItemInHandRenderer = m_pItemInHandRenderer;
}
GameRenderer::~GameRenderer()
{
delete m_pItemInHandRenderer;
}
void GameRenderer::zoomRegion(float a, float b, float c)
{
field_44 = a;
field_48 = b;
field_4C = c;
}
void GameRenderer::unZoomRegion()
{
field_44 = 1.0f;
}
void GameRenderer::setupCamera(float f, int i)
{
field_8 = float(256 >> m_pMinecraft->getOptions()->m_iViewDistance);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if (m_pMinecraft->getOptions()->m_bAnaglyphs)
{
glTranslatef(float(1 - 2 * i) * 0.07f, 0.0f, 0.0f);
}
if (field_44 != 1.0)
{
glTranslatef(field_48, -field_4C, 0.0);
glScalef(field_44, field_44, 1.0);
}
float fov = getFov(f);
gluPerspective(fov, float(Minecraft::width) / float(Minecraft::height), 0.05f, field_8);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
if (m_pMinecraft->getOptions()->m_bAnaglyphs)
{
glTranslatef(float(2 * i - 1) * 0.1f, 0.0f, 0.0f);
}
bobHurt(f);
if (m_pMinecraft->getOptions()->m_bViewBobbing)
bobView(f);
moveCameraToPlayer(f);
}
void GameRenderer::moveCameraToPlayer(float f)
{
Mob* pMob = m_pMinecraft->m_pMobPersp;
float headHeightDiff = pMob->field_84 - 1.62f;
float posX = Lerp(pMob->field_3C.x, pMob->m_pos.x, f);
float posY = Lerp(pMob->field_3C.y, pMob->m_pos.y, f);
float posZ = Lerp(pMob->field_3C.z, pMob->m_pos.z, f);
glRotatef(field_5C + f * (field_58 - field_5C), 0.0f, 0.0f, 1.0f);
if (m_pMinecraft->getOptions()->m_bThirdPerson)
{
float v11 = field_30 + (field_2C - field_30) * f;
if (m_pMinecraft->getOptions()->field_241)
{
glTranslatef(0.0f, 0.0f, -v11);
glRotatef(field_38 + (field_34 - field_38) * f, 1.0f, 0.0f, 0.0f);
glRotatef(field_40 + (field_3C - field_40) * f, 0.0f, 1.0f, 0.0f);
}
else
{
float mob_yaw = pMob->m_yaw;
float mob_pitch = pMob->m_pitch;
float pitchRad = mob_pitch / 180.0f * float(M_PI);
float aX = posX - (-(Mth::sin(mob_yaw / 180.0f * float(M_PI)) * Mth::cos(pitchRad)) * v11);
float aY = posY + (Mth::sin(pitchRad) * v11);
float aZ = posZ - ((Mth::cos(mob_yaw / 180.0f * float(M_PI)) * Mth::cos(pitchRad)) * v11);
for (int i = 0; i < 8; i++)
{
float offsX = (2 * (i & 1) - 1) * 0.1f;
float offsY = ((i & 2) - 1) * 0.1f;
float offsZ = (2 * ((i >> 2) & 1) - 1) * 0.1f;
HitResult hr = m_pMinecraft->m_pLevel->clip(
Vec3(posX + offsX, posY + offsY, posZ + offsZ),
Vec3(aX + offsX + offsZ, aY + offsY, aZ + offsZ) // @NOTE: Not sure why it adds offsZ to offsX.
);
if (hr.m_hitType != HitResult::NONE)
{
float dX = posX - hr.m_hitPos.x;
float dY = posY - hr.m_hitPos.y;
float dZ = posZ - hr.m_hitPos.z;
float dist = sqrtf(dX * dX + dY * dY + dZ * dZ);
if (v11 > dist)
v11 = dist;
}
}
// @HUH: Why the hell is it rotating by 0
glRotatef(pMob->m_pitch - mob_pitch, 1.0f, 0.0f, 0.0f);
glRotatef(pMob->m_yaw - mob_yaw, 0.0f, 1.0f, 0.0f);
glTranslatef(0.0, 0.0, -v11);
glRotatef(mob_yaw - pMob->m_yaw, 0.0f, 1.0f, 0.0f);
glRotatef(mob_pitch - pMob->m_pitch, 1.0f, 0.0f, 0.0f);
}
}
else
{
glTranslatef(0.0f, 0.0f, -0.1f);
}
if (!m_pMinecraft->getOptions()->field_241)
{
glRotatef(pMob->field_60 + f * (pMob->m_pitch - pMob->field_60), 1.0f, 0.0f, 0.0f);
glRotatef(pMob->field_5C + f * (pMob->m_yaw - pMob->field_5C) + 180.0f, 0.0f, 1.0f, 0.0f);
}
glTranslatef(0.0f, headHeightDiff, 0.0f);
}
void GameRenderer::saveMatrices()
{
glGetFloatv(GL_PROJECTION_MATRIX, m_matrix_projection);
glGetFloatv(GL_MODELVIEW_MATRIX, m_matrix_model_view);
}
void GameRenderer::setupGuiScreen()
{
float x = Gui::InvGuiScale * Minecraft::width;
float y = Gui::InvGuiScale * Minecraft::height;
glClear(GL_ACCUM);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
xglOrthof(0, x, y, 0, 2000.0f, 3000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, -2000.0f);
}
void GameRenderer::bobHurt(float f)
{
Mob* pMob = m_pMinecraft->m_pMobPersp;
if (pMob->m_health <= 0)
glRotatef(-8000.0f / (float(pMob->field_110) + f + 200.0f) + 40.0f, 0.0f, 0.0f, 1.0f);
if (pMob->field_104 > 0)
{
float val = (pMob->field_104 - f) / pMob->field_108;
glRotatef(-pMob->field_10C, 0.0f, 1.0f, 0.0f);
glRotatef(Mth::sin(val * val * val * val * 3.1416f) * -14.0f, 0.0f, 0.0f, 1.0f);
glRotatef(pMob->field_10C, 0.0f, 1.0f, 0.0f);
}
}
void GameRenderer::bobView(float f)
{
if (!m_pMinecraft->m_pMobPersp->isPlayer())
return;
Player* player = (Player*)m_pMinecraft->m_pMobPersp;
float f1 = Lerp(player->field_B9C, player->field_BA0, f);
float f2 = Lerp(player->field_118, player->field_11C, f);
// @NOTE: Multiplying by M_PI inside of the paren makes it stuttery for some reason? Anyways it works now :)
float f3 = -(player->field_94 + (player->field_94 - player->field_90) * f) * float(M_PI);
float f4 = Mth::sin(f3);
float f5 = Mth::cos(f3);
glTranslatef((f4 * f1) * 0.5f, -fabsf(f5 * f1), 0.0f);
float f6 = Mth::sin(f3);
glRotatef((f6 * f1) * 3.0f, 0.0f, 0.0f, 1.0f);
float f7 = Mth::cos(f3 - 0.2f);
glRotatef(fabsf(f7 * f1) * 5.0f, 1.0f, 0.0f, 0.0f);
glRotatef(f2, 1.0f, 0.0f, 0.0f);
}
void GameRenderer::setupClearColor(float f)
{
Minecraft* pMC = m_pMinecraft;
Level* pLevel = pMC->m_pLevel;
Mob* pMob = pMC->m_pMobPersp;
float x1 = 1.0f - powf(1.0f / float(4 - pMC->getOptions()->m_iViewDistance), 0.25f);
Vec3 skyColor = pLevel->getSkyColor(pMob, f), fogColor = pLevel->getFogColor(f);
//@BUG: double set to these?
field_60 = fogColor.x;
field_64 = fogColor.y;
field_60 = fogColor.x + (skyColor.x - fogColor.x) * x1;
field_64 = fogColor.y + (skyColor.y - fogColor.y) * x1;
field_68 = fogColor.z + (skyColor.z - fogColor.z) * x1;
if (pMob->isUnderLiquid(Material::water))
{
field_60 = 0.02f;
field_64 = 0.02f;
field_68 = 0.2f;
}
else if (pMob->isUnderLiquid(Material::lava))
{
field_60 = 0.6f;
field_64 = 0.1f;
field_68 = 0.0f;
}
float x2 = field_6C + (field_70 - field_6C) * f;
field_60 *= x2;
field_64 *= x2;
field_68 *= x2;
if (pMC->getOptions()->m_bAnaglyphs)
{
float r = (field_60 * 30.0f + field_64 * 59.0f + field_68 * 11.0f) / 100.0f;
float g = (field_60 * 30.0f + field_64 * 70.0f) / 100.0f;
float b = (field_60 * 30.0f + field_68 * 70.0f) / 100.0f;
field_60 = r;
field_64 = g;
field_68 = b;
}
glClearColor(field_60, field_64, field_68, 1.0f);
}
#ifndef ORIGINAL_CODE
void GameRenderer::renderNoCamera()
{
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
#endif
void GameRenderer::setupFog(int i)
{
float fog_color[4];
fog_color[0] = field_60;
fog_color[1] = field_64;
fog_color[2] = field_68;
fog_color[3] = 1.0f;
glFogfv(GL_FOG_COLOR, fog_color);
glNormal3f(0.0f, -1.0f, 0.0f);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
if (m_pMinecraft->m_pMobPersp->isUnderLiquid(Material::water))
{
#ifdef ORIGINAL_CODE
glFogx(GL_FOG_MODE, 0x0800);
#else
glFogi(GL_FOG_MODE, GL_EXP);
#endif
glFogf(GL_FOG_DENSITY, 0.1f);
}
else if (m_pMinecraft->m_pMobPersp->isUnderLiquid(Material::lava))
{
#ifdef ORIGINAL_CODE
glFogx(GL_FOG_MODE, 0x0800);
#else
glFogi(GL_FOG_MODE, GL_EXP);
#endif
glFogf(GL_FOG_DENSITY, 2.0f);
}
else
{
#ifdef ORIGINAL_CODE
glFogx(GL_FOG_MODE, GL_LINEAR);
#else
glFogi(GL_FOG_MODE, GL_LINEAR);
glFogf(GL_FOG_START, field_8 * 0.25f);
glFogf(GL_FOG_END, field_8);
if (i < 0)
{
glFogf(GL_FOG_START, 0.0f);
glFogf(GL_FOG_END, field_8 * 0.8f);
}
if (m_pMinecraft->m_pLevel->m_pDimension->field_C)
{
glFogf(GL_FOG_START, 0.0f);
}
#endif
}
glEnable(GL_COLOR_MATERIAL);
}
float GameRenderer::getFov(float f)
{
Mob* pMob = m_pMinecraft->m_pMobPersp;
float x1 = 70.0f;
if (pMob->isUnderLiquid(Material::water))
x1 = 60.0f;
if (pMob->m_health <= 0)
{
float x2 = 1.0f + (-500.0f / ((pMob->field_110 + f) + 500.0f));
x1 /= (1.0f + 2.0f * x2);
}
return field_54 + x1 + f * (field_50 - field_54);
}
void GameRenderer::renderLevel(float f)
{
if (!m_pMinecraft->m_pMobPersp)
{
m_pMinecraft->m_pMobPersp = m_pMinecraft->m_pLocalPlayer;
if (!m_pMinecraft->m_pMobPersp)
{
#ifndef ORIGINAL_CODE
renderNoCamera();
#endif
return;
}
}
pick(f);
Mob* pMob = m_pMinecraft->m_pMobPersp;
Vec3 fCamPos;
fCamPos.x = pMob->field_98.x + (pMob->m_pos.x - pMob->field_98.x) * f;
fCamPos.y = pMob->field_98.y + (pMob->m_pos.y - pMob->field_98.y) * f;
fCamPos.z = pMob->field_98.z + (pMob->m_pos.z - pMob->field_98.z) * f;
bool bAnaglyph = m_pMinecraft->getOptions()->m_bAnaglyphs;
LevelRenderer* pLR = m_pMinecraft->m_pLevelRenderer;
ParticleEngine* pPE = m_pMinecraft->m_pParticleEngine;
for (int i = 0; i < 2; i++)
{
if (bAnaglyph)
{
if (i > 0)
glColorMask(true, false, false, false);
else
glColorMask(false, true, true, false);
}
glViewport(0, 0, Minecraft::width, Minecraft::height);
setupClearColor(f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_CULL_FACE);
setupCamera(f, i);
saveMatrices();
/*
if (m_pMinecraft->getOptions()->m_iViewDistance <= 1)
{
#ifndef ORIGINAL_CODE
// @NOTE: For whatever reason, Minecraft doesn't enable GL_FOG right away.
// It appears to work in bluestacks for whatever reason though...
glEnable(GL_FOG);
#endif
setupFog(-1);
pLR->renderSky(f);
}
*/
glEnable(GL_FOG);
setupFog(1);
if (m_pMinecraft->getOptions()->m_bAmbientOcclusion)
glShadeModel(GL_SMOOTH);
Frustum& frust = Frustum::frustum;
Frustum::doOurJobInGameRenderer();
FrustumCuller frustumCuller;
frustumCuller.m_frustumData.x = frust;
frustumCuller.prepare(fCamPos.x, fCamPos.y, fCamPos.z);
pLR->cull(&frustumCuller, f);
pLR->updateDirtyChunks(pMob, false);
// TODO[v0.6.1]: what is (this+4)+63 (byte)?
prepareAndRenderClouds(pLR, f);
setupFog(0);
glEnable(GL_FOG);
m_pMinecraft->m_pTextures->loadAndBindTexture(C_TERRAIN_NAME);
// render the opaque layer
pLR->render(pMob, 0, f);
glShadeModel(GL_FLAT);
pLR->renderEntities(pMob->getPos(f), &frustumCuller, f);
pPE->render(pMob, f);
glEnable(GL_ALPHA);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
setupFog(0);
#ifndef ORIGINAL_CODE
glShadeModel(GL_SMOOTH);
#endif
glEnable(GL_BLEND);
glDisable(GL_CULL_FACE);
// glDepthMask(false); -- added in 0.1.1j. Introduces more issues than fixes
// render the alpha layer
m_pMinecraft->m_pTextures->loadAndBindTexture(C_TERRAIN_NAME);
pLR->render(pMob, 1, f);
glDepthMask(true);
#ifndef ORIGINAL_CODE
glShadeModel(GL_FLAT);
#endif
glEnable(GL_CULL_FACE);
glDisable(GL_BLEND);
if (field_44 == 1.0f && pMob->isPlayer() && m_pMinecraft->m_hitResult.m_hitType != HitResult::NONE && !pMob->isUnderLiquid(Material::water))
{
glDisable(GL_ALPHA_TEST);
//pLR->renderHitOutline((Player*)pMob, m_pMinecraft->m_hitResult, 0, nullptr, f);
pLR->renderHitSelect((Player*)pMob, m_pMinecraft->m_hitResult, 0, nullptr, f);
// added by iProgramInCpp
pLR->renderHit((Player*)pMob, m_pMinecraft->m_hitResult, 0, nullptr, f);
glEnable(GL_ALPHA_TEST);
}
// @BUG?
glDisable(GL_FOG);
if (field_44 == 1.0f)
{
glClear(GL_DEPTH_BUFFER_BIT);
renderItemInHand(f, i);
}
if (!bAnaglyph)
break;
}
if (bAnaglyph)
glColorMask(true, true, true, false);
}
void GameRenderer::render(float f)
{
if (m_pMinecraft->m_pLocalPlayer && m_pMinecraft->m_bGrabbedMouse)
{
Minecraft *pMC = m_pMinecraft;
ITurnInput::Delta delta = pMC->m_pTurnInput->getTurnDelta();
pMC->field_D20 = delta.x;
pMC->field_D24 = delta.y;
#ifndef ENH_DISABLE_TURN_ACCEL
float multPitch = -1.0f;
float mult1 = 2.0f * (0.2f + pMC->getOptions()->field_8 * 0.6f);
mult1 = mult1 * mult1 * mult1;
float xd = 4.0f * mult1 * pMC->field_D20;
float yd = 4.0f * mult1 * pMC->field_D24;
float old_field_84 = field_84;
field_84 = float(m_rotX) + f;
float diff_field_84 = field_84 - old_field_84;
field_74 += xd;
field_78 += yd;
if (diff_field_84 > 3.0f)
diff_field_84 = 3.0f;
if (pMC->getOptions()->m_bInvertMouse)
multPitch = 1.0f;
if (!pMC->getOptions()->field_240)
{
// @TODO: untangle this code
float v17 = xd + m_rotZ;
float v18 = field_18;
float v19 = field_1C;
m_rotZ = v17;
float v20 = mult1 * 0.25f * (v17 - v18);
float v21 = v19 + (v20 - v19) * 0.5f;
field_1C = v21;
if ((v20 <= 0.0 || v20 <= v21) && (v20 >= 0.0 || v20 >= v21))
v21 = mult1 * 0.25f * (v17 - v18);
float v22 = yd + field_20;
field_18 = v18 + v21;
float v23 = field_24;
field_20 = v22;
float v24 = mult1 * 0.15f * (v22 - v23);
float v25 = field_28 + (v24 - field_28) * 0.5f;
field_28 = v25;
if ((v24 <= 0.0 || v24 <= v25) && (v24 >= 0.0 || v24 >= v25))
v25 = v24;
field_24 = v23 + v25;
}
#else
float multPitch = -1.0f;
if (pMC->getOptions()->m_bInvertMouse)
multPitch = 1.0f;
float diff_field_84 = 1.0f;
field_7C = pMC->field_D20;
field_80 = pMC->field_D24;
#endif
pMC->m_pLocalPlayer->turn(diff_field_84 * field_7C, diff_field_84 * multPitch * field_80);
}
int mouseX = int(Mouse::getX() * Gui::InvGuiScale);
int mouseY = int(Mouse::getY() * Gui::InvGuiScale);
// note: Multitouch code here
if (m_pMinecraft->isLevelGenerated())
{
if (t_keepPic < 0)
{
renderLevel(f);
if (m_pMinecraft->getOptions()->m_bDontRenderGui)
{
if (!m_pMinecraft->m_pScreen)
return;
}
m_pMinecraft->m_gui.render(f, m_pMinecraft->m_pScreen != nullptr, mouseX, mouseY);
}
}
else
{
glViewport(0, 0, Minecraft::width, Minecraft::height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
setupGuiScreen();
}
if (m_pMinecraft->m_pScreen)
{
glClear(GL_ACCUM);
m_pMinecraft->m_pScreen->render(mouseX, mouseY, f);
if (m_pMinecraft->m_pScreen && !m_pMinecraft->m_pScreen->isInGameScreen())
{
#ifdef ORIGINAL_CODE
// force some lag for some reason. I guess it's to make it spend more time actually generating the world?
sleepMs(15);
#endif
}
}
std::stringstream debugText;
debugText << "ReMinecraftPE " << m_pMinecraft->getVersionString();
debugText << "\n" << m_shownFPS << " fps, " << m_shownChunkUpdates << " chunk updates";
if (m_pMinecraft->getOptions()->m_bDebugText)
{
if (m_pMinecraft->m_pLocalPlayer)
{
char posStr[96];
Vec3 pos = m_pMinecraft->m_pLocalPlayer->getPos(f);
sprintf(posStr, "%.2f, %.2f, %.2f", pos.x, pos.y, pos.z);
debugText << "\npos: " << posStr;
debugText << "\nentities: " << m_pMinecraft->m_pLevel->m_entities.size();
debugText << "\n" << m_pMinecraft->m_pLevelRenderer->gatherStats1();
}
m_pMinecraft->m_pFont->drawShadow(debugText.str(), 2, 2, 0xFFFFFF);
}
int timeMs = getTimeMs();
if (timeMs - m_lastUpdatedMS >= 1000)
{
m_lastUpdatedMS = timeMs;
m_shownFPS = m_pMinecraft->getFpsIntlCounter();
m_shownChunkUpdates = Chunk::updates;
Chunk::updates = 0;
}
}
void GameRenderer::tick()
{
--t_keepPic;
#ifndef ORIGINAL_CODE
// @BUG: If the game is left on for approximately 1,242 days, the counter will underflow,
// causing the screen to appear frozen, and the level to not render.
if (t_keepPic < -100)
t_keepPic = -100;
#endif
if (m_pMinecraft->m_pLocalPlayer)
{
float x1 = powf(fabsf(field_74), 1.2f);
field_7C = x1 * 0.4f;
if (field_74 < 0.0f)
field_7C = -field_7C;
float x2 = powf(fabsf(field_78), 1.2f);
field_80 = x2 * 0.4f;
if (field_78 < 0.0f)
field_80 = -field_80;
field_74 = 0.0f;
field_78 = 0.0f;
field_6C = field_70;
field_30 = field_2C;
field_38 = field_34;
field_40 = field_3C;
field_54 = field_50;
field_5C = field_58;
Mob* pMob = m_pMinecraft->m_pMobPersp;
if (!pMob)
{
pMob = m_pMinecraft->m_pMobPersp = m_pMinecraft->m_pLocalPlayer;
}
float bright = m_pMinecraft->m_pLevel->getBrightness(Mth::floor(pMob->m_pos.x), Mth::floor(pMob->m_pos.y), Mth::floor(pMob->m_pos.z));
float x3 = float(3 - m_pMinecraft->getOptions()->m_iViewDistance);
field_C++;
float x4 = x3 / 3.0f;
float x5 = (x4 + bright * (1.0f - x4) - field_70) * 0.1f;
field_70 += x5;
m_pItemInHandRenderer->tick();
}
}
void GameRenderer::renderItemInHand(float f, int i)
{
glLoadIdentity();
if (m_pMinecraft->getOptions()->m_bAnaglyphs)
glTranslatef(float(2 * i - 1) * 0.1f, 0.0f, 0.0f);
glPushMatrix();
bobHurt(f);
if (m_pMinecraft->getOptions()->m_bViewBobbing)
bobView(f);
if (!m_pMinecraft->getOptions()->m_bThirdPerson && !m_pMinecraft->getOptions()->m_bDontRenderGui)
m_pItemInHandRenderer->render(f);
glPopMatrix();
if (!m_pMinecraft->getOptions()->m_bThirdPerson)
{
m_pItemInHandRenderer->renderScreenEffect(f);
bobHurt(f);
}
if (m_pMinecraft->getOptions()->m_bViewBobbing)
bobView(f);
}
void GameRenderer::prepareAndRenderClouds(LevelRenderer* pLR, float f)
{
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluPerspective(getFov(f), float(Minecraft::width) / float(Minecraft::height), 0.05f, field_8 * 512.0f);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
setupFog(0);
glDepthMask(false);
glEnable(GL_FOG);
glFogf(GL_FOG_START, field_8 * 0.2f);
glFogf(GL_FOG_END, field_8 * 0.75f);
pLR->renderSky(f);
glFogf(GL_FOG_START, field_8 * 4.2f * 0.6f);
glFogf(GL_FOG_END, field_8 * 4.2f);
pLR->renderClouds(f);
glFogf(GL_FOG_START, field_8 * 0.6f);
glFogf(GL_FOG_END, field_8);
glDisable(GL_FOG);
glDepthMask(true);
setupFog(1);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}
void GameRenderer::onGraphicsReset()
{
}
void GameRenderer::pick(float f)
{
if (!m_pMinecraft->m_pMobPersp || !m_pMinecraft->m_pLevel)
return;
HitResult& mchr = m_pMinecraft->m_hitResult;
Mob* pMob = m_pMinecraft->m_pMobPersp;
float dist = m_pMinecraft->m_pGameMode->getPickRange();
HitResult hrMob = pMob->pick(dist, f);
mchr = hrMob;
Vec3 mobPos = pMob->getPos(f);
if (m_pMinecraft->m_hitResult.m_hitType != HitResult::NONE)
{
float dX = mobPos.x - mchr.m_hitPos.x;
float dY = mobPos.y - mchr.m_hitPos.y;
float dZ = mobPos.z - mchr.m_hitPos.z;
dist = sqrtf(dX * dX + dY * dY + dZ * dZ);
}
if (m_pMinecraft->m_pGameMode->isCreativeType())
dist = 32.0f;
else if (dist > 3.0f)
dist = 3.0f;
Vec3 view = pMob->getViewVector(f);
Vec3 exp = view * dist;
Vec3 limit = mobPos + view * dist;
field_10 = nullptr;
AABB scanAABB = pMob->m_hitbox;
if (exp.x < 0) scanAABB.min.x += exp.x;
if (exp.x > 0) scanAABB.max.x += exp.x;
if (exp.y < 0) scanAABB.min.y += exp.y;
if (exp.y > 0) scanAABB.max.y += exp.y;
if (exp.z < 0) scanAABB.min.z += exp.z;
if (exp.z > 0) scanAABB.max.z += exp.z;
scanAABB.grow(1, 1, 1);
EntityVector* pEnts = m_pMinecraft->m_pLevel->getEntities(pMob, scanAABB);
float fDist = 0.0f;
for (int i = 0; i < int(pEnts->size()); i++)
{
Entity *pEnt = (*pEnts)[i];
if (!pEnt->isPickable())
continue;
AABB checkAABB = pEnt->m_hitbox;
checkAABB.grow(pEnt->getPickRadius());
HitResult hrMobChk = checkAABB.clip(mobPos, limit);
if (checkAABB.contains(mobPos))
{
if (fDist >= 0.0f)
{
//this is it brother
field_10 = pEnt;
fDist = 0.0f;
}
continue;
}
if (hrMobChk.m_hitType != HitResult::NONE)
{
float dX = hrMobChk.m_hitPos.x - mobPos.x;
float dY = hrMobChk.m_hitPos.y - mobPos.y;
float dZ = hrMobChk.m_hitPos.z - mobPos.z;
float fNewDist = sqrtf(dX * dX + dY * dY + dZ * dZ);
if (fDist > fNewDist || fDist == 0.0f)
{
field_10 = pEnt;
fDist = fNewDist;
}
}
}
// picked entities take priority over tiles (?!)
if (field_10)
{
m_pMinecraft->m_hitResult = HitResult(field_10);
return;
}
if (m_pMinecraft->m_hitResult.m_hitType != HitResult::NONE || view.y >= -0.7f)
return;
mobPos = pMob->getPos(f);
Vec3 checkVec = mobPos;
checkVec.translate(0, -2, 0);
HitResult hrLevelChk = m_pMinecraft->m_pLevel->clip(mobPos, checkVec);
if (hrLevelChk.m_hitType == HitResult::NONE)
return;
mchr = hrLevelChk;
mchr.m_bUnk24 = true;
if (fabsf(view.x) <= fabsf(view.z))
{
m_pMinecraft->m_hitResult.m_hitSide = view.z >= 0.0f ? HitResult::MAXZ : HitResult::MINZ;
}
else
{
m_pMinecraft->m_hitResult.m_hitSide = view.x >= 0.0f ? HitResult::MAXX : HitResult::MINX;
}
}