Merge branch 'smartcmd:main' into main

This commit is contained in:
disintegrate 2026-03-24 15:45:46 +08:00 committed by GitHub
commit 464d6c7ec8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
28 changed files with 439 additions and 274 deletions

View file

@ -4036,6 +4036,8 @@ void ClientConnection::handleSetPlayerTeamPacket(shared_ptr<SetPlayerTeamPacket>
void ClientConnection::handleParticleEvent(shared_ptr<LevelParticlesPacket> packet) void ClientConnection::handleParticleEvent(shared_ptr<LevelParticlesPacket> packet)
{ {
ePARTICLE_TYPE particleId = (ePARTICLE_TYPE)Integer::parseInt(packet->getName());
for (int i = 0; i < packet->getCount(); i++) for (int i = 0; i < packet->getCount(); i++)
{ {
double xVarience = random->nextGaussian() * packet->getXDist(); double xVarience = random->nextGaussian() * packet->getXDist();
@ -4045,10 +4047,6 @@ void ClientConnection::handleParticleEvent(shared_ptr<LevelParticlesPacket> pack
double ya = random->nextGaussian() * packet->getMaxSpeed(); double ya = random->nextGaussian() * packet->getMaxSpeed();
double za = random->nextGaussian() * packet->getMaxSpeed(); double za = random->nextGaussian() * packet->getMaxSpeed();
// TODO: determine particle ID from name
assert(0);
ePARTICLE_TYPE particleId = eParticleType_heart;
level->addParticle(particleId, packet->getX() + xVarience, packet->getY() + yVarience, packet->getZ() + zVarience, xa, ya, za); level->addParticle(particleId, packet->getX() + xVarience, packet->getY() + yVarience, packet->getZ() + zVarience, xa, ya, za);
} }
} }

View file

@ -9,6 +9,7 @@
#include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.entity.h" #include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.entity.h"
#include "..\..\MultiplayerLocalPlayer.h" #include "..\..\MultiplayerLocalPlayer.h"
#include "..\..\Minecraft.h" #include "..\..\Minecraft.h"
#include "..\..\Options.h"
#ifdef __ORBIS__ #ifdef __ORBIS__
#include <pad.h> #include <pad.h>
@ -16,8 +17,6 @@
#ifdef _WINDOWS64 #ifdef _WINDOWS64
#include "..\..\Windows64\KeyboardMouseInput.h" #include "..\..\Windows64\KeyboardMouseInput.h"
SavedInventoryCursorPos g_savedInventoryCursorPos = { 0.0f, 0.0f, false };
#endif #endif
IUIScene_AbstractContainerMenu::IUIScene_AbstractContainerMenu() IUIScene_AbstractContainerMenu::IUIScene_AbstractContainerMenu()
@ -1677,7 +1676,13 @@ vector<HtmlString> *IUIScene_AbstractContainerMenu::GetItemDescription(Slot *slo
{ {
if(slot == nullptr) return nullptr; if(slot == nullptr) return nullptr;
vector<HtmlString> *lines = slot->getItem()->getHoverText(nullptr, false); bool advanced = false;
if (const Minecraft* pMinecraft = Minecraft::GetInstance())
{
if (pMinecraft->options)
advanced = pMinecraft->options->advancedTooltips;
}
vector<HtmlString> *lines = slot->getItem()->getHoverText(nullptr, advanced);
// Add rarity to first line // Add rarity to first line
if (lines->size() > 0) if (lines->size() > 0)

View file

@ -1,15 +1,5 @@
#pragma once #pragma once
#ifdef _WINDOWS64
struct SavedInventoryCursorPos
{
float x;
float y;
bool hasSavedPos;
};
extern SavedInventoryCursorPos g_savedInventoryCursorPos;
#endif
// Uncomment to enable tap input detection to jump 1 slot. Doesn't work particularly well yet, and I feel the system does not need it. // Uncomment to enable tap input detection to jump 1 slot. Doesn't work particularly well yet, and I feel the system does not need it.
// Would probably be required if we decide to slow down the pointer movement. // Would probably be required if we decide to slow down the pointer movement.
// 4J Stu - There was a request to be able to navigate the scenes with the dpad, so I have used much of the TAP_DETECTION // 4J Stu - There was a request to be able to navigate the scenes with the dpad, so I have used much of the TAP_DETECTION

View file

@ -20,9 +20,9 @@ protected:
eGroupTab_Right eGroupTab_Right
}; };
static const int m_iMaxHSlotC = 12; static const int m_iMaxHSlotC = 40;
static const int m_iMaxHCraftingSlotC = 10; static const int m_iMaxHCraftingSlotC = 40;
static const int m_iMaxVSlotC = 17; static const int m_iMaxVSlotC = 99;
static const int m_iMaxDisplayedVSlotC = 3; static const int m_iMaxDisplayedVSlotC = 3;
static const int m_iIngredients3x3SlotC = 9; static const int m_iIngredients3x3SlotC = 9;
static const int m_iIngredients2x2SlotC = 4; static const int m_iIngredients2x2SlotC = 4;

View file

@ -4,6 +4,7 @@
#include "..\..\..\Minecraft.World\net.minecraft.world.item.h" #include "..\..\..\Minecraft.World\net.minecraft.world.item.h"
#include "..\..\..\Minecraft.World\net.minecraft.network.packet.h" #include "..\..\..\Minecraft.World\net.minecraft.network.packet.h"
#include "..\..\Minecraft.h" #include "..\..\Minecraft.h"
#include "..\..\Options.h"
#include "..\..\MultiPlayerLocalPlayer.h" #include "..\..\MultiPlayerLocalPlayer.h"
#include "..\..\ClientConnection.h" #include "..\..\ClientConnection.h"
#include "IUIScene_TradingMenu.h" #include "IUIScene_TradingMenu.h"
@ -368,7 +369,13 @@ void IUIScene_TradingMenu::setTradeItem(int index, shared_ptr<ItemInstance> item
vector<HtmlString> *IUIScene_TradingMenu::GetItemDescription(shared_ptr<ItemInstance> item) vector<HtmlString> *IUIScene_TradingMenu::GetItemDescription(shared_ptr<ItemInstance> item)
{ {
vector<HtmlString> *lines = item->getHoverText(nullptr, false); bool advanced = false;
if (const Minecraft* pMinecraft = Minecraft::GetInstance())
{
if (pMinecraft->options)
advanced = pMinecraft->options->advancedTooltips;
}
vector<HtmlString> *lines = item->getHoverText(nullptr, advanced);
// Add rarity to first line // Add rarity to first line
if (lines->size() > 0) if (lines->size() > 0)

View file

@ -1,6 +1,7 @@
#include "stdafx.h" #include "stdafx.h"
#include "UI.h" #include "UI.h"
#include "UIControl_TextInput.h" #include "UIControl_TextInput.h"
#include "..\..\Screen.h"
UIControl_TextInput::UIControl_TextInput() UIControl_TextInput::UIControl_TextInput()
{ {
@ -211,6 +212,31 @@ UIControl_TextInput::EDirectEditResult UIControl_TextInput::tickDirectEdit()
} }
} }
// Paste from clipboard
if (g_KBMInput.IsKeyPressed('V') && g_KBMInput.IsKeyDown(VK_CONTROL))
{
wstring pasted = Screen::getClipboard();
wstring sanitized;
sanitized.reserve(pasted.length());
for (wchar_t pc : pasted)
{
if (pc >= 0x20) // Keep printable characters
{
if (m_iCharLimit > 0 && (m_editBuffer.length() + sanitized.length()) >= (size_t)m_iCharLimit)
break;
sanitized += pc;
}
}
if (!sanitized.empty())
{
m_editBuffer.insert(m_iCursorPos, sanitized);
m_iCursorPos += (int)sanitized.length();
changed = true;
}
}
// Arrow keys, Home, End, Delete for cursor movement // Arrow keys, Home, End, Delete for cursor movement
if (g_KBMInput.IsKeyPressed(VK_LEFT) && m_iCursorPos > 0) if (g_KBMInput.IsKeyPressed(VK_LEFT) && m_iCursorPos > 0)
{ {

View file

@ -41,10 +41,6 @@ void UIScene_AbstractContainerMenu::handleDestroy()
app.DebugPrintf("UIScene_AbstractContainerMenu::handleDestroy\n"); app.DebugPrintf("UIScene_AbstractContainerMenu::handleDestroy\n");
#ifdef _WINDOWS64 #ifdef _WINDOWS64
g_savedInventoryCursorPos.x = m_pointerPos.x;
g_savedInventoryCursorPos.y = m_pointerPos.y;
g_savedInventoryCursorPos.hasSavedPos = true;
g_KBMInput.SetScreenCursorHidden(false); g_KBMInput.SetScreenCursorHidden(false);
g_KBMInput.SetCursorHiddenForUI(false); g_KBMInput.SetCursorHiddenForUI(false);
#endif #endif
@ -173,16 +169,16 @@ void UIScene_AbstractContainerMenu::PlatformInitialize(int iPad, int startIndex)
m_pointerPos = vPointerPos; m_pointerPos = vPointerPos;
#ifdef _WINDOWS64 #ifdef _WINDOWS64
if (g_savedInventoryCursorPos.hasSavedPos) if ((iPad == 0) && g_KBMInput.IsKBMActive())
{ {
m_pointerPos.x = g_savedInventoryCursorPos.x; m_pointerPos.x = ((m_fPanelMinX + m_fPanelMaxX) * 0.5f) - m_fPointerImageOffsetX;
m_pointerPos.y = g_savedInventoryCursorPos.y; m_pointerPos.y = ((m_fPanelMinY + m_fPanelMaxY) * 0.5f) - m_fPointerImageOffsetY;
if (m_pointerPos.x < m_fPointerMinX) m_pointerPos.x = m_fPointerMinX;
if (m_pointerPos.x > m_fPointerMaxX) m_pointerPos.x = m_fPointerMaxX;
if (m_pointerPos.y < m_fPointerMinY) m_pointerPos.y = m_fPointerMinY;
if (m_pointerPos.y > m_fPointerMaxY) m_pointerPos.y = m_fPointerMaxY;
} }
if (m_pointerPos.x < m_fPointerMinX) m_pointerPos.x = m_fPointerMinX;
if (m_pointerPos.x > m_fPointerMaxX) m_pointerPos.x = m_fPointerMaxX;
if (m_pointerPos.y < m_fPointerMinY) m_pointerPos.y = m_fPointerMinY;
if (m_pointerPos.y > m_fPointerMaxY) m_pointerPos.y = m_fPointerMaxY;
#endif #endif
IggyEvent mouseEvent; IggyEvent mouseEvent;

View file

@ -1,6 +1,7 @@
#include "stdafx.h" #include "stdafx.h"
#include "UI.h" #include "UI.h"
#include "UIScene_Keyboard.h" #include "UIScene_Keyboard.h"
#include "..\..\Screen.h"
#ifdef _WINDOWS64 #ifdef _WINDOWS64
// Global buffer that stores the text entered in the native keyboard scene. // Global buffer that stores the text entered in the native keyboard scene.
@ -224,6 +225,38 @@ void UIScene_Keyboard::tick()
} }
} }
// Paste from clipboard
if (g_KBMInput.IsKeyPressed('V') && g_KBMInput.IsKeyDown(VK_CONTROL))
{
wstring pasted = Screen::getClipboard();
wstring sanitized;
sanitized.reserve(pasted.length());
for (wchar_t pc : pasted)
{
if (pc >= 0x20) // Keep printable characters
{
if (static_cast<int>(m_win64TextBuffer.length() + sanitized.length()) >= m_win64MaxChars)
break;
sanitized += pc;
}
}
if (!sanitized.empty())
{
if (m_bPCMode)
{
m_win64TextBuffer.insert(m_iCursorPos, sanitized);
m_iCursorPos += (int)sanitized.length();
}
else
{
m_win64TextBuffer += sanitized;
}
changed = true;
}
}
if (m_bPCMode) if (m_bPCMode)
{ {
// Arrow keys, Home, End, Delete for cursor movement // Arrow keys, Home, End, Delete for cursor movement

View file

@ -222,9 +222,8 @@ void UIScene_SettingsGraphicsMenu::handleSliderMove(F64 sliderId, F64 currentVal
const int fovValue = sliderValueToFov(value); const int fovValue = sliderValueToFov(value);
pMinecraft->gameRenderer->SetFovVal(static_cast<float>(fovValue)); pMinecraft->gameRenderer->SetFovVal(static_cast<float>(fovValue));
app.SetGameSettings(m_iPad, eGameSetting_FOV, value); app.SetGameSettings(m_iPad, eGameSetting_FOV, value);
WCHAR tempString[256]; swprintf(TempString, 256, L"FOV: %d", fovValue);
swprintf(tempString, 256, L"FOV: %d", fovValue); m_sliderFOV.setLabel(TempString);
m_sliderFOV.setLabel(tempString);
} }
break; break;

View file

@ -45,46 +45,46 @@ Font::Font(Options *options, const wstring& name, Textures* textures, bool enfor
random = new Random(); random = new Random();
// Load the image // Load the image
BufferedImage *img = textures->readImage(textureLocation->getTexture(), name); BufferedImage *img = textures->readImage(textureLocation->getTexture(), name);
/* - 4J - TODO /* - 4J - TODO
try { try {
img = ImageIO.read(Textures.class.getResourceAsStream(name)); img = ImageIO.read(Textures.class.getResourceAsStream(name));
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
*/ */
int w = img->getWidth(); int w = img->getWidth();
int h = img->getHeight(); int h = img->getHeight();
intArray rawPixels(w * h); intArray rawPixels(w * h);
img->getRGB(0, 0, w, h, rawPixels, 0, w); img->getRGB(0, 0, w, h, rawPixels, 0, w);
for (int i = 0; i < charC; i++) for (int i = 0; i < charC; i++)
{ {
int xt = i % m_cols; int xt = i % m_cols;
int yt = i / m_cols; int yt = i / m_cols;
int x = 7; int x = 7;
for (; x >= 0; x--) for (; x >= 0; x--)
{ {
int xPixel = xt * 8 + x; int xPixel = xt * 8 + x;
bool emptyColumn = true; bool emptyColumn = true;
for (int y = 0; y < 8 && emptyColumn; y++) for (int y = 0; y < 8 && emptyColumn; y++)
{ {
int yPixel = (yt * 8 + y) * w; int yPixel = (yt * 8 + y) * w;
bool emptyPixel = (rawPixels[xPixel + yPixel] >> 24) == 0; // Check the alpha value bool emptyPixel = (rawPixels[xPixel + yPixel] >> 24) == 0; // Check the alpha value
if (!emptyPixel) emptyColumn = false; if (!emptyPixel) emptyColumn = false;
} }
if (!emptyColumn) if (!emptyColumn)
{ {
break; break;
} }
} }
if (i == ' ') x = 4 - 2; if (i == ' ') x = 4 - 2;
charWidths[i] = x + 2; charWidths[i] = x + 2;
} }
delete img; delete img;
@ -130,6 +130,7 @@ Font::~Font()
} }
#endif #endif
// Legacy helper used by renderCharacter() only.
void Font::renderStyleLine(float x0, float y0, float x1, float y1) void Font::renderStyleLine(float x0, float y0, float x1, float y1)
{ {
Tesselator* t = Tesselator::getInstance(); Tesselator* t = Tesselator::getInstance();
@ -146,7 +147,20 @@ void Font::renderStyleLine(float x0, float y0, float x1, float y1)
t->end(); t->end();
} }
void Font::addCharacterQuad(wchar_t c) void Font::addSolidQuad(float x0, float y0, float x1, float y1)
{
Tesselator *t = Tesselator::getInstance();
t->tex(0.0f, 0.0f);
t->vertex(x0, y1, 0.0f);
t->tex(0.0f, 0.0f);
t->vertex(x1, y1, 0.0f);
t->tex(0.0f, 0.0f);
t->vertex(x1, y0, 0.0f);
t->tex(0.0f, 0.0f);
t->vertex(x0, y0, 0.0f);
}
void Font::emitCharacterGeometry(wchar_t c)
{ {
float xOff = c % m_cols * m_charWidth; float xOff = c % m_cols * m_charWidth;
float yOff = c / m_cols * m_charHeight; // was m_charWidth — wrong when glyphs aren't square float yOff = c / m_cols * m_charHeight; // was m_charWidth — wrong when glyphs aren't square
@ -180,52 +194,45 @@ void Font::addCharacterQuad(wchar_t c)
t->tex(xOff / fontWidth, yOff / fontHeight); t->tex(xOff / fontWidth, yOff / fontHeight);
t->vertex(x0 + dx, y0, 0.0f); t->vertex(x0 + dx, y0, 0.0f);
} }
xPos += static_cast<float>(charWidths[c]);
} }
void Font::addCharacterQuad(wchar_t c)
{
float height = m_charHeight - .01f;
float x0 = xPos;
float y0 = yPos;
float y1 = yPos + height;
float advance = static_cast<float>(charWidths[c]);
emitCharacterGeometry(c);
if (m_underline)
{
addSolidQuad(x0, y1 - 1.0f, xPos + advance, y1);
}
if (m_strikethrough)
{
float mid = y0 + height * 0.5f;
addSolidQuad(x0, mid - 0.5f, xPos + advance, mid + 0.5f);
}
xPos += advance;
}
// Legacy helper used by drawLiteral() only.
void Font::renderCharacter(wchar_t c) void Font::renderCharacter(wchar_t c)
{ {
float xOff = c % m_cols * m_charWidth;
float yOff = c / m_cols * m_charHeight; // was m_charWidth — wrong when glyphs aren't square
float width = charWidths[c] - .01f;
float height = m_charHeight - .01f; float height = m_charHeight - .01f;
float x0 = xPos;
float fontWidth = m_cols * m_charWidth; float y0 = yPos;
float fontHeight = m_rows * m_charHeight; float y1 = yPos + height;
const float shear = m_italic ? (height * 0.25f) : 0.0f;
float x0 = xPos, x1 = xPos + width + shear;
float y0 = yPos, y1 = yPos + height;
Tesselator *t = Tesselator::getInstance(); Tesselator *t = Tesselator::getInstance();
t->begin(); t->begin();
t->tex(xOff / fontWidth, (yOff + 7.99f) / fontHeight); emitCharacterGeometry(c);
t->vertex(x0, y1, 0.0f);
t->tex((xOff + width) / fontWidth, (yOff + 7.99f) / fontHeight);
t->vertex(x1, y1, 0.0f);
t->tex((xOff + width) / fontWidth, yOff / fontHeight);
t->vertex(x1, y0, 0.0f);
t->tex(xOff / fontWidth, yOff / fontHeight);
t->vertex(x0, y0, 0.0f);
t->end(); t->end();
if (m_bold)
{
float dx = 1.0f;
t->begin();
t->tex(xOff / fontWidth, (yOff + 7.99f) / fontHeight);
t->vertex(x0 + dx, y1, 0.0f);
t->tex((xOff + width) / fontWidth, (yOff + 7.99f) / fontHeight);
t->vertex(x1 + dx, y1, 0.0f);
t->tex((xOff + width) / fontWidth, yOff / fontHeight);
t->vertex(x1 + dx, y0, 0.0f);
t->tex(xOff / fontWidth, yOff / fontHeight);
t->vertex(x0 + dx, y0, 0.0f);
t->end();
}
if (m_underline) if (m_underline)
renderStyleLine(x0, y1 - 1.0f, xPos + static_cast<float>(charWidths[c]), y1); renderStyleLine(x0, y1 - 1.0f, xPos + static_cast<float>(charWidths[c]), y1);
@ -240,8 +247,8 @@ void Font::renderCharacter(wchar_t c)
void Font::drawShadow(const wstring& str, int x, int y, int color) void Font::drawShadow(const wstring& str, int x, int y, int color)
{ {
draw(str, x + 1, y + 1, color, true); draw(str, x + 1, y + 1, color, true);
draw(str, x, y, color, false); draw(str, x, y, color, false);
} }
void Font::drawShadowLiteral(const wstring& str, int x, int y, int color) void Font::drawShadowLiteral(const wstring& str, int x, int y, int color)
@ -289,7 +296,7 @@ static bool isSectionFormatCode(wchar_t ca)
return l == L'l' || l == L'o' || l == L'n' || l == L'm' || l == L'r' || l == L'k'; return l == L'l' || l == L'o' || l == L'n' || l == L'm' || l == L'r' || l == L'k';
} }
void Font::draw(const wstring &str, bool dropShadow) void Font::draw(const wstring &str, bool dropShadow, int initialColor)
{ {
// Bind the texture // Bind the texture
textures->bindTexture(m_textureLocation); textures->bindTexture(m_textureLocation);
@ -297,8 +304,11 @@ void Font::draw(const wstring &str, bool dropShadow)
m_bold = m_italic = m_underline = m_strikethrough = false; m_bold = m_italic = m_underline = m_strikethrough = false;
wstring cleanStr = sanitize(str); wstring cleanStr = sanitize(str);
int currentColor = initialColor;
Tesselator *t = Tesselator::getInstance(); Tesselator *t = Tesselator::getInstance();
t->begin(); t->begin();
t->color(currentColor & 0x00ffffff, (currentColor >> 24) & 255);
for (int i = 0; i < static_cast<int>(cleanStr.length()); ++i) for (int i = 0; i < static_cast<int>(cleanStr.length()); ++i)
{ {
@ -310,10 +320,8 @@ void Font::draw(const wstring &str, bool dropShadow)
wchar_t ca = cleanStr[i+1]; wchar_t ca = cleanStr[i+1];
if (!isSectionFormatCode(ca)) if (!isSectionFormatCode(ca))
{ {
t->end(); addCharacterQuad(167);
renderCharacter(167); addCharacterQuad(ca);
renderCharacter(ca);
t->begin();
i += 1; i += 1;
continue; continue;
} }
@ -329,7 +337,12 @@ void Font::draw(const wstring &str, bool dropShadow)
else if (l == L'o') m_italic = true; else if (l == L'o') m_italic = true;
else if (l == L'n') m_underline = true; else if (l == L'n') m_underline = true;
else if (l == L'm') m_strikethrough = true; else if (l == L'm') m_strikethrough = true;
else if (l == L'r') m_bold = m_italic = m_underline = m_strikethrough = noise = false; else if (l == L'r')
{
m_bold = m_italic = m_underline = m_strikethrough = noise = false;
currentColor = initialColor;
t->color(currentColor & 0x00ffffff, (currentColor >> 24) & 255);
}
else if (l == L'k') noise = true; else if (l == L'k') noise = true;
} }
else else
@ -337,8 +350,8 @@ void Font::draw(const wstring &str, bool dropShadow)
noise = false; noise = false;
if (colorN < 0 || colorN > 15) colorN = 15; if (colorN < 0 || colorN > 15) colorN = 15;
if (dropShadow) colorN += 16; if (dropShadow) colorN += 16;
int color = colors[colorN]; currentColor = (initialColor & 0xff000000) | colors[colorN];
glColor3f((color >> 16) / 255.0F, ((color >> 8) & 255) / 255.0F, (color & 255) / 255.0F); t->color(currentColor & 0x00ffffff, (currentColor >> 24) & 255);
} }
i += 1; i += 1;
continue; continue;
@ -371,11 +384,11 @@ void Font::draw(const wstring& str, int x, int y, int color, bool dropShadow)
if (dropShadow) // divide RGB by 4, preserve alpha if (dropShadow) // divide RGB by 4, preserve alpha
color = (color & 0xfcfcfc) >> 2 | (color & (-1 << 24)); color = (color & 0xfcfcfc) >> 2 | (color & (-1 << 24));
glColor4f((color >> 16 & 255) / 255.0F, (color >> 8 & 255) / 255.0F, (color & 255) / 255.0F, (color >> 24 & 255) / 255.0F); glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
xPos = x; xPos = x;
yPos = y; yPos = y;
draw(str, dropShadow); draw(str, dropShadow, color);
} }
} }
@ -422,9 +435,9 @@ wstring Font::sanitize(const wstring& str)
{ {
wstring sb = str; wstring sb = str;
for (unsigned int i = 0; i < sb.length(); i++) for (unsigned int i = 0; i < sb.length(); i++)
{ {
if (CharacterExists(sb[i])) if (CharacterExists(sb[i]))
{ {
sb[i] = MapCharacter(sb[i]); sb[i] = MapCharacter(sb[i]);
} }
@ -433,8 +446,8 @@ wstring Font::sanitize(const wstring& str)
// If this character isn't supported, just show the first character (empty square box character) // If this character isn't supported, just show the first character (empty square box character)
sb[i] = 0; sb[i] = 0;
} }
} }
return sb; return sb;
} }
int Font::MapCharacter(wchar_t c) int Font::MapCharacter(wchar_t c)
@ -487,95 +500,95 @@ void Font::drawWordWrap(const wstring &string, int x, int y, int w, int col, boo
void Font::drawWordWrapInternal(const wstring& string, int x, int y, int w, int col, bool darken, int h) void Font::drawWordWrapInternal(const wstring& string, int x, int y, int w, int col, bool darken, int h)
{ {
vector<wstring>lines = stringSplit(string,L'\n'); vector<wstring>lines = stringSplit(string,L'\n');
if (lines.size() > 1) if (lines.size() > 1)
{ {
for ( auto& it : lines ) for ( auto& it : lines )
{ {
// 4J Stu - Don't draw text that will be partially cutoff/overlap something it shouldn't // 4J Stu - Don't draw text that will be partially cutoff/overlap something it shouldn't
if( (y + this->wordWrapHeight(it, w)) > h) break; if( (y + this->wordWrapHeight(it, w)) > h) break;
drawWordWrapInternal(it, x, y, w, col, h); drawWordWrapInternal(it, x, y, w, col, h);
y += this->wordWrapHeight(it, w); y += this->wordWrapHeight(it, w);
} }
return; return;
} }
vector<wstring> words = stringSplit(string,L' '); vector<wstring> words = stringSplit(string,L' ');
unsigned int pos = 0; unsigned int pos = 0;
while (pos < words.size()) while (pos < words.size())
{ {
wstring line = words[pos++] + L" "; wstring line = words[pos++] + L" ";
while (pos < words.size() && width(line + words[pos]) < w) while (pos < words.size() && width(line + words[pos]) < w)
{ {
line += words[pos++] + L" "; line += words[pos++] + L" ";
} }
while (width(line) > w) while (width(line) > w)
{ {
int l = 0; int l = 0;
while (width(line.substr(0, l + 1)) <= w) while (width(line.substr(0, l + 1)) <= w)
{ {
l++; l++;
} }
if (trimString(line.substr(0, l)).length() > 0) if (trimString(line.substr(0, l)).length() > 0)
{ {
draw(line.substr(0, l), x, y, col); draw(line.substr(0, l), x, y, col);
y += 8; y += 8;
} }
line = line.substr(l); line = line.substr(l);
// 4J Stu - Don't draw text that will be partially cutoff/overlap something it shouldn't // 4J Stu - Don't draw text that will be partially cutoff/overlap something it shouldn't
if( (y + 8) > h) break; if( (y + 8) > h) break;
} }
// 4J Stu - Don't draw text that will be partially cutoff/overlap something it shouldn't // 4J Stu - Don't draw text that will be partially cutoff/overlap something it shouldn't
if (trimString(line).length() > 0 && !( (y + 8) > h) ) if (trimString(line).length() > 0 && !( (y + 8) > h) )
{ {
draw(line, x, y, col); draw(line, x, y, col);
y += 8; y += 8;
} }
} }
} }
int Font::wordWrapHeight(const wstring& string, int w) int Font::wordWrapHeight(const wstring& string, int w)
{ {
vector<wstring> lines = stringSplit(string,L'\n'); vector<wstring> lines = stringSplit(string,L'\n');
if (lines.size() > 1) if (lines.size() > 1)
{ {
int h = 0; int h = 0;
for ( auto& it : lines ) for ( auto& it : lines )
{ {
h += this->wordWrapHeight(it, w); h += this->wordWrapHeight(it, w);
} }
return h; return h;
} }
vector<wstring> words = stringSplit(string,L' '); vector<wstring> words = stringSplit(string,L' ');
unsigned int pos = 0; unsigned int pos = 0;
int y = 0; int y = 0;
while (pos < words.size()) while (pos < words.size())
{ {
wstring line = words[pos++] + L" "; wstring line = words[pos++] + L" ";
while (pos < words.size() && width(line + words[pos]) < w) while (pos < words.size() && width(line + words[pos]) < w)
{ {
line += words[pos++] + L" "; line += words[pos++] + L" ";
} }
while (width(line) > w) while (width(line) > w)
{ {
int l = 0; int l = 0;
while (width(line.substr(0, l + 1)) <= w) while (width(line.substr(0, l + 1)) <= w)
{ {
l++; l++;
} }
if (trimString(line.substr(0, l)).length() > 0) if (trimString(line.substr(0, l)).length() > 0)
{ {
y += 8; y += 8;
} }
line = line.substr(l); line = line.substr(l);
} }
if (trimString(line).length() > 0) { if (trimString(line).length() > 0) {
y += 8; y += 8;
} }
} }
if (y < 8) y += 8; if (y < 8) y += 8;
return y; return y;
} }

View file

@ -38,7 +38,7 @@ private:
std::map<int, int> m_charMap; std::map<int, int> m_charMap;
public: public:
Font(Options *options, const wstring& name, Textures* textures, bool enforceUnicode, ResourceLocation *textureLocation, int cols, int rows, int charWidth, int charHeight, unsigned short charMap[] = nullptr); Font(Options *options, const wstring& name, Textures* textures, bool enforceUnicode, ResourceLocation *textureLocation, int cols, int rows, int charWidth, int charHeight, unsigned short charMap[] = nullptr);
#ifndef _XBOX #ifndef _XBOX
// 4J Stu - This dtor clashes with one in xui! We never delete these anyway so take it out for now. Can go back when we have got rid of XUI // 4J Stu - This dtor clashes with one in xui! We never delete these anyway so take it out for now. Can go back when we have got rid of XUI
~Font(); ~Font();
@ -48,6 +48,8 @@ public:
private: private:
void renderCharacter(wchar_t c); // 4J added void renderCharacter(wchar_t c); // 4J added
void addCharacterQuad(wchar_t c); void addCharacterQuad(wchar_t c);
void addSolidQuad(float x0, float y0, float x1, float y1);
void emitCharacterGeometry(wchar_t c);
void renderStyleLine(float x0, float y0, float x1, float y1); // solid line for underline/strikethrough void renderStyleLine(float x0, float y0, float x1, float y1); // solid line for underline/strikethrough
public: public:
@ -65,7 +67,7 @@ public:
private: private:
wstring reorderBidi(const wstring &str); wstring reorderBidi(const wstring &str);
void draw(const wstring &str, bool dropShadow); void draw(const wstring &str, bool dropShadow, int baseColor);
void draw(const wstring& str, int x, int y, int color, bool dropShadow); void draw(const wstring& str, int x, int y, int color, bool dropShadow);
void drawLiteral(const wstring& str, int x, int y, int color); // no § parsing void drawLiteral(const wstring& str, int x, int y, int color); // no § parsing
int MapCharacter(wchar_t c); // 4J added int MapCharacter(wchar_t c); // 4J added

View file

@ -1070,111 +1070,146 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
lines.push_back(ClientConstants::VERSION_STRING); lines.push_back(ClientConstants::VERSION_STRING);
lines.push_back(ClientConstants::BRANCH_STRING); lines.push_back(ClientConstants::BRANCH_STRING);
} }
if (minecraft->options->renderDebug && minecraft->player != nullptr && minecraft->level != nullptr) if (minecraft->options->renderDebug && minecraft->player != nullptr && minecraft->level != nullptr)
{ {
lines.push_back(minecraft->fpsString); lines.push_back(minecraft->fpsString);
lines.push_back(L"E: " + std::to_wstring(minecraft->level->getAllEntities().size())); lines.push_back(L"E: " + std::to_wstring(minecraft->level->getAllEntities().size()));
int renderDistance = app.GetGameSettings(iPad, eGameSetting_RenderDistance); int renderDistance = app.GetGameSettings(iPad, eGameSetting_RenderDistance);
// Calculate the chunk sections using 16 * (2n + 1)^2
lines.push_back(L"C: " + std::to_wstring(16 * (2 * renderDistance + 1) * (2 * renderDistance + 1)) + L" D: " + std::to_wstring(renderDistance)); lines.push_back(L"C: " + std::to_wstring(16 * (2 * renderDistance + 1) * (2 * renderDistance + 1)) + L" D: " + std::to_wstring(renderDistance));
lines.push_back(minecraft->gatherStats4()); lines.push_back(minecraft->gatherStats4());
// Dimension
wstring dimension = L"unknown"; wstring dimension = L"unknown";
switch (minecraft->player->dimension) switch (minecraft->player->dimension)
{ {
case -1: dimension = L"minecraft:the_nether"; break; case -1:
case 0: dimension = L"minecraft:overworld"; break; dimension = L"minecraft:the_nether";
case 1: dimension = L"minecraft:the_end"; break; break;
case 0:
dimension = L"minecraft:overworld";
break;
case 1:
dimension = L"minecraft:the_end";
break;
} }
lines.push_back(dimension); lines.push_back(dimension);
lines.push_back(L"");
lines.push_back(L""); // Spacer
// Players block pos
int xBlockPos = Mth::floor(minecraft->player->x); int xBlockPos = Mth::floor(minecraft->player->x);
int yBlockPos = Mth::floor(minecraft->player->y); int yBlockPos = Mth::floor(minecraft->player->y);
int zBlockPos = Mth::floor(minecraft->player->z); int zBlockPos = Mth::floor(minecraft->player->z);
// Chunk player is in
int xChunkPos = xBlockPos >> 4; int xChunkPos = xBlockPos >> 4;
int yChunkPos = yBlockPos >> 4; int yChunkPos = yBlockPos >> 4;
int zChunkPos = zBlockPos >> 4; int zChunkPos = zBlockPos >> 4;
// Players offset within the chunk
int xChunkOffset = xBlockPos & 15; int xChunkOffset = xBlockPos & 15;
int yChunkOffset = yBlockPos & 15; int yChunkOffset = yBlockPos & 15;
int zChunkOffset = zBlockPos & 15; int zChunkOffset = zBlockPos & 15;
WCHAR posString[44]; // Format the position like java with limited decumal places
WCHAR posString[44]; // Allows upto 7 digit positions (+-9_999_999)
swprintf(posString, 44, L"%.3f / %.5f / %.3f", minecraft->player->x, minecraft->player->y, minecraft->player->z); swprintf(posString, 44, L"%.3f / %.5f / %.3f", minecraft->player->x, minecraft->player->y, minecraft->player->z);
lines.push_back(L"XYZ: " + std::wstring(posString)); lines.push_back(L"XYZ: " + std::wstring(posString));
lines.push_back(L"Block: " + std::to_wstring(xBlockPos) + L" " + std::to_wstring(yBlockPos) + L" " + std::to_wstring(zBlockPos)); lines.push_back(L"Block: " + std::to_wstring(xBlockPos) + L" " + std::to_wstring(yBlockPos) + L" " + std::to_wstring(zBlockPos));
lines.push_back(L"Chunk: " + std::to_wstring(xChunkOffset) + L" " + std::to_wstring(yChunkOffset) + L" " + std::to_wstring(zChunkOffset) + L" in " + std::to_wstring(xChunkPos) + L" " + std::to_wstring(yChunkPos) + L" " + std::to_wstring(zChunkPos)); lines.push_back(L"Chunk: " + std::to_wstring(xChunkOffset) + L" " + std::to_wstring(yChunkOffset) + L" " + std::to_wstring(zChunkOffset) + L" in " + std::to_wstring(xChunkPos) + L" " + std::to_wstring(yChunkPos) + L" " + std::to_wstring(zChunkPos));
// Wrap the yRot to 360 then adjust to (-180 to 180) range to match java
float yRotDisplay = fmod(minecraft->player->yRot, 360.0f); float yRotDisplay = fmod(minecraft->player->yRot, 360.0f);
if (yRotDisplay > 180.0f) yRotDisplay -= 360.0f; if (yRotDisplay > 180.0f) yRotDisplay -= 360.0f;
if (yRotDisplay < -180.0f) yRotDisplay += 360.0f; if (yRotDisplay < -180.0f) yRotDisplay += 360.0f;
// Generate the angle string in the format "yRot / xRot" with one decimal place, similar to java edition
WCHAR angleString[16]; WCHAR angleString[16];
swprintf(angleString, 16, L"%.1f / %.1f", yRotDisplay, minecraft->player->xRot); swprintf(angleString, 16, L"%.1f / %.1f", yRotDisplay, minecraft->player->xRot);
// Work out the named direction
int direction = Mth::floor(minecraft->player->yRot * 4.0f / 360.0f + 0.5) & 0x3; int direction = Mth::floor(minecraft->player->yRot * 4.0f / 360.0f + 0.5) & 0x3;
const wchar_t* cardinals[] = { L"south", L"west", L"north", L"east" }; const wchar_t* cardinals[] = { L"south", L"west", L"north", L"east" };
lines.push_back(L"Facing: " + std::wstring(cardinals[direction]) + L" (" + angleString + L")"); lines.push_back(L"Facing: " + std::wstring(cardinals[direction]) + L" (" + angleString + L")");
// We have to limit y to 256 as we don't get any information past that
if (minecraft->level != NULL && minecraft->level->hasChunkAt(xBlockPos, fmod(yBlockPos, 256), zBlockPos)) if (minecraft->level != NULL && minecraft->level->hasChunkAt(xBlockPos, fmod(yBlockPos, 256), zBlockPos))
{ {
LevelChunk *chunkAt = minecraft->level->getChunkAt(xBlockPos, zBlockPos); LevelChunk *chunkAt = minecraft->level->getChunkAt(xBlockPos, zBlockPos);
if (chunkAt != NULL) if (chunkAt != NULL)
{ {
int skyLight = chunkAt->getBrightness(LightLayer::Sky, xChunkOffset, yChunkOffset, zChunkOffset); int skyLight = chunkAt->getBrightness(LightLayer::Sky, xChunkOffset, yChunkOffset, zChunkOffset);
int blockLight = chunkAt->getBrightness(LightLayer::Block, xChunkOffset, yChunkOffset, zChunkOffset); int blockLight = chunkAt->getBrightness(LightLayer::Block, xChunkOffset, yChunkOffset, zChunkOffset);
int maxLight = fmax(skyLight, blockLight); int maxLight = fmax(skyLight, blockLight);
lines.push_back(L"Light: " + std::to_wstring(maxLight) + L" (" + std::to_wstring(skyLight) + L" sky, " + std::to_wstring(blockLight) + L" block)"); lines.push_back(L"Light: " + std::to_wstring(maxLight) + L" (" + std::to_wstring(skyLight) + L" sky, " + std::to_wstring(blockLight) + L" block)");
lines.push_back(L"CH S: " + std::to_wstring(chunkAt->getHeightmap(xChunkOffset, zChunkOffset))); lines.push_back(L"CH S: " + std::to_wstring(chunkAt->getHeightmap(xChunkOffset, zChunkOffset)));
Biome *biome = chunkAt->getBiome(xChunkOffset, zChunkOffset, minecraft->level->getBiomeSource()); Biome *biome = chunkAt->getBiome(xChunkOffset, zChunkOffset, minecraft->level->getBiomeSource());
lines.push_back(L"Biome: " + biome->m_name + L" (" + std::to_wstring(biome->id) + L")"); lines.push_back(L"Biome: " + biome->m_name + L" (" + std::to_wstring(biome->id) + L")");
lines.push_back(L"Difficulty: " + std::to_wstring(minecraft->level->difficulty) + L" (Day " + std::to_wstring(minecraft->level->getGameTime() / Level::TICKS_PER_DAY) + L")"); lines.push_back(L"Difficulty: " + std::to_wstring(minecraft->level->difficulty) + L" (Day " + std::to_wstring(minecraft->level->getGameTime() / Level::TICKS_PER_DAY) + L")");
} }
} }
lines.push_back(L""); // This is all LCE only stuff, it was never on java
lines.push_back(L""); // Spacer
lines.push_back(L"Seed: " + std::to_wstring(minecraft->level->getLevelData()->getSeed())); lines.push_back(L"Seed: " + std::to_wstring(minecraft->level->getLevelData()->getSeed()));
lines.push_back(minecraft->gatherStats1()); lines.push_back(minecraft->gatherStats1()); // Time to autosave
lines.push_back(minecraft->gatherStats2()); lines.push_back(minecraft->gatherStats2()); // Empty currently - CPlatformNetworkManagerStub::GatherStats()
lines.push_back(minecraft->gatherStats3()); lines.push_back(minecraft->gatherStats3()); // RTT
}
#ifdef _DEBUG #ifdef _DEBUG // Only show terrain features in debug builds not release
if (minecraft->options->renderDebug && minecraft->player != nullptr && minecraft->level != nullptr && minecraft->level->dimension->id == 0)
{ // No point trying to render this when not in the overworld
wstring wfeature[eTerrainFeature_Count]; if (minecraft->level->dimension->id == 0)
wfeature[eTerrainFeature_Stronghold] = L"Stronghold: ";
wfeature[eTerrainFeature_Mineshaft] = L"Mineshaft: ";
wfeature[eTerrainFeature_Village] = L"Village: ";
wfeature[eTerrainFeature_Ravine] = L"Ravine: ";
// maxW in font units: physical width divided by font scale
float maxW = (static_cast<float>(g_rScreenWidth) - debugLeft - 8) / fontScale;
float maxWForContent = maxW - static_cast<float>(font->width(L"..."));
bool truncated[eTerrainFeature_Count] = {};
for (size_t i = 0; i < app.m_vTerrainFeatures.size(); i++)
{ {
FEATURE_DATA *pFeatureData = app.m_vTerrainFeatures[i]; wstring wfeature[eTerrainFeature_Count];
int type = pFeatureData->eTerrainFeature; wfeature[eTerrainFeature_Stronghold] = L"Stronghold: ";
if (type < eTerrainFeature_Stronghold || type > eTerrainFeature_Ravine) continue; wfeature[eTerrainFeature_Mineshaft] = L"Mineshaft: ";
if (truncated[type]) continue; wfeature[eTerrainFeature_Village] = L"Village: ";
wstring itemInfo = L"[" + std::to_wstring(pFeatureData->x * 16) + L", " + std::to_wstring(pFeatureData->z * 16) + L"] "; wfeature[eTerrainFeature_Ravine] = L"Ravine: ";
if (font->width(wfeature[type] + itemInfo) <= maxWForContent)
wfeature[type] += itemInfo; // maxW in font units: physical width divided by font scale
else float maxW = (static_cast<float>(g_rScreenWidth) - debugLeft - 8) / fontScale;
float maxWForContent = maxW - static_cast<float>(font->width(L"..."));
bool truncated[eTerrainFeature_Count] = {};
for (size_t i = 0; i < app.m_vTerrainFeatures.size(); i++)
{ {
wfeature[type] += L"..."; FEATURE_DATA *pFeatureData = app.m_vTerrainFeatures[i];
truncated[type] = true; int type = pFeatureData->eTerrainFeature;
if (type < eTerrainFeature_Stronghold || type > eTerrainFeature_Ravine) continue;
if (truncated[type]) continue;
wstring itemInfo = L"[" + std::to_wstring(pFeatureData->x * 16) + L", " + std::to_wstring(pFeatureData->z * 16) + L"] ";
if (font->width(wfeature[type] + itemInfo) <= maxWForContent)
{
wfeature[type] += itemInfo;
}
else
{
wfeature[type] += L"...";
truncated[type] = true;
}
} }
lines.push_back(L""); // Spacer
for (int i = eTerrainFeature_Stronghold; i <= static_cast<int>(eTerrainFeature_Ravine); i++)
{
lines.push_back(wfeature[i]);
}
lines.push_back(L""); // Spacer
} }
lines.push_back(L"");
for (int i = eTerrainFeature_Stronghold; i <= static_cast<int>(eTerrainFeature_Ravine); i++)
lines.push_back(wfeature[i]);
lines.push_back(L"");
}
#endif #endif
}
// Disable the depth test so the text shows on top of the paperdoll
glDisable(GL_DEPTH_TEST);
// Loop through the lines and draw them all on screen
int yPos = debugTop; int yPos = debugTop;
for (const auto &line : lines) for (const auto &line : lines)
{ {
@ -1182,6 +1217,9 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse)
yPos += 10; yPos += 10;
} }
// Restore the depth test
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glPopMatrix(); glPopMatrix();
glMatrixMode(GL_PROJECTION); glMatrixMode(GL_PROJECTION);

