Files
MinecraftConsoles/Minecraft.Client/Gui.cpp
Loki Rautio 84c06dde72 Switch back to Iggy chat temporarily
Partially reverts changes in #682 that uses a better technique for rendering
the chat in favor of Iggy. We will need to go back once we update that
version for better visual parity with the Iggy chat rendering (position,
spacing, font size) but this works for now. Fixes #718
2026-03-06 12:54:28 -06:00

1581 lines
49 KiB
C++

#include "stdafx.h"
#include "Gui.h"
#include "ItemRenderer.h"
#include "GameRenderer.h"
#include "Options.h"
#include "MultiplayerLocalPlayer.h"
#include "Textures.h"
#include "TextureAtlas.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"
ResourceLocation Gui::PUMPKIN_BLUR_LOCATION = ResourceLocation(TN__BLUR__MISC_PUMPKINBLUR);
#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
// happens in split screen modes results in a final scaling of 1 rather than 1.5.
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,iSafezoneTopYHalf=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;
}
// 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%
iSafezoneTopYHalf = iSafezoneYHalf;
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;
iSafezoneTopYHalf = screenHeight/10;
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)
iSafezoneTopYHalf = 0;
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)
iSafezoneTopYHalf = screenHeight/10;
fScaleFactorHeight=0.5f;
iHeightOffset=screenHeight;
iTooltipsYOffset=44;
bTwoPlayerSplitscreen=true;
currentGuiScaleFactor *= 0.5f;
break;
case C4JRender::VIEWPORT_TYPE_SPLIT_RIGHT:
iSafezoneXHalf = 0;
iSafezoneYHalf = splitYOffset + screenHeight/10;// 5% (need to treat the whole screen is 2x this screen)
iSafezoneTopYHalf = splitYOffset + screenHeight/10;
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;
iSafezoneTopYHalf = screenHeight/10;
iTooltipsYOffset=44;
currentGuiScaleFactor *= 0.5f;
break;
case C4JRender::VIEWPORT_TYPE_QUADRANT_TOP_RIGHT:
iSafezoneXHalf = 0;
iSafezoneYHalf = splitYOffset; // 5%
iSafezoneTopYHalf = screenHeight/10;
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)
iSafezoneTopYHalf = 0;
iTooltipsYOffset=44;
currentGuiScaleFactor *= 0.5f;
break;
case C4JRender::VIEWPORT_TYPE_QUADRANT_BOTTOM_RIGHT:
iSafezoneXHalf = 0;
iSafezoneYHalf = splitYOffset + screenHeight/10; // 5% (the whole screen is 2x this screen)
iSafezoneTopYHalf = 0;
iTooltipsYOffset=44;
currentGuiScaleFactor *= 0.5f;
break;
}
// 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
if(app.GetGameSettings(iPad,eGameSetting_Tooltips)==0 && bDisplayGui)
{
switch(minecraft->player->m_iScreenSection)
{
case C4JRender::VIEWPORT_TYPE_FULLSCREEN:
iTooltipsYOffset=screenHeight/10;
break;
default:
//iTooltipsYOffset=screenHeight/10;
switch(guiScale)
{
case 3:
iTooltipsYOffset=28;//screenHeight/10;
break;
case 4:
iTooltipsYOffset=28;//screenHeight/10;
break;
default: // 2
iTooltipsYOffset=14;//screenHeight/10;
break;
}
break;
}
}
// 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);
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
if (Minecraft::useFancyGraphics())
{
renderVignette(minecraft->player->getBrightness(a), screenWidth, screenHeight);
}
/////////////////////////////////////////////////////////////////////////////////////
// Display the pumpkin screen effect
/////////////////////////////////////////////////////////////////////////////////////
shared_ptr<ItemInstance> headGear = minecraft->player->inventory->getArmor(3);
// 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
glPushMatrix();
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);
shared_ptr<Inventory> inventory = minecraft->player->inventory;
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
//glPushMatrix();
//glScalef(fScaleFactorWidth, fScaleFactorHeight, fScaleFactorWidth);
// 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();
// if (false) //(true)
// {
// renderBossHealth();
// }
/////////////////////////////////////////////////////////////////////////////////////
// Display the experience, food, armour, health and the air bubbles
/////////////////////////////////////////////////////////////////////////////////////
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;
}
double maxHealth = minecraft->localplayers[iPad]->getAttribute(SharedMonsterAttributes.MAX_HEALTH);
double totalAbsorption = minecraft->localplayers[iPad]->getAbsorptionAmount();
int numHealthRows = Mth.ceil((maxHealth + totalAbsorption) / 2 / (float) NUM_HEARTS_PER_ROW);
int healthRowHeight = Math.max(10 - (numHealthRows - 2), 3);
int yLine2 = yLine1 - (numHealthRows - 1) * healthRowHeight - 10;
absorption = totalAbsorption;
int armor = minecraft->player->getArmorValue();
int heartOffsetIndex = -1;
if (minecraft->player->hasEffect(MobEffect::regeneration))
{
heartOffsetIndex = tickCount % (int) ceil(maxHealth + 5);
}
// render health and armor
//minecraft.profiler.push("armor");
for (int i = 0; i < Player::MAX_HEALTH / 2; i++)
{
if (armor > 0)
{
int xo = xLeft + i * 8;
if (i * 2 + 1 < armor) blit(xo, yLine2, 16 + 2 * 9, 9, 9, 9);
if (i * 2 + 1 == armor) blit(xo, yLine2, 16 + 1 * 9, 9, 9, 9);
if (i * 2 + 1 > armor) blit(xo, yLine2, 16 + 0 * 9, 9, 9, 9);
}
}
//minecraft.profiler.popPush("health");
for (int i = Mth.ceil((maxHealth + totalAbsorption) / 2) - 1; i >= 0; i--)
{
int healthTexBaseX = 16;
if (minecraft.player.hasEffect(MobEffect.poison))
{
healthTexBaseX += 4 * 9;
}
else if (minecraft.player.hasEffect(MobEffect.wither))
{
healthTexBaseX += 8 * 9;
}
int bg = 0;
if (blink) bg = 1;
int rowIndex = Mth.ceil((i + 1) / (float) NUM_HEARTS_PER_ROW) - 1;
int xo = xLeft + (i % NUM_HEARTS_PER_ROW) * 8;
int yo = yLine1 - rowIndex * healthRowHeight;
if (currentHealth <= 4)
{
yo += random.nextInt(2);
}
if (i == heartOffsetIndex)
{
yo -= 2;
}
int y0 = 0;
// No hardcore on console
/*if (minecraft->level.getLevelData().isHardcore())
{
y0 = 5;
}*/
blit(xo, yo, 16 + bg * 9, 9 * y0, 9, 9);
if (blink)
{
if (i * 2 + 1 < oldHealth) blit(xo, yo, healthTexBaseX + 6 * 9, 9 * y0, 9, 9);
if (i * 2 + 1 == oldHealth) blit(xo, yo, healthTexBaseX + 7 * 9, 9 * y0, 9, 9);
}
if (absorption > 0)
{
if (absorption == totalAbsorption && totalAbsorption % 2 == 1)
{
blit(xo, yo, healthTexBaseX + 17 * 9, 9 * y0, 9, 9);
}
else
{
blit(xo, yo, healthTexBaseX + 16 * 9, 9 * y0, 9, 9);
}
absorption -= 2;
}
else
{
if (i * 2 + 1 < currentHealth) blit(xo, yo, healthTexBaseX + 4 * 9, 9 * y0, 9, 9);
if (i * 2 + 1 == currentHealth) blit(xo, yo, healthTexBaseX + 5 * 9, 9 * y0, 9, 9);
}
}
std::shared_ptr<Entity> riding = minecraft->localplayers[iPad].get()->riding;
std::shared_ptr<LivingEntity> living = dynamic_pointer_cast<LivingEntity>(riding);
if (riding == NULL)
{
// 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);
}
}
else if (living != nullptr)
{
// Render mount health
int riderCurrentHealth = (int) ceil(living.get()->GetHealth());
float maxRiderHealth = living->GetMaxHealth();
int hearts = (int) (maxRiderHealth + .5f) / 2;
if (hearts > 30)
{
hearts = 30;
}
int yo = yLine1;
int baseHealth = 0;
while (hearts > 0)
{
int rowHearts = min(hearts, 10);
hearts -= rowHearts;
for (int i = 0; i < rowHearts; i++)
{
int texBaseX = 52;
int bg = 0;
if (foodBlink) bg = 1;
int xo = xRight - i * 8 - 9;
blit(xo, yo, texBaseX + bg * 9, 9 * 1, 9, 9);
if (i * 2 + 1 + baseHealth < riderCurrentHealth) blit(xo, yo, texBaseX + 4 * 9, 9 * 1, 9, 9);
if (i * 2 + 1 + baseHealth == riderCurrentHealth) blit(xo, yo, texBaseX + 5 * 9, 9 * 1, 9, 9);
}
yo -= 10;
baseHealth += 20;
}
}
// 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();
int x,y;
for (int i = 0; i < 9; i++)
{
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;
}
else if( minecraft->player->abilities.flying)
{
characterDisplayTimer[iPad] = 5; // quickly get rid of the player display if they stop flying
}
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->crosshairPickMob, minecraft->options, a);
glEnable(GL_RESCALE_NORMAL);
glEnable(GL_COLOR_MATERIAL);
// 4J - TomK now using safe zone values directly instead of the magic number calculation that lived here before (which only worked for medium scale, the other two were off!)
int xo = iSafezoneXHalf + 10;
int yo = iSafezoneTopYHalf + 10;
#ifdef __PSVITA__
// align directly with corners, there are no safe zones on vita
xo = 10;
yo = 10;
#endif
glPushMatrix();
glTranslatef((float)xo, (float)yo, 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);
// 4J - TomK don't offset the player. it's easier to align it with the safe zones that way!
//glTranslatef(0, minecraft->player->heightOffset, 0);
glTranslatef(0, 0, 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;
}
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);
font->drawShadow(L"Seed: " + std::to_wstring(minecraft->level->getLevelData()->getSeed() ), iSafezoneXHalf+2, 32 + 00, 0xffffff);
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"[" + std::to_wstring( pFeatureData->x*16 ) + L", " + std::to_wstring( 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: " + std::to_wstring(minecraft->player->x) + L"/ Head: " + std::to_wstring(static_cast<int>(xBlockPos)) + L"/ Chunk: " + std::to_wstring(minecraft->player->xChunk), iSafezoneXHalf+2, iYPos + 8 * 0, 0xe0e0e0);
drawString(font, L"y: " + std::to_wstring(minecraft->player->y) + L"/ Head: " + std::to_wstring(static_cast<int>(yBlockPos)), iSafezoneXHalf+2, iYPos + 8 * 1, 0xe0e0e0);
drawString(font, L"z: " + std::to_wstring(minecraft->player->z) + L"/ Head: " + std::to_wstring(static_cast<int>(zBlockPos)) + L"/ Chunk: " + std::to_wstring(minecraft->player->zChunk), iSafezoneXHalf+2, iYPos + 8 * 2, 0xe0e0e0);
drawString(font, L"f: " + std::to_wstring(Mth::floor(minecraft->player->yRot * 4.0f / 360.0f + 0.5) & 0x3) + L"/ yRot: " + std::to_wstring(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" (" + std::to_wstring(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;
if (alpha > 0)
{
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
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);
#if 0 // defined(_WINDOWS64) // Temporarily disable this chat in favor of iggy chat until we have better visual parity
glPushMatrix();
glTranslatef(0.0f, static_cast<float>(screenHeight - iSafezoneYHalf - iTooltipsYOffset - 16 - 3 + 22) - 24.0f, 0.0f);
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 = static_cast<int>(255 * t);
if (isChatting) alpha = 255;
if (alpha > 0)
{
int x = iSafezoneXHalf+2;
int y = -(static_cast<int>(i)) * 9;
if(bTwoPlayerSplitscreen)
{
y+= iHeightOffset;
}
wstring msg = guiMessages[iPad][i].string;
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;
//
// shared_ptr<EnderDragon> boss = EnderDragonRenderer::bossInstance;
// EnderDragonRenderer::bossInstance = NULL;
//
// Minecraft *pMinecraft=Minecraft::GetInstance();
//
// Font *font = pMinecraft->font;
//
// ScreenSizeCalculator ssc(pMinecraft->options, pMinecraft->width_phys, pMinecraft->height_phys);
// int screenWidth = ssc.getWidth();
//
// int w = 182;
// int xLeft = screenWidth / 2 - w / 2;
//
// int progress = (int) (boss->getSynchedHealth() / (float) boss->getMaxHealth() * (float) (w + 1));
//
// int yo = 12;
// blit(xLeft, yo, 0, 74, w, 5);
// blit(xLeft, yo, 0, 74, w, 5);
// if (progress > 0)
// {
// blit(xLeft, yo, 0, 79, progress, 5);
// }
//
// 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"));
//
// }
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(&PUMPKIN_BLUR_LOCATION);
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);
}
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(&TextureAtlas::LOCATION_BLOCKS);
MemSect(0);
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)
{
shared_ptr<ItemInstance> item = minecraft->player->inventory->items[slot];
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++)
{
// 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))
{
for (auto& it : guiMessages[iPad])
{
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();
}
}
}
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
void Gui::renderGraph(int dataLength, int dataPos, __int64 *dataA, float dataAScale, int dataAWarning, __int64 *dataB, float dataBScale, int dataBWarning)
{
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);
}
__int64 aVal = dataA[i] / dataAScale;
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));
}
if( dataB != NULL )
{
if (dataB[i]>dataBWarning)
{
t->color(0xff000000 + cc * 65536 + cc * 256 + cc * 1);
}
else
{
t->color(0xff808080 + cc/2 * 256);
}
__int64 bVal = dataB[i] / dataBScale;
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);
}
void Gui::renderStackedGraph(int dataPos, int dataLength, int dataSources, __int64 (*func)(unsigned int dataPos, unsigned int dataSource) )
{
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);
__int64 thisVal = 0;
__int64 topVal = 0;
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);
}