diff --git a/Minecraft.Client/ClientConnection.cpp b/Minecraft.Client/ClientConnection.cpp index 325e949bb..a80af5d2c 100644 --- a/Minecraft.Client/ClientConnection.cpp +++ b/Minecraft.Client/ClientConnection.cpp @@ -4036,6 +4036,8 @@ void ClientConnection::handleSetPlayerTeamPacket(shared_ptr void ClientConnection::handleParticleEvent(shared_ptr packet) { + ePARTICLE_TYPE particleId = (ePARTICLE_TYPE)Integer::parseInt(packet->getName()); + for (int i = 0; i < packet->getCount(); i++) { double xVarience = random->nextGaussian() * packet->getXDist(); @@ -4045,10 +4047,6 @@ void ClientConnection::handleParticleEvent(shared_ptr pack double ya = 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); } } diff --git a/Minecraft.Client/Common/Media/MediaWindows64.arc b/Minecraft.Client/Common/Media/MediaWindows64.arc index 4d0995321..b810e4d88 100644 Binary files a/Minecraft.Client/Common/Media/MediaWindows64.arc and b/Minecraft.Client/Common/Media/MediaWindows64.arc differ diff --git a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp index 7502d6bf2..7db52b3f9 100644 --- a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp +++ b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.cpp @@ -9,6 +9,7 @@ #include "..\..\..\Minecraft.World\net.minecraft.world.level.tile.entity.h" #include "..\..\MultiplayerLocalPlayer.h" #include "..\..\Minecraft.h" +#include "..\..\Options.h" #ifdef __ORBIS__ #include @@ -16,8 +17,6 @@ #ifdef _WINDOWS64 #include "..\..\Windows64\KeyboardMouseInput.h" - -SavedInventoryCursorPos g_savedInventoryCursorPos = { 0.0f, 0.0f, false }; #endif IUIScene_AbstractContainerMenu::IUIScene_AbstractContainerMenu() @@ -1677,7 +1676,13 @@ vector *IUIScene_AbstractContainerMenu::GetItemDescription(Slot *slo { if(slot == nullptr) return nullptr; - vector *lines = slot->getItem()->getHoverText(nullptr, false); + bool advanced = false; + if (const Minecraft* pMinecraft = Minecraft::GetInstance()) + { + if (pMinecraft->options) + advanced = pMinecraft->options->advancedTooltips; + } + vector *lines = slot->getItem()->getHoverText(nullptr, advanced); // Add rarity to first line if (lines->size() > 0) diff --git a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.h b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.h index 718a2d447..6710e18f5 100644 --- a/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.h +++ b/Minecraft.Client/Common/UI/IUIScene_AbstractContainerMenu.h @@ -1,15 +1,5 @@ #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. // 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 diff --git a/Minecraft.Client/Common/UI/IUIScene_CraftingMenu.h b/Minecraft.Client/Common/UI/IUIScene_CraftingMenu.h index 03a58378c..fa8d9bd16 100644 --- a/Minecraft.Client/Common/UI/IUIScene_CraftingMenu.h +++ b/Minecraft.Client/Common/UI/IUIScene_CraftingMenu.h @@ -20,9 +20,9 @@ protected: eGroupTab_Right }; - static const int m_iMaxHSlotC = 12; - static const int m_iMaxHCraftingSlotC = 10; - static const int m_iMaxVSlotC = 17; + static const int m_iMaxHSlotC = 40; + static const int m_iMaxHCraftingSlotC = 40; + static const int m_iMaxVSlotC = 99; static const int m_iMaxDisplayedVSlotC = 3; static const int m_iIngredients3x3SlotC = 9; static const int m_iIngredients2x2SlotC = 4; diff --git a/Minecraft.Client/Common/UI/IUIScene_TradingMenu.cpp b/Minecraft.Client/Common/UI/IUIScene_TradingMenu.cpp index 0b1e0df24..d7939d8c5 100644 --- a/Minecraft.Client/Common/UI/IUIScene_TradingMenu.cpp +++ b/Minecraft.Client/Common/UI/IUIScene_TradingMenu.cpp @@ -4,6 +4,7 @@ #include "..\..\..\Minecraft.World\net.minecraft.world.item.h" #include "..\..\..\Minecraft.World\net.minecraft.network.packet.h" #include "..\..\Minecraft.h" +#include "..\..\Options.h" #include "..\..\MultiPlayerLocalPlayer.h" #include "..\..\ClientConnection.h" #include "IUIScene_TradingMenu.h" @@ -368,7 +369,13 @@ void IUIScene_TradingMenu::setTradeItem(int index, shared_ptr item vector *IUIScene_TradingMenu::GetItemDescription(shared_ptr item) { - vector *lines = item->getHoverText(nullptr, false); + bool advanced = false; + if (const Minecraft* pMinecraft = Minecraft::GetInstance()) + { + if (pMinecraft->options) + advanced = pMinecraft->options->advancedTooltips; + } + vector *lines = item->getHoverText(nullptr, advanced); // Add rarity to first line if (lines->size() > 0) diff --git a/Minecraft.Client/Common/UI/UIControl_TextInput.cpp b/Minecraft.Client/Common/UI/UIControl_TextInput.cpp index 8e679b7c7..76f25afb3 100644 --- a/Minecraft.Client/Common/UI/UIControl_TextInput.cpp +++ b/Minecraft.Client/Common/UI/UIControl_TextInput.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "UI.h" #include "UIControl_TextInput.h" +#include "..\..\Screen.h" 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 if (g_KBMInput.IsKeyPressed(VK_LEFT) && m_iCursorPos > 0) { diff --git a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp index 0c3b6096d..c5dc0554b 100644 --- a/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_AbstractContainerMenu.cpp @@ -41,10 +41,6 @@ void UIScene_AbstractContainerMenu::handleDestroy() app.DebugPrintf("UIScene_AbstractContainerMenu::handleDestroy\n"); #ifdef _WINDOWS64 - g_savedInventoryCursorPos.x = m_pointerPos.x; - g_savedInventoryCursorPos.y = m_pointerPos.y; - g_savedInventoryCursorPos.hasSavedPos = true; - g_KBMInput.SetScreenCursorHidden(false); g_KBMInput.SetCursorHiddenForUI(false); #endif @@ -173,16 +169,16 @@ void UIScene_AbstractContainerMenu::PlatformInitialize(int iPad, int startIndex) m_pointerPos = vPointerPos; #ifdef _WINDOWS64 - if (g_savedInventoryCursorPos.hasSavedPos) + if ((iPad == 0) && g_KBMInput.IsKBMActive()) { - m_pointerPos.x = g_savedInventoryCursorPos.x; - m_pointerPos.y = g_savedInventoryCursorPos.y; - - 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; + m_pointerPos.x = ((m_fPanelMinX + m_fPanelMaxX) * 0.5f) - m_fPointerImageOffsetX; + 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; #endif IggyEvent mouseEvent; diff --git a/Minecraft.Client/Common/UI/UIScene_Keyboard.cpp b/Minecraft.Client/Common/UI/UIScene_Keyboard.cpp index 2f2f91326..35edf17fd 100644 --- a/Minecraft.Client/Common/UI/UIScene_Keyboard.cpp +++ b/Minecraft.Client/Common/UI/UIScene_Keyboard.cpp @@ -1,6 +1,7 @@ #include "stdafx.h" #include "UI.h" #include "UIScene_Keyboard.h" +#include "..\..\Screen.h" #ifdef _WINDOWS64 // 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(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) { // Arrow keys, Home, End, Delete for cursor movement diff --git a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp index b258d8c31..e9a85fa54 100644 --- a/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp +++ b/Minecraft.Client/Common/UI/UIScene_SettingsGraphicsMenu.cpp @@ -222,9 +222,8 @@ void UIScene_SettingsGraphicsMenu::handleSliderMove(F64 sliderId, F64 currentVal const int fovValue = sliderValueToFov(value); pMinecraft->gameRenderer->SetFovVal(static_cast(fovValue)); app.SetGameSettings(m_iPad, eGameSetting_FOV, value); - WCHAR tempString[256]; - swprintf(tempString, 256, L"FOV: %d", fovValue); - m_sliderFOV.setLabel(tempString); + swprintf(TempString, 256, L"FOV: %d", fovValue); + m_sliderFOV.setLabel(TempString); } break; diff --git a/Minecraft.Client/Font.cpp b/Minecraft.Client/Font.cpp index db2a18c04..1040eaa08 100644 --- a/Minecraft.Client/Font.cpp +++ b/Minecraft.Client/Font.cpp @@ -45,46 +45,46 @@ Font::Font(Options *options, const wstring& name, Textures* textures, bool enfor random = new Random(); // Load the image - BufferedImage *img = textures->readImage(textureLocation->getTexture(), name); + BufferedImage *img = textures->readImage(textureLocation->getTexture(), name); /* - 4J - TODO try { - img = ImageIO.read(Textures.class.getResourceAsStream(name)); - } catch (IOException e) { - throw new RuntimeException(e); - } + img = ImageIO.read(Textures.class.getResourceAsStream(name)); + } catch (IOException e) { + throw new RuntimeException(e); + } */ - int w = img->getWidth(); - int h = img->getHeight(); - intArray rawPixels(w * h); - img->getRGB(0, 0, w, h, rawPixels, 0, w); + int w = img->getWidth(); + int h = img->getHeight(); + intArray rawPixels(w * h); + 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 yt = i / m_cols; + int xt = i % m_cols; + int yt = i / m_cols; - int x = 7; - for (; x >= 0; x--) + int x = 7; + for (; x >= 0; x--) { - int xPixel = xt * 8 + x; - bool emptyColumn = true; - for (int y = 0; y < 8 && emptyColumn; y++) + int xPixel = xt * 8 + x; + bool emptyColumn = true; + 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 - if (!emptyPixel) emptyColumn = false; - } - if (!emptyColumn) + if (!emptyPixel) emptyColumn = false; + } + if (!emptyColumn) { - break; - } - } + break; + } + } - if (i == ' ') x = 4 - 2; - charWidths[i] = x + 2; - } + if (i == ' ') x = 4 - 2; + charWidths[i] = x + 2; + } delete img; @@ -130,6 +130,7 @@ Font::~Font() } #endif +// Legacy helper used by renderCharacter() only. void Font::renderStyleLine(float x0, float y0, float x1, float y1) { Tesselator* t = Tesselator::getInstance(); @@ -146,7 +147,20 @@ void Font::renderStyleLine(float x0, float y0, float x1, float y1) 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 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->vertex(x0 + dx, y0, 0.0f); } - - xPos += static_cast(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(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) { - 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 fontWidth = m_cols * m_charWidth; - float fontHeight = m_rows * m_charHeight; - - const float shear = m_italic ? (height * 0.25f) : 0.0f; - float x0 = xPos, x1 = xPos + width + shear; - float y0 = yPos, y1 = yPos + height; + float x0 = xPos; + float y0 = yPos; + float y1 = yPos + height; Tesselator *t = Tesselator::getInstance(); t->begin(); - t->tex(xOff / fontWidth, (yOff + 7.99f) / fontHeight); - 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); + emitCharacterGeometry(c); 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) renderStyleLine(x0, y1 - 1.0f, xPos + static_cast(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) { - draw(str, x + 1, y + 1, color, true); - draw(str, x, y, color, false); + draw(str, x + 1, y + 1, color, true); + draw(str, x, y, color, false); } 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'; } -void Font::draw(const wstring &str, bool dropShadow) +void Font::draw(const wstring &str, bool dropShadow, int initialColor) { // Bind the texture 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; wstring cleanStr = sanitize(str); + int currentColor = initialColor; + Tesselator *t = Tesselator::getInstance(); t->begin(); + t->color(currentColor & 0x00ffffff, (currentColor >> 24) & 255); for (int i = 0; i < static_cast(cleanStr.length()); ++i) { @@ -310,10 +320,8 @@ void Font::draw(const wstring &str, bool dropShadow) wchar_t ca = cleanStr[i+1]; if (!isSectionFormatCode(ca)) { - t->end(); - renderCharacter(167); - renderCharacter(ca); - t->begin(); + addCharacterQuad(167); + addCharacterQuad(ca); i += 1; 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'n') m_underline = 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 @@ -337,8 +350,8 @@ void Font::draw(const wstring &str, bool dropShadow) noise = false; if (colorN < 0 || colorN > 15) colorN = 15; if (dropShadow) colorN += 16; - int color = colors[colorN]; - glColor3f((color >> 16) / 255.0F, ((color >> 8) & 255) / 255.0F, (color & 255) / 255.0F); + currentColor = (initialColor & 0xff000000) | colors[colorN]; + t->color(currentColor & 0x00ffffff, (currentColor >> 24) & 255); } i += 1; 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 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; yPos = y; - draw(str, dropShadow); + draw(str, dropShadow, color); } } @@ -422,9 +435,9 @@ wstring Font::sanitize(const wstring& 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]); } @@ -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) sb[i] = 0; } - } - return sb; + } + return sb; } 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) { - vectorlines = stringSplit(string,L'\n'); - if (lines.size() > 1) + vectorlines = stringSplit(string,L'\n'); + 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 if( (y + this->wordWrapHeight(it, w)) > h) break; - drawWordWrapInternal(it, x, y, w, col, h); - y += this->wordWrapHeight(it, w); - } - return; - } - vector words = stringSplit(string,L' '); - unsigned int pos = 0; - while (pos < words.size()) + drawWordWrapInternal(it, x, y, w, col, h); + y += this->wordWrapHeight(it, w); + } + return; + } + vector words = stringSplit(string,L' '); + unsigned int pos = 0; + while (pos < words.size()) { - wstring line = words[pos++] + L" "; - while (pos < words.size() && width(line + words[pos]) < w) + wstring line = words[pos++] + L" "; + while (pos < words.size() && width(line + words[pos]) < w) { - line += words[pos++] + L" "; - } - while (width(line) > w) + line += words[pos++] + L" "; + } + while (width(line) > w) { - int l = 0; - while (width(line.substr(0, l + 1)) <= w) + int l = 0; + while (width(line.substr(0, l + 1)) <= w) { - l++; - } - if (trimString(line.substr(0, l)).length() > 0) + l++; + } + if (trimString(line.substr(0, l)).length() > 0) { - draw(line.substr(0, l), x, y, col); - y += 8; - } - line = line.substr(l); + draw(line.substr(0, l), x, y, col); + y += 8; + } + line = line.substr(l); // 4J Stu - Don't draw text that will be partially cutoff/overlap something it shouldn't if( (y + 8) > h) break; - } + } // 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); - y += 8; - } - } + draw(line, x, y, col); + y += 8; + } + } } int Font::wordWrapHeight(const wstring& string, int w) { - vector lines = stringSplit(string,L'\n'); - if (lines.size() > 1) + vector lines = stringSplit(string,L'\n'); + if (lines.size() > 1) { - int h = 0; - for ( auto& it : lines ) - { - h += this->wordWrapHeight(it, w); - } - return h; - } + int h = 0; + for ( auto& it : lines ) + { + h += this->wordWrapHeight(it, w); + } + return h; + } vector words = stringSplit(string,L' '); - unsigned int pos = 0; - int y = 0; - while (pos < words.size()) + unsigned int pos = 0; + int y = 0; + while (pos < words.size()) { - wstring line = words[pos++] + L" "; - while (pos < words.size() && width(line + words[pos]) < w) + wstring line = words[pos++] + L" "; + while (pos < words.size() && width(line + words[pos]) < w) { - line += words[pos++] + L" "; - } - while (width(line) > w) + line += words[pos++] + L" "; + } + while (width(line) > w) { - int l = 0; + int l = 0; while (width(line.substr(0, l + 1)) <= w) { - l++; - } - if (trimString(line.substr(0, l)).length() > 0) + l++; + } + if (trimString(line.substr(0, l)).length() > 0) { - y += 8; - } - line = line.substr(l); - } - if (trimString(line).length() > 0) { - y += 8; - } - } - if (y < 8) y += 8; - return y; + y += 8; + } + line = line.substr(l); + } + if (trimString(line).length() > 0) { + y += 8; + } + } + if (y < 8) y += 8; + return y; } diff --git a/Minecraft.Client/Font.h b/Minecraft.Client/Font.h index c78ea6785..58bceb4c0 100644 --- a/Minecraft.Client/Font.h +++ b/Minecraft.Client/Font.h @@ -38,7 +38,7 @@ private: std::map m_charMap; 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 // 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(); @@ -48,6 +48,8 @@ public: private: void renderCharacter(wchar_t c); // 4J added 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 public: @@ -65,7 +67,7 @@ public: private: 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 drawLiteral(const wstring& str, int x, int y, int color); // no § parsing int MapCharacter(wchar_t c); // 4J added diff --git a/Minecraft.Client/Gui.cpp b/Minecraft.Client/Gui.cpp index f0d44319a..5e3a954fe 100644 --- a/Minecraft.Client/Gui.cpp +++ b/Minecraft.Client/Gui.cpp @@ -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::BRANCH_STRING); } + if (minecraft->options->renderDebug && minecraft->player != nullptr && minecraft->level != nullptr) { lines.push_back(minecraft->fpsString); lines.push_back(L"E: " + std::to_wstring(minecraft->level->getAllEntities().size())); 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(minecraft->gatherStats4()); + // Dimension wstring dimension = L"unknown"; switch (minecraft->player->dimension) { - case -1: dimension = L"minecraft:the_nether"; break; - case 0: dimension = L"minecraft:overworld"; break; - case 1: dimension = L"minecraft:the_end"; break; + case -1: + dimension = L"minecraft:the_nether"; + break; + case 0: + dimension = L"minecraft:overworld"; + break; + case 1: + dimension = L"minecraft:the_end"; + break; } lines.push_back(dimension); - lines.push_back(L""); + lines.push_back(L""); // Spacer + + // Players block pos int xBlockPos = Mth::floor(minecraft->player->x); int yBlockPos = Mth::floor(minecraft->player->y); int zBlockPos = Mth::floor(minecraft->player->z); + + // Chunk player is in int xChunkPos = xBlockPos >> 4; int yChunkPos = yBlockPos >> 4; int zChunkPos = zBlockPos >> 4; + + // Players offset within the chunk int xChunkOffset = xBlockPos & 15; int yChunkOffset = yBlockPos & 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); 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"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); 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]; 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; const wchar_t* cardinals[] = { L"south", L"west", L"north", L"east" }; 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)) { LevelChunk *chunkAt = minecraft->level->getChunkAt(xBlockPos, zBlockPos); 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 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"CH S: " + std::to_wstring(chunkAt->getHeightmap(xChunkOffset, zChunkOffset))); + 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"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(minecraft->gatherStats1()); - lines.push_back(minecraft->gatherStats2()); - lines.push_back(minecraft->gatherStats3()); - } + lines.push_back(minecraft->gatherStats1()); // Time to autosave + lines.push_back(minecraft->gatherStats2()); // Empty currently - CPlatformNetworkManagerStub::GatherStats() + lines.push_back(minecraft->gatherStats3()); // RTT -#ifdef _DEBUG - if (minecraft->options->renderDebug && minecraft->player != nullptr && minecraft->level != nullptr && 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: "; - - // maxW in font units: physical width divided by font scale - float maxW = (static_cast(g_rScreenWidth) - debugLeft - 8) / fontScale; - float maxWForContent = maxW - static_cast(font->width(L"...")); - bool truncated[eTerrainFeature_Count] = {}; - - for (size_t i = 0; i < app.m_vTerrainFeatures.size(); i++) +#ifdef _DEBUG // Only show terrain features in debug builds not release + + // No point trying to render this when not in the overworld + if (minecraft->level->dimension->id == 0) { - FEATURE_DATA *pFeatureData = app.m_vTerrainFeatures[i]; - 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 + wstring wfeature[eTerrainFeature_Count]; + 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(g_rScreenWidth) - debugLeft - 8) / fontScale; + float maxWForContent = maxW - static_cast(font->width(L"...")); + bool truncated[eTerrainFeature_Count] = {}; + + for (size_t i = 0; i < app.m_vTerrainFeatures.size(); i++) { - wfeature[type] += L"..."; - truncated[type] = true; + FEATURE_DATA *pFeatureData = app.m_vTerrainFeatures[i]; + 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(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(eTerrainFeature_Ravine); i++) - lines.push_back(wfeature[i]); - lines.push_back(L""); - } #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; for (const auto &line : lines) { @@ -1182,6 +1217,9 @@ void Gui::render(float a, bool mouseFree, int xMouse, int yMouse) yPos += 10; } + // Restore the depth test + glEnable(GL_DEPTH_TEST); + glMatrixMode(GL_MODELVIEW); glPopMatrix(); glMatrixMode(GL_PROJECTION); diff --git a/Minecraft.Client/Options.cpp b/Minecraft.Client/Options.cpp index ebe1295af..60886597e 100644 --- a/Minecraft.Client/Options.cpp +++ b/Minecraft.Client/Options.cpp @@ -170,6 +170,7 @@ void Options::init() particles = 0; fov = 0; gamma = 0; + advancedTooltips = false; } 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"ao") ambientOcclusion = 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"lastServer") lastMpIp = cmds[1]; + if (cmds[0] == L"advancedTooltips") advancedTooltips = cmds[1]==L"false"; + if (cmds[0] == L"skin") skin = cmds[1]; + if (cmds[0] == L"lastServer") lastMpIp = cmds[1]; 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(ambientOcclusion ? L"ao:true" : L"ao: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); for (int i = 0; i < keyMappings_length; i++) diff --git a/Minecraft.Client/Options.h b/Minecraft.Client/Options.h index 8be61ac6e..29cd83ac9 100644 --- a/Minecraft.Client/Options.h +++ b/Minecraft.Client/Options.h @@ -110,6 +110,7 @@ public: int particles; // 0 is all, 1 is decreased and 2 is minimal float fov; float gamma; + bool advancedTooltips; void init(); // 4J added Options(Minecraft *minecraft, File workingDirectory); diff --git a/Minecraft.Client/PlayerConnection.cpp b/Minecraft.Client/PlayerConnection.cpp index 6319b660e..1fb7c3988 100644 --- a/Minecraft.Client/PlayerConnection.cpp +++ b/Minecraft.Client/PlayerConnection.cpp @@ -1631,8 +1631,10 @@ bool PlayerConnection::isDisconnected() void PlayerConnection::handleDebugOptions(shared_ptr packet) { - //Player player = dynamic_pointer_cast( player->shared_from_this() ); - player->SetDebugOptions(packet->m_uiVal); +#ifdef _DEBUG + // Player player = dynamic_pointer_cast( player->shared_from_this() ); + player->SetDebugOptions(packet->m_uiVal); +#endif } void PlayerConnection::handleCraftItem(shared_ptr packet) diff --git a/Minecraft.Client/Windows64/KeyboardMouseInput.cpp b/Minecraft.Client/Windows64/KeyboardMouseInput.cpp index 54191ebcb..be6efe906 100644 --- a/Minecraft.Client/Windows64/KeyboardMouseInput.cpp +++ b/Minecraft.Client/Windows64/KeyboardMouseInput.cpp @@ -234,6 +234,13 @@ bool KeyboardMouseInput::IsKeyReleased(int vkCode) const 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 { if (button >= 0 && button < MAX_MOUSE_BUTTONS) diff --git a/Minecraft.Client/Windows64/KeyboardMouseInput.h b/Minecraft.Client/Windows64/KeyboardMouseInput.h index 5c406983f..e8b5f5888 100644 --- a/Minecraft.Client/Windows64/KeyboardMouseInput.h +++ b/Minecraft.Client/Windows64/KeyboardMouseInput.h @@ -56,6 +56,8 @@ public: bool IsKeyPressed(int vkCode) const; bool IsKeyReleased(int vkCode) const; + int GetPressedKey() const; + bool IsMouseButtonDown(int button) const; bool IsMouseButtonPressed(int button) const; bool IsMouseButtonReleased(int button) const; diff --git a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp index 81430ffcc..fa5f4cccb 100644 --- a/Minecraft.Client/Windows64/Windows64_Minecraft.cpp +++ b/Minecraft.Client/Windows64/Windows64_Minecraft.cpp @@ -36,6 +36,7 @@ //#include "NetworkManager.h" #include "..\..\Minecraft.Client\Tesselator.h" #include "..\..\Minecraft.Client\Options.h" +#include "..\Gui.h" #include "Sentient\SentientManager.h" #include "..\..\Minecraft.World\IntCache.h" #include "..\Textures.h" @@ -107,6 +108,7 @@ int g_iScreenHeight = 1080; // always matches the current window, even after a resize. int g_rScreenWidth = 1920; int g_rScreenHeight = 1080; +static bool f3ComboUsed = false; float g_iAspectRatio = static_cast(g_iScreenWidth) / g_iScreenHeight; static bool g_bResizeReady = false; @@ -1774,17 +1776,37 @@ int APIENTRY _tWinMain(_In_ HINSTANCE hInstance, } // 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) - { - pMinecraft->options->renderDebug = !pMinecraft->options->renderDebug; - } + // advanced tooltips + case 'H': + 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 // F6 Open debug console if (g_KBMInput.IsKeyPressed(KeyboardMouseInput::KEY_DEBUG_CONSOLE)) diff --git a/Minecraft.Client/Windows64Media/DLC/Natural/Data/x32Data.pck b/Minecraft.Client/Windows64Media/DLC/Natural/Data/x32Data.pck index c5f592c42..5bb3ebfc2 100644 Binary files a/Minecraft.Client/Windows64Media/DLC/Natural/Data/x32Data.pck and b/Minecraft.Client/Windows64Media/DLC/Natural/Data/x32Data.pck differ diff --git a/Minecraft.World/AbstractContainerMenu.cpp b/Minecraft.World/AbstractContainerMenu.cpp index c98fc22c5..0b2abc23a 100644 --- a/Minecraft.World/AbstractContainerMenu.cpp +++ b/Minecraft.World/AbstractContainerMenu.cpp @@ -157,7 +157,7 @@ shared_ptr AbstractContainerMenu::clicked(int slotIndex, int butto shared_ptr clickedEntity = nullptr; shared_ptr inventory = player->inventory; - if (slotIndex < 0 || slotIndex >= (int)slots.size()) + if ((slotIndex < 0 && slotIndex != SLOT_CLICKED_OUTSIDE) || slotIndex >= (int)slots.size()) return nullptr; if (clickType == CLICK_QUICK_CRAFT) diff --git a/Minecraft.World/ClothDyeRecipes.cpp b/Minecraft.World/ClothDyeRecipes.cpp index c0625d2e1..35d0b5b84 100644 --- a/Minecraft.World/ClothDyeRecipes.cpp +++ b/Minecraft.World/ClothDyeRecipes.cpp @@ -21,20 +21,20 @@ void ClothDyeRecipes::addRecipes(Recipes *r) L'#', new ItemInstance(Tile::clayHardened), L'X', new ItemInstance(Item::dye_powder, 1, i),L'D'); -#if 0 - 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, i), // - L"ssczg", - L"###", - L"###", - L'#', new ItemInstance(Tile::stained_glass, 1, i), L'D'); -#endif +//#if 0 +// 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, i), // +// L"ssczg", +// L"###", +// L"###", +// L'#', new ItemInstance(Tile::stained_glass, 1, i), L'D'); +//#endif } // some dye recipes diff --git a/Minecraft.World/ItemInstance.cpp b/Minecraft.World/ItemInstance.cpp index 4906c22e6..e4af60c67 100644 --- a/Minecraft.World/ItemInstance.cpp +++ b/Minecraft.World/ItemInstance.cpp @@ -562,34 +562,27 @@ vector *ItemInstance::getHoverText(shared_ptr player, bool a title.italics = true; } - // 4J: This is for showing aux values, not useful in console version - /* if (advanced) { wstring suffix = L""; - if (title.length() > 0) + if (title.text.length() > 0) { - title += L" ("; + title.text += L" ("; suffix = L")"; } + wchar_t buf[64]; if (isStackedByData()) - { - title += String.format("#%04d/%d%s", id, auxValue, suffix); - } + swprintf_s(buf, 64, L"#%04d/%d%s", id, auxValue, suffix.c_str()); else - { - title += String.format("#%04d%s", id, suffix); - } + swprintf_s(buf, 64, L"#%04d%s", id, suffix.c_str()); + title.text += buf; } else if (!hasCustomHoverName() && id == Item::map_Id) - */ - - /*if (!hasCustomHoverName() && id == Item::map_Id) { title.text += L" #" + std::to_wstring(auxValue); - }*/ + } lines->push_back(title); @@ -615,7 +608,7 @@ vector *ItemInstance::getHoverText(shared_ptr player, bool a if (tag->contains(L"display")) { - //CompoundTag *display = tag->getCompound(L"display"); + CompoundTag *display = tag->getCompound(L"display"); //if (display->contains(L"color")) //{ @@ -631,8 +624,7 @@ vector *ItemInstance::getHoverText(shared_ptr player, bool a // } //} - // 4J: Lore isn't in use in game - /*if (display->contains(L"Lore")) + if (display->contains(L"Lore")) { ListTag *lore = (ListTag *) display->getList(L"Lore"); if (lore->size() > 0) @@ -643,7 +635,7 @@ vector *ItemInstance::getHoverText(shared_ptr player, bool a lines->push_back(lore->get(i)->data); } } - }*/ + } } } @@ -674,7 +666,7 @@ vector *ItemInstance::getHoverText(shared_ptr player, bool a { 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)); } } diff --git a/Minecraft.World/Level.h b/Minecraft.World/Level.h index 2be874722..3892d97ee 100644 --- a/Minecraft.World/Level.h +++ b/Minecraft.World/Level.h @@ -63,10 +63,10 @@ public: public: - static const int MAX_XBOX_BOATS = 40; // Max number of boats - static const int MAX_CONSOLE_MINECARTS = 40; - static const int MAX_DISPENSABLE_FIREBALLS = 200; - static const int MAX_DISPENSABLE_PROJECTILES = 300; + static const int MAX_XBOX_BOATS = 60; // Max number of boats + static const int MAX_CONSOLE_MINECARTS = 60; + static const int MAX_DISPENSABLE_FIREBALLS = 300; + static const int MAX_DISPENSABLE_PROJECTILES = 400; static const int MAX_LEVEL_SIZE = 30000000; static const int maxMovementHeight = 512; // 4J added diff --git a/Minecraft.World/Recipes.cpp b/Minecraft.World/Recipes.cpp index 24faaebec..48a04e15a 100644 --- a/Minecraft.World/Recipes.cpp +++ b/Minecraft.World/Recipes.cpp @@ -299,6 +299,7 @@ Recipes::Recipes() pClothDyeRecipes->addRecipes(this); + addShapedRecipy(new ItemInstance(Tile::snow, 1), // L"sscig", L"##", // diff --git a/Minecraft.World/StructureRecipies.cpp b/Minecraft.World/StructureRecipies.cpp index 1706a7ced..652a730cb 100644 --- a/Minecraft.World/StructureRecipies.cpp +++ b/Minecraft.World/StructureRecipies.cpp @@ -115,6 +115,28 @@ void StructureRecipies::addRecipes(Recipes *r) L'#', Tile::glass, 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), // L"sscig", diff --git a/Minecraft.World/Tile.cpp b/Minecraft.World/Tile.cpp index de113714d..e80ac1081 100644 --- a/Minecraft.World/Tile.cpp +++ b/Minecraft.World/Tile.cpp @@ -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::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::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(); diff --git a/cmake/CopyFileScript.cmake b/cmake/CopyFileScript.cmake index a6b2f8397..ac156ca14 100644 --- a/cmake/CopyFileScript.cmake +++ b/cmake/CopyFileScript.cmake @@ -3,6 +3,7 @@ # Required: # COPY_SOURCE – pipe-separated list of source file paths # COPY_DEST – destination directory +cmake_minimum_required(VERSION 3.24) if(NOT COPY_SOURCE OR NOT COPY_DEST) message(FATAL_ERROR "COPY_SOURCE and COPY_DEST must be set.")