View file

@ -170,6 +170,7 @@ void Options::init()
particles = 0; particles = 0;
fov = 0; fov = 0;
gamma = 0; gamma = 0;
advancedTooltips = false;
} }
Options::Options(Minecraft *minecraft, File workingDirectory) Options::Options(Minecraft *minecraft, File workingDirectory)
@ -451,8 +452,9 @@ void Options::load()
if (cmds[0] == L"fancyGraphics") fancyGraphics = cmds[1]==L"true"; if (cmds[0] == L"fancyGraphics") fancyGraphics = cmds[1]==L"true";
if (cmds[0] == L"ao") ambientOcclusion = cmds[1]==L"true"; if (cmds[0] == L"ao") ambientOcclusion = cmds[1]==L"true";
if (cmds[0] == L"clouds") renderClouds = cmds[1]==L"true"; if (cmds[0] == L"clouds") renderClouds = cmds[1]==L"true";
if (cmds[0] == L"skin") skin = cmds[1]; if (cmds[0] == L"advancedTooltips") advancedTooltips = cmds[1]==L"false";
if (cmds[0] == L"lastServer") lastMpIp = cmds[1]; if (cmds[0] == L"skin") skin = cmds[1];
if (cmds[0] == L"lastServer") lastMpIp = cmds[1];
for (int i = 0; i < keyMappings_length; i++) for (int i = 0; i < keyMappings_length; i++)
{ {
@ -508,7 +510,8 @@ void Options::save()
dos.writeChars(L"fancyGraphics:" + wstring(fancyGraphics ? L"true" : L"false")); dos.writeChars(L"fancyGraphics:" + wstring(fancyGraphics ? L"true" : L"false"));
dos.writeChars(ambientOcclusion ? L"ao:true" : L"ao:false"); dos.writeChars(ambientOcclusion ? L"ao:true" : L"ao:false");
dos.writeChars(renderClouds ? L"clouds:true" : L"clouds:false"); dos.writeChars(renderClouds ? L"clouds:true" : L"clouds:false");
dos.writeChars(L"skin:" + skin); dos.writeChars(advancedTooltips ? L"advancedTooltips:true" : L"advancedTooltips:false");
dos.writeChars(L"skin:" + skin);
dos.writeChars(L"lastServer:" + lastMpIp); dos.writeChars(L"lastServer:" + lastMpIp);
for (int i = 0; i < keyMappings_length; i++) for (int i = 0; i < keyMappings_length; i++)

View file

@ -110,6 +110,7 @@ public:
int particles; // 0 is all, 1 is decreased and 2 is minimal int particles; // 0 is all, 1 is decreased and 2 is minimal
float fov; float fov;
float gamma; float gamma;
bool advancedTooltips;
void init(); // 4J added void init(); // 4J added
Options(Minecraft *minecraft, File workingDirectory); Options(Minecraft *minecraft, File workingDirectory);

View file

@ -1631,8 +1631,10 @@ bool PlayerConnection::isDisconnected()
void PlayerConnection::handleDebugOptions(shared_ptr<DebugOptionsPacket> packet) void PlayerConnection::handleDebugOptions(shared_ptr<DebugOptionsPacket> packet)
{ {
//Player player = dynamic_pointer_cast<Player>( player->shared_from_this() ); #ifdef _DEBUG
player->SetDebugOptions(packet->m_uiVal); // Player player = dynamic_pointer_cast<Player>( player->shared_from_this() );
player->SetDebugOptions(packet->m_uiVal);
#endif
} }
void PlayerConnection::handleCraftItem(shared_ptr<CraftItemPacket> packet) void PlayerConnection::handleCraftItem(shared_ptr<CraftItemPacket> packet)

View file

@ -234,6 +234,13 @@ bool KeyboardMouseInput::IsKeyReleased(int vkCode) const
return false; return false;
} }
int KeyboardMouseInput::GetPressedKey() const
{
for (int i = 0; i < MAX_KEYS; ++i)
if (m_keyPressed[i]) return i;
return 0;
}
bool KeyboardMouseInput::IsMouseButtonDown(int button) const bool KeyboardMouseInput::IsMouseButtonDown(int button) const
{ {
if (button >= 0 && button < MAX_MOUSE_BUTTONS) if (button >= 0 && button < MAX_MOUSE_BUTTONS)

View file

@ -56,6 +56,8 @@ public:
bool IsKeyPressed(int vkCode) const; bool IsKeyPressed(int vkCode) const;
bool IsKeyReleased(int vkCode) const; bool IsKeyReleased(int vkCode) const;
int GetPressedKey() const;
bool IsMouseButtonDown(int button) const; bool IsMouseButtonDown(int button) const;
bool IsMouseButtonPressed(int button) const; bool IsMouseButtonPressed(int button) const;
bool IsMouseButtonReleased(int button) const; bool IsMouseButtonReleased(int button) const;

View file

@ -36,6 +36,7 @@
//#include "NetworkManager.h" //#include "NetworkManager.h"
#include "..\..\Minecraft.Client\Tesselator.h" #include "..\..\Minecraft.Client\Tesselator.h"
#include "..\..\Minecraft.Client\Options.h" #include "..\..\Minecraft.Client\Options.h"
#include "..\Gui.h"
#include "Sentient\SentientManager.h" #include "Sentient\SentientManager.h"
#include "..\..\Minecraft.World\IntCache.h" #include "..\..\Minecraft.World\IntCache.h"
#include "..\Textures.h" #include "..\Textures.h"
@ -107,6 +108,7 @@ int g_iScreenHeight = 1080;
// always matches the current window, even after a resize. // always matches the current window, even after a resize.
int g_rScreenWidth = 1920; int g_rScreenWidth = 1920;
int g_rScreenHeight = 1080; int g_rScreenHeight = 1080;
static bool f3ComboUsed = false;
float g_iAspectRatio = static_cast<float>(g_iScreenWidth) / g_iScreenHeight; float g_iAspectRatio = static_cast<float>(g_iScreenWidth) / g_iScreenHeight;
static bool g_bResizeReady = false; static bool g_bResizeReady = false;
@ -1774,17 +1776,37 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance,
} }
// F3 toggles onscreen debug info // F3 toggles onscreen debug info
if (g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_DEBUG_INFO)) if (g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_DEBUG_INFO)) f3ComboUsed = false;
// f3 combo
if (g_KBMInput.IsKeyDown(KeyboardMouseInput::KEY_DEBUG_INFO))
{ {
if (const Minecraft* pMinecraft = Minecraft::GetInstance()) switch (g_KBMInput.GetPressedKey())
{ {
if (pMinecraft->options) // advanced tooltips
{ case 'H':
pMinecraft->options->renderDebug = !pMinecraft->options->renderDebug; if (pMinecraft->options && app.GetGameStarted())
} {
pMinecraft->options->advancedTooltips = !pMinecraft->options->advancedTooltips;
pMinecraft->options->save();
const wstring msg = wstring(L"Advanced tooltips: ") + (pMinecraft->options->advancedTooltips ? L"shown" : L"hidden");
const int primaryPad = ProfileManager.GetPrimaryPad();
if (pMinecraft->gui) pMinecraft->gui->addMessage(msg, primaryPad);
f3ComboUsed = true;
}
break;
} }
} }
// no combo
if (g_KBMInput.IsKeyReleased(KeyboardMouseInput::KEY_DEBUG_INFO) && !f3ComboUsed)
if (pMinecraft->options)
pMinecraft->options->renderDebug = !pMinecraft->options->renderDebug;
#ifdef _DEBUG_MENUS_ENABLED #ifdef _DEBUG_MENUS_ENABLED
// F6 Open debug console // F6 Open debug console
if (g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_DEBUG_CONSOLE)) if (g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_DEBUG_CONSOLE))

View file

@ -157,7 +157,7 @@ shared_ptr<ItemInstance> AbstractContainerMenu::clicked(int slotIndex, int butto
shared_ptr<ItemInstance> clickedEntity = nullptr; shared_ptr<ItemInstance> clickedEntity = nullptr;
shared_ptr<Inventory> inventory = player->inventory; shared_ptr<Inventory> inventory = player->inventory;
if (slotIndex < 0 || slotIndex >= (int)slots.size()) if ((slotIndex < 0 && slotIndex != SLOT_CLICKED_OUTSIDE) || slotIndex >= (int)slots.size())
return nullptr; return nullptr;
if (clickType == CLICK_QUICK_CRAFT) if (clickType == CLICK_QUICK_CRAFT)

View file

@ -21,20 +21,20 @@ void ClothDyeRecipes::addRecipes(Recipes *r)
L'#', new ItemInstance(Tile::clayHardened), L'#', new ItemInstance(Tile::clayHardened),
L'X', new ItemInstance(Item::dye_powder, 1, i),L'D'); L'X', new ItemInstance(Item::dye_powder, 1, i),L'D');
#if 0 //#if 0
r->addShapedRecipy(new ItemInstance(Tile::stained_glass, 8, ColoredTile::getItemAuxValueForTileData(i)), // // r->addShapedRecipy(new ItemInstance(Tile::stained_glass, 8, ColoredTile::getItemAuxValueForTileData(i)), //
L"sssczczg", // L"sssczczg",
L"###", // L"###",
L"#X#", // L"#X#",
L"###", // L"###",
L'#', new ItemInstance(Tile::glass), // L'#', new ItemInstance(Tile::glass),
L'X', new ItemInstance(Item::dye_powder, 1, i), L'D'); // L'X', new ItemInstance(Item::dye_powder, 1, i), L'D');
r->addShapedRecipy(new ItemInstance(Tile::stained_glass_pane, 16, i), // // r->addShapedRecipy(new ItemInstance(Tile::stained_glass_pane, 16, i), //
L"ssczg", // L"ssczg",
L"###", // L"###",
L"###", // L"###",
L'#', new ItemInstance(Tile::stained_glass, 1, i), L'D'); // L'#', new ItemInstance(Tile::stained_glass, 1, i), L'D');
#endif //#endif
} }
// some dye recipes // some dye recipes

View file

@ -562,34 +562,27 @@ vector<HtmlString> *ItemInstance::getHoverText(shared_ptr<Player> player, bool a
title.italics = true; title.italics = true;
} }
// 4J: This is for showing aux values, not useful in console version
/*
if (advanced) if (advanced)
{ {
wstring suffix = L""; wstring suffix = L"";
if (title.length() > 0) if (title.text.length() > 0)
{ {
title += L" ("; title.text += L" (";
suffix = L")"; suffix = L")";
} }
wchar_t buf[64];
if (isStackedByData()) if (isStackedByData())
{ swprintf_s(buf, 64, L"#%04d/%d%s", id, auxValue, suffix.c_str());
title += String.format("#%04d/%d%s", id, auxValue, suffix);
}
else else
{ swprintf_s(buf, 64, L"#%04d%s", id, suffix.c_str());
title += String.format("#%04d%s", id, suffix); title.text += buf;
}
} }
else if (!hasCustomHoverName() && id == Item::map_Id) else if (!hasCustomHoverName() && id == Item::map_Id)
*/
/*if (!hasCustomHoverName() && id == Item::map_Id)
{ {
title.text += L" #" + std::to_wstring(auxValue); title.text += L" #" + std::to_wstring(auxValue);
}*/ }
lines->push_back(title); lines->push_back(title);
@ -615,7 +608,7 @@ vector<HtmlString> *ItemInstance::getHoverText(shared_ptr<Player> player, bool a
if (tag->contains(L"display")) if (tag->contains(L"display"))
{ {
//CompoundTag *display = tag->getCompound(L"display"); CompoundTag *display = tag->getCompound(L"display");
//if (display->contains(L"color")) //if (display->contains(L"color"))
//{ //{
@ -631,8 +624,7 @@ vector<HtmlString> *ItemInstance::getHoverText(shared_ptr<Player> player, bool a
// } // }
//} //}
// 4J: Lore isn't in use in game if (display->contains(L"Lore"))
/*if (display->contains(L"Lore"))
{ {
ListTag<StringTag> *lore = (ListTag<StringTag> *) display->getList(L"Lore"); ListTag<StringTag> *lore = (ListTag<StringTag> *) display->getList(L"Lore");
if (lore->size() > 0) if (lore->size() > 0)
@ -643,7 +635,7 @@ vector<HtmlString> *ItemInstance::getHoverText(shared_ptr<Player> player, bool a
lines->push_back(lore->get(i)->data); lines->push_back(lore->get(i)->data);
} }
} }
}*/ }
} }
} }
@ -674,7 +666,7 @@ vector<HtmlString> *ItemInstance::getHoverText(shared_ptr<Player> player, bool a
{ {
if (isDamaged()) if (isDamaged())
{ {
wstring damageStr = L"Durability: LOCALISE " + std::to_wstring((getMaxDamage()) - getDamageValue()) + L" / " + std::to_wstring(getMaxDamage()); wstring damageStr = L"Durability: " + std::to_wstring((getMaxDamage()) - getDamageValue()) + L" / " + std::to_wstring(getMaxDamage());
lines->push_back(HtmlString(damageStr)); lines->push_back(HtmlString(damageStr));
} }
} }

View file

@ -63,10 +63,10 @@ public:
public: public:
static const int MAX_XBOX_BOATS = 40; // Max number of boats static const int MAX_XBOX_BOATS = 60; // Max number of boats
static const int MAX_CONSOLE_MINECARTS = 40; static const int MAX_CONSOLE_MINECARTS = 60;
static const int MAX_DISPENSABLE_FIREBALLS = 200; static const int MAX_DISPENSABLE_FIREBALLS = 300;
static const int MAX_DISPENSABLE_PROJECTILES = 300; static const int MAX_DISPENSABLE_PROJECTILES = 400;
static const int MAX_LEVEL_SIZE = 30000000; static const int MAX_LEVEL_SIZE = 30000000;
static const int maxMovementHeight = 512; // 4J added static const int maxMovementHeight = 512; // 4J added

View file

@ -299,6 +299,7 @@ Recipes::Recipes()
pClothDyeRecipes->addRecipes(this); pClothDyeRecipes->addRecipes(this);
addShapedRecipy(new ItemInstance(Tile::snow, 1), // addShapedRecipy(new ItemInstance(Tile::snow, 1), //
L"sscig", L"sscig",
L"##", // L"##", //

View file

@ -115,6 +115,28 @@ void StructureRecipies::addRecipes(Recipes *r)
L'#', Tile::glass, L'#', Tile::glass,
L'D'); L'D');
// Stained Glass block + pane per color
for (int i = 0; i < 16; i++)
{
r->addShapedRecipy(new ItemInstance(Tile::stained_glass, 8, ColoredTile::getItemAuxValueForTileData(i)),
L"sssczczg",
L"###",
L"#X#",
L"###",
L'#', new ItemInstance(Tile::glass),
L'X', new ItemInstance(Item::dye_powder, 1, i),
L'D');
r->addShapedRecipy(new ItemInstance(Tile::stained_glass_pane, 16, ColoredTile::getItemAuxValueForTileData(i)),
L"ssczg",
L"###",
L"###",
L'#', new ItemInstance(Tile::stained_glass, 1, ColoredTile::getItemAuxValueForTileData(i)),
L'D');
}
r->addShapedRecipy(new ItemInstance(Tile::netherBrick, 1), // r->addShapedRecipy(new ItemInstance(Tile::netherBrick, 1), //
L"sscig", L"sscig",

View file

@ -371,7 +371,12 @@ void Tile::staticCtor()
Tile::ironFence = (new ThinFenceTile(101, L"iron_bars", L"iron_bars", Material::metal, true)) ->setBaseItemTypeAndMaterial(Item::eBaseItemType_fence, Item::eMaterial_iron)->setDestroyTime(5.0f)->setExplodeable(10)->setSoundType(SOUND_METAL)->setDescriptionId(IDS_TILE_IRON_FENCE)->setUseDescriptionId(IDS_DESC_IRON_FENCE); Tile::ironFence = (new ThinFenceTile(101, L"iron_bars", L"iron_bars", Material::metal, true)) ->setBaseItemTypeAndMaterial(Item::eBaseItemType_fence, Item::eMaterial_iron)->setDestroyTime(5.0f)->setExplodeable(10)->setSoundType(SOUND_METAL)->setDescriptionId(IDS_TILE_IRON_FENCE)->setUseDescriptionId(IDS_DESC_IRON_FENCE);
Tile::thinGlass = (new ThinFenceTile(102, L"glass", L"glass_pane_top", Material::glass, false)) ->setDestroyTime(0.3f)->setSoundType(SOUND_GLASS)->setDescriptionId(IDS_TILE_THIN_GLASS)->setUseDescriptionId(IDS_DESC_THIN_GLASS); Tile::thinGlass = (new ThinFenceTile(102, L"glass", L"glass_pane_top", Material::glass, false))
->setBaseItemTypeAndMaterial(Item::eBaseItemType_glass, Item::eMaterial_glass)
->setDestroyTime(0.3f)
->setSoundType(SOUND_GLASS)
->setDescriptionId(IDS_TILE_THIN_GLASS)
->setUseDescriptionId(IDS_DESC_THIN_GLASS);
Tile::melon = (new MelonTile(103)) ->setDestroyTime(1.0f)->setSoundType(SOUND_WOOD)->setIconName(L"melon")->setDescriptionId(IDS_TILE_MELON)->setUseDescriptionId(IDS_DESC_MELON_BLOCK); Tile::melon = (new MelonTile(103)) ->setDestroyTime(1.0f)->setSoundType(SOUND_WOOD)->setIconName(L"melon")->setDescriptionId(IDS_TILE_MELON)->setUseDescriptionId(IDS_DESC_MELON_BLOCK);
Tile::pumpkinStem = (new StemTile(104, Tile::pumpkin)) ->setDestroyTime(0.0f)->setSoundType(SOUND_WOOD)->setIconName(L"pumpkin_stem")->setDescriptionId(IDS_TILE_PUMPKIN_STEM)->sendTileData(); Tile::pumpkinStem = (new StemTile(104, Tile::pumpkin)) ->setDestroyTime(0.0f)->setSoundType(SOUND_WOOD)->setIconName(L"pumpkin_stem")->setDescriptionId(IDS_TILE_PUMPKIN_STEM)->sendTileData();
Tile::melonStem = (new StemTile(105, Tile::melon)) ->setDestroyTime(0.0f)->setSoundType(SOUND_WOOD)->setIconName(L"melon_stem")->setDescriptionId(IDS_TILE_MELON_STEM)->sendTileData(); Tile::melonStem = (new StemTile(105, Tile::melon)) ->setDestroyTime(0.0f)->setSoundType(SOUND_WOOD)->setIconName(L"melon_stem")->setDescriptionId(IDS_TILE_MELON_STEM)->sendTileData();

View file

@ -3,6 +3,7 @@
# Required: # Required:
# COPY_SOURCE pipe-separated list of source file paths # COPY_SOURCE pipe-separated list of source file paths
# COPY_DEST destination directory # COPY_DEST destination directory
cmake_minimum_required(VERSION 3.24)
if(NOT COPY_SOURCE OR NOT COPY_DEST) if(NOT COPY_SOURCE OR NOT COPY_DEST)
message(FATAL_ERROR "COPY_SOURCE and COPY_DEST must be set.") message(FATAL_ERROR "COPY_SOURCE and COPY_DEST must be set.")