2026-03-01 12:16:08 +08:00
# include "stdafx.h"
# include "Gui.h"
# include "ItemRenderer.h"
# include "GameRenderer.h"
# include "Options.h"
# include "MultiplayerLocalPlayer.h"
# include "Textures.h"
# include "GameMode.h"
# include "Lighting.h"
# include "ChatScreen.h"
# include "MultiPlayerLevel.h"
# include "..\Minecraft.World\JavaMath.h"
# include "..\Minecraft.World\net.minecraft.world.entity.player.h"
# include "..\Minecraft.World\net.minecraft.world.effect.h"
# include "..\Minecraft.World\net.minecraft.world.food.h"
# include "..\Minecraft.World\net.minecraft.world.item.h"
# include "..\Minecraft.World\net.minecraft.world.level.h"
# include "..\Minecraft.World\LevelData.h"
# include "..\Minecraft.World\net.minecraft.world.level.tile.h"
# include "..\Minecraft.World\System.h"
# include "..\Minecraft.World\Language.h"
# include "EntityRenderDispatcher.h"
# include "..\Minecraft.World\Dimension.h"
# include "..\Minecraft.World\net.minecraft.world.entity.boss.enderdragon.h"
# include "EnderDragonRenderer.h"
# include "..\Minecraft.World\net.minecraft.h"
# include "..\Minecraft.World\net.minecraft.world.h"
# include "..\Minecraft.World\LevelChunk.h"
# include "..\Minecraft.World\Biome.h"
# define RENDER_HUD 0
//#ifndef _XBOX
//#undef RENDER_HUD
//#define RENDER_HUD 1
//#endif
float Gui : : currentGuiBlendFactor = 1.0f ; // 4J added
float Gui : : currentGuiScaleFactor = 1.0f ; // 4J added
ItemRenderer * Gui : : itemRenderer = new ItemRenderer ( ) ;
Gui : : Gui ( Minecraft * minecraft )
{
// 4J - initialisers added
random = new Random ( ) ;
tickCount = 0 ;
overlayMessageTime = 0 ;
animateOverlayMessageColor = false ;
progress = 0.0f ;
tbr = 1.0f ;
fAlphaIncrementPerCent = 255.0f / 100.0f ;
this - > minecraft = minecraft ;
lastTickA = 0.0f ;
}
void Gui : : render ( float a , bool mouseFree , int xMouse , int yMouse )
{
// 4J Stu - I have copied this code for XUI_BaseScene. If/when it gets changed it should be broken out
// 4J - altered to force full screen mode to 3X scaling, and any split screen modes to 2X scaling. This is so that the further scaling by 0.5 that
2026-03-02 15:53:32 +07:00
// happens in split screen modes results in a final scaling of 1 rather than 1.5.
2026-03-01 12:16:08 +08:00
int splitYOffset ; // = 20; // This offset is applied when doing the 2X scaling above to move the gui out of the way of the tool tips
int guiScale ; // = ( minecraft->player->m_iScreenSection == C4JRender::VIEWPORT_TYPE_FULLSCREEN ? 3 : 2 );
int iPad = minecraft - > player - > GetXboxPad ( ) ;
int iWidthOffset = 0 , iHeightOffset = 0 ; // used to get the interface looking right on a 2 player split screen game
// 4J-PB - selected the gui scale based on the slider settings
if ( minecraft - > player - > m_iScreenSection = = C4JRender : : VIEWPORT_TYPE_FULLSCREEN )
{
guiScale = app . GetGameSettings ( iPad , eGameSetting_UISize ) + 2 ;
}
else
{
guiScale = app . GetGameSettings ( iPad , eGameSetting_UISizeSplitscreen ) + 2 ;
}
ScreenSizeCalculator ssc ( minecraft - > options , minecraft - > width , minecraft - > height , guiScale ) ;
int screenWidth = ssc . getWidth ( ) ;
int screenHeight = ssc . getHeight ( ) ;
int iSafezoneXHalf = 0 , iSafezoneYHalf = 0 ;
int iTooltipsYOffset = 0 ;
int quickSelectWidth = 182 ;
int quickSelectHeight = 22 ;
float fScaleFactorWidth = 1.0f , fScaleFactorHeight = 1.0f ;
bool bTwoPlayerSplitscreen = false ;
currentGuiScaleFactor = ( float ) guiScale ; // Keep static copy of scale so we know how gui coordinates map to physical pixels - this is also affected by the viewport
switch ( guiScale )
{
case 3 :
splitYOffset = 0 ;
break ;
case 4 :
splitYOffset = - 5 ;
break ;
default : // 2
splitYOffset = 10 ;
break ;
2026-03-02 15:53:32 +07:00
}
2026-03-01 12:16:08 +08:00
// Check which screen section this player is in
switch ( minecraft - > player - > m_iScreenSection )
{
case C4JRender : : VIEWPORT_TYPE_FULLSCREEN :
// single player
iSafezoneXHalf = screenWidth / 20 ; // 5%
iSafezoneYHalf = screenHeight / 20 ; // 5%
iTooltipsYOffset = 40 + splitYOffset ;
break ;
case C4JRender : : VIEWPORT_TYPE_SPLIT_TOP :
iSafezoneXHalf = screenWidth / 10 ; // 5% (need to treat the whole screen is 2x this screen)
iSafezoneYHalf = splitYOffset ;
fScaleFactorWidth = 0.5f ;
iWidthOffset = ( int ) ( ( float ) screenWidth * ( 1.0f - fScaleFactorWidth ) ) ;
iTooltipsYOffset = 44 ;
bTwoPlayerSplitscreen = true ;
currentGuiScaleFactor * = 0.5f ;
break ;
case C4JRender : : VIEWPORT_TYPE_SPLIT_BOTTOM :
iSafezoneXHalf = screenWidth / 10 ; // 5% (need to treat the whole screen is 2x this screen)
iSafezoneYHalf = splitYOffset + screenHeight / 10 ; // 5% (need to treat the whole screen is 2x this screen)
fScaleFactorWidth = 0.5f ;
iWidthOffset = ( int ) ( ( float ) screenWidth * ( 1.0f - fScaleFactorWidth ) ) ;
iTooltipsYOffset = 44 ;
bTwoPlayerSplitscreen = true ;
currentGuiScaleFactor * = 0.5f ;
break ;
case C4JRender : : VIEWPORT_TYPE_SPLIT_LEFT :
iSafezoneXHalf = screenWidth / 10 ; // 5% (the whole screen is 2x this screen)
iSafezoneYHalf = splitYOffset + screenHeight / 10 ; // 5% (need to treat the whole screen is 2x this screen)
fScaleFactorHeight = 0.5f ;
iHeightOffset = screenHeight ;
iTooltipsYOffset = 44 ;
bTwoPlayerSplitscreen = true ;
currentGuiScaleFactor * = 0.5f ;
break ;
case C4JRender : : VIEWPORT_TYPE_SPLIT_RIGHT :
2026-03-02 15:53:32 +07:00
iSafezoneXHalf = 0 ;
2026-03-01 12:16:08 +08:00
iSafezoneYHalf = splitYOffset + screenHeight / 10 ; // 5% (need to treat the whole screen is 2x this screen)
fScaleFactorHeight = 0.5f ;
iHeightOffset = screenHeight ;
iTooltipsYOffset = 44 ;
bTwoPlayerSplitscreen = true ;
currentGuiScaleFactor * = 0.5f ;
break ;
case C4JRender : : VIEWPORT_TYPE_QUADRANT_TOP_LEFT :
iSafezoneXHalf = screenWidth / 10 ; // 5% (the whole screen is 2x this screen)
iSafezoneYHalf = splitYOffset ;
iTooltipsYOffset = 44 ;
currentGuiScaleFactor * = 0.5f ;
break ;
case C4JRender : : VIEWPORT_TYPE_QUADRANT_TOP_RIGHT :
2026-03-02 15:53:32 +07:00
iSafezoneXHalf = 0 ;
2026-03-01 12:16:08 +08:00
iSafezoneYHalf = splitYOffset ; // 5%
iTooltipsYOffset = 44 ;
currentGuiScaleFactor * = 0.5f ;
break ;
case C4JRender : : VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT :
iSafezoneXHalf = screenWidth / 10 ; // 5% (the whole screen is 2x this screen)
iSafezoneYHalf = splitYOffset + screenHeight / 10 ; // 5% (the whole screen is 2x this screen)
iTooltipsYOffset = 44 ;
currentGuiScaleFactor * = 0.5f ;
break ;
case C4JRender : : VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT :
2026-03-02 15:53:32 +07:00
iSafezoneXHalf = 0 ;
2026-03-01 12:16:08 +08:00
iSafezoneYHalf = splitYOffset + screenHeight / 10 ; // 5% (the whole screen is 2x this screen)
iTooltipsYOffset = 44 ;
currentGuiScaleFactor * = 0.5f ;
break ;
2026-03-02 15:53:32 +07:00
2026-03-01 12:16:08 +08:00
}
// 4J-PB - turn off the slot display if a xui menu is up, or if we're autosaving
bool bDisplayGui = ! ui . GetMenuDisplayed ( iPad ) & & ! ( app . GetXuiAction ( iPad ) = = eAppAction_AutosaveSaveGameCapturedThumbnail ) ;
// if tooltips are off, set the y offset to zero
2026-03-02 15:53:32 +07:00
if ( app . GetGameSettings ( iPad , eGameSetting_Tooltips ) = = 0 & & bDisplayGui )
2026-03-01 12:16:08 +08:00
{
switch ( minecraft - > player - > m_iScreenSection )
{
case C4JRender : : VIEWPORT_TYPE_FULLSCREEN :
2026-03-02 15:53:32 +07:00
iTooltipsYOffset = screenHeight / 10 ;
2026-03-01 12:16:08 +08:00
break ;
default :
2026-03-02 15:53:32 +07:00
//iTooltipsYOffset=screenHeight/10;
2026-03-01 12:16:08 +08:00
switch ( guiScale )
{
case 3 :
iTooltipsYOffset = 28 ; //screenHeight/10;
break ;
case 4 :
iTooltipsYOffset = 28 ; //screenHeight/10;
break ;
default : // 2
iTooltipsYOffset = 14 ; //screenHeight/10;
break ;
2026-03-02 15:53:32 +07:00
}
2026-03-01 12:16:08 +08:00
break ;
}
}
2026-03-02 15:53:32 +07:00
2026-03-01 12:16:08 +08:00
// 4J-PB - Turn off interface if eGameSetting_DisplayHUD is off - for screen shots/videos.
if ( app . GetGameSettings ( iPad , eGameSetting_DisplayHUD ) = = 0 )
{
bDisplayGui = false ;
}
Font * font = minecraft - > font ;
minecraft - > gameRenderer - > setupGuiScreen ( guiScale ) ;
2026-03-02 15:53:32 +07:00
2026-03-01 12:16:08 +08:00
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ; // 4J - added - this did actually get set in renderVignette but that code is currently commented out
2026-03-02 15:53:32 +07:00
if ( Minecraft : : useFancyGraphics ( ) )
2026-03-01 12:16:08 +08:00
{
renderVignette ( minecraft - > player - > getBrightness ( a ) , screenWidth , screenHeight ) ;
}
/////////////////////////////////////////////////////////////////////////////////////
// Display the pumpkin screen effect
/////////////////////////////////////////////////////////////////////////////////////
2026-03-02 15:58:20 +07:00
std : : shared_ptr < ItemInstance > headGear = minecraft - > player - > inventory - > getArmor ( 3 ) ;
2026-03-01 12:16:08 +08:00
// 4J-PB - changing this to be per player
//if (!minecraft->options->thirdPersonView && headGear != NULL && headGear->id == Tile::pumpkin_Id) renderPumpkin(screenWidth, screenHeight);
if ( ( minecraft - > player - > ThirdPersonView ( ) = = 0 ) & & headGear ! = NULL & & headGear - > id = = Tile : : pumpkin_Id ) renderPumpkin ( screenWidth , screenHeight ) ;
if ( ! minecraft - > player - > hasEffect ( MobEffect : : confusion ) )
{
float pt = minecraft - > player - > oPortalTime + ( minecraft - > player - > portalTime - minecraft - > player - > oPortalTime ) * a ;
if ( pt > 0 )
{
renderTp ( pt , screenWidth , screenHeight ) ;
}
}
if ( ! minecraft - > gameMode - > isCutScene ( ) )
{
if ( bDisplayGui & & bTwoPlayerSplitscreen )
{
// need to apply scale factors depending on the mode
2026-03-02 15:53:32 +07:00
glPushMatrix ( ) ;
2026-03-01 12:16:08 +08:00
glScalef ( fScaleFactorWidth , fScaleFactorHeight , fScaleFactorWidth ) ;
}
# if RENDER_HUD
/////////////////////////////////////////////////////////////////////////////////////
// Display the quick select background, the quick select selection, and the crosshair
/////////////////////////////////////////////////////////////////////////////////////
glColor4f ( 1 , 1 , 1 , 1 ) ;
// 4J - this is where to set the blend factor for gui things
// use the primary player's settings
unsigned char ucAlpha = app . GetGameSettings ( ProfileManager . GetPrimaryPad ( ) , eGameSetting_InterfaceOpacity ) ;
// If the user has started to navigate their quickselect bar, ignore the alpha setting, and display at default value
float fVal = fAlphaIncrementPerCent * ( float ) ucAlpha ;
if ( ucAlpha < 80 )
{
// check if we have the timer running for the opacity
unsigned int uiOpacityTimer = app . GetOpacityTimer ( iPad ) ;
if ( uiOpacityTimer ! = 0 )
{
if ( uiOpacityTimer < 10 )
{
float fStep = ( 80.0f - ( float ) ucAlpha ) / 10.0f ;
fVal = fAlphaIncrementPerCent * ( 80.0f - ( ( 10.0f - ( float ) uiOpacityTimer ) * fStep ) ) ;
}
else
{
fVal = fAlphaIncrementPerCent * 80.0f ;
}
}
else
{
fVal = fAlphaIncrementPerCent * ( float ) ucAlpha ;
}
}
else
{
fVal = fAlphaIncrementPerCent * ( float ) ucAlpha ;
}
RenderManager . StateSetBlendFactor ( 0xffffff | ( ( ( unsigned int ) fVal ) < < 24 ) ) ;
currentGuiBlendFactor = fVal / 255.0f ;
// RenderManager.StateSetBlendFactor(0x40ffffff);
glBlendFunc ( GL_CONSTANT_ALPHA , GL_ONE_MINUS_CONSTANT_ALPHA ) ;
blitOffset = - 90 ;
/////////////////////////////////////////////////////////////////////////////////////
// Display the quick select background, the quick select selection, and the crosshair
/////////////////////////////////////////////////////////////////////////////////////
if ( bDisplayGui )
{
MemSect ( 31 ) ;
minecraft - > textures - > bindTexture ( TN_GUI_GUI ) ; // 4J was L"/gui/gui.png"
MemSect ( 0 ) ;
2026-03-02 15:58:20 +07:00
std : : shared_ptr < Inventory > inventory = minecraft - > player - > inventory ;
2026-03-01 12:16:08 +08:00
if ( bTwoPlayerSplitscreen )
{
// need to apply scale factors depending on the mode
// 4J Stu - Moved this push and scale further up as we still need to do it for the few HUD components not replaced by xui
2026-03-02 15:53:32 +07:00
//glPushMatrix();
2026-03-01 12:16:08 +08:00
//glScalef(fScaleFactorWidth, fScaleFactorHeight, fScaleFactorWidth);
2026-03-02 15:53:32 +07:00
2026-03-01 12:16:08 +08:00
// 4J-PB - move into the safe zone, and account for 2 player splitscreen
blit ( iWidthOffset + ( screenWidth - quickSelectWidth ) / 2 , iHeightOffset + screenHeight - iSafezoneYHalf - iTooltipsYOffset , 0 , 0 , 182 , 22 ) ;
blit ( iWidthOffset + ( screenWidth - quickSelectWidth ) / 2 - 1 + inventory - > selected * 20 , iHeightOffset + screenHeight - iSafezoneYHalf - iTooltipsYOffset - 1 , 0 , 22 , 24 , 22 ) ;
}
else
{
blit ( iWidthOffset + screenWidth / 2 - quickSelectWidth / 2 , iHeightOffset + screenHeight - iSafezoneYHalf - iTooltipsYOffset , 0 , 0 , 182 , 22 ) ;
blit ( iWidthOffset + screenWidth / 2 - quickSelectWidth / 2 - 1 + inventory - > selected * 20 , iHeightOffset + screenHeight - iSafezoneYHalf - iTooltipsYOffset - 1 , 0 , 22 , 24 , 22 ) ;
}
MemSect ( 31 ) ;
minecraft - > textures - > bindTexture ( TN_GUI_ICONS ) ; //L"/gui/icons.png"));
MemSect ( 0 ) ;
glEnable ( GL_BLEND ) ;
RenderManager . StateSetBlendFactor ( 0xffffff | ( ( ( unsigned int ) fVal ) < < 24 ) ) ;
glBlendFunc ( GL_CONSTANT_ALPHA , GL_ONE_MINUS_CONSTANT_ALPHA ) ;
//glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR);
// 4J Stu - We don't want to adjust the cursor by the safezone, we want it centred
if ( bTwoPlayerSplitscreen )
{
blit ( iWidthOffset + screenWidth / 2 - 7 , ( iHeightOffset + screenHeight ) / 2 - 7 , 0 , 0 , 16 , 16 ) ;
}
else
{
blit ( screenWidth / 2 - 7 , screenHeight / 2 - 7 , 0 , 0 , 16 , 16 ) ;
}
glDisable ( GL_BLEND ) ;
// if(bTwoPlayerSplitscreen)
// {
// glPopMatrix();
// }
}
bool blink = minecraft - > player - > invulnerableTime / 3 % 2 = = 1 ;
if ( minecraft - > player - > invulnerableTime < 10 ) blink = false ;
int iHealth = minecraft - > player - > getHealth ( ) ;
int iLastHealth = minecraft - > player - > lastHealth ;
random - > setSeed ( tickCount * 312871 ) ;
bool foodBlink = false ;
FoodData * foodData = minecraft - > player - > getFoodData ( ) ;
int food = foodData - > getFoodLevel ( ) ;
int oldFood = foodData - > getLastFoodLevel ( ) ;
2026-03-02 15:53:32 +07:00
// if (false) //(true)
2026-03-01 12:16:08 +08:00
// {
// renderBossHealth();
// }
/////////////////////////////////////////////////////////////////////////////////////
2026-03-02 15:53:32 +07:00
// Display the experience, food, armour, health and the air bubbles
2026-03-01 12:16:08 +08:00
/////////////////////////////////////////////////////////////////////////////////////
if ( bDisplayGui )
{
// 4J - added blend for fading gui
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_CONSTANT_ALPHA , GL_ONE_MINUS_CONSTANT_ALPHA ) ;
if ( minecraft - > gameMode - > canHurtPlayer ( ) )
{
int xLeft , xRight ;
// 4J Stu - TODO Work out proper positioning for splitscreen
if ( bTwoPlayerSplitscreen )
{
xLeft = iWidthOffset + ( screenWidth - quickSelectWidth ) / 2 ;
xRight = iWidthOffset + ( screenWidth + quickSelectWidth ) / 2 ;
}
else
{
xLeft = ( screenWidth - quickSelectWidth ) / 2 ;
xRight = ( screenWidth + quickSelectWidth ) / 2 ;
}
// render experience bar
int xpNeededForNextLevel = minecraft - > player - > getXpNeededForNextLevel ( ) ;
if ( xpNeededForNextLevel > 0 )
{
int w = 182 ;
int progress = ( int ) ( minecraft - > player - > experienceProgress * ( float ) ( w + 1 ) ) ;
int yo = screenHeight - iSafezoneYHalf - iTooltipsYOffset - 8 ;
if ( bTwoPlayerSplitscreen )
{
yo + = iHeightOffset ;
}
blit ( xLeft , yo , 0 , 64 , w , 5 ) ;
if ( progress > 0 )
{
blit ( xLeft , yo , 0 , 69 , progress , 5 ) ;
}
}
int yLine1 , yLine2 ;
if ( bTwoPlayerSplitscreen )
{
//yo = iHeightOffset + screenHeight - 10 - iSafezoneYHalf - iTooltipsYOffset;
yLine1 = iHeightOffset + screenHeight - 18 - iSafezoneYHalf - iTooltipsYOffset ;
yLine2 = yLine1 - 10 ;
}
else
{
//yo = screenHeight - 10 - iSafezoneYHalf - iTooltipsYOffset;
yLine1 = screenHeight - 18 - iSafezoneYHalf - iTooltipsYOffset ;
yLine2 = yLine1 - 10 ;
}
int armor = minecraft - > player - > getArmorValue ( ) ;
int heartOffsetIndex = - 1 ;
if ( minecraft - > player - > hasEffect ( MobEffect : : regeneration ) )
{
heartOffsetIndex = tickCount % 25 ;
}
// render health and armor
for ( int i = 0 ; i < Player : : MAX_HEALTH / 2 ; i + + )
{
if ( armor > 0 )
{
int xo = xLeft + i * 8 ;
// HEALTH
if ( i * 2 + 1 < armor ) blit ( xo , yLine2 , 16 + 2 * 9 , 9 * 1 , 9 , 9 ) ;
if ( i * 2 + 1 = = armor ) blit ( xo , yLine2 , 16 + 1 * 9 , 9 * 1 , 9 , 9 ) ;
if ( i * 2 + 1 > armor ) blit ( xo , yLine2 , 16 + 0 * 9 , 9 * 1 , 9 , 9 ) ;
}
int healthTexBaseX = 16 ;
if ( minecraft - > player - > hasEffect ( MobEffect : : poison ) )
{
healthTexBaseX + = 4 * 9 ;
}
int bg = 0 ;
if ( blink ) bg = 1 ;
int xo = xLeft + i * 8 ;
int yo = yLine1 ;
2026-03-02 15:53:32 +07:00
2026-03-01 12:16:08 +08:00
if ( iHealth < = 4 )
{
yo + = random - > nextInt ( 2 ) ;
}
if ( i = = heartOffsetIndex )
{
yo - = 2 ;
}
int y0 = 0 ;
// 4J-PB - no hardcore in xbox
// if (minecraft.level.getLevelData().isHardcore()) {
// y0 = 5;
// }
blit ( xo , yo , 16 + bg * 9 , 9 * 0 , 9 , 9 ) ;
if ( blink )
{
if ( i * 2 + 1 < iLastHealth ) blit ( xo , yo , healthTexBaseX + 6 * 9 , 9 * y0 , 9 , 9 ) ;
if ( i * 2 + 1 = = iLastHealth ) blit ( xo , yo , healthTexBaseX + 7 * 9 , 9 * y0 , 9 , 9 ) ;
}
if ( i * 2 + 1 < iHealth ) blit ( xo , yo , healthTexBaseX + 4 * 9 , 9 * y0 , 9 , 9 ) ;
if ( i * 2 + 1 = = iHealth ) blit ( xo , yo , healthTexBaseX + 5 * 9 , 9 * y0 , 9 , 9 ) ;
}
// render food
for ( int i = 0 ; i < FoodConstants : : MAX_FOOD / 2 ; i + + )
{
int yo = yLine1 ;
int texBaseX = 16 ;
int bg = 0 ;
if ( minecraft - > player - > hasEffect ( MobEffect : : hunger ) )
{
texBaseX + = 4 * 9 ;
bg = 13 ;
}
if ( minecraft - > player - > getFoodData ( ) - > getSaturationLevel ( ) < = 0 )
{
if ( ( tickCount % ( food * 3 + 1 ) ) = = 0 )
{
yo + = random - > nextInt ( 3 ) - 1 ;
}
}
if ( foodBlink ) bg = 1 ;
int xo = xRight - i * 8 - 9 ;
blit ( xo , yo , 16 + bg * 9 , 9 * 3 , 9 , 9 ) ;
if ( foodBlink )
{
if ( i * 2 + 1 < oldFood ) blit ( xo , yo , texBaseX + 6 * 9 , 9 * 3 , 9 , 9 ) ;
if ( i * 2 + 1 = = oldFood ) blit ( xo , yo , texBaseX + 7 * 9 , 9 * 3 , 9 , 9 ) ;
}
if ( i * 2 + 1 < food ) blit ( xo , yo , texBaseX + 4 * 9 , 9 * 3 , 9 , 9 ) ;
if ( i * 2 + 1 = = food ) blit ( xo , yo , texBaseX + 5 * 9 , 9 * 3 , 9 , 9 ) ;
}
// render air bubbles
if ( minecraft - > player - > isUnderLiquid ( Material : : water ) )
{
int count = ( int ) ceil ( ( minecraft - > player - > getAirSupply ( ) - 2 ) * 10.0f / Player : : TOTAL_AIR_SUPPLY ) ;
int extra = ( int ) ceil ( ( minecraft - > player - > getAirSupply ( ) ) * 10.0f / Player : : TOTAL_AIR_SUPPLY ) - count ;
for ( int i = 0 ; i < count + extra ; i + + )
{
// Air bubbles
if ( i < count ) blit ( xRight - i * 8 - 9 , yLine2 , 16 , 9 * 2 , 9 , 9 ) ;
else blit ( xRight - i * 8 - 9 , yLine2 , 16 + 9 , 9 * 2 , 9 , 9 ) ;
}
}
}
}
// 4J-PB - turn off the slot display if a xui menu is up
////////////////////////////
// render the slot contents
////////////////////////////
if ( bDisplayGui )
{
// glDisable(GL_BLEND); 4J - removed - we want to be able to fade our gui
glEnable ( GL_RESCALE_NORMAL ) ;
Lighting : : turnOnGui ( ) ;
2026-03-02 15:53:32 +07:00
2026-03-01 12:16:08 +08:00
int x , y ;
for ( int i = 0 ; i < 9 ; i + + )
2026-03-02 15:53:32 +07:00
{
2026-03-01 12:16:08 +08:00
if ( bTwoPlayerSplitscreen )
{
x = iWidthOffset + screenWidth / 2 - 9 * 10 + i * 20 + 2 ;
y = iHeightOffset + screenHeight - iSafezoneYHalf - iTooltipsYOffset - 16 - 3 + 22 ;
}
else
{
x = screenWidth / 2 - 9 * 10 + i * 20 + 2 ;
y = screenHeight - iSafezoneYHalf - iTooltipsYOffset - 16 - 3 + 22 ;
}
this - > renderSlot ( i , x , y , a ) ;
}
Lighting : : turnOff ( ) ;
glDisable ( GL_RESCALE_NORMAL ) ;
}
# endif // RENDER_HUD
// 4J - do render of crouched player. This code is largely taken from the inventory render of the player, with some special hard-coded positions
// worked out by hand from the xui implementation of the crouch icon
if ( app . GetGameSettings ( iPad , eGameSetting_AnimatedCharacter ) )
{
//int playerIdx = minecraft->player->GetXboxPad();
static int characterDisplayTimer [ 4 ] = { 0 } ;
if ( ! bDisplayGui )
{
characterDisplayTimer [ iPad ] = 0 ;
}
else if ( minecraft - > player - > isSneaking ( ) )
{
characterDisplayTimer [ iPad ] = 30 ;
}
else if ( minecraft - > player - > isSprinting ( ) )
{
characterDisplayTimer [ iPad ] = 30 ;
2026-03-02 15:53:32 +07:00
}
2026-03-01 12:16:08 +08:00
else if ( minecraft - > player - > abilities . flying )
{
characterDisplayTimer [ iPad ] = 5 ; // quickly get rid of the player display if they stop flying
2026-03-02 15:53:32 +07:00
}
2026-03-01 12:16:08 +08:00
else if ( characterDisplayTimer [ iPad ] > 0 )
{
- - characterDisplayTimer [ iPad ] ;
}
bool displayCrouch = minecraft - > player - > isSneaking ( ) | | ( characterDisplayTimer [ iPad ] > 0 ) ;
bool displaySprint = minecraft - > player - > isSprinting ( ) | | ( characterDisplayTimer [ iPad ] > 0 ) ;
bool displayFlying = minecraft - > player - > abilities . flying | | ( characterDisplayTimer [ iPad ] > 0 ) ;
if ( bDisplayGui & & ( displayCrouch | | displaySprint | | displayFlying ) )
{
EntityRenderDispatcher : : instance - > prepare ( minecraft - > level , minecraft - > textures , minecraft - > font , minecraft - > cameraTargetPlayer , minecraft - > options , a ) ;
glEnable ( GL_RESCALE_NORMAL ) ;
glEnable ( GL_COLOR_MATERIAL ) ;
int xo = 0 ;
int yo = 0 ;
switch ( minecraft - > player - > m_iScreenSection )
{
case C4JRender : : VIEWPORT_TYPE_FULLSCREEN :
default :
if ( RenderManager . IsHiDef ( ) ) xo = - 22 ;
yo = - 36 ;
break ;
case C4JRender : : VIEWPORT_TYPE_SPLIT_TOP :
xo = 0 ; yo = - 25 ;
break ;
case C4JRender : : VIEWPORT_TYPE_SPLIT_BOTTOM :
xo = 0 ; yo = - 48 ;
break ;
case C4JRender : : VIEWPORT_TYPE_SPLIT_LEFT :
xo = 0 ; yo = - 25 ;
break ;
case C4JRender : : VIEWPORT_TYPE_SPLIT_RIGHT :
xo = - 43 ; yo = - 25 ;
break ;
case C4JRender : : VIEWPORT_TYPE_QUADRANT_TOP_LEFT :
xo = 0 ; yo = - 25 ;
break ;
case C4JRender : : VIEWPORT_TYPE_QUADRANT_TOP_RIGHT :
xo = - 43 ; yo = - 25 ;
break ;
case C4JRender : : VIEWPORT_TYPE_QUADRANT_BOTTOM_LEFT :
xo = 0 ; yo = - 48 ;
break ;
case C4JRender : : VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT :
xo = - 43 ; yo = - 48 ;
break ;
}
glPushMatrix ( ) ;
glTranslatef ( ( float ) xo + 51 , ( float ) yo + 75 , 50 ) ;
float ss = 12 ;
glScalef ( - ss , ss , ss ) ;
glRotatef ( 180 , 0 , 0 , 1 ) ;
float oyr = minecraft - > player - > yRot ;
float oyrO = minecraft - > player - > yRotO ;
float oxr = minecraft - > player - > xRot ;
int ofire = minecraft - > player - > onFire ;
bool ofireflag = minecraft - > player - > getSharedFlag ( Entity : : FLAG_ONFIRE ) ;
float xd = - 40 ;
float yd = 10 ;
// 4J Stu - This is all based on the inventory player renderer, with changes to ensure that capes render correctly
// by minimising the changes to member variables of the player which are all related
glRotatef ( 45 + 90 , 0 , 1 , 0 ) ;
Lighting : : turnOn ( ) ;
glRotatef ( - 45 - 90 , 0 , 1 , 0 ) ;
glRotatef ( - ( float ) atan ( yd / 40.0f ) * 20 , 1 , 0 , 0 ) ;
float bodyRot = ( minecraft - > player - > yBodyRotO + ( minecraft - > player - > yBodyRot - minecraft - > player - > yBodyRotO ) ) ;
// Fixed rotation angle of degrees, adjusted by bodyRot to negate the rotation that occurs in the renderer
// bodyRot in the rotation below is a simplification of "180 - (180 - bodyRot)" where the first 180 is EntityRenderDispatcher::instance->playerRotY that we set below
// and (180 - bodyRot) is the angle of rotation that is performed within the mob renderer
glRotatef ( bodyRot - ( ( float ) atan ( xd / 40.0f ) * 20 ) , 0 , 1 , 0 ) ;
glColor4f ( 1.0f , 1.0f , 1.0f , 1.0f ) ;
// Set head rotation to body rotation to make head static
minecraft - > player - > yRot = bodyRot ;
minecraft - > player - > yRotO = minecraft - > player - > yRot ;
minecraft - > player - > xRot = - ( float ) atan ( yd / 40.0f ) * 20 ;
minecraft - > player - > onFire = 0 ;
minecraft - > player - > setSharedFlag ( Entity : : FLAG_ONFIRE , false ) ;
2026-03-02 15:53:32 +07:00
2026-03-01 12:16:08 +08:00
glTranslatef ( 0 , minecraft - > player - > heightOffset , 0 ) ;
EntityRenderDispatcher : : instance - > playerRotY = 180 ;
EntityRenderDispatcher : : instance - > isGuiRender = true ;
EntityRenderDispatcher : : instance - > render ( minecraft - > player , 0 , 0 , 0 , 0 , 1 ) ;
EntityRenderDispatcher : : instance - > isGuiRender = false ;
minecraft - > player - > yRot = oyr ;
minecraft - > player - > yRotO = oyrO ;
minecraft - > player - > xRot = oxr ;
minecraft - > player - > onFire = ofire ;
minecraft - > player - > setSharedFlag ( Entity : : FLAG_ONFIRE , ofireflag ) ;
glPopMatrix ( ) ;
Lighting : : turnOff ( ) ;
glDisable ( GL_RESCALE_NORMAL ) ;
}
}
}
# if RENDER_HUD
// Moved so the opacity blend is applied to it
if ( bDisplayGui & & minecraft - > gameMode - > hasExperience ( ) & & minecraft - > player - > experienceLevel > 0 )
{
if ( true )
{
bool blink = false ;
int col = blink ? 0xffffff : 0x80ff20 ;
wchar_t formatted [ 10 ] ;
swprintf ( formatted , 10 , L " %d " , minecraft - > player - > experienceLevel ) ;
wstring str = formatted ;
int x = iWidthOffset + ( screenWidth - font - > width ( str ) ) / 2 ;
int y = screenHeight - iSafezoneYHalf - iTooltipsYOffset ;
// If we're in creative mode, we don't need to offset the XP display so much
if ( minecraft - > gameMode - > canHurtPlayer ( ) )
{
y - = 18 ;
}
else
{
y - = 13 ;
}
2026-03-02 15:53:32 +07:00
2026-03-01 12:16:08 +08:00
if ( bTwoPlayerSplitscreen )
{
y + = iHeightOffset ;
}
//int y = screenHeight - 31 - 4;
font - > draw ( str , x + 1 , y , 0x000000 ) ;
font - > draw ( str , x - 1 , y , 0x000000 ) ;
font - > draw ( str , x , y + 1 , 0x000000 ) ;
font - > draw ( str , x , y - 1 , 0x000000 ) ;
// font->draw(str, x + 1, y + 1, 0x000000);
// font->draw(str, x - 1, y + 1, 0x000000);
// font->draw(str, x + 1, y - 1, 0x000000);
// font->draw(str, x - 1, y - 1, 0x000000);
font - > draw ( str , x , y , col ) ;
}
}
# endif // RENDER_HUD
// 4J - added to disable blends, which we have enabled previously to allow gui fading
glDisable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
// if the player is falling asleep we render a dark overlay
if ( minecraft - > player - > getSleepTimer ( ) > 0 )
{
glDisable ( GL_DEPTH_TEST ) ;
glDisable ( GL_ALPHA_TEST ) ;
int timer = minecraft - > player - > getSleepTimer ( ) ;
float amount = ( float ) timer / ( float ) Player : : SLEEP_DURATION ;
if ( amount > 1 )
{
// waking up
amount = 1.0f - ( ( float ) ( timer - Player : : SLEEP_DURATION ) / ( float ) Player : : WAKE_UP_DURATION ) ;
}
int color = ( int ) ( 220.0f * amount ) < < 24 | ( 0x101020 ) ;
fill ( 0 , 0 , screenWidth / fScaleFactorWidth , screenHeight / fScaleFactorHeight , color ) ;
glEnable ( GL_ALPHA_TEST ) ;
glEnable ( GL_DEPTH_TEST ) ;
}
// 4J-PB - Request from Mojang to have a red death screen
if ( ! minecraft - > player - > isAlive ( ) )
{
glDisable ( GL_DEPTH_TEST ) ;
glDisable ( GL_ALPHA_TEST ) ;
int timer = minecraft - > player - > getDeathFadeTimer ( ) ;
float amount = ( float ) timer / ( float ) Player : : DEATHFADE_DURATION ;
int color = ( int ) ( 220.0f * amount ) < < 24 | ( 0x200000 ) ;
fill ( 0 , 0 , screenWidth / fScaleFactorWidth , screenHeight / fScaleFactorHeight , color ) ;
glEnable ( GL_ALPHA_TEST ) ;
glEnable ( GL_DEPTH_TEST ) ;
}
// {
// String str = "" + minecraft.player.getFoodData().getExhaustionLevel() + ", " + minecraft.player.getFoodData().getSaturationLevel();
// int x = (screenWidth - font.width(str)) / 2;
// int y = screenHeight - 64;
// font.draw(str, x + 1, y, 0xffffff);
// }
# ifndef _FINAL_BUILD
MemSect ( 31 ) ;
if ( minecraft - > options - > renderDebug )
{
glPushMatrix ( ) ;
if ( Minecraft : : warezTime > 0 ) glTranslatef ( 0 , 32 , 0 ) ;
font - > drawShadow ( ClientConstants : : VERSION_STRING + L " ( " + minecraft - > fpsString + L " ) " , iSafezoneXHalf + 2 , 20 , 0xffffff ) ;
2026-03-02 15:53:32 +07:00
font - > drawShadow ( L " Seed: " + _toString < int64_t > ( minecraft - > level - > getLevelData ( ) - > getSeed ( ) ) , iSafezoneXHalf + 2 , 32 + 00 , 0xffffff ) ;
2026-03-01 12:16:08 +08:00
font - > drawShadow ( minecraft - > gatherStats1 ( ) , iSafezoneXHalf + 2 , 32 + 10 , 0xffffff ) ;
font - > drawShadow ( minecraft - > gatherStats2 ( ) , iSafezoneXHalf + 2 , 32 + 20 , 0xffffff ) ;
font - > drawShadow ( minecraft - > gatherStats3 ( ) , iSafezoneXHalf + 2 , 32 + 30 , 0xffffff ) ;
font - > drawShadow ( minecraft - > gatherStats4 ( ) , iSafezoneXHalf + 2 , 32 + 40 , 0xffffff ) ;
// TERRAIN FEATURES
int iYPos = 82 ;
if ( minecraft - > level - > dimension - > id = = 0 )
{
wstring wfeature [ eTerrainFeature_Count ] ;
wfeature [ eTerrainFeature_Stronghold ] = L " Stronghold: " ;
wfeature [ eTerrainFeature_Mineshaft ] = L " Mineshaft: " ;
wfeature [ eTerrainFeature_Village ] = L " Village: " ;
wfeature [ eTerrainFeature_Ravine ] = L " Ravine: " ;
for ( int i = 0 ; i < app . m_vTerrainFeatures . size ( ) ; i + + )
{
FEATURE_DATA * pFeatureData = app . m_vTerrainFeatures [ i ] ;
wstring itemInfo = L " [ " + _toString < int > ( pFeatureData - > x * 16 ) + L " , " + _toString < int > ( pFeatureData - > z * 16 ) + L " ] " ;
wfeature [ pFeatureData - > eTerrainFeature ] + = itemInfo ;
}
for ( int i = eTerrainFeature_Stronghold ; i < ( int ) eTerrainFeature_Count ; i + + )
{
font - > drawShadow ( wfeature [ i ] , iSafezoneXHalf + 2 , iYPos , 0xffffff ) ;
iYPos + = 10 ;
}
}
//font->drawShadow(minecraft->gatherStats5(), iSafezoneXHalf+2, 32 + 10, 0xffffff);
{
/* 4J - removed
long max = Runtime . getRuntime ( ) . maxMemory ( ) ;
long total = Runtime . getRuntime ( ) . totalMemory ( ) ;
long free = Runtime . getRuntime ( ) . freeMemory ( ) ;
long used = total - free ;
String msg = " Used memory: " + ( used * 100 / max ) + " % ( " + ( used / 1024 / 1024 ) + " MB) of " + ( max / 1024 / 1024 ) + " MB " ;
drawString ( font , msg , screenWidth - font . width ( msg ) - 2 , 2 , 0xe0e0e0 ) ;
msg = " Allocated memory: " + ( total * 100 / max ) + " % ( " + ( total / 1024 / 1024 ) + " MB) " ;
drawString ( font , msg , screenWidth - font . width ( msg ) - 2 , 12 , 0xe0e0e0 ) ;
*/
}
// 4J Stu - Moved these so that they don't overlap
double xBlockPos = floor ( minecraft - > player - > x ) ;
double yBlockPos = floor ( minecraft - > player - > y ) ;
double zBlockPos = floor ( minecraft - > player - > z ) ;
drawString ( font , L " x: " + _toString < double > ( minecraft - > player - > x ) + L " / Head: " + _toString < double > ( xBlockPos ) + L " / Chunk: " + _toString < double > ( minecraft - > player - > xChunk ) , iSafezoneXHalf + 2 , iYPos + 8 * 0 , 0xe0e0e0 ) ;
drawString ( font , L " y: " + _toString < double > ( minecraft - > player - > y ) + L " / Head: " + _toString < double > ( yBlockPos ) , iSafezoneXHalf + 2 , iYPos + 8 * 1 , 0xe0e0e0 ) ;
drawString ( font , L " z: " + _toString < double > ( minecraft - > player - > z ) + L " / Head: " + _toString < double > ( zBlockPos ) + L " / Chunk: " + _toString < double > ( minecraft - > player - > zChunk ) , iSafezoneXHalf + 2 , iYPos + 8 * 2 , 0xe0e0e0 ) ;
drawString ( font , L " f: " + _toString < double > ( Mth : : floor ( minecraft - > player - > yRot * 4.0f / 360.0f + 0.5 ) & 0x3 ) + L " / yRot: " + _toString < double > ( minecraft - > player - > yRot ) , iSafezoneXHalf + 2 , iYPos + 8 * 3 , 0xe0e0e0 ) ;
iYPos + = 8 * 4 ;
int px = Mth : : floor ( minecraft - > player - > x ) ;
int py = Mth : : floor ( minecraft - > player - > y ) ;
int pz = Mth : : floor ( minecraft - > player - > z ) ;
if ( minecraft - > level ! = NULL & & minecraft - > level - > hasChunkAt ( px , py , pz ) )
{
LevelChunk * chunkAt = minecraft - > level - > getChunkAt ( px , pz ) ;
Biome * biome = chunkAt - > getBiome ( px & 15 , pz & 15 , minecraft - > level - > getBiomeSource ( ) ) ;
drawString (
font ,
L " b: " + biome - > m_name + L " ( " + _toString < int > ( biome - > id ) + L " ) " , iSafezoneXHalf + 2 , iYPos , 0xe0e0e0 ) ;
}
glPopMatrix ( ) ;
}
MemSect ( 0 ) ;
# endif
lastTickA = a ;
// 4J Stu - This is now displayed in a xui scene
#if 0
// Jukebox CD message
if ( overlayMessageTime > 0 )
{
float t = overlayMessageTime - a ;
int alpha = ( int ) ( t * 256 / 20 ) ;
if ( alpha > 255 ) alpha = 255 ;
2026-03-02 15:53:32 +07:00
if ( alpha > 0 )
2026-03-01 12:16:08 +08:00
{
glPushMatrix ( ) ;
if ( bTwoPlayerSplitscreen )
{
glTranslatef ( ( float ) ( ( screenWidth / 2 ) + iWidthOffset ) , ( ( float ) ( screenHeight + iHeightOffset ) ) - iTooltipsYOffset - 12 - iSafezoneYHalf , 0 ) ;
}
else
{
glTranslatef ( ( ( float ) screenWidth ) / 2 , ( ( float ) screenHeight ) - iTooltipsYOffset - 12 - iSafezoneYHalf , 0 ) ;
}
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
int col = 0xffffff ;
if ( animateOverlayMessageColor )
{
col = Color : : HSBtoRGB ( t / 50.0f , 0.7f , 0.6f ) & 0xffffff ;
}
// 4J-PB - this is the string displayed when cds are placed in a jukebox
font - > draw ( overlayMessageString , - font - > width ( overlayMessageString ) / 2 , - 20 , col + ( alpha < < 24 ) ) ;
glDisable ( GL_BLEND ) ;
glPopMatrix ( ) ;
}
}
# endif
2026-03-02 15:53:32 +07:00
2026-03-01 12:16:08 +08:00
unsigned int max = 10 ;
bool isChatting = false ;
if ( dynamic_cast < ChatScreen * > ( minecraft - > screen ) ! = NULL )
{
max = 20 ;
isChatting = true ;
}
glEnable ( GL_BLEND ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
glDisable ( GL_ALPHA_TEST ) ;
// 4J Stu - We have moved the chat text to a xui
#if 0
glPushMatrix ( ) ;
// 4J-PB we need to move this up a bit because we've moved the quick select
//glTranslatef(0, ((float)screenHeight) - 48, 0);
glTranslatef ( 0.0f , ( float ) ( screenHeight - iSafezoneYHalf - iTooltipsYOffset - 16 - 3 + 22 ) - 24.0f , 0.0f ) ;
// glScalef(1.0f / ssc.scale, 1.0f / ssc.scale, 1);
// 4J-PB - we need gui messages for each of the possible 4 splitscreen players
if ( bDisplayGui )
{
int iPad = minecraft - > player - > GetXboxPad ( ) ;
for ( unsigned int i = 0 ; i < guiMessages [ iPad ] . size ( ) & & i < max ; i + + )
{
if ( guiMessages [ iPad ] [ i ] . ticks < 20 * 10 | | isChatting )
{
double t = guiMessages [ iPad ] [ i ] . ticks / ( 20 * 10.0 ) ;
t = 1 - t ;
t = t * 10 ;
if ( t < 0 ) t = 0 ;
if ( t > 1 ) t = 1 ;
t = t * t ;
int alpha = ( int ) ( 255 * t ) ;
if ( isChatting ) alpha = 255 ;
if ( alpha > 0 )
{
int x = iSafezoneXHalf + 2 ;
int y = - ( ( int ) i ) * 9 ;
if ( bTwoPlayerSplitscreen )
{
y + = iHeightOffset ;
}
wstring msg = guiMessages [ iPad ] [ i ] . string ;
// 4J-PB - fill the black bar across the whole screen, otherwise it looks odd due to the safe area
this - > fill ( 0 , y - 1 , screenWidth / fScaleFactorWidth , y + 8 , ( alpha / 2 ) < < 24 ) ;
glEnable ( GL_BLEND ) ;
font - > drawShadow ( msg , iSafezoneXHalf + 4 , y , 0xffffff + ( alpha < < 24 ) ) ;
}
}
}
}
glPopMatrix ( ) ;
# endif
// 4J Stu - Copied over but not used
#if 0
if ( minecraft . player instanceof MultiplayerLocalPlayer & & minecraft . options . keyPlayerList . isDown )
{
ClientConnection connection = ( ( MultiplayerLocalPlayer ) minecraft . player ) . connection ;
List < PlayerInfo > playerInfos = connection . playerInfos ;
int slots = connection . maxPlayers ;
int rows = slots ;
int cols = 1 ;
while ( rows > 20 ) {
cols + + ;
rows = ( slots + cols - 1 ) / cols ;
}
/*
* int fakeCount = 39 ; while ( playerInfos . size ( ) > fakeCount )
* playerInfos . remove ( playerInfos . size ( ) - 1 ) ; while ( playerInfos . size ( ) <
* fakeCount ) playerInfos . add ( new PlayerInfo ( " fiddle " ) ) ;
*/
int slotWidth = 300 / cols ;
if ( slotWidth > 150 ) slotWidth = 150 ;
int xxo = ( screenWidth - cols * slotWidth ) / 2 ;
int yyo = 10 ;
fill ( xxo - 1 , yyo - 1 , xxo + slotWidth * cols , yyo + 9 * rows , 0x80000000 ) ;
for ( int i = 0 ; i < slots ; i + + ) {
int xo = xxo + i % cols * slotWidth ;
int yo = yyo + i / cols * 9 ;
fill ( xo , yo , xo + slotWidth - 1 , yo + 8 , 0x20ffffff ) ;
glColor4f ( 1 , 1 , 1 , 1 ) ;
glEnable ( GL_ALPHA_TEST ) ;
if ( i < playerInfos . size ( ) ) {
PlayerInfo pl = playerInfos . get ( i ) ;
font . drawShadow ( pl . name , xo , yo , 0xffffff ) ;
minecraft . textures . bind ( minecraft . textures . loadTexture ( " /gui/icons.png " ) ) ;
int xt = 0 ;
int yt = 0 ;
xt = 0 ;
yt = 0 ;
if ( pl . latency < 0 ) yt = 5 ;
else if ( pl . latency < 150 ) yt = 0 ;
else if ( pl . latency < 300 ) yt = 1 ;
else if ( pl . latency < 600 ) yt = 2 ;
else if ( pl . latency < 1000 ) yt = 3 ;
else yt = 4 ;
blitOffset + = 100 ;
blit ( xo + slotWidth - 12 , yo , 0 + xt * 10 , 176 + yt * 8 , 10 , 8 ) ;
blitOffset - = 100 ;
}
}
}
# endif
if ( bDisplayGui & & bTwoPlayerSplitscreen )
{
// pop the scaled matrix
glPopMatrix ( ) ;
}
glColor4f ( 1 , 1 , 1 , 1 ) ;
glDisable ( GL_BLEND ) ;
glEnable ( GL_ALPHA_TEST ) ;
}
// Moved to the xui base scene
// void Gui::renderBossHealth(void)
// {
// if (EnderDragonRenderer::bossInstance == NULL) return;
2026-03-02 15:53:32 +07:00
//
2026-03-02 15:58:20 +07:00
// std::shared_ptr<EnderDragon> boss = EnderDragonRenderer::bossInstance;
2026-03-01 12:16:08 +08:00
// EnderDragonRenderer::bossInstance = NULL;
2026-03-02 15:53:32 +07:00
//
2026-03-01 12:16:08 +08:00
// Minecraft *pMinecraft=Minecraft::GetInstance();
2026-03-02 15:53:32 +07:00
//
2026-03-01 12:16:08 +08:00
// Font *font = pMinecraft->font;
2026-03-02 15:53:32 +07:00
//
2026-03-01 12:16:08 +08:00
// ScreenSizeCalculator ssc(pMinecraft->options, pMinecraft->width_phys, pMinecraft->height_phys);
// int screenWidth = ssc.getWidth();
2026-03-02 15:53:32 +07:00
//
2026-03-01 12:16:08 +08:00
// int w = 182;
// int xLeft = screenWidth / 2 - w / 2;
2026-03-02 15:53:32 +07:00
//
2026-03-01 12:16:08 +08:00
// int progress = (int) (boss->getSynchedHealth() / (float) boss->getMaxHealth() * (float) (w + 1));
2026-03-02 15:53:32 +07:00
//
2026-03-01 12:16:08 +08:00
// int yo = 12;
// blit(xLeft, yo, 0, 74, w, 5);
// blit(xLeft, yo, 0, 74, w, 5);
2026-03-02 15:53:32 +07:00
// if (progress > 0)
2026-03-01 12:16:08 +08:00
// {
// blit(xLeft, yo, 0, 79, progress, 5);
// }
2026-03-02 15:53:32 +07:00
//
2026-03-01 12:16:08 +08:00
// wstring msg = L"Boss health - NON LOCALISED";
// font->drawShadow(msg, screenWidth / 2 - font->width(msg) / 2, yo - 10, 0xff00ff);
// glColor4f(1, 1, 1, 1);
// glBindTexture(GL_TEXTURE_2D, pMinecraft->textures->loadTexture(TN_GUI_ICONS) );//"/gui/icons.png"));
2026-03-02 15:53:32 +07:00
//
2026-03-01 12:16:08 +08:00
// }
void Gui : : renderPumpkin ( int w , int h )
{
glDisable ( GL_DEPTH_TEST ) ;
glDepthMask ( false ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
glColor4f ( 1 , 1 , 1 , 1 ) ;
glDisable ( GL_ALPHA_TEST ) ;
MemSect ( 31 ) ;
minecraft - > textures - > bindTexture ( TN__BLUR__MISC_PUMPKINBLUR ) ; //L"%blur%/misc/pumpkinblur.png"));
MemSect ( 0 ) ;
Tesselator * t = Tesselator : : getInstance ( ) ;
t - > begin ( ) ;
t - > vertexUV ( ( float ) ( 0 ) , ( float ) ( h ) , ( float ) ( - 90 ) , ( float ) ( 0 ) , ( float ) ( 1 ) ) ;
t - > vertexUV ( ( float ) ( w ) , ( float ) ( h ) , ( float ) ( - 90 ) , ( float ) ( 1 ) , ( float ) ( 1 ) ) ;
t - > vertexUV ( ( float ) ( w ) , ( float ) ( 0 ) , ( float ) ( - 90 ) , ( float ) ( 1 ) , ( float ) ( 0 ) ) ;
t - > vertexUV ( ( float ) ( 0 ) , ( float ) ( 0 ) , ( float ) ( - 90 ) , ( float ) ( 0 ) , ( float ) ( 0 ) ) ;
t - > end ( ) ;
glDepthMask ( true ) ;
glEnable ( GL_DEPTH_TEST ) ;
glEnable ( GL_ALPHA_TEST ) ;
glColor4f ( 1 , 1 , 1 , 1 ) ;
}
2026-03-02 15:53:32 +07:00
2026-03-01 12:16:08 +08:00
void Gui : : renderVignette ( float br , int w , int h )
{
br = 1 - br ;
if ( br < 0 ) br = 0 ;
if ( br > 1 ) br = 1 ;
tbr + = ( br - tbr ) * 0.01f ;
#if 0 // 4J - removed - TODO put back when we have blend functions implemented
glDisable ( GL_DEPTH_TEST ) ;
glDepthMask ( false ) ;
glBlendFunc ( GL_ZERO , GL_ONE_MINUS_SRC_COLOR ) ;
glColor4f ( tbr , tbr , tbr , 1 ) ;
glBindTexture ( GL_TEXTURE_2D , minecraft - > textures - > loadTexture ( TN__BLUR__MISC_VIGNETTE ) ) ; //L"%blur%/misc/vignette.png"));
Tesselator * t = Tesselator : : getInstance ( ) ;
t - > begin ( ) ;
t - > vertexUV ( ( float ) ( 0 ) , ( float ) ( h ) , ( float ) ( - 90 ) , ( float ) ( 0 ) , ( float ) ( 1 ) ) ;
t - > vertexUV ( ( float ) ( w ) , ( float ) ( h ) , ( float ) ( - 90 ) , ( float ) ( 1 ) , ( float ) ( 1 ) ) ;
t - > vertexUV ( ( float ) ( w ) , ( float ) ( 0 ) , ( float ) ( - 90 ) , ( float ) ( 1 ) , ( float ) ( 0 ) ) ;
t - > vertexUV ( ( float ) ( 0 ) , ( float ) ( 0 ) , ( float ) ( - 90 ) , ( float ) ( 0 ) , ( float ) ( 0 ) ) ;
t - > end ( ) ;
glDepthMask ( true ) ;
glEnable ( GL_DEPTH_TEST ) ;
glColor4f ( 1 , 1 , 1 , 1 ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
# endif
}
void Gui : : renderTp ( float br , int w , int h )
{
if ( br < 1 )
{
br = br * br ;
br = br * br ;
br = br * 0.8f + 0.2f ;
}
glDisable ( GL_ALPHA_TEST ) ;
glDisable ( GL_DEPTH_TEST ) ;
glDepthMask ( false ) ;
glBlendFunc ( GL_SRC_ALPHA , GL_ONE_MINUS_SRC_ALPHA ) ;
glColor4f ( 1 , 1 , 1 , br ) ;
MemSect ( 31 ) ;
minecraft - > textures - > bindTexture ( TN_TERRAIN ) ; //L"/terrain.png"));
MemSect ( 0 ) ;
2026-03-02 15:53:32 +07:00
2026-03-01 12:16:08 +08:00
Icon * slot = Tile : : portalTile - > getTexture ( Facing : : UP ) ;
float u0 = slot - > getU0 ( ) ;
float v0 = slot - > getV0 ( ) ;
float u1 = slot - > getU1 ( ) ;
float v1 = slot - > getV1 ( ) ;
Tesselator * t = Tesselator : : getInstance ( ) ;
t - > begin ( ) ;
t - > vertexUV ( ( float ) ( 0 ) , ( float ) ( h ) , ( float ) ( - 90 ) , ( float ) ( u0 ) , ( float ) ( v1 ) ) ;
t - > vertexUV ( ( float ) ( w ) , ( float ) ( h ) , ( float ) ( - 90 ) , ( float ) ( u1 ) , ( float ) ( v1 ) ) ;
t - > vertexUV ( ( float ) ( w ) , ( float ) ( 0 ) , ( float ) ( - 90 ) , ( float ) ( u1 ) , ( float ) ( v0 ) ) ;
t - > vertexUV ( ( float ) ( 0 ) , ( float ) ( 0 ) , ( float ) ( - 90 ) , ( float ) ( u0 ) , ( float ) ( v0 ) ) ;
t - > end ( ) ;
glDepthMask ( true ) ;
glEnable ( GL_DEPTH_TEST ) ;
glEnable ( GL_ALPHA_TEST ) ;
glColor4f ( 1 , 1 , 1 , 1 ) ;
}
void Gui : : renderSlot ( int slot , int x , int y , float a )
{
2026-03-02 15:58:20 +07:00
std : : shared_ptr < ItemInstance > item = minecraft - > player - > inventory - > items [ slot ] ;
2026-03-01 12:16:08 +08:00
if ( item = = NULL ) return ;
float pop = item - > popTime - a ;
if ( pop > 0 )
{
glPushMatrix ( ) ;
float squeeze = 1 + pop / ( float ) Inventory : : POP_TIME_DURATION ;
glTranslatef ( ( float ) ( x + 8 ) , ( float ) ( y + 12 ) , 0 ) ;
glScalef ( 1 / squeeze , ( squeeze + 1 ) / 2 , 1 ) ;
glTranslatef ( ( float ) - ( x + 8 ) , ( float ) - ( y + 12 ) , 0 ) ;
}
itemRenderer - > renderAndDecorateItem ( minecraft - > font , minecraft - > textures , item , x , y ) ;
if ( pop > 0 )
{
glPopMatrix ( ) ;
}
itemRenderer - > renderGuiItemDecorations ( minecraft - > font , minecraft - > textures , item , x , y ) ;
}
void Gui : : tick ( )
{
if ( overlayMessageTime > 0 ) overlayMessageTime - - ;
tickCount + + ;
for ( int iPad = 0 ; iPad < XUSER_MAX_COUNT ; iPad + + )
2026-03-02 15:53:32 +07:00
{
2026-03-01 12:16:08 +08:00
// 4J Stu - Fix for #10929 - MP LAB: Network Disconnects: Host does not receive an error message stating the client left the game when viewing the Pause Menu.
// We don't show the guiMessages when a menu is up, so don't fade them out
if ( ! ui . GetMenuDisplayed ( iPad ) )
{
AUTO_VAR ( itEnd , guiMessages [ iPad ] . end ( ) ) ;
for ( AUTO_VAR ( it , guiMessages [ iPad ] . begin ( ) ) ; it ! = itEnd ; it + + )
{
( * it ) . ticks + + ;
}
}
}
}
void Gui : : clearMessages ( int iPad )
{
if ( iPad = = - 1 )
{
for ( int i = 0 ; i < XUSER_MAX_COUNT ; i + + )
{
if ( minecraft - > localplayers [ i ] )
{
guiMessages [ i ] . clear ( ) ;
}
2026-03-02 15:53:32 +07:00
}
2026-03-01 12:16:08 +08:00
}
else
{
guiMessages [ iPad ] . clear ( ) ;
}
}
void Gui : : addMessage ( const wstring & _string , int iPad , bool bIsDeathMessage )
{
wstring string = _string ; // 4J - Take copy of input as it is const
//int iScale=1;
//if((minecraft->player->m_iScreenSection==C4JRender::VIEWPORT_TYPE_SPLIT_TOP) ||
// (minecraft->player->m_iScreenSection==C4JRender::VIEWPORT_TYPE_SPLIT_BOTTOM))
//{
// iScale=2;
//}
// while (minecraft->font->width(string) > (m_iMaxMessageWidth*iScale))
//{
// unsigned int i = 1;
// while (i < string.length() && minecraft->font->width(string.substr(0, i + 1)) <= (m_iMaxMessageWidth*iScale))
// {
// i++;
// }
// int iLast=string.find_last_of(L" ",i);
// // if a space was found, include the space on this line
// if(iLast!=i)
// {
// iLast++;
// }
// addMessage(string.substr(0, iLast), iPad);
// string = string.substr(iLast);
// }
int maximumChars ;
switch ( minecraft - > player - > m_iScreenSection )
{
case C4JRender : : VIEWPORT_TYPE_SPLIT_TOP :
case C4JRender : : VIEWPORT_TYPE_SPLIT_BOTTOM :
case C4JRender : : VIEWPORT_TYPE_FULLSCREEN :
if ( RenderManager . IsHiDef ( ) )
{
maximumChars = 105 ;
}
else
{
maximumChars = 55 ;
}
# ifdef __PSVITA__
maximumChars = 90 ;
# endif
switch ( XGetLanguage ( ) )
{
case XC_LANGUAGE_JAPANESE :
case XC_LANGUAGE_TCHINESE :
case XC_LANGUAGE_KOREAN :
if ( RenderManager . IsHiDef ( ) )
{
maximumChars = 70 ;
}
else
{
maximumChars = 35 ;
}
# ifdef __PSVITA__
maximumChars = 55 ;
# endif
break ;
}
break ;
default :
maximumChars = 55 ;
switch ( XGetLanguage ( ) )
{
case XC_LANGUAGE_JAPANESE :
case XC_LANGUAGE_TCHINESE :
case XC_LANGUAGE_KOREAN :
maximumChars = 35 ;
break ;
}
break ;
}
while ( string . length ( ) > maximumChars )
{
unsigned int i = 1 ;
while ( i < string . length ( ) & & ( i + 1 ) < = maximumChars )
{
i + + ;
}
int iLast = ( int ) string . find_last_of ( L " " , i ) ;
switch ( XGetLanguage ( ) )
{
case XC_LANGUAGE_JAPANESE :
case XC_LANGUAGE_TCHINESE :
case XC_LANGUAGE_KOREAN :
iLast = maximumChars ;
break ;
default :
iLast = ( int ) string . find_last_of ( L " " , i ) ;
break ;
}
// if a space was found, include the space on this line
if ( iLast ! = i )
{
iLast + + ;
}
addMessage ( string . substr ( 0 , iLast ) , iPad , bIsDeathMessage ) ;
string = string . substr ( iLast ) ;
}
if ( iPad = = - 1 )
{
// add to all
for ( int i = 0 ; i < XUSER_MAX_COUNT ; i + + )
{
if ( minecraft - > localplayers [ i ] & & ! ( bIsDeathMessage & & app . GetGameSettings ( i , eGameSetting_DeathMessages ) = = 0 ) )
{
guiMessages [ i ] . insert ( guiMessages [ i ] . begin ( ) , GuiMessage ( string ) ) ;
while ( guiMessages [ i ] . size ( ) > 50 )
{
guiMessages [ i ] . pop_back ( ) ;
}
}
}
}
else if ( ! ( bIsDeathMessage & & app . GetGameSettings ( iPad , eGameSetting_DeathMessages ) = = 0 ) )
{
guiMessages [ iPad ] . insert ( guiMessages [ iPad ] . begin ( ) , GuiMessage ( string ) ) ;
while ( guiMessages [ iPad ] . size ( ) > 50 )
{
guiMessages [ iPad ] . pop_back ( ) ;
}
}
}
// 4J Added
float Gui : : getOpacity ( int iPad , DWORD index )
{
float opacityPercentage = 0 ;
if ( guiMessages [ iPad ] . size ( ) > index & & guiMessages [ iPad ] [ index ] . ticks < 20 * 10 )
{
double t = guiMessages [ iPad ] [ index ] . ticks / ( 20 * 10.0 ) ;
t = 1 - t ;
t = t * 10 ;
if ( t < 0 ) t = 0 ;
if ( t > 1 ) t = 1 ;
t = t * t ;
opacityPercentage = t ;
}
return opacityPercentage ;
}
float Gui : : getJukeboxOpacity ( int iPad )
{
float t = overlayMessageTime - lastTickA ;
int alpha = ( int ) ( t * 256 / 20 ) ;
if ( alpha > 255 ) alpha = 255 ;
alpha / = 255 ;
return alpha ;
}
void Gui : : setNowPlaying ( const wstring & string )
{
// overlayMessageString = L"Now playing: " + string;
overlayMessageString = app . GetString ( IDS_NOWPLAYING ) + string ;
overlayMessageTime = 20 * 3 ;
animateOverlayMessageColor = true ;
}
void Gui : : displayClientMessage ( int messageId , int iPad )
{
//Language *language = Language::getInstance();
wstring languageString = app . GetString ( messageId ) ; //language->getElement(messageId);
addMessage ( languageString , iPad ) ;
}
// 4J Added
2026-03-02 15:53:32 +07:00
void Gui : : renderGraph ( int dataLength , int dataPos , int64_t * dataA , float dataAScale , int dataAWarning , int64_t * dataB , float dataBScale , int dataBWarning )
2026-03-01 12:16:08 +08:00
{
int height = minecraft - > height ;
// This causes us to cover xScale*dataLength pixels in the horizontal
int xScale = 1 ;
if ( dataA ! = NULL & & dataB ! = NULL ) xScale = 2 ;
glClear ( GL_DEPTH_BUFFER_BIT ) ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
glOrtho ( 0 , ( float ) minecraft - > width , ( float ) height , 0 , 1000 , 3000 ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
glTranslatef ( 0 , 0 , - 2000 ) ;
glLineWidth ( 1 ) ;
glDisable ( GL_TEXTURE_2D ) ;
Tesselator * t = Tesselator : : getInstance ( ) ;
t - > begin ( GL_LINES ) ;
for ( int i = 0 ; i < dataLength ; i + + )
{
int col = ( ( i - dataPos ) & ( dataLength - 1 ) ) * 255 / dataLength ;
int cc = col * col / 255 ;
cc = cc * cc / 255 ;
int cc2 = cc * cc / 255 ;
cc2 = cc2 * cc2 / 255 ;
if ( dataA ! = NULL )
{
if ( dataA [ i ] > dataAWarning )
{
t - > color ( 0xff000000 + cc * 65536 ) ;
}
else
{
t - > color ( 0xff000000 + cc * 256 ) ;
}
2026-03-02 15:53:32 +07:00
int64_t aVal = dataA [ i ] / dataAScale ;
2026-03-01 12:16:08 +08:00
t - > vertex ( ( float ) ( xScale * i + 0.5f ) , ( float ) ( height - aVal + 0.5f ) , ( float ) ( 0 ) ) ;
t - > vertex ( ( float ) ( xScale * i + 0.5f ) , ( float ) ( height + 0.5f ) , ( float ) ( 0 ) ) ;
}
2026-03-02 15:53:32 +07:00
2026-03-01 12:16:08 +08:00
if ( dataB ! = NULL )
{
if ( dataB [ i ] > dataBWarning )
{
t - > color ( 0xff000000 + cc * 65536 + cc * 256 + cc * 1 ) ;
}
else
{
t - > color ( 0xff808080 + cc / 2 * 256 ) ;
}
2026-03-02 15:53:32 +07:00
int64_t bVal = dataB [ i ] / dataBScale ;
2026-03-01 12:16:08 +08:00
t - > vertex ( ( float ) ( xScale * i + ( xScale - 1 ) + 0.5f ) , ( float ) ( height - bVal + 0.5f ) , ( float ) ( 0 ) ) ;
t - > vertex ( ( float ) ( xScale * i + ( xScale - 1 ) + 0.5f ) , ( float ) ( height + 0.5f ) , ( float ) ( 0 ) ) ;
}
}
t - > end ( ) ;
glEnable ( GL_TEXTURE_2D ) ;
}
2026-03-02 15:53:32 +07:00
void Gui : : renderStackedGraph ( int dataPos , int dataLength , int dataSources , int64_t ( * func ) ( unsigned int dataPos , unsigned int dataSource ) )
2026-03-01 12:16:08 +08:00
{
int height = minecraft - > height ;
glClear ( GL_DEPTH_BUFFER_BIT ) ;
glMatrixMode ( GL_PROJECTION ) ;
glLoadIdentity ( ) ;
glOrtho ( 0 , ( float ) minecraft - > width , ( float ) height , 0 , 1000 , 3000 ) ;
glMatrixMode ( GL_MODELVIEW ) ;
glLoadIdentity ( ) ;
glTranslatef ( 0 , 0 , - 2000 ) ;
glLineWidth ( 1 ) ;
glDisable ( GL_TEXTURE_2D ) ;
Tesselator * t = Tesselator : : getInstance ( ) ;
t - > begin ( GL_LINES ) ;
2026-03-02 15:53:32 +07:00
int64_t thisVal = 0 ;
int64_t topVal = 0 ;
2026-03-01 12:16:08 +08:00
for ( int i = 0 ; i < dataLength ; i + + )
{
thisVal = 0 ;
topVal = 0 ;
int col = ( ( i - dataPos ) & ( dataLength - 1 ) ) * 255 / dataLength ;
int cc = col * col / 255 ;
cc = cc * cc / 255 ;
int cc2 = cc * cc / 255 ;
cc2 = cc2 * cc2 / 255 ;
for ( unsigned int source = 0 ; source < dataSources ; + + source )
{
thisVal = func ( i , source ) ;
if ( thisVal > 0 )
{
float vary = ( float ) source / dataSources ;
int fColour = floor ( vary * 0xffffff ) ;
int colour = 0xff000000 + fColour ;
//printf("Colour is %x\n", colour);
t - > color ( colour ) ;
t - > vertex ( ( float ) ( i + 0.5f ) , ( float ) ( height - topVal - thisVal + 0.5f ) , ( float ) ( 0 ) ) ;
t - > vertex ( ( float ) ( i + 0.5f ) , ( float ) ( height - topVal + 0.5f ) , ( float ) ( 0 ) ) ;
topVal + = thisVal ;
}
}
// Draw some horizontals
for ( unsigned int horiz = 1 ; horiz < 7 ; + + horiz )
{
t - > color ( 0xff000000 ) ;
t - > vertex ( ( float ) ( 0 + 0.5f ) , ( float ) ( height - ( horiz * 100 ) + 0.5f ) , ( float ) ( 0 ) ) ;
t - > vertex ( ( float ) ( dataLength + 0.5f ) , ( float ) ( height - ( horiz * 100 ) + 0.5f ) , ( float ) ( 0 ) ) ;
}
}
t - > end ( ) ;
glEnable ( GL_TEXTURE_2D ) ;
}