mirror of
https://github.com/celisej567/mcpe.git
synced 2026-09-17 20:10:23 +03:00
github.dev removing files randomly lmfao
This commit is contained in:
39
source/gui/AvailableGamesList.cpp
Normal file
39
source/gui/AvailableGamesList.cpp
Normal file
@@ -0,0 +1,39 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "AvailableGamesList.hpp"
|
||||
|
||||
AvailableGamesList::AvailableGamesList(Minecraft* a, int b, int c, int d, int e, int f) :
|
||||
ScrolledSelectionList(a, b, c, d, e, f)
|
||||
{
|
||||
}
|
||||
|
||||
int AvailableGamesList::getNumberOfItems()
|
||||
{
|
||||
return int(m_games.size());
|
||||
}
|
||||
|
||||
bool AvailableGamesList::isSelectedItem(int i)
|
||||
{
|
||||
return m_selectedIndex == i;
|
||||
}
|
||||
|
||||
void AvailableGamesList::renderBackground()
|
||||
{
|
||||
}
|
||||
|
||||
void AvailableGamesList::renderItem(int idx, int x, int y, int width, Tesselator& t)
|
||||
{
|
||||
drawString(m_pMinecraft->m_pFont, std::string(m_games[idx].m_name.C_String()), x, y + 2, 0xFFFFA0);
|
||||
drawString(m_pMinecraft->m_pFont, std::string(m_games[idx].m_address.ToString()), x, y + 16, 0xFFFFA0);
|
||||
}
|
||||
|
||||
void AvailableGamesList::selectItem(int index, bool b)
|
||||
{
|
||||
m_selectedIndex = index;
|
||||
}
|
||||
28
source/gui/AvailableGamesList.hpp
Normal file
28
source/gui/AvailableGamesList.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ScrolledSelectionList.hpp"
|
||||
#include "PingedCompatibleServer.hpp"
|
||||
|
||||
class AvailableGamesList : public ScrolledSelectionList
|
||||
{
|
||||
public:
|
||||
AvailableGamesList(Minecraft*, int, int, int, int, int);
|
||||
int getNumberOfItems() override;
|
||||
bool isSelectedItem(int i) override;
|
||||
void renderBackground() override;
|
||||
void renderItem(int, int, int, int, Tesselator& t) override;
|
||||
void selectItem(int, bool) override;
|
||||
|
||||
public:
|
||||
int m_selectedIndex;
|
||||
std::vector<PingedCompatibleServer> m_games;
|
||||
};
|
||||
|
||||
97
source/gui/Button.cpp
Normal file
97
source/gui/Button.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "Button.hpp"
|
||||
|
||||
Button::Button(int a2, int xPos, int yPos, int btnWidth, int btnHeight, const std::string& text)
|
||||
{
|
||||
field_30 = a2;
|
||||
m_xPos = xPos;
|
||||
m_yPos = yPos;
|
||||
field_18 = text;
|
||||
m_width = btnWidth;
|
||||
m_height = btnHeight;
|
||||
}
|
||||
|
||||
Button::Button(int a2, int xPos, int yPos, const std::string& text)
|
||||
{
|
||||
field_30 = a2;
|
||||
m_xPos = xPos;
|
||||
m_yPos = yPos;
|
||||
field_18 = text;
|
||||
m_width = 200;
|
||||
m_height = 24;
|
||||
}
|
||||
|
||||
Button::Button(int a2, const std::string& text)
|
||||
{
|
||||
field_30 = a2;
|
||||
field_18 = text;
|
||||
m_width = 200;
|
||||
m_height = 24;
|
||||
}
|
||||
|
||||
bool Button::clicked(Minecraft* pMinecraft, int xPos, int yPos)
|
||||
{
|
||||
if (!m_bEnabled) return false;
|
||||
if (xPos < m_xPos) return false;
|
||||
if (yPos < m_yPos) return false;
|
||||
if (xPos >= m_xPos + m_width) return false;
|
||||
if (yPos >= m_yPos + m_height) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int Button::getYImage(bool bHovered)
|
||||
{
|
||||
if (!m_bEnabled) return 0;
|
||||
if (bHovered) return 2;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Button::released(int xPos, int yPos)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Button::renderBg(Minecraft*, int, int)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Button::render(Minecraft* pMinecraft, int xPos, int yPos)
|
||||
{
|
||||
if (!m_bVisible) return;
|
||||
|
||||
#ifdef ENH_HIGHLIGHT_BY_HOVER
|
||||
field_36 = clicked(pMinecraft, xPos, yPos);
|
||||
#endif
|
||||
|
||||
Font* pFont = pMinecraft->m_pFont;
|
||||
Textures* pTexs = pMinecraft->m_pTextures;
|
||||
|
||||
pTexs->loadAndBindTexture("gui/gui.png");
|
||||
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
int iYPos = 20 * getYImage(field_36) + 46;
|
||||
|
||||
blit(m_xPos, m_yPos, 0, iYPos, m_width / 2, m_height, 0, 20);
|
||||
blit(m_xPos + m_width / 2, m_yPos, 200 - m_width / 2, iYPos, m_width / 2, m_height, 0, 20);
|
||||
|
||||
renderBg(pMinecraft, xPos, yPos);
|
||||
|
||||
int textColor;
|
||||
if (!m_bEnabled)
|
||||
textColor = int(0xFFA0A0A0U);
|
||||
else if (field_36)
|
||||
textColor = int(0xFFFFA0U);
|
||||
else
|
||||
textColor = int(0xE0E0E0U);
|
||||
|
||||
drawCenteredString(pFont, field_18, m_xPos + m_width / 2, m_yPos + (m_height - 8) / 2, textColor);
|
||||
}
|
||||
46
source/gui/Button.hpp
Normal file
46
source/gui/Button.hpp
Normal file
@@ -0,0 +1,46 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GuiComponent.hpp"
|
||||
#include "Minecraft.hpp"
|
||||
|
||||
class Screen;
|
||||
|
||||
class Button : public GuiComponent
|
||||
{
|
||||
public:
|
||||
Button(int, int x, int y, int width, int height, const std::string&);
|
||||
Button(int, int x, int y, const std::string&);
|
||||
Button(int, const std::string&);
|
||||
|
||||
// I can't possibly explain why Minecraft is referenced here
|
||||
bool clicked(Minecraft*, int xPos, int yPos);
|
||||
int getYImage(bool bHovered);
|
||||
void released(int xPos, int yPos);
|
||||
void renderBg(Minecraft*, int, int);
|
||||
void render(Minecraft*, int xPos, int yPos);
|
||||
|
||||
public:
|
||||
int m_width = 0;
|
||||
int m_height = 0;
|
||||
int m_xPos = 0;
|
||||
int m_yPos = 0;
|
||||
std::string field_18 = "";
|
||||
int field_30;
|
||||
bool m_bEnabled = true;
|
||||
bool m_bVisible = true;
|
||||
bool field_36 = false;
|
||||
|
||||
#ifndef ORIGINAL_CODE
|
||||
int m_lastX = 0;
|
||||
int m_lastY = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
416
source/gui/Gui.cpp
Normal file
416
source/gui/Gui.cpp
Normal file
@@ -0,0 +1,416 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "Minecraft.hpp"
|
||||
#include "IngameBlockSelectionScreen.hpp"
|
||||
#include "ItemRenderer.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning(disable : 4244)
|
||||
#endif
|
||||
|
||||
#ifdef ENH_USE_GUI_SCALE_2
|
||||
float Gui::InvGuiScale = 0.5f;
|
||||
#else
|
||||
float Gui::InvGuiScale = 0.333333f;
|
||||
#endif
|
||||
|
||||
Gui::Gui(Minecraft* pMinecraft)
|
||||
{
|
||||
m_pMinecraft = pMinecraft;
|
||||
|
||||
xglGenBuffers(1, &m_renderChunk.field_0);
|
||||
}
|
||||
|
||||
void Gui::addMessage(const std::string& s)
|
||||
{
|
||||
std::string str = s;
|
||||
|
||||
while (m_pMinecraft->m_pFont->width(str) > 320)
|
||||
{
|
||||
int i = 2;
|
||||
for (; i < int(str.size()); i++)
|
||||
{
|
||||
std::string sstr = str.substr(0, i);
|
||||
|
||||
// this sucks
|
||||
if (m_pMinecraft->m_pFont->width(sstr) > 320)
|
||||
break;
|
||||
}
|
||||
|
||||
std::string sstr = str.substr(0, i - 1);
|
||||
addMessage(sstr);
|
||||
str = str.substr(i - 1);
|
||||
}
|
||||
|
||||
if (m_guiMessages.size() > 50)
|
||||
{
|
||||
m_guiMessages.erase(m_guiMessages.end());
|
||||
}
|
||||
|
||||
m_guiMessages.insert(m_guiMessages.begin(), GuiMessage(str, 0));
|
||||
}
|
||||
|
||||
void Gui::setNowPlaying(const std::string& str)
|
||||
{
|
||||
field_A00 = "Now playing: " + str;
|
||||
field_A18 = 60;
|
||||
field_A1C = true;
|
||||
}
|
||||
|
||||
void Gui::renderVignette(float a2, int a3, int a4)
|
||||
{
|
||||
a2 = 1.0f - a2;
|
||||
if (a2 > 1.0f)
|
||||
a2 = 1.0f;
|
||||
if (a2 < 0.0f)
|
||||
a2 = 0.0f;
|
||||
|
||||
field_A20 += ((a2 - field_A20) * 0.01f);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glDepthMask(false);
|
||||
glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
|
||||
glColor4f(field_A20, field_A20, field_A20, 1.0f);
|
||||
|
||||
//! @BUG: No misc/vignette.png to be found in the original.
|
||||
//! This function is unused anyways
|
||||
m_pMinecraft->m_pTextures->loadAndBindTexture("misc/vignette.png");
|
||||
|
||||
Tesselator& t = Tesselator::instance;
|
||||
t.begin();
|
||||
t.vertexUV(0.0f, a4, -90.0f, 0.0f, 1.0f);
|
||||
t.vertexUV(a3, a4, -90.0f, 1.0f, 1.0f);
|
||||
t.vertexUV(a3, 0.0f, -90.0f, 1.0f, 0.0f);
|
||||
t.vertexUV(0.0f, 0.0f, -90.0f, 0.0f, 0.0f);
|
||||
t.draw();
|
||||
|
||||
glDepthMask(true);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
}
|
||||
|
||||
void Gui::inventoryUpdated()
|
||||
{
|
||||
field_A3C = true;
|
||||
}
|
||||
|
||||
void Gui::render(float f, bool bHaveScreen, int mouseX, int mouseY)
|
||||
{
|
||||
Minecraft* m = m_pMinecraft;
|
||||
|
||||
m->m_pGameRenderer->setupGuiScreen();
|
||||
|
||||
if (!m->m_pLevel || !m->m_pLocalPlayer)
|
||||
return;
|
||||
|
||||
field_4 = -90.0f;
|
||||
|
||||
#ifndef ENH_TRANSPARENT_HOTBAR
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.5f);
|
||||
#else
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
#endif
|
||||
|
||||
m->m_pTextures->loadAndBindTexture("gui/gui.png");
|
||||
|
||||
Inventory* pInventory = m->m_pLocalPlayer->m_pInventory;
|
||||
|
||||
field_4 = -90.0f;
|
||||
|
||||
int width = Minecraft::width * InvGuiScale,
|
||||
height = Minecraft::height * InvGuiScale;
|
||||
|
||||
#ifdef ENH_TRANSPARENT_HOTBAR
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
#endif
|
||||
|
||||
// hotbar
|
||||
int cenX = width / 2;
|
||||
blit(cenX - 182 / 2, height - 22, 0, 0, 182, 22, 0, 0);
|
||||
|
||||
// selection mark
|
||||
blit(cenX - 92 + 20 * pInventory->m_SelectedHotbarSlot, height - 23, 0, 22, 24, 22, 0, 0);
|
||||
|
||||
m->m_pTextures->loadAndBindTexture("gui/icons.png");
|
||||
|
||||
#ifndef ENH_TRANSPARENT_HOTBAR
|
||||
glEnable(GL_BLEND);
|
||||
#endif
|
||||
|
||||
glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE_MINUS_SRC_COLOR);
|
||||
|
||||
// crosshair
|
||||
blit(cenX - 8, height / 2 - 8, 0, 0, 16, 16, 0, 0);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
|
||||
if (m_pMinecraft->m_pGameMode->canHurtPlayer())
|
||||
{
|
||||
LocalPlayer* pLP = m_pMinecraft->m_pLocalPlayer;
|
||||
|
||||
// why??
|
||||
m_random.init_genrand(312871 * field_9FC);
|
||||
|
||||
int emptyHeartX = 16;
|
||||
bool b1 = false;
|
||||
if (pLP->field_B8 < 10)
|
||||
{
|
||||
b1 = pLP->field_B8 / 3 % 2;
|
||||
emptyHeartX += 9 * b1;
|
||||
}
|
||||
|
||||
// @NOTE: At the default scale, this would go off screen.
|
||||
|
||||
int heartX = cenX - 191; // why?
|
||||
int heartYStart = height - 10;
|
||||
|
||||
//@NOTE: Alpha-style health UI. I'll probably remove this on release.
|
||||
#ifndef ORIGINAL_CODE
|
||||
heartX = cenX - 91;
|
||||
heartYStart = height - 32;
|
||||
#endif
|
||||
|
||||
int playerHealth = pLP->m_health;
|
||||
|
||||
for (int healthNo = 1; healthNo <= C_MAX_MOB_HEALTH; healthNo += 2)
|
||||
{
|
||||
int heartY = heartYStart;
|
||||
|
||||
if (playerHealth <= 4 && m_random.genrand_int32() % 2)
|
||||
heartY++;
|
||||
|
||||
blit(heartX, heartY, emptyHeartX, 0, 9, 9, 0, 0);
|
||||
|
||||
if (b1)
|
||||
{
|
||||
if (healthNo < pLP->field_100)
|
||||
blit(heartX, heartY, 70, 0, 9, 9, 0, 0);
|
||||
else if (healthNo == pLP->field_100)
|
||||
blit(heartX, heartY, 79, 0, 9, 9, 0, 0);
|
||||
}
|
||||
|
||||
if (healthNo < playerHealth)
|
||||
blit(heartX, heartY, 52, 0, 9, 9, 0, 0);
|
||||
else if (healthNo == playerHealth)
|
||||
blit(heartX, heartY, 61, 0, 9, 9, 0, 0);
|
||||
|
||||
heartX += 8;
|
||||
}
|
||||
|
||||
if (m->m_pLocalPlayer->isUnderLiquid(Material::water))
|
||||
{
|
||||
int breathRaw = m->m_pLocalPlayer->field_BC;
|
||||
int breathFull = int(ceilf((float(breathRaw - 2) * 10.0f) / 300.0f));
|
||||
int breathMeter = int(ceilf((float(breathRaw) * 10.0f) / 300.0f)) - breathFull;
|
||||
|
||||
int bubbleX = cenX - 191;
|
||||
int bubbleY = height - 19;
|
||||
|
||||
#ifndef ORIGINAL_CODE
|
||||
bubbleX = cenX - 91;
|
||||
bubbleY = height - 41;
|
||||
#endif
|
||||
|
||||
//@NOTE: Not sure this works as it should
|
||||
|
||||
for (int bubbleNo = 0; bubbleNo < breathFull + breathMeter; bubbleNo++)
|
||||
{
|
||||
if (bubbleNo < breathFull)
|
||||
blit(bubbleX, bubbleY, 16, 18, 9, 9, 0, 0);
|
||||
else
|
||||
blit(bubbleX, bubbleY, 25, 18, 9, 9, 0, 0);
|
||||
|
||||
bubbleX += 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m->m_pTextures->loadAndBindTexture("gui/gui_blocks.png");
|
||||
|
||||
int slotX = cenX - 88;
|
||||
for (int i = 0; i < C_MAX_HOTBAR_ITEMS; i++)
|
||||
{
|
||||
renderSlot(i, slotX, height - 19, f);
|
||||
|
||||
slotX += 20;
|
||||
}
|
||||
|
||||
slotX = cenX - 88;
|
||||
for (int i = 0; i < C_MAX_HOTBAR_ITEMS; i++)
|
||||
{
|
||||
renderSlotOverlay(i, slotX, height - 19, f);
|
||||
|
||||
slotX += 20;
|
||||
}
|
||||
|
||||
field_A3C = false;
|
||||
|
||||
// blit the "more items" button
|
||||
#ifndef ENH_ENABLE_9TH_SLOT
|
||||
m->m_pTextures->loadAndBindTexture(C_TERRAIN_NAME);
|
||||
blit(cenX + 72, height - 19, 208, 208, 16, 16, 0, 0);
|
||||
#endif
|
||||
|
||||
// render messages
|
||||
|
||||
int topEdge = height - 49;
|
||||
|
||||
for (auto& msg : m_guiMessages)
|
||||
{
|
||||
if (msg.field_18 > 199)
|
||||
continue;
|
||||
|
||||
int bkgdColor = 0x7F000000, textColor = 0xFFFFFFFF;
|
||||
|
||||
float fade = 10.0f * (1.0f - (float(msg.field_18) / 200.0f));
|
||||
if (fade <= 0.0f)
|
||||
continue;
|
||||
|
||||
if (fade < 1.0f)
|
||||
{
|
||||
int x = int(fade * fade * 255.0f);
|
||||
if (x == 0)
|
||||
continue;
|
||||
|
||||
bkgdColor = (x / 2) << 24;
|
||||
textColor = (x << 24) + 0xFFFFFF;
|
||||
}
|
||||
|
||||
fill(2, topEdge, 322, topEdge + 9, bkgdColor);
|
||||
glEnable(GL_BLEND);
|
||||
m->m_pFont->drawShadow(msg.msg, 2, topEdge + 1, textColor);
|
||||
|
||||
topEdge -= 9;
|
||||
}
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void Gui::tick()
|
||||
{
|
||||
for (auto& msg : m_guiMessages)
|
||||
{
|
||||
msg.field_18++;
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::renderSlot(int slot, int x, int y, float f)
|
||||
{
|
||||
Inventory* pInv = m_pMinecraft->m_pLocalPlayer->m_pInventory;
|
||||
|
||||
ItemInstance* pInst = pInv->getQuickSlotItem(slot);
|
||||
if (!pInst)
|
||||
return;
|
||||
|
||||
if (!pInst->m_itemID)
|
||||
return;
|
||||
|
||||
ItemRenderer::renderGuiItem(m_pMinecraft->m_pFont, m_pMinecraft->m_pTextures, pInst, x, y, true);
|
||||
}
|
||||
|
||||
void Gui::renderSlotOverlay(int slot, int x, int y, float f)
|
||||
{
|
||||
Inventory* pInv = m_pMinecraft->m_pLocalPlayer->m_pInventory;
|
||||
|
||||
ItemInstance* pInst = pInv->getQuickSlotItem(slot);
|
||||
if (!pInst)
|
||||
return;
|
||||
|
||||
if (!pInst->m_itemID)
|
||||
return;
|
||||
|
||||
ItemRenderer::renderGuiItemOverlay(m_pMinecraft->m_pFont, m_pMinecraft->m_pTextures, pInst, x, y);
|
||||
}
|
||||
|
||||
int Gui::getSlotIdAt(int mouseX, int mouseY)
|
||||
{
|
||||
int scaledY = int(InvGuiScale * mouseY);
|
||||
int scaledHeight = int(InvGuiScale * Minecraft::height);
|
||||
|
||||
if (scaledY >= scaledHeight)
|
||||
return -1;
|
||||
if (scaledY < scaledHeight-19)
|
||||
return -1;
|
||||
|
||||
int slotX = (int(InvGuiScale * mouseX) - int(InvGuiScale * Minecraft::width) / 2 + 88 + 20) / 20;
|
||||
|
||||
//@NOTE: Why not just -88?
|
||||
if (slotX >= 0)
|
||||
slotX--;
|
||||
|
||||
if (slotX > 8)
|
||||
slotX = -1;
|
||||
|
||||
return slotX;
|
||||
}
|
||||
|
||||
bool Gui::isInside(int mouseX, int mouseY)
|
||||
{
|
||||
return getSlotIdAt(mouseX, mouseY) != -1;
|
||||
}
|
||||
|
||||
void Gui::handleClick(int clickID, int mouseX, int mouseY)
|
||||
{
|
||||
if (clickID != 1)
|
||||
return;
|
||||
|
||||
int slot = getSlotIdAt(mouseX, mouseY);
|
||||
if (slot == -1)
|
||||
return;
|
||||
|
||||
#ifndef ENH_ENABLE_9TH_SLOT
|
||||
if (slot == 8)
|
||||
{
|
||||
m_pMinecraft->setScreen(new IngameBlockSelectionScreen);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
m_pMinecraft->m_pLocalPlayer->m_pInventory->selectSlot(slot);
|
||||
}
|
||||
}
|
||||
|
||||
void Gui::handleKeyPressed(int keyCode)
|
||||
{
|
||||
switch (keyCode)
|
||||
{
|
||||
case AKEYCODE_BUTTON_Y:
|
||||
{
|
||||
m_pMinecraft->setScreen(new IngameBlockSelectionScreen);
|
||||
break;
|
||||
}
|
||||
|
||||
case AKEYCODE_BACK:
|
||||
{
|
||||
int* slot = &m_pMinecraft->m_pLocalPlayer->m_pInventory->m_SelectedHotbarSlot;
|
||||
|
||||
#ifdef ENH_ENABLE_9TH_SLOT
|
||||
#define MAX_ITEMS (C_MAX_HOTBAR_ITEMS - 2)
|
||||
#else
|
||||
#define MAX_ITEMS (C_MAX_HOTBAR_ITEMS - 3)
|
||||
#endif
|
||||
//@HUH: for whatever reason, it ignores the 7th item
|
||||
if (*slot <= MAX_ITEMS)
|
||||
(*slot)++;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case AKEYCODE_BUTTON_X:
|
||||
{
|
||||
int* slot = &m_pMinecraft->m_pLocalPlayer->m_pInventory->m_SelectedHotbarSlot;
|
||||
|
||||
if (*slot > 0)
|
||||
(*slot)--;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
64
source/gui/Gui.hpp
Normal file
64
source/gui/Gui.hpp
Normal file
@@ -0,0 +1,64 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GuiComponent.hpp"
|
||||
#include "Minecraft.hpp"
|
||||
#include "Random.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
class Minecraft; // in case we're included from Minecraft.hpp
|
||||
|
||||
struct GuiMessage
|
||||
{
|
||||
std::string msg;
|
||||
int field_18;
|
||||
|
||||
GuiMessage(const std::string& x, int a) : msg(x), field_18(a) {}
|
||||
};
|
||||
|
||||
class Gui : public GuiComponent
|
||||
{
|
||||
public:
|
||||
Gui(Minecraft* pMinecraft);
|
||||
|
||||
void addMessage(const std::string& str);
|
||||
void inventoryUpdated();
|
||||
void renderVignette(float, int, int);
|
||||
void setNowPlaying(const std::string& str);
|
||||
void render(float f, bool bHaveScreen, int mouseX, int mouseY);
|
||||
void tick();
|
||||
void renderSlot(int slot, int x, int y, float f);
|
||||
void renderSlotOverlay(int slot, int x, int y, float f);
|
||||
int getSlotIdAt(int mx, int my);
|
||||
bool isInside(int mx, int my);
|
||||
void handleClick(int id, int mx, int my);
|
||||
void handleKeyPressed(int keyCode);
|
||||
|
||||
public:
|
||||
static float InvGuiScale;
|
||||
|
||||
public:
|
||||
float field_8 = 0;
|
||||
std::string field_C = "";
|
||||
std::vector<GuiMessage> m_guiMessages;
|
||||
int field_24 = 0;
|
||||
int field_28 = 0;
|
||||
int field_2C = 0;
|
||||
Random m_random;
|
||||
Minecraft* m_pMinecraft;
|
||||
int field_9FC = 0;
|
||||
std::string field_A00 = "";
|
||||
int field_A18 = 0;
|
||||
bool field_A1C = false;
|
||||
float field_A20 = 1.0f;
|
||||
RenderChunk m_renderChunk;
|
||||
bool field_A3C = true;
|
||||
};
|
||||
|
||||
90
source/gui/GuiComponent.cpp
Normal file
90
source/gui/GuiComponent.cpp
Normal file
@@ -0,0 +1,90 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "GuiComponent.hpp"
|
||||
|
||||
#ifdef _WIN32
|
||||
#pragma warning (disable : 4244)
|
||||
#endif
|
||||
|
||||
void GuiComponent::blit(int dx, int dy, int sx, int sy, int tw, int th, int sw, int sh)
|
||||
{
|
||||
auto& t = Tesselator::instance;
|
||||
|
||||
if (!sh) sh = th;
|
||||
if (!sw) sw = tw;
|
||||
|
||||
int width = sw, height = sh;
|
||||
|
||||
t.begin();
|
||||
t.vertexUV(dx, dy + th, field_4, float(sx) / 256.0f, float(sy + sh) / 256.0f);
|
||||
t.vertexUV(dx + tw, dy + th, field_4, float(sx + sw) / 256.0f, float(sy + sh) / 256.0f);
|
||||
t.vertexUV(dx + tw, dy, field_4, float(sx + sw) / 256.0f, float(sy) / 256.0f);
|
||||
t.vertexUV(dx, dy, field_4, float(sx) / 256.0f, float(sy) / 256.0f);
|
||||
t.draw();
|
||||
}
|
||||
|
||||
void GuiComponent::drawCenteredString(Font* pFont, const std::string& str, int cx, int cy, int color)
|
||||
{
|
||||
int width = pFont->width(str);
|
||||
int height = pFont->height(str);
|
||||
pFont->drawShadow(str, cx - width / 2, cy - height / 2, color);
|
||||
}
|
||||
|
||||
void GuiComponent::drawString(Font* pFont, const std::string& str, int cx, int cy, int color)
|
||||
{
|
||||
pFont->drawShadow(str, cx, cy, color);
|
||||
}
|
||||
|
||||
void GuiComponent::fill(int a2, int a3, int a4, int a5, int a6)
|
||||
{
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glColor4f(float(GET_RED(a6)) / 255.0f, float(GET_GREEN(a6)) / 255.0f, float(GET_BLUE(a6)) / 255.0f, float(GET_ALPHA(a6)) / 255.0f);
|
||||
|
||||
Tesselator& t = Tesselator::instance;
|
||||
t.begin();
|
||||
|
||||
t.vertex(a2, a5, 0.0f);
|
||||
t.vertex(a4, a5, 0.0f);
|
||||
t.vertex(a4, a3, 0.0f);
|
||||
t.vertex(a2, a3, 0.0f);
|
||||
|
||||
t.draw();
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void GuiComponent::fillGradient(int a2, int a3, int a4, int a5, int a6, int a7)
|
||||
{
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
|
||||
Tesselator& t = Tesselator::instance;
|
||||
t.begin();
|
||||
|
||||
// note: for some stupid reason OG uses the float overload.
|
||||
t.color(float(GET_RED(a6)) / 255.0f, float(GET_GREEN(a6)) / 255.0f, float(GET_BLUE(a6)) / 255.0f, float(GET_ALPHA(a6)) / 255.0f);
|
||||
t.vertex(a2, a5, 0.0f);
|
||||
t.vertex(a4, a5, 0.0f);
|
||||
t.color(float(GET_RED(a7)) / 255.0f, float(GET_GREEN(a7)) / 255.0f, float(GET_BLUE(a7)) / 255.0f, float(GET_ALPHA(a7)) / 255.0f);
|
||||
t.vertex(a4, a3, 0.0f);
|
||||
t.vertex(a2, a3, 0.0f);
|
||||
|
||||
t.draw();
|
||||
|
||||
glShadeModel(GL_FLAT);
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
26
source/gui/GuiComponent.hpp
Normal file
26
source/gui/GuiComponent.hpp
Normal file
@@ -0,0 +1,26 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Tesselator.hpp"
|
||||
#include "Font.hpp"
|
||||
|
||||
class GuiComponent
|
||||
{
|
||||
public:
|
||||
void blit(int dstX, int dstY, int srcX, int srcY, int dstWidth, int dstHeight, int srcWidth, int srcHeight);
|
||||
void drawCenteredString(Font*, const std::string&, int cx, int cy, int color);
|
||||
void drawString(Font*, const std::string&, int cx, int cy, int color);
|
||||
void fill(int left, int top, int right, int bottom, int color);
|
||||
void fillGradient(int left, int top, int right, int bottom, int colorUp, int colorDown);
|
||||
|
||||
public:
|
||||
float field_4;
|
||||
};
|
||||
|
||||
327
source/gui/RolledSelectionList.cpp
Normal file
327
source/gui/RolledSelectionList.cpp
Normal file
@@ -0,0 +1,327 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "RolledSelectionList.hpp"
|
||||
|
||||
static float g_RolledSelectionListUnk, g_RolledSelectionListUnk2;
|
||||
|
||||
RolledSelectionList::RolledSelectionList(Minecraft* minecraft, int a, int b, int c, int d, int e, int f, int g)
|
||||
{
|
||||
m_pMinecraft = minecraft;
|
||||
m_itemWidth = g;
|
||||
field_18 = a;
|
||||
field_C = float(c);
|
||||
field_10 = float(d);
|
||||
field_1C = b;
|
||||
field_20 = float(e);
|
||||
field_24 = float(f);
|
||||
g_RolledSelectionListUnk = field_30 = field_34 = float(g - a) / 2.0f;
|
||||
}
|
||||
|
||||
int RolledSelectionList::getItemAtXPositionRaw(int x)
|
||||
{
|
||||
if (x < 0)
|
||||
return -1;
|
||||
|
||||
// @NOTE: redundant check
|
||||
int idx = x / m_itemWidth;
|
||||
if (idx < 0)
|
||||
return -1;
|
||||
|
||||
if (idx >= getNumberOfItems())
|
||||
return -1;
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
int RolledSelectionList::getItemAtPosition(int x, int y)
|
||||
{
|
||||
if (float(y) < field_20)
|
||||
return -1;
|
||||
if (float(y) > field_24)
|
||||
return -1;
|
||||
|
||||
return getItemAtXPositionRaw(transformX(x));
|
||||
}
|
||||
|
||||
bool RolledSelectionList::capXPosition()
|
||||
{
|
||||
float f1 = float(m_itemWidth - field_18) / 2.0f;
|
||||
int i1 = getNumberOfItems();
|
||||
|
||||
if (field_30 < f1)
|
||||
{
|
||||
field_30 = f1;
|
||||
field_38 = 0.0f;
|
||||
return true;
|
||||
}
|
||||
|
||||
f1 += float(m_itemWidth * (i1 - 1));
|
||||
if (field_30 > f1)
|
||||
{
|
||||
field_30 = f1;
|
||||
field_38 = 0.0f;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void RolledSelectionList::tick()
|
||||
{
|
||||
float diff = g_RolledSelectionListUnk - field_34;
|
||||
g_RolledSelectionListUnk = field_34;
|
||||
g_RolledSelectionListUnk2 = diff;
|
||||
field_34 = field_30 - field_38;
|
||||
}
|
||||
|
||||
void RolledSelectionList::render(int mouseX, int mouseY, float f)
|
||||
{
|
||||
renderBackground();
|
||||
|
||||
int nItems = getNumberOfItems();
|
||||
|
||||
// @TODO: fix gotos.
|
||||
if (!Mouse::_buttonStates[1])
|
||||
{
|
||||
if (field_28 < 0)
|
||||
{
|
||||
_crap:
|
||||
field_28 = -1;
|
||||
field_30 = getPos(f);
|
||||
goto _done;
|
||||
}
|
||||
|
||||
if (g_RolledSelectionListUnk2 < 0.0f)
|
||||
field_38 = Mth::Max(-20.0f, g_RolledSelectionListUnk2);
|
||||
else
|
||||
field_38 = Mth::Min(20.0f, g_RolledSelectionListUnk2);
|
||||
|
||||
if (fabsf(field_38) < 2.0f)
|
||||
{
|
||||
field_38 = 0.0f;
|
||||
|
||||
_continue:
|
||||
if (getTimeMs() - field_4C < 300)
|
||||
{
|
||||
int idx = transformX(mouseX) / m_itemWidth;
|
||||
if (idx >= 0)
|
||||
{
|
||||
if (field_50 == idx && abs(field_3C - mouseX) <= 9)
|
||||
selectItem(field_50, 0);
|
||||
}
|
||||
goto _crap;
|
||||
}
|
||||
goto _crap;
|
||||
}
|
||||
|
||||
if (fabsf(field_38) > 10.0f)
|
||||
{
|
||||
goto _crap;
|
||||
}
|
||||
|
||||
goto _continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
touched();
|
||||
|
||||
if (float(mouseY) >= field_20 && float(mouseY) <= field_24)
|
||||
{
|
||||
if (field_28 == -1)
|
||||
{
|
||||
field_4C = getTimeMs();
|
||||
field_3C = mouseX;
|
||||
field_50 = getItemAtPosition(mouseX, field_1C / 2);
|
||||
}
|
||||
else if (field_28 >= 0)
|
||||
{
|
||||
field_34 = field_30 = field_30 - (float(mouseX) - field_2C);
|
||||
}
|
||||
|
||||
field_28 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
_done:
|
||||
field_2C = float(mouseX);
|
||||
|
||||
capXPosition();
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_FOG);
|
||||
|
||||
m_pMinecraft->m_pTextures->loadAndBindTexture("gui/background.png");
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
Tesselator& t = Tesselator::instance;
|
||||
t.begin();
|
||||
t.color(0x202020);
|
||||
t.vertexUV(field_C, field_24, 0.0f, (field_C + float(int(field_30))) / 32.0f, field_24 / 32.0f);
|
||||
t.vertexUV(field_10, field_24, 0.0f, (field_10 + float(int(field_30))) / 32.0f, field_24 / 32.0f);
|
||||
t.vertexUV(field_10, field_20, 0.0f, (field_10 + float(int(field_30))) / 32.0f, field_20 / 32.0f);
|
||||
t.vertexUV(field_C, field_20, 0.0f, (field_C + float(int(field_30))) / 32.0f, field_20 / 32.0f);
|
||||
t.draw();
|
||||
|
||||
if (!getNumberOfItems())
|
||||
field_30 = 0.0f;
|
||||
|
||||
if (field_48)
|
||||
renderHeader(int(field_C + 4.0f - float(int(field_30))), field_1C / 2 - 40, t);
|
||||
|
||||
for (int i = 0; i < nItems; i++)
|
||||
{
|
||||
float itemX = float(field_44 + float(int(field_C + 4.0f - float(field_30))) + m_itemWidth * i);
|
||||
if (field_10 < itemX) continue;
|
||||
|
||||
float width = m_itemWidth - 4.0f;
|
||||
if (itemX + width < field_C) continue;
|
||||
|
||||
if (m_bRenderSelection && isSelectedItem(i))
|
||||
{
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
t.begin();
|
||||
t.color(m_bComponentSelected ? 0x7F89BF : 0x808080);
|
||||
|
||||
float right = itemX + width;
|
||||
float up = float(field_1C) / 2.0f - 48.0f - 4.0f;
|
||||
float dn = float(field_1C) / 2.0f + 48.0f - 4.0f;
|
||||
|
||||
t.vertexUV(itemX - 2, up, 0.0f, 0.0f, 0.0f);
|
||||
t.vertexUV(itemX - 2, dn, 0.0f, 1.0f, 0.0f);
|
||||
t.vertexUV(right + 2, dn, 0.0f, 1.0f, 1.0f);
|
||||
t.vertexUV(right + 2, up, 0.0f, 0.0f, 1.0f);
|
||||
t.color(0x000000);
|
||||
t.vertexUV(itemX - 1, up + 1.0f, 0.0f, 0.0f, 0.0f);
|
||||
t.vertexUV(itemX - 1, dn - 1.0f, 0.0f, 1.0f, 0.0f);
|
||||
t.vertexUV(right + 1, dn - 1.0f, 0.0f, 1.0f, 1.0f);
|
||||
t.vertexUV(right + 1, up + 1.0f, 0.0f, 0.0f, 1.0f);
|
||||
t.draw();
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
renderItem(i, int(itemX), field_1C / 2 - 40, int(width), t);
|
||||
}
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
renderHoleBackground(0.0f, field_20, 255, 255);
|
||||
renderHoleBackground(field_24, float(field_1C), 255, 255);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
// @BUG: The X and Y coordinates have been swapped. This causes the gradient to not render
|
||||
// in the right place.
|
||||
#ifdef ORIGINAL_CODE
|
||||
t.begin();
|
||||
t.color(0, 0);
|
||||
t.vertexUV(field_20, field_C + 4.0f, 0.0f, 0.0f, 1.0f);
|
||||
t.vertexUV(field_24, field_C + 4.0f, 0.0f, 1.0f, 1.0f);
|
||||
t.color(0, 255);
|
||||
t.vertexUV(field_24, field_C, 0.0f, 1.0f, 0.0f);
|
||||
t.vertexUV(field_20, field_C, 0.0f, 0.0f, 0.0f);
|
||||
t.draw();
|
||||
|
||||
t.begin();
|
||||
t.color(0, 255);
|
||||
t.vertexUV(field_20, field_10, 0.0f, 0.0f, 1.0f);
|
||||
t.vertexUV(field_24, field_10, 0.0f, 1.0f, 1.0f);
|
||||
t.color(0, 0);
|
||||
t.vertexUV(field_24, field_10 - 4.0f, 0.0f, 1.0f, 0.0f);
|
||||
t.vertexUV(field_20, field_10 - 4.0f, 0.0f, 0.0f, 0.0f);
|
||||
t.draw();
|
||||
#else
|
||||
t.begin();
|
||||
t.color(0, 0);
|
||||
t.vertexUV(field_C + 4.0f, field_20, 0.0f, 0.0f, 1.0f);
|
||||
t.vertexUV(field_C + 4.0f, field_24, 0.0f, 1.0f, 1.0f);
|
||||
t.color(0, 255);
|
||||
t.vertexUV(field_C, field_24, 0.0f, 1.0f, 0.0f);
|
||||
t.vertexUV(field_C, field_20, 0.0f, 0.0f, 0.0f);
|
||||
t.draw();
|
||||
|
||||
t.begin();
|
||||
t.color(0, 255);
|
||||
t.vertexUV(field_10, field_20, 0.0f, 0.0f, 1.0f);
|
||||
t.vertexUV(field_10, field_24, 0.0f, 1.0f, 1.0f);
|
||||
t.color(0, 0);
|
||||
t.vertexUV(field_10 - 4.0f, field_24, 0.0f, 1.0f, 0.0f);
|
||||
t.vertexUV(field_10 - 4.0f, field_20, 0.0f, 0.0f, 0.0f);
|
||||
t.draw();
|
||||
#endif
|
||||
|
||||
renderDecorations(mouseX, mouseY);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glShadeModel(GL_FLAT);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void RolledSelectionList::renderHoleBackground(float y1, float y2, int a, int b)
|
||||
{
|
||||
m_pMinecraft->m_pTextures->loadAndBindTexture("gui/background.png");
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
Tesselator& t = Tesselator::instance;
|
||||
t.begin();
|
||||
t.color(0x505050, b);
|
||||
t.vertexUV(0.0f, y2, 0.0f, 0.0f, y2 / 32.0f);
|
||||
t.vertexUV(float(field_18), y2, 0.0f, float(field_18) / 32.0f, y2 / 32.0f);
|
||||
t.color(0x505050, a);
|
||||
t.vertexUV(float(field_18), y1, 0.0f, float(field_18) / 32.0f, y1 / 32.0f);
|
||||
t.vertexUV(0.0f, y1, 0.0f, 0.0f, y1 / 32.0f);
|
||||
t.draw();
|
||||
}
|
||||
|
||||
void RolledSelectionList::setRenderSelection(bool b)
|
||||
{
|
||||
m_bRenderSelection = b;
|
||||
}
|
||||
|
||||
void RolledSelectionList::setComponentSelected(bool b)
|
||||
{
|
||||
m_bComponentSelected = b;
|
||||
}
|
||||
|
||||
int RolledSelectionList::getMaxPosition()
|
||||
{
|
||||
return field_44 + m_itemWidth * getNumberOfItems();
|
||||
}
|
||||
|
||||
float RolledSelectionList::getPos(float f)
|
||||
{
|
||||
return field_34 - field_38 * f;
|
||||
}
|
||||
|
||||
void RolledSelectionList::touched()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RolledSelectionList::renderHeader(int a, int b, Tesselator& t)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void RolledSelectionList::renderDecorations(int x, int y)
|
||||
{
|
||||
}
|
||||
|
||||
void RolledSelectionList::clickedHeader(int x, int y)
|
||||
{
|
||||
|
||||
}
|
||||
67
source/gui/RolledSelectionList.hpp
Normal file
67
source/gui/RolledSelectionList.hpp
Normal file
@@ -0,0 +1,67 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GuiComponent.hpp"
|
||||
#include "Minecraft.hpp"
|
||||
|
||||
class RolledSelectionList : public GuiComponent
|
||||
{
|
||||
public:
|
||||
RolledSelectionList(Minecraft*, int, int, int, int, int, int, int);
|
||||
virtual int getItemAtPosition(int, int);
|
||||
virtual bool capXPosition();
|
||||
virtual void tick();
|
||||
virtual void render(int mouseX, int mouseY, float);
|
||||
virtual void renderHoleBackground(float y1, float y2, int a, int b);
|
||||
virtual void setRenderSelection(bool);
|
||||
virtual void setComponentSelected(bool);
|
||||
virtual int getNumberOfItems() = 0;
|
||||
virtual void selectItem(int, bool) = 0;
|
||||
virtual bool isSelectedItem(int) = 0;
|
||||
virtual int getMaxPosition();
|
||||
virtual float getPos(float f);
|
||||
virtual void touched();
|
||||
virtual void renderItem(int, int, int, int, Tesselator&) = 0;
|
||||
virtual void renderHeader(int, int, Tesselator&);
|
||||
virtual void renderBackground() = 0;
|
||||
virtual void renderDecorations(int x, int y);
|
||||
virtual void clickedHeader(int, int);
|
||||
|
||||
int getItemAtXPositionRaw(int x);
|
||||
|
||||
// @NOTE: This is inlined.
|
||||
inline int transformX(int x)
|
||||
{
|
||||
return int(x - field_C - float(field_44) + float(int(field_30)) - 4.0f);
|
||||
}
|
||||
|
||||
public:
|
||||
Minecraft* m_pMinecraft;
|
||||
float field_C;
|
||||
float field_10;
|
||||
int m_itemWidth;
|
||||
int field_18;
|
||||
int field_1C;
|
||||
float field_20;
|
||||
float field_24;
|
||||
int field_28 = -2;
|
||||
float field_2C = 0.0f;
|
||||
float field_30;
|
||||
float field_34;
|
||||
float field_38 = 0.0f;
|
||||
int field_3C = -1;
|
||||
bool m_bRenderSelection = true;
|
||||
bool m_bComponentSelected = false;
|
||||
int field_44 = 0;
|
||||
bool field_48 = false;
|
||||
int field_4C = 0;
|
||||
int field_50 = -1;
|
||||
};
|
||||
|
||||
40
source/gui/Screen/ChatScreen.cpp
Normal file
40
source/gui/Screen/ChatScreen.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "ChatScreen.hpp"
|
||||
|
||||
// @NOTE: This is unused.
|
||||
|
||||
void ChatScreen::buttonClicked(Button* pButton)
|
||||
{
|
||||
}
|
||||
|
||||
void ChatScreen::init()
|
||||
{
|
||||
m_pMinecraft->platform()->showDialog(AppPlatform::DLG_CHAT);
|
||||
m_pMinecraft->platform()->createUserInput();
|
||||
}
|
||||
|
||||
void ChatScreen::render(int mouseX, int mouseY, float f)
|
||||
{
|
||||
int userInputStatus = m_pMinecraft->platform()->getUserInputStatus();
|
||||
if (userInputStatus < 0)
|
||||
return;
|
||||
|
||||
if (userInputStatus == 1)
|
||||
{
|
||||
std::vector<std::string> userInput = m_pMinecraft->platform()->getUserInput();
|
||||
if (userInput.size() >= 1)
|
||||
{
|
||||
// @NOTE: No sending multiplayer chats. Weird
|
||||
m_pMinecraft->m_gui.addMessage(userInput[0]);
|
||||
}
|
||||
}
|
||||
|
||||
m_pMinecraft->setScreen(nullptr);
|
||||
}
|
||||
20
source/gui/Screen/ChatScreen.hpp
Normal file
20
source/gui/Screen/ChatScreen.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Screen.hpp"
|
||||
|
||||
class ChatScreen : public Screen
|
||||
{
|
||||
public:
|
||||
void buttonClicked(Button*) override;
|
||||
void init() override;
|
||||
void render(int mouseX, int mouseY, float f) override;
|
||||
};
|
||||
|
||||
75
source/gui/Screen/ConfirmScreen.cpp
Normal file
75
source/gui/Screen/ConfirmScreen.cpp
Normal file
@@ -0,0 +1,75 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "ConfirmScreen.hpp"
|
||||
|
||||
ConfirmScreen::ConfirmScreen(Screen* pScreen, const std::string& line1, const std::string& line2, int x) :
|
||||
m_btnOK (0, 0, 0, "Ok"),
|
||||
m_btnCancel(1, 0, 0, "Cancel"),
|
||||
m_textLine1(line1),
|
||||
m_textLine2(line2),
|
||||
m_pScreen(pScreen),
|
||||
field_40(x)
|
||||
{
|
||||
}
|
||||
|
||||
ConfirmScreen::ConfirmScreen(Screen* pScreen, const std::string& line1, const std::string& line2, const std::string& ok, const std::string& cancel, int x) :
|
||||
m_btnOK (0, 0, 0, ok),
|
||||
m_btnCancel(1, 0, 0, cancel),
|
||||
m_textLine1(line1),
|
||||
m_textLine2(line2),
|
||||
m_pScreen(pScreen),
|
||||
field_40(x)
|
||||
{
|
||||
}
|
||||
|
||||
// @NOTE: potential memory leak if pScreen is set and not destroyed!
|
||||
|
||||
void ConfirmScreen::buttonClicked(Button* pButton)
|
||||
{
|
||||
postResult(pButton->field_30 == 0);
|
||||
}
|
||||
|
||||
bool ConfirmScreen::handleBackEvent(bool b)
|
||||
{
|
||||
if (!b)
|
||||
postResult(false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConfirmScreen::init()
|
||||
{
|
||||
m_btnOK.m_xPos = m_width / 2 - 4 - 120;
|
||||
m_btnCancel.m_xPos = m_width / 2 + 4;
|
||||
|
||||
m_btnCancel.m_yPos = m_btnOK.m_yPos = m_height / 6 + 72;
|
||||
|
||||
m_btnOK.m_width = m_btnCancel.m_width = 120;
|
||||
m_btnOK.m_height = m_btnCancel.m_height = 24;
|
||||
|
||||
m_buttons.push_back(&m_btnOK);
|
||||
m_buttons.push_back(&m_btnCancel);
|
||||
m_buttonTabList.push_back(&m_btnOK);
|
||||
m_buttonTabList.push_back(&m_btnCancel);
|
||||
}
|
||||
|
||||
void ConfirmScreen::render(int mouseX, int mouseY, float f)
|
||||
{
|
||||
renderBackground();
|
||||
drawCenteredString(m_pFont, m_textLine1, m_width / 2, 50, 0xFFFFFF);
|
||||
drawCenteredString(m_pFont, m_textLine2, m_width / 2, 70, 0xFFFFFF);
|
||||
Screen::render(mouseX, mouseY, f);
|
||||
}
|
||||
|
||||
void ConfirmScreen::postResult(bool b)
|
||||
{
|
||||
m_pScreen->confirmResult(b, field_40);
|
||||
}
|
||||
|
||||
|
||||
35
source/gui/Screen/ConfirmScreen.hpp
Normal file
35
source/gui/Screen/ConfirmScreen.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Screen.hpp"
|
||||
#include "SmallButton.hpp"
|
||||
|
||||
class ConfirmScreen : public Screen
|
||||
{
|
||||
public:
|
||||
ConfirmScreen(Screen* pScreen, const std::string& line1, const std::string& line2, int x);
|
||||
ConfirmScreen(Screen* pScreen, const std::string& line1, const std::string& line2, const std::string& ok, const std::string& cancel, int x);
|
||||
|
||||
void buttonClicked(Button* pButton) override;
|
||||
bool handleBackEvent(bool b) override;
|
||||
void init() override;
|
||||
void render(int mouseX, int mouseY, float f) override;
|
||||
|
||||
virtual void postResult(bool b);
|
||||
|
||||
private:
|
||||
Screen* m_pScreen = nullptr;
|
||||
int field_40 = 0;
|
||||
std::string m_textLine1;
|
||||
std::string m_textLine2;
|
||||
SmallButton m_btnOK;
|
||||
SmallButton m_btnCancel;
|
||||
};
|
||||
|
||||
120
source/gui/Screen/CreateWorldScreen.cpp
Normal file
120
source/gui/Screen/CreateWorldScreen.cpp
Normal file
@@ -0,0 +1,120 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "CreateWorldScreen.hpp"
|
||||
#include "SelectWorldScreen.hpp"
|
||||
#include "ProgressScreen.hpp"
|
||||
#include "Util.hpp"
|
||||
|
||||
CreateWorldScreen::CreateWorldScreen() :
|
||||
m_textName(1, 0, 0, 0, 0, "", "Unnamed world"),
|
||||
m_textSeed(2, 0, 0, 0, 0, ""),
|
||||
m_btnBack(3, "Cancel"),
|
||||
m_btnCreate(4, "Create New World")
|
||||
{
|
||||
}
|
||||
|
||||
void CreateWorldScreen::init()
|
||||
{
|
||||
m_textName.m_width = m_textSeed.m_width = 200;
|
||||
m_textName.m_height = m_textSeed.m_height = 20;
|
||||
m_textName.m_xPos = m_textSeed.m_xPos = (m_width - 200) / 2;
|
||||
m_textName.m_yPos = 60;
|
||||
m_textSeed.m_yPos = 100;
|
||||
|
||||
m_btnCreate.m_yPos = m_height - 56;
|
||||
m_btnBack.m_yPos = m_height - 30;
|
||||
m_btnBack.m_width = m_btnCreate.m_width = 200;
|
||||
m_btnBack.m_height = m_btnCreate.m_height = 20;
|
||||
|
||||
m_btnBack.m_xPos = m_width / 2 - 200 / 2;
|
||||
m_btnCreate.m_xPos = m_width / 2 - 200 / 2;
|
||||
|
||||
m_textInputs.push_back(&m_textName);
|
||||
m_textInputs.push_back(&m_textSeed);
|
||||
m_buttons.push_back(&m_btnBack);
|
||||
m_buttons.push_back(&m_btnCreate);
|
||||
m_buttonTabList.push_back(&m_btnBack);
|
||||
m_buttonTabList.push_back(&m_btnCreate);
|
||||
m_textName.init(m_pFont);
|
||||
m_textSeed.init(m_pFont);
|
||||
}
|
||||
|
||||
static char g_CreateWorldFilterArray[] = { '/','\n','\r','\x09','\0','\xC','`','?','*','\\','<','>','|','"',':' };
|
||||
|
||||
static std::string GetUniqueLevelName(LevelStorageSource* pSource, const std::string& in)
|
||||
{
|
||||
std::set<std::string> maps;
|
||||
|
||||
std::vector<LevelSummary> vls;
|
||||
pSource->getLevelList(vls);
|
||||
|
||||
for (const auto& ls : vls)
|
||||
{
|
||||
maps.insert(ls.field_0);
|
||||
}
|
||||
|
||||
std::string out = in;
|
||||
while (maps.find(out) != maps.end())
|
||||
out += "-";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void CreateWorldScreen::buttonClicked(Button* pButton)
|
||||
{
|
||||
if (pButton->field_30 == m_btnBack.field_30)
|
||||
{
|
||||
m_pMinecraft->setScreen(new SelectWorldScreen);
|
||||
}
|
||||
|
||||
if (pButton->field_30 == m_btnCreate.field_30)
|
||||
{
|
||||
std::string nameStr = m_textName.m_text;
|
||||
std::string seedStr = m_textSeed.m_text;
|
||||
|
||||
std::string levelNickname = Util::stringTrim(nameStr);
|
||||
std::string levelUniqueName = levelNickname;
|
||||
|
||||
for (int i = 0; i < sizeof(g_CreateWorldFilterArray); i++)
|
||||
{
|
||||
std::string str;
|
||||
str.push_back(g_CreateWorldFilterArray[i]);
|
||||
Util::stringReplace(levelUniqueName, str, "");
|
||||
}
|
||||
|
||||
levelUniqueName = GetUniqueLevelName(m_pMinecraft->m_pLevelStorageSource, levelUniqueName);
|
||||
|
||||
int seed = int(getEpochTimeS());
|
||||
|
||||
std::string seedThing = Util::stringTrim(seedStr);
|
||||
if (!seedThing.empty())
|
||||
{
|
||||
int num;
|
||||
if (sscanf(seedThing.c_str(), "%d", &num) > 0)
|
||||
seed = num;
|
||||
else
|
||||
seed = Util::hashCode(seedThing);
|
||||
}
|
||||
|
||||
m_pMinecraft->selectLevel(levelUniqueName, levelNickname, seed);
|
||||
m_pMinecraft->hostMultiplayer();
|
||||
m_pMinecraft->setScreen(new ProgressScreen);
|
||||
}
|
||||
}
|
||||
|
||||
void CreateWorldScreen::render(int mouseX, int mouseY, float f)
|
||||
{
|
||||
renderBackground();
|
||||
Screen::render(mouseX, mouseY, f);
|
||||
|
||||
drawCenteredString(m_pFont, "Create New World", m_width / 2, 30, 0xFFFFFF);
|
||||
drawString(m_pFont, "World name", m_textName.m_xPos, m_textName.m_yPos - 10, 0xDDDDDD);
|
||||
drawString(m_pFont, "Seed for the World Generator", m_textSeed.m_xPos, m_textSeed.m_yPos - 10, 0xDDDDDD);
|
||||
drawString(m_pFont, "Leave blank for a random seed", m_textSeed.m_xPos, m_textSeed.m_yPos + 22, 0x999999);
|
||||
}
|
||||
31
source/gui/Screen/CreateWorldScreen.hpp
Normal file
31
source/gui/Screen/CreateWorldScreen.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Screen.hpp"
|
||||
|
||||
#ifndef ORIGINAL_CODE
|
||||
|
||||
class CreateWorldScreen : public Screen
|
||||
{
|
||||
public:
|
||||
CreateWorldScreen();
|
||||
|
||||
void init() override;
|
||||
void buttonClicked(Button* pButton) override;
|
||||
void render(int mouseX, int mouseY, float f) override;
|
||||
|
||||
public:
|
||||
TextInputBox m_textName;
|
||||
TextInputBox m_textSeed;
|
||||
Button m_btnBack;
|
||||
Button m_btnCreate;
|
||||
};
|
||||
|
||||
#endif
|
||||
31
source/gui/Screen/DeleteWorldScreen.cpp
Normal file
31
source/gui/Screen/DeleteWorldScreen.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "DeleteWorldScreen.hpp"
|
||||
#include "SelectWorldScreen.hpp"
|
||||
|
||||
DeleteWorldScreen::DeleteWorldScreen(const LevelSummary& level) :
|
||||
ConfirmScreen(nullptr,
|
||||
"Are you sure you want to delete this world?",
|
||||
"'" + level.field_18 + "' will be lost forever!",
|
||||
"Delete", "Cancel", 0),
|
||||
m_level(level)
|
||||
{
|
||||
// highlight the cancel button so the user will have to do 1 extra action to delete their world
|
||||
m_tabButtonIndex = 1;
|
||||
}
|
||||
|
||||
void DeleteWorldScreen::postResult(bool b)
|
||||
{
|
||||
if (b)
|
||||
{
|
||||
m_pMinecraft->getLevelSource()->deleteLevel(m_level.field_0);
|
||||
}
|
||||
|
||||
m_pMinecraft->setScreen(new SelectWorldScreen);
|
||||
}
|
||||
23
source/gui/Screen/DeleteWorldScreen.hpp
Normal file
23
source/gui/Screen/DeleteWorldScreen.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ConfirmScreen.hpp"
|
||||
|
||||
class DeleteWorldScreen : public ConfirmScreen
|
||||
{
|
||||
public:
|
||||
DeleteWorldScreen(const LevelSummary& level);
|
||||
|
||||
void postResult(bool b) override;
|
||||
|
||||
private:
|
||||
LevelSummary m_level;
|
||||
};
|
||||
|
||||
175
source/gui/Screen/IngameBlockSelectionScreen.cpp
Normal file
175
source/gui/Screen/IngameBlockSelectionScreen.cpp
Normal file
@@ -0,0 +1,175 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "IngameBlockSelectionScreen.hpp"
|
||||
#include "ItemRenderer.hpp"
|
||||
|
||||
std::string g_sNotAvailableInDemoVersion = "Not available in the demo version";
|
||||
|
||||
Inventory* IngameBlockSelectionScreen::getInventory()
|
||||
{
|
||||
return m_pMinecraft->m_pLocalPlayer->m_pInventory;
|
||||
}
|
||||
|
||||
int IngameBlockSelectionScreen::getBottomY()
|
||||
{
|
||||
// -1 for some reason, -2 to make it align between top of screen and top of hotbar instead
|
||||
return (m_height - 22 * (getSlotsHeight() - 2)) / 2;
|
||||
}
|
||||
|
||||
int IngameBlockSelectionScreen::getSelectedSlot(int x, int y)
|
||||
{
|
||||
int slotsHeight = getSlotsHeight();
|
||||
int bottom = m_height - getBottomY();
|
||||
int top = bottom - slotsHeight * 22;
|
||||
int left = m_width / 2 - 87;
|
||||
|
||||
if (y < top)
|
||||
return -1;
|
||||
if (x < left)
|
||||
return -1;
|
||||
|
||||
int idx = (x - left) / 20;
|
||||
if (idx > 8)
|
||||
return -1;
|
||||
|
||||
return idx + 9 * slotsHeight - 9 * ((y - top) / 22);
|
||||
}
|
||||
|
||||
int IngameBlockSelectionScreen::getSlotPosX(int x)
|
||||
{
|
||||
return m_width / 2 - 88 + 20 * x;
|
||||
}
|
||||
|
||||
int IngameBlockSelectionScreen::getSlotPosY(int y)
|
||||
{
|
||||
return m_height - getBottomY() - 22 * y;
|
||||
}
|
||||
|
||||
int IngameBlockSelectionScreen::getSlotsHeight()
|
||||
{
|
||||
return (getInventory()->getNumSlots() + 8) / 9;
|
||||
}
|
||||
|
||||
bool IngameBlockSelectionScreen::isAllowed(int slot)
|
||||
{
|
||||
return slot >= 0 && slot < getInventory()->getNumSlots();
|
||||
}
|
||||
|
||||
void IngameBlockSelectionScreen::init()
|
||||
{
|
||||
Inventory* pInv = getInventory();
|
||||
|
||||
int nItems = pInv->getNumItems();
|
||||
|
||||
for (int i = 0; i < nItems; i++)
|
||||
{
|
||||
if (pInv->getItem(i)->m_itemID == pInv->getSelectedItemId())
|
||||
{
|
||||
m_selectedSlot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isAllowed(m_selectedSlot))
|
||||
m_selectedSlot = 0;
|
||||
}
|
||||
|
||||
void IngameBlockSelectionScreen::renderSlot(int index, int x, int y, float f)
|
||||
{
|
||||
ItemInstance* pItem = getInventory()->getItem(index);
|
||||
if (!pItem)
|
||||
return;
|
||||
|
||||
if (!pItem->m_itemID)
|
||||
return;
|
||||
|
||||
ItemRenderer::renderGuiItem(m_pMinecraft->m_pFont, m_pMinecraft->m_pTextures, pItem, x, y, true);
|
||||
ItemRenderer::renderGuiItemOverlay(m_pMinecraft->m_pFont, m_pMinecraft->m_pTextures, pItem, x, y);
|
||||
}
|
||||
|
||||
void IngameBlockSelectionScreen::renderSlots()
|
||||
{
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
m_pMinecraft->m_pTextures->loadAndBindTexture("gui/gui.png");
|
||||
|
||||
for (int y = 0; y != -22 * getSlotsHeight(); y -= 22)
|
||||
blit(m_width / 2 - 182 / 2, m_height - 3 - getBottomY() + y, 0, 0, 182, 22, 0, 0);
|
||||
|
||||
if (m_selectedSlot >= 0)
|
||||
blit(m_width / 2 - 92 + 20 * (m_selectedSlot % 9), m_height - 4 - getBottomY() - 22 * (m_selectedSlot / 9), 0, 22, 24, 22, 0, 0);
|
||||
|
||||
for (int y = 0, index = 0; y < getSlotsHeight(); y++)
|
||||
{
|
||||
int posY = getSlotPosY(y);
|
||||
for (int x = 0; x < 9; x++)
|
||||
{
|
||||
int posX = getSlotPosX(x);
|
||||
renderSlot(index++, posX, posY, 0.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void IngameBlockSelectionScreen::renderDemoOverlay()
|
||||
{
|
||||
fill(getSlotPosX(0) - 3, getSlotPosY(1) - 3, getSlotPosX(9), getSlotPosY(-1), 0xA0000000);
|
||||
|
||||
int x = (getSlotPosX(4) + getSlotPosX(5)) / 2;
|
||||
int y = (getSlotPosY(0) + getSlotPosY(1)) / 2 + 5;
|
||||
|
||||
drawCenteredString(m_pMinecraft->m_pFont, g_sNotAvailableInDemoVersion, x, y, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
void IngameBlockSelectionScreen::render(int x, int y, float f)
|
||||
{
|
||||
Screen::render(x, y, f);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
fill(0, 0, m_width, m_height, 0x80000000);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
renderSlots();
|
||||
|
||||
#ifdef DEMO
|
||||
renderDemoOverlay();
|
||||
#endif
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void IngameBlockSelectionScreen::mouseClicked(int x, int y, int type)
|
||||
{
|
||||
// not a left click
|
||||
if (type != 1)
|
||||
return;
|
||||
|
||||
int slot = getSelectedSlot(x, y);
|
||||
if (isAllowed(slot))
|
||||
m_selectedSlot = slot;
|
||||
}
|
||||
|
||||
void IngameBlockSelectionScreen::mouseReleased(int x, int y, int type)
|
||||
{
|
||||
// not a left click
|
||||
if (type != 1)
|
||||
return;
|
||||
|
||||
int slot = getSelectedSlot(x, y);
|
||||
if (isAllowed(slot) && slot == m_selectedSlot)
|
||||
selectSlotAndClose();
|
||||
}
|
||||
|
||||
void IngameBlockSelectionScreen::selectSlotAndClose()
|
||||
{
|
||||
Inventory* pInv = getInventory();
|
||||
|
||||
pInv->selectItem(m_selectedSlot);
|
||||
|
||||
m_pMinecraft->m_pSoundEngine->play("random.click");
|
||||
m_pMinecraft->setScreen(nullptr);
|
||||
}
|
||||
38
source/gui/Screen/IngameBlockSelectionScreen.hpp
Normal file
38
source/gui/Screen/IngameBlockSelectionScreen.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Screen.hpp"
|
||||
|
||||
class Inventory;
|
||||
|
||||
class IngameBlockSelectionScreen : public Screen
|
||||
{
|
||||
public:
|
||||
Inventory* getInventory();
|
||||
int getBottomY();
|
||||
int getSelectedSlot(int x, int y);
|
||||
int getSlotPosX(int x);
|
||||
int getSlotPosY(int y);
|
||||
int getSlotsHeight();
|
||||
bool isAllowed(int slot);
|
||||
void renderSlots();
|
||||
void renderDemoOverlay();
|
||||
void renderSlot(int index, int x, int y, float f);
|
||||
void selectSlotAndClose();
|
||||
|
||||
virtual void init() override;
|
||||
virtual void render(int x, int y, float f) override;
|
||||
virtual void mouseClicked(int x, int y, int type) override;
|
||||
virtual void mouseReleased(int x, int y, int type) override;
|
||||
|
||||
private:
|
||||
int m_selectedSlot = 0;
|
||||
};
|
||||
|
||||
69
source/gui/Screen/InvalidLicenseScreen.cpp
Normal file
69
source/gui/Screen/InvalidLicenseScreen.cpp
Normal file
@@ -0,0 +1,69 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "InvalidLicenseScreen.hpp"
|
||||
|
||||
InvalidLicenseScreen::InvalidLicenseScreen(int error, bool bHasQuitButton) :
|
||||
m_error(error),
|
||||
m_btnOk (1, "Ok"),
|
||||
m_btnBuy(2, "Buy"),
|
||||
m_bHasQuitButton(bHasQuitButton)
|
||||
{
|
||||
if (bHasQuitButton)
|
||||
m_btnOk.field_18 = "Quit";
|
||||
}
|
||||
|
||||
void InvalidLicenseScreen::buttonClicked(Button* pButton)
|
||||
{
|
||||
if (pButton->field_30 == m_btnOk.field_30)
|
||||
{
|
||||
m_pMinecraft->quit();
|
||||
}
|
||||
|
||||
if (pButton->field_30 == m_btnBuy.field_30)
|
||||
{
|
||||
m_pMinecraft->platform()->buyGame();
|
||||
}
|
||||
}
|
||||
|
||||
void InvalidLicenseScreen::init()
|
||||
{
|
||||
field_E4 = m_height / 3;
|
||||
if (m_bHasQuitButton)
|
||||
field_E4 -= 24;
|
||||
|
||||
if (m_error > 1)
|
||||
{
|
||||
char str[20] = { 0 };
|
||||
sprintf(str, "%d", m_error);
|
||||
m_textLine1 = "License verification failed (error " + std::string(str) + ")";
|
||||
m_textLine2 = "Try again later.";
|
||||
}
|
||||
|
||||
m_btnOk.m_xPos = m_btnBuy.m_xPos = (m_width - m_btnOk.m_width) / 2;
|
||||
|
||||
m_btnOk.m_yPos = field_E4 + 60;
|
||||
m_btnBuy.m_yPos = field_E4 + 88;
|
||||
|
||||
m_buttons.push_back(&m_btnOk);
|
||||
m_buttons.push_back(&m_btnBuy);
|
||||
m_buttonTabList.push_back(&m_btnOk);
|
||||
m_buttonTabList.push_back(&m_btnBuy);
|
||||
}
|
||||
|
||||
void InvalidLicenseScreen::tick()
|
||||
{
|
||||
}
|
||||
|
||||
void InvalidLicenseScreen::render(int mouseX, int mouseY, float f)
|
||||
{
|
||||
renderDirtBackground(0);
|
||||
drawCenteredString(m_pMinecraft->m_pFont, m_textLine1, m_width / 2, field_E4, 0xFFFFFF);
|
||||
drawCenteredString(m_pMinecraft->m_pFont, m_textLine2, m_width / 2, field_E4 + 24, 0xFFFFFF);
|
||||
Screen::render(mouseX, mouseY, f);
|
||||
}
|
||||
31
source/gui/Screen/InvalidLicenseScreen.hpp
Normal file
31
source/gui/Screen/InvalidLicenseScreen.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Screen.hpp"
|
||||
|
||||
class InvalidLicenseScreen : public Screen
|
||||
{
|
||||
public:
|
||||
InvalidLicenseScreen(int error, bool bHasQuitButton);
|
||||
void buttonClicked(Button* pButton) override;
|
||||
void init() override;
|
||||
void tick() override;
|
||||
void render(int mouseX, int mouseY, float f) override;
|
||||
|
||||
private:
|
||||
int m_error;
|
||||
std::string m_textLine1;
|
||||
std::string m_textLine2;
|
||||
Button m_btnOk;
|
||||
Button m_btnBuy;
|
||||
bool m_bHasQuitButton;
|
||||
int field_E4 = 0;
|
||||
};
|
||||
|
||||
163
source/gui/Screen/JoinGameScreen.cpp
Normal file
163
source/gui/Screen/JoinGameScreen.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "JoinGameScreen.hpp"
|
||||
#include "ProgressScreen.hpp"
|
||||
#include "StartMenuScreen.hpp"
|
||||
|
||||
JoinGameScreen::JoinGameScreen() :
|
||||
m_btnJoin(2, "Join Game"),
|
||||
m_btnBack(3, "Back")
|
||||
{
|
||||
}
|
||||
|
||||
JoinGameScreen::~JoinGameScreen()
|
||||
{
|
||||
if (m_pAvailableGamesList)
|
||||
delete m_pAvailableGamesList;
|
||||
}
|
||||
|
||||
void JoinGameScreen::buttonClicked(Button* pButton)
|
||||
{
|
||||
if (pButton->field_30 == m_btnJoin.field_30)
|
||||
{
|
||||
if (isIndexValid(m_pAvailableGamesList->m_selectedIndex))
|
||||
{
|
||||
m_pMinecraft->joinMultiplayer(m_pAvailableGamesList->m_games[m_pAvailableGamesList->m_selectedIndex]);
|
||||
m_pMinecraft->setScreen(new ProgressScreen);
|
||||
|
||||
m_btnJoin.m_bEnabled = false;
|
||||
m_btnBack.m_bEnabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (pButton->field_30 == m_btnBack.field_30)
|
||||
{
|
||||
m_pMinecraft->setScreen(new StartMenuScreen);
|
||||
}
|
||||
}
|
||||
|
||||
bool JoinGameScreen::handleBackEvent(bool b)
|
||||
{
|
||||
if (!b)
|
||||
{
|
||||
m_pMinecraft->cancelLocateMultiplayer();
|
||||
m_pMinecraft->setScreen(new StartMenuScreen);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void JoinGameScreen::init()
|
||||
{
|
||||
m_btnBack.m_yPos = m_btnJoin.m_yPos = m_height - 26;
|
||||
m_btnBack.m_width = m_btnJoin.m_width = 120;
|
||||
|
||||
m_btnJoin.m_xPos = m_width / 2 - 124;
|
||||
m_btnBack.m_xPos = m_width / 2 + 4;
|
||||
|
||||
m_buttons.push_back(&m_btnJoin);
|
||||
m_buttons.push_back(&m_btnBack);
|
||||
|
||||
m_pMinecraft->m_pRakNetInstance->clearServerList();
|
||||
|
||||
m_pAvailableGamesList = new AvailableGamesList(m_pMinecraft, m_width, m_height, 24, m_height - 30, 28);
|
||||
|
||||
m_buttonTabList.push_back(&m_btnJoin);
|
||||
m_buttonTabList.push_back(&m_btnBack);
|
||||
}
|
||||
|
||||
bool JoinGameScreen::isInGameScreen()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void JoinGameScreen::render(int mouseX, int mouseY, float f)
|
||||
{
|
||||
renderBackground();
|
||||
m_pAvailableGamesList->render(mouseX, mouseY, f);
|
||||
Screen::render(mouseX, mouseY, f);
|
||||
|
||||
drawCenteredString(m_pMinecraft->m_pFont, "Scanning for Games...", m_width / 2, 8, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
void JoinGameScreen::tick()
|
||||
{
|
||||
std::vector<PingedCompatibleServer> *serverList, serverListFiltered;
|
||||
serverList = m_pMinecraft->m_pRakNetInstance->getServerList();
|
||||
|
||||
for (const PingedCompatibleServer& pcs : *serverList)
|
||||
{
|
||||
if (pcs.m_name.GetLength())
|
||||
serverListFiltered.push_back(pcs);
|
||||
}
|
||||
|
||||
if (serverListFiltered.size() != m_pAvailableGamesList->m_games.size())
|
||||
{
|
||||
PingedCompatibleServer selectedItem;
|
||||
|
||||
if (isIndexValid(m_pAvailableGamesList->m_selectedIndex))
|
||||
{
|
||||
selectedItem = m_pAvailableGamesList->m_games[m_pAvailableGamesList->m_selectedIndex];
|
||||
|
||||
m_pAvailableGamesList->m_games = serverListFiltered;
|
||||
m_pAvailableGamesList->selectItem(-1, false);
|
||||
|
||||
// relocate the new list item, if possible
|
||||
for (int i = 0; i < int(serverListFiltered.size()); i++)
|
||||
{
|
||||
if (serverListFiltered[i].m_address == selectedItem.m_address)
|
||||
{
|
||||
m_pAvailableGamesList->selectItem(i, false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pAvailableGamesList->m_games = serverListFiltered;
|
||||
m_pAvailableGamesList->selectItem(-1, false);
|
||||
}
|
||||
}
|
||||
else if (!serverListFiltered.empty())
|
||||
{
|
||||
// Update the names of the items already in the available games list.
|
||||
// @BUG: What would happen if the filtered server list removes an IP and adds another all in the same tick?
|
||||
|
||||
std::vector<PingedCompatibleServer>* pGames = &m_pAvailableGamesList->m_games;
|
||||
for (int i = int(pGames->size() - 1); i >= 0; i--)
|
||||
{
|
||||
int j = 0;
|
||||
for (; j < int(serverListFiltered.size()); j++)
|
||||
{
|
||||
if (serverListFiltered[j].m_address == (*pGames)[i].m_address)
|
||||
break;
|
||||
}
|
||||
|
||||
if (j == serverListFiltered.size())
|
||||
continue;
|
||||
|
||||
(*pGames)[i].m_name = serverListFiltered[j].m_name;
|
||||
}
|
||||
}
|
||||
|
||||
m_btnJoin.m_bEnabled = isIndexValid(m_pAvailableGamesList->m_selectedIndex);
|
||||
}
|
||||
|
||||
bool JoinGameScreen::isIndexValid(int idx)
|
||||
{
|
||||
if (!m_pAvailableGamesList)
|
||||
return false;
|
||||
|
||||
if (idx < 0)
|
||||
return false;
|
||||
if (idx >= m_pAvailableGamesList->getNumberOfItems())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
33
source/gui/Screen/JoinGameScreen.hpp
Normal file
33
source/gui/Screen/JoinGameScreen.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Screen.hpp"
|
||||
#include "AvailableGamesList.hpp"
|
||||
|
||||
class JoinGameScreen : public Screen
|
||||
{
|
||||
public:
|
||||
JoinGameScreen();
|
||||
~JoinGameScreen();
|
||||
void buttonClicked(Button* pButton) override;
|
||||
bool handleBackEvent(bool b) override;
|
||||
void init() override;
|
||||
bool isInGameScreen() override;
|
||||
void render(int mouseX, int mouseY, float f) override;
|
||||
void tick() override;
|
||||
|
||||
virtual bool isIndexValid(int idx);
|
||||
|
||||
public:
|
||||
Button m_btnJoin;
|
||||
Button m_btnBack;
|
||||
AvailableGamesList* m_pAvailableGamesList = nullptr;
|
||||
};
|
||||
|
||||
210
source/gui/Screen/OptionsScreen.cpp
Normal file
210
source/gui/Screen/OptionsScreen.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "OptionsScreen.hpp"
|
||||
#include "StartMenuScreen.hpp"
|
||||
#include "PauseScreen.hpp"
|
||||
|
||||
enum eOptionsButton
|
||||
{
|
||||
OB_BACK = 1,
|
||||
OB_AO,
|
||||
OB_SRV_VIS,
|
||||
OB_FANCY_GFX,
|
||||
OB_INVERT_Y,
|
||||
OB_ANAGLYPHS,
|
||||
OB_VIEW_BOB,
|
||||
OB_VIEW_DIST,
|
||||
OB_FLY_HAX,
|
||||
};
|
||||
|
||||
OptionsScreen::OptionsScreen()
|
||||
#ifndef ORIGINAL_CODE
|
||||
:m_BackButton (1, 0, 0, 200, 20, "Done"),
|
||||
m_AOButton (2, 0, 0, 150, 20, ""),
|
||||
m_srvVisButton (3, 0, 0, 150, 20, ""),
|
||||
m_fancyGfxButton (4, 0, 0, 150, 20, ""),
|
||||
m_invertYButton (5, 0, 0, 150, 20, ""),
|
||||
m_anaglyphsButton(6, 0, 0, 150, 20, ""),
|
||||
m_viewBobButton (7, 0, 0, 150, 20, ""),
|
||||
m_viewDistButton (8, 0, 0, 150, 20, ""),
|
||||
m_flightHaxButton(9, 0, 0, 150, 20, "")
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
#ifndef ORIGINAL_CODE
|
||||
static std::string BoolOptionStr(bool b)
|
||||
{
|
||||
return b ? "ON" : "OFF";
|
||||
}
|
||||
static std::string ViewDistanceStr(int dist)
|
||||
{
|
||||
switch (dist)
|
||||
{
|
||||
case 0: return "EXTREME";
|
||||
case 1: return "FAR";
|
||||
case 2: return "NORMAL";
|
||||
case 3: return "SHORT";
|
||||
case 4: return "TINY";
|
||||
default:
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << dist;
|
||||
return ss.str();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OptionsScreen::UpdateTexts()
|
||||
{
|
||||
Options& o = m_pMinecraft->m_options;
|
||||
|
||||
m_AOButton.field_18 = "Smooth lighting: " + BoolOptionStr(o.field_18);
|
||||
m_invertYButton.field_18 = "Invert Y-axis: " + BoolOptionStr(o.m_bInvertMouse);
|
||||
m_viewBobButton.field_18 = "View bobbing: " + BoolOptionStr(o.field_14);
|
||||
m_anaglyphsButton.field_18 = "3d Anaglyphs: " + BoolOptionStr(o.m_bAnaglyphs);
|
||||
m_fancyGfxButton.field_18 = "Fancy graphics: " + BoolOptionStr(o.m_bFancyGraphics);
|
||||
m_flightHaxButton.field_18 = "Flight hax: " + BoolOptionStr(o.m_bFlyCheat);
|
||||
m_viewDistButton.field_18 = "View distance: " + ViewDistanceStr(o.field_10);
|
||||
m_srvVisButton.field_18 = "Server " + std::string(o.m_bServerVisibleDefault ? "visible" : "invisible") + " by default";
|
||||
}
|
||||
#endif
|
||||
|
||||
void OptionsScreen::init()
|
||||
{
|
||||
m_pMinecraft->platform()->showDialog(AppPlatform::DLG_OPTIONS);
|
||||
m_pMinecraft->platform()->createUserInput();
|
||||
|
||||
#ifndef ORIGINAL_CODE
|
||||
m_BackButton.m_xPos = m_width / 2 - m_BackButton.m_width / 2;
|
||||
m_BackButton.m_yPos = m_height - 33;
|
||||
m_BackButton.m_height = 20;
|
||||
m_buttons.push_back(&m_BackButton);
|
||||
|
||||
m_AOButton.m_xPos =
|
||||
m_srvVisButton.m_xPos =
|
||||
m_fancyGfxButton.m_xPos =
|
||||
m_viewDistButton.m_xPos = m_width / 2 - m_AOButton.m_width - 5;
|
||||
|
||||
m_invertYButton.m_xPos =
|
||||
m_anaglyphsButton.m_xPos =
|
||||
m_viewBobButton.m_xPos =
|
||||
m_flightHaxButton.m_xPos = m_width / 2 + 5;
|
||||
|
||||
int yPos = 40;
|
||||
m_AOButton.m_yPos = m_invertYButton.m_yPos = yPos; yPos += 25;
|
||||
m_srvVisButton.m_yPos = m_anaglyphsButton.m_yPos = yPos; yPos += 25;
|
||||
m_fancyGfxButton.m_yPos = m_viewBobButton.m_yPos = yPos; yPos += 25;
|
||||
m_viewDistButton.m_yPos = m_flightHaxButton.m_yPos = yPos; yPos += 25;
|
||||
|
||||
m_buttons.push_back(&m_AOButton);
|
||||
m_buttons.push_back(&m_srvVisButton);
|
||||
m_buttons.push_back(&m_fancyGfxButton);
|
||||
m_buttons.push_back(&m_invertYButton);
|
||||
m_buttons.push_back(&m_anaglyphsButton);
|
||||
m_buttons.push_back(&m_viewBobButton);
|
||||
m_buttons.push_back(&m_viewDistButton);
|
||||
m_buttons.push_back(&m_flightHaxButton);
|
||||
|
||||
m_buttonTabList.push_back(&m_AOButton);
|
||||
m_buttonTabList.push_back(&m_srvVisButton);
|
||||
m_buttonTabList.push_back(&m_fancyGfxButton);
|
||||
m_buttonTabList.push_back(&m_viewDistButton);
|
||||
m_buttonTabList.push_back(&m_invertYButton);
|
||||
m_buttonTabList.push_back(&m_anaglyphsButton);
|
||||
m_buttonTabList.push_back(&m_viewBobButton);
|
||||
m_buttonTabList.push_back(&m_flightHaxButton);
|
||||
|
||||
m_buttonTabList.push_back(&m_BackButton);
|
||||
|
||||
UpdateTexts();
|
||||
#endif
|
||||
}
|
||||
|
||||
void OptionsScreen::render(int a, int b, float c)
|
||||
{
|
||||
renderBackground();
|
||||
|
||||
if (m_pMinecraft->m_pPlatform->getUserInputStatus() >= 0)
|
||||
{
|
||||
m_pMinecraft->setScreen(new StartMenuScreen);
|
||||
}
|
||||
|
||||
#ifndef ORIGINAL_CODE
|
||||
drawCenteredString(m_pFont, "Options", m_width / 2, 20, 0xFFFFFF);
|
||||
|
||||
Screen::render(a, b, c);
|
||||
#endif
|
||||
}
|
||||
|
||||
void OptionsScreen::removed()
|
||||
{
|
||||
#ifdef ORIGINAL_CODE // Reloading options will reload the options.txt we introduced. Don't do this
|
||||
m_pMinecraft->reloadOptions();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef ORIGINAL_CODE
|
||||
|
||||
void OptionsScreen::buttonClicked(Button* pButton)
|
||||
{
|
||||
Options& o = m_pMinecraft->m_options;
|
||||
|
||||
bool* pOption = nullptr;
|
||||
switch (pButton->field_30)
|
||||
{
|
||||
case OB_BACK:
|
||||
if (m_pMinecraft->isLevelGenerated())
|
||||
m_pMinecraft->setScreen(new PauseScreen);
|
||||
else
|
||||
m_pMinecraft->setScreen(new StartMenuScreen);
|
||||
return;
|
||||
|
||||
case OB_AO:
|
||||
o.field_18 ^= 1;
|
||||
Minecraft::useAmbientOcclusion = o.field_18;
|
||||
m_pMinecraft->m_pLevelRenderer->allChanged();
|
||||
UpdateTexts();
|
||||
return;
|
||||
case OB_FANCY_GFX:
|
||||
o.m_bFancyGraphics ^= 1;
|
||||
m_pMinecraft->m_pLevelRenderer->allChanged();
|
||||
UpdateTexts();
|
||||
return;
|
||||
case OB_VIEW_DIST:
|
||||
// @TODO: fix the 'extreme' render distance
|
||||
o.field_10 = (o.field_10 + 1) % 4;
|
||||
UpdateTexts();
|
||||
return;
|
||||
|
||||
case OB_ANAGLYPHS:
|
||||
pOption = &o.m_bAnaglyphs;
|
||||
break;
|
||||
case OB_INVERT_Y:
|
||||
pOption = &o.m_bInvertMouse;
|
||||
break;
|
||||
case OB_SRV_VIS:
|
||||
pOption = &o.m_bServerVisibleDefault;
|
||||
break;
|
||||
case OB_VIEW_BOB:
|
||||
pOption = &o.field_14;
|
||||
break;
|
||||
case OB_FLY_HAX:
|
||||
pOption = &o.m_bFlyCheat;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pOption)
|
||||
return;
|
||||
|
||||
*pOption ^= 1;
|
||||
UpdateTexts();
|
||||
}
|
||||
|
||||
#endif
|
||||
38
source/gui/Screen/OptionsScreen.hpp
Normal file
38
source/gui/Screen/OptionsScreen.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Screen.hpp"
|
||||
|
||||
class OptionsScreen : public Screen
|
||||
{
|
||||
public:
|
||||
OptionsScreen();
|
||||
void init() override;
|
||||
void render(int, int, float) override;
|
||||
void removed() override;
|
||||
|
||||
#ifndef ORIGINAL_CODE
|
||||
void buttonClicked(Button* pButton) override;
|
||||
|
||||
void UpdateTexts();
|
||||
|
||||
private:
|
||||
Button m_BackButton;
|
||||
Button m_AOButton;
|
||||
Button m_srvVisButton;
|
||||
Button m_fancyGfxButton;
|
||||
Button m_invertYButton;
|
||||
Button m_anaglyphsButton;
|
||||
Button m_viewBobButton;
|
||||
Button m_viewDistButton;
|
||||
Button m_flightHaxButton;
|
||||
#endif
|
||||
};
|
||||
|
||||
123
source/gui/Screen/PauseScreen.cpp
Normal file
123
source/gui/Screen/PauseScreen.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "PauseScreen.hpp"
|
||||
#include "OptionsScreen.hpp"
|
||||
#include "ServerSideNetworkHandler.hpp"
|
||||
|
||||
PauseScreen::PauseScreen() :
|
||||
m_btnBack(1, "Back to game"),
|
||||
m_btnQuit(2, "Quit to title"),
|
||||
m_btnQuitAndCopy(3, "Quit and copy map"),
|
||||
m_btnVisible(4, "")
|
||||
#ifdef ENH_ADD_OPTIONS_PAUSE
|
||||
, m_btnOptions(999, "Options")
|
||||
#endif
|
||||
{
|
||||
}
|
||||
|
||||
void PauseScreen::init()
|
||||
{
|
||||
m_btnQuit.m_width = 160;
|
||||
m_btnBack.m_width = 160;
|
||||
m_btnVisible.m_width = 160;
|
||||
m_btnQuitAndCopy.m_width = 160;
|
||||
|
||||
m_btnBack.m_yPos = 48;
|
||||
m_btnQuit.m_yPos = 80;
|
||||
m_btnBack.m_xPos = (m_width - 160) / 2;
|
||||
m_btnQuit.m_xPos = (m_width - 160) / 2;
|
||||
m_btnVisible.m_xPos = (m_width - 160) / 2;
|
||||
m_btnQuitAndCopy.m_xPos = (m_width - 160) / 2;
|
||||
|
||||
m_btnVisible.m_yPos = 112;
|
||||
m_btnQuitAndCopy.m_yPos = 112;
|
||||
|
||||
#ifdef ENH_ADD_OPTIONS_PAUSE
|
||||
// TODO: when visible or quit© are on, lower this
|
||||
m_btnOptions.m_width = 160;
|
||||
m_btnOptions.m_yPos = 112;
|
||||
m_btnOptions.m_xPos = m_btnBack.m_xPos;
|
||||
#endif
|
||||
|
||||
// add the buttons to the screen:
|
||||
m_buttons.push_back(&m_btnBack);
|
||||
m_buttons.push_back(&m_btnQuit);
|
||||
|
||||
#ifdef ENH_ADD_OPTIONS_PAUSE
|
||||
m_buttons.push_back(&m_btnOptions);
|
||||
#endif
|
||||
|
||||
//m_buttons.push_back(&m_btnQuitAndCopy);
|
||||
|
||||
if (m_pMinecraft->m_pRakNetInstance && m_pMinecraft->m_pRakNetInstance->m_bIsHost)
|
||||
{
|
||||
updateServerVisibilityText();
|
||||
m_buttons.push_back(&m_btnVisible);
|
||||
#ifdef ENH_ADD_OPTIONS_PAUSE
|
||||
m_btnOptions.m_yPos += 32;
|
||||
#endif
|
||||
}
|
||||
|
||||
for (auto thing : m_buttons)
|
||||
m_buttonTabList.push_back(thing);
|
||||
}
|
||||
|
||||
void PauseScreen::updateServerVisibilityText()
|
||||
{
|
||||
if (!m_pMinecraft->m_pRakNetInstance) return;
|
||||
if (!m_pMinecraft->m_pRakNetInstance->m_bIsHost) return;
|
||||
|
||||
ServerSideNetworkHandler* pSSNH = (ServerSideNetworkHandler*)m_pMinecraft->m_pNetEventCallback;
|
||||
|
||||
if (pSSNH->m_bAllowIncoming)
|
||||
m_btnVisible.field_18 = "Server is visible";
|
||||
else
|
||||
m_btnVisible.field_18 = "Server is invisible";
|
||||
}
|
||||
|
||||
void PauseScreen::tick()
|
||||
{
|
||||
field_40++;
|
||||
}
|
||||
|
||||
void PauseScreen::render(int a, int b, float c)
|
||||
{
|
||||
renderBackground();
|
||||
|
||||
drawCenteredString(m_pFont, "Game menu", m_width / 2, 24, 0xFFFFFF);
|
||||
Screen::render(a, b, c);
|
||||
}
|
||||
|
||||
void PauseScreen::buttonClicked(Button* pButton)
|
||||
{
|
||||
if (pButton->field_30 == m_btnBack.field_30)
|
||||
m_pMinecraft->setScreen(nullptr);
|
||||
|
||||
if (pButton->field_30 == m_btnQuit.field_30)
|
||||
m_pMinecraft->leaveGame(false);
|
||||
|
||||
if (pButton->field_30 == m_btnQuitAndCopy.field_30)
|
||||
m_pMinecraft->leaveGame(true);
|
||||
|
||||
if (pButton->field_30 == m_btnVisible.field_30)
|
||||
{
|
||||
if (m_pMinecraft->m_pRakNetInstance && m_pMinecraft->m_pRakNetInstance->m_bIsHost)
|
||||
{
|
||||
ServerSideNetworkHandler* pSSNH = (ServerSideNetworkHandler*)m_pMinecraft->m_pNetEventCallback;
|
||||
pSSNH->allowIncomingConnections(!pSSNH->m_bAllowIncoming);
|
||||
|
||||
updateServerVisibilityText();
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENH_ADD_OPTIONS_PAUSE
|
||||
if (pButton->field_30 == m_btnOptions.field_30)
|
||||
m_pMinecraft->setScreen(new OptionsScreen);
|
||||
#endif
|
||||
}
|
||||
36
source/gui/Screen/PauseScreen.hpp
Normal file
36
source/gui/Screen/PauseScreen.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Screen.hpp"
|
||||
|
||||
class PauseScreen : public Screen
|
||||
{
|
||||
public:
|
||||
PauseScreen();
|
||||
virtual void init() override;
|
||||
virtual void tick() override;
|
||||
virtual void render(int a, int b, float c) override;
|
||||
virtual void buttonClicked(Button*) override;
|
||||
|
||||
void updateServerVisibilityText();
|
||||
|
||||
private:
|
||||
int field_3C = 0;
|
||||
int field_40 = 0;
|
||||
Button m_btnBack;
|
||||
Button m_btnQuit;
|
||||
Button m_btnQuitAndCopy;
|
||||
Button m_btnVisible;
|
||||
|
||||
#ifdef ENH_ADD_OPTIONS_PAUSE
|
||||
Button m_btnOptions;
|
||||
#endif
|
||||
};
|
||||
|
||||
86
source/gui/Screen/ProgressScreen.cpp
Normal file
86
source/gui/Screen/ProgressScreen.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "ProgressScreen.hpp"
|
||||
|
||||
bool ProgressScreen::isInGameScreen()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void ProgressScreen::render(int a, int b, float c)
|
||||
{
|
||||
if (m_pMinecraft->isLevelGenerated())
|
||||
{
|
||||
m_pMinecraft->setScreen(nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
renderBackground();
|
||||
|
||||
// render the dirt background
|
||||
// for some reason, this was manually written:
|
||||
|
||||
m_pMinecraft->m_pTextures->loadAndBindTexture("gui/background.png");
|
||||
|
||||
//! why not use the screen stuff
|
||||
int x_width = int(Minecraft::width * Gui::InvGuiScale);
|
||||
int x_height = int(Minecraft::height * Gui::InvGuiScale);
|
||||
|
||||
Tesselator& t = Tesselator::instance;
|
||||
t.begin();
|
||||
t.color(0x404040);
|
||||
t.vertexUV(0.0f, float(x_height), 0, 0, float(x_height) / 32.0f);
|
||||
t.vertexUV(float(x_width), float(x_height), 0, float(x_width) / 32.0f, float(x_height) / 32.0f);
|
||||
t.vertexUV(float(x_width), 0, 0, float(x_width) / 32.0f, 0);
|
||||
t.vertexUV(0.0f, 0, 0, 0, 0);
|
||||
t.draw();
|
||||
|
||||
int yPos = x_height / 2;
|
||||
|
||||
if (m_pMinecraft->m_progressPercent >= 0)
|
||||
{
|
||||
float lX = float(x_width) / 2 - 50, rX = float(x_width) / 2 + 50;
|
||||
float prog = float(m_pMinecraft->m_progressPercent);
|
||||
|
||||
// disable the texturing
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
t.begin();
|
||||
|
||||
t.color(0x808080); // gray background
|
||||
t.vertex(lX, float(yPos + 16), 0);
|
||||
t.vertex(lX, float(yPos + 18), 0);
|
||||
t.vertex(rX, float(yPos + 18), 0);
|
||||
t.vertex(rX, float(yPos + 16), 0);
|
||||
|
||||
t.color(0x80FF80); // the green stuff
|
||||
t.vertex(lX, float(yPos + 16), 0);
|
||||
t.vertex(lX, float(yPos + 18), 0);
|
||||
t.vertex(lX + prog, float(yPos + 18), 0);
|
||||
t.vertex(lX + prog, float(yPos + 16), 0);
|
||||
|
||||
t.draw();
|
||||
|
||||
// restore old state
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
//! Using m_pMinecraft->m_pFont instead of m_pFont.
|
||||
Font* pFont = m_pMinecraft->m_pFont;
|
||||
|
||||
int width = pFont->width("Generating world");
|
||||
pFont->drawShadow("Generating world", (x_width - width) / 2, yPos - 20, 0xFFFFFF);
|
||||
|
||||
width = pFont->width(m_pMinecraft->getProgressMessage());
|
||||
pFont->drawShadow(m_pMinecraft->getProgressMessage(), (x_width - width) / 2, yPos + 4, 0xFFFFFF);
|
||||
|
||||
#ifdef ORIGINAL_CODE
|
||||
sleepMs(50);
|
||||
#endif
|
||||
}
|
||||
19
source/gui/Screen/ProgressScreen.hpp
Normal file
19
source/gui/Screen/ProgressScreen.hpp
Normal file
@@ -0,0 +1,19 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Screen.hpp"
|
||||
|
||||
class ProgressScreen : public Screen
|
||||
{
|
||||
public:
|
||||
void render(int, int, float) override;
|
||||
bool isInGameScreen() override;
|
||||
};
|
||||
|
||||
38
source/gui/Screen/RenameMPLevelScreen.cpp
Normal file
38
source/gui/Screen/RenameMPLevelScreen.cpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "RenameMPLevelScreen.hpp"
|
||||
#include "StartMenuScreen.hpp"
|
||||
|
||||
RenameMPLevelScreen::RenameMPLevelScreen(const std::string& levelName) : m_levelName(levelName)
|
||||
{
|
||||
}
|
||||
|
||||
void RenameMPLevelScreen::init()
|
||||
{
|
||||
m_pMinecraft->platform()->showDialog(AppPlatform::DLG_RENAME_MP_WORLD);
|
||||
m_pMinecraft->platform()->createUserInput();
|
||||
}
|
||||
|
||||
void RenameMPLevelScreen::render(int mouseX, int mouseY, float f)
|
||||
{
|
||||
int userInputStatus = m_pMinecraft->platform()->getUserInputStatus();
|
||||
if (userInputStatus < 0)
|
||||
return;
|
||||
|
||||
if (userInputStatus == 1)
|
||||
{
|
||||
std::vector<std::string> input = m_pMinecraft->platform()->getUserInput();
|
||||
if (input.size() > 0 && !input[0].empty())
|
||||
{
|
||||
m_pMinecraft->getLevelSource()->renameLevel(m_levelName, input[0]);
|
||||
}
|
||||
}
|
||||
|
||||
m_pMinecraft->setScreen(new StartMenuScreen);
|
||||
}
|
||||
23
source/gui/Screen/RenameMPLevelScreen.hpp
Normal file
23
source/gui/Screen/RenameMPLevelScreen.hpp
Normal file
@@ -0,0 +1,23 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Screen.hpp"
|
||||
|
||||
class RenameMPLevelScreen : public Screen
|
||||
{
|
||||
public:
|
||||
RenameMPLevelScreen(const std::string& levelName);
|
||||
void init() override;
|
||||
void render(int mouseX, int mouseY, float f) override;
|
||||
|
||||
private:
|
||||
std::string m_levelName;
|
||||
};
|
||||
|
||||
71
source/gui/Screen/SavingWorldScreen.cpp
Normal file
71
source/gui/Screen/SavingWorldScreen.cpp
Normal file
@@ -0,0 +1,71 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "SavingWorldScreen.hpp"
|
||||
#include "RenameMPLevelScreen.hpp"
|
||||
#include "StartMenuScreen.hpp"
|
||||
|
||||
#ifdef ENH_IMPROVED_SAVING
|
||||
|
||||
SavingWorldScreen::SavingWorldScreen(bool bCopyMap)
|
||||
{
|
||||
m_bCopyMapAtEnd = bCopyMap;
|
||||
m_timer = 0;
|
||||
}
|
||||
|
||||
void SavingWorldScreen::render(int mouseX, int mouseY, float f)
|
||||
{
|
||||
renderDirtBackground(0);
|
||||
|
||||
int x_width = int(Minecraft::width * Gui::InvGuiScale);
|
||||
int x_height = int(Minecraft::height * Gui::InvGuiScale);
|
||||
int yPos = x_height / 2;
|
||||
|
||||
int width = m_pFont->width("Saving chunks");
|
||||
m_pFont->drawShadow("Saving chunks", (x_width - width) / 2, yPos, 0xFFFFFF);
|
||||
}
|
||||
|
||||
void SavingWorldScreen::tick()
|
||||
{
|
||||
if (m_timer < 0)
|
||||
return;
|
||||
|
||||
m_timer++;
|
||||
|
||||
if (m_timer >= 5)
|
||||
{
|
||||
m_timer = -1;
|
||||
|
||||
Level* pLevel = m_pMinecraft->m_pLevel;
|
||||
if (pLevel)
|
||||
{
|
||||
pLevel->saveUnsavedChunks();
|
||||
pLevel->saveLevelData();
|
||||
pLevel->savePlayerData();
|
||||
|
||||
LevelStorage* pStorage = pLevel->getLevelStorage();
|
||||
SAFE_DELETE(pStorage);
|
||||
SAFE_DELETE(pLevel);
|
||||
|
||||
m_pMinecraft->m_pLevel = nullptr;
|
||||
}
|
||||
|
||||
m_pMinecraft->field_DB0 = true;
|
||||
|
||||
if (m_bCopyMapAtEnd)
|
||||
m_pMinecraft->setScreen(new RenameMPLevelScreen("_LastJoinedServer"));
|
||||
else
|
||||
m_pMinecraft->setScreen(new StartMenuScreen);
|
||||
|
||||
m_pMinecraft->field_DB0 = false;
|
||||
|
||||
m_pMinecraft->field_288 = false;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
28
source/gui/Screen/SavingWorldScreen.hpp
Normal file
28
source/gui/Screen/SavingWorldScreen.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Screen.hpp"
|
||||
|
||||
#ifdef ENH_IMPROVED_SAVING
|
||||
|
||||
class SavingWorldScreen : public Screen
|
||||
{
|
||||
public:
|
||||
SavingWorldScreen(bool bCopyMap);
|
||||
|
||||
void render(int mouseX, int mouseY, float f) override;
|
||||
void tick() override;
|
||||
|
||||
public:
|
||||
bool m_bCopyMapAtEnd;
|
||||
int m_timer = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
260
source/gui/Screen/Screen.cpp
Normal file
260
source/gui/Screen/Screen.cpp
Normal file
@@ -0,0 +1,260 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "Screen.hpp"
|
||||
|
||||
Screen::Screen()
|
||||
{
|
||||
}
|
||||
|
||||
Screen::~Screen()
|
||||
{
|
||||
m_pClickedButton = nullptr;
|
||||
m_buttons.clear();
|
||||
}
|
||||
|
||||
void Screen::init(Minecraft* pMinecraft, int a3, int a4)
|
||||
{
|
||||
m_width = a3;
|
||||
m_height = a4;
|
||||
m_pMinecraft = pMinecraft;
|
||||
m_pFont = pMinecraft->m_pFont;
|
||||
init();
|
||||
updateTabButtonSelection();
|
||||
}
|
||||
|
||||
void Screen::init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Screen::buttonClicked(Button* pButton)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Screen::confirmResult(bool b, int i)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Screen::handleBackEvent(bool b)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Screen::isPauseScreen()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Screen::isErrorScreen()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Screen::isInGameScreen()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void Screen::keyPressed(int key)
|
||||
{
|
||||
if (key == '\x1B')//escape
|
||||
{
|
||||
m_pMinecraft->setScreen(nullptr);
|
||||
}
|
||||
|
||||
if (m_buttonTabList.size())
|
||||
{
|
||||
#ifndef ENH_HIGHLIGHT_BY_HOVER
|
||||
if (m_pMinecraft->m_options.m_keyBinds[Options::MENU_NEXT].value == key)
|
||||
{
|
||||
m_tabButtonIndex++;
|
||||
if (m_tabButtonIndex == int(m_buttonTabList.size()))
|
||||
m_tabButtonIndex = 0;
|
||||
}
|
||||
if (m_pMinecraft->m_options.m_keyBinds[Options::MENU_PREVIOUS].value == key)
|
||||
{
|
||||
m_tabButtonIndex--;
|
||||
if (m_tabButtonIndex == -1)
|
||||
m_tabButtonIndex = int(m_buttonTabList.size() - 1);
|
||||
}
|
||||
if (m_pMinecraft->m_options.m_keyBinds[Options::MENU_OK].value == key)
|
||||
{
|
||||
if (m_buttonTabList[m_tabButtonIndex]->m_bEnabled)
|
||||
{
|
||||
m_pMinecraft->m_pSoundEngine->play("random.click");
|
||||
buttonClicked(m_buttonTabList[m_tabButtonIndex]);
|
||||
}
|
||||
}
|
||||
|
||||
updateTabButtonSelection();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef ORIGINAL_CODE
|
||||
for (auto textInput : m_textInputs)
|
||||
{
|
||||
textInput->keyPressed(m_pMinecraft, key);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Screen::mouseClicked(int xPos, int yPos, int d) // d = clicked?
|
||||
{
|
||||
if (!d) return;
|
||||
|
||||
for (auto button : m_buttons)
|
||||
{
|
||||
if (button->clicked(m_pMinecraft, xPos, yPos))
|
||||
{
|
||||
m_pClickedButton = button;
|
||||
m_pMinecraft->m_pSoundEngine->play("random.click");
|
||||
|
||||
buttonClicked(button);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ORIGINAL_CODE
|
||||
for (auto textInput : m_textInputs)
|
||||
{
|
||||
textInput->onClick(xPos, yPos);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Screen::mouseReleased(int xPos, int yPos, int d)
|
||||
{
|
||||
if (!d) return;
|
||||
|
||||
if (m_pClickedButton)
|
||||
{
|
||||
m_pClickedButton->released(xPos, yPos);
|
||||
m_pClickedButton = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::render(int xPos, int yPos, float unused)
|
||||
{
|
||||
for (auto button : m_buttons)
|
||||
{
|
||||
button->render(m_pMinecraft, xPos, yPos);
|
||||
}
|
||||
|
||||
#ifndef ORIGINAL_CODE
|
||||
for (auto textInput : m_textInputs)
|
||||
{
|
||||
textInput->tick();
|
||||
textInput->render();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void Screen::tick()
|
||||
{
|
||||
}
|
||||
|
||||
void Screen::removed()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void Screen::setSize(int width, int height)
|
||||
{
|
||||
m_width = width;
|
||||
m_height = height;
|
||||
}
|
||||
|
||||
void Screen::updateEvents()
|
||||
{
|
||||
if (field_10) return;
|
||||
|
||||
for (int i = Mouse::_index + 1; i<int(Mouse::_inputs.size()); i++)
|
||||
{
|
||||
Mouse::_index = i;
|
||||
mouseEvent();
|
||||
}
|
||||
|
||||
for (int i = Keyboard::_index + 1; i<int(Keyboard::_inputs.size()); i++)
|
||||
{
|
||||
Keyboard::_index = i;
|
||||
keyboardEvent();
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::keyboardEvent()
|
||||
{
|
||||
// @UB: This probably behaves in an unexpected way if _inputs is empty
|
||||
|
||||
#ifndef ORIGINAL_CODE
|
||||
if (Keyboard::_inputs.empty() || Keyboard::_index < 0)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (Keyboard::_inputs[Keyboard::_index].field_0)
|
||||
keyPressed(Keyboard::_inputs[Keyboard::_index].field_4);
|
||||
}
|
||||
|
||||
void Screen::mouseEvent()
|
||||
{
|
||||
MouseInput& inp = Mouse::_inputs[Mouse::_index];
|
||||
|
||||
if (1 <= inp.field_0 && inp.field_0 <= 2)
|
||||
{
|
||||
if (inp.field_4 == 1)
|
||||
mouseClicked(m_width * Mouse::_x / Minecraft::width, m_height * Mouse::_y / Minecraft::height - 1, inp.field_0);
|
||||
else
|
||||
mouseReleased(m_width * Mouse::_x / Minecraft::width, m_height * Mouse::_y / Minecraft::height - 1, inp.field_0);
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::renderBackground(int unk)
|
||||
{
|
||||
if (m_pMinecraft->isLevelGenerated())
|
||||
{
|
||||
fillGradient(0, 0, m_width, m_height, 0xC0101010, 0xD0101010);
|
||||
}
|
||||
else
|
||||
{
|
||||
renderDirtBackground(unk);
|
||||
}
|
||||
}
|
||||
|
||||
void Screen::renderBackground()
|
||||
{
|
||||
renderBackground(0);
|
||||
}
|
||||
|
||||
void Screen::renderDirtBackground(int unk)
|
||||
{
|
||||
glDisable(GL_FOG);
|
||||
|
||||
m_pMinecraft->m_pTextures->loadAndBindTexture("gui/background.png");
|
||||
glColor4f(1, 1, 1, 1);
|
||||
|
||||
Tesselator& t = Tesselator::instance;
|
||||
t.begin();
|
||||
t.color(0x404040);
|
||||
t.vertexUV(0.0f, float(m_height), 0, 0, float(unk) + float(m_height) / 32.0f);
|
||||
t.vertexUV(float(m_width), float(m_height), 0, float(unk) + float(m_width) / 32.0f, float(unk) + float(m_height) / 32.0f);
|
||||
t.vertexUV(float(m_width), 0, 0, float(unk) + float(m_width) / 32.0f, 0);
|
||||
t.vertexUV(0.0f, 0, 0, 0, 0);
|
||||
t.draw();
|
||||
}
|
||||
|
||||
|
||||
void Screen::updateTabButtonSelection()
|
||||
{
|
||||
#ifndef ENH_HIGHLIGHT_BY_HOVER
|
||||
for (int i = 0; i < int(m_buttonTabList.size()); i++)
|
||||
{
|
||||
m_buttonTabList[i]->field_36 = m_tabButtonIndex == i;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
63
source/gui/Screen/Screen.hpp
Normal file
63
source/gui/Screen/Screen.hpp
Normal file
@@ -0,0 +1,63 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Mouse.hpp"
|
||||
#include "Keyboard.hpp"
|
||||
#include "Button.hpp"
|
||||
#include "TextInputBox.hpp"
|
||||
|
||||
class Button;
|
||||
|
||||
class Screen : public GuiComponent
|
||||
{
|
||||
public:
|
||||
Screen();
|
||||
virtual ~Screen();
|
||||
|
||||
void init(Minecraft*, int, int);
|
||||
void updateTabButtonSelection();
|
||||
void setSize(int width, int height);
|
||||
|
||||
virtual void render(int, int, float);
|
||||
virtual void init();
|
||||
virtual void updateEvents();
|
||||
virtual void mouseEvent();
|
||||
virtual void keyboardEvent();
|
||||
virtual bool handleBackEvent(bool);
|
||||
virtual void tick();
|
||||
virtual void removed();
|
||||
virtual void renderBackground(int);
|
||||
virtual void renderBackground();
|
||||
virtual void renderDirtBackground(int);
|
||||
virtual bool isPauseScreen();
|
||||
virtual bool isErrorScreen();
|
||||
virtual bool isInGameScreen();
|
||||
virtual void confirmResult(bool, int);
|
||||
virtual void buttonClicked(Button*);
|
||||
virtual void mouseClicked(int, int, int);
|
||||
virtual void mouseReleased(int, int, int);
|
||||
virtual void keyPressed(int);
|
||||
|
||||
public:
|
||||
int m_width = 1;
|
||||
int m_height = 1;
|
||||
bool field_10 = false;
|
||||
Minecraft* m_pMinecraft;
|
||||
std::vector<Button*> m_buttons;
|
||||
std::vector<Button*> m_buttonTabList;
|
||||
int m_tabButtonIndex = 0;
|
||||
Font* m_pFont;
|
||||
Button* m_pClickedButton = 0;
|
||||
|
||||
#ifndef ORIGINAL_CODE
|
||||
std::vector<TextInputBox*> m_textInputs;
|
||||
#endif
|
||||
};
|
||||
|
||||
263
source/gui/Screen/SelectWorldScreen.cpp
Normal file
263
source/gui/Screen/SelectWorldScreen.cpp
Normal file
@@ -0,0 +1,263 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "SelectWorldScreen.hpp"
|
||||
#include "DeleteWorldScreen.hpp"
|
||||
#include "CreateWorldScreen.hpp"
|
||||
#include "ProgressScreen.hpp"
|
||||
#include "StartMenuScreen.hpp"
|
||||
#include "Util.hpp"
|
||||
|
||||
SelectWorldScreen::SelectWorldScreen() :
|
||||
m_btnDelete (1, "Delete"),
|
||||
m_btnCreateNew(2, "Create new"),
|
||||
m_btnBack (3, "Back"),
|
||||
m_btnUnknown (4, "")
|
||||
{
|
||||
m_btnDelete.m_bEnabled = false;
|
||||
}
|
||||
|
||||
void SelectWorldScreen::init()
|
||||
{
|
||||
m_pWorldSelectionList = new WorldSelectionList(m_pMinecraft, m_width, m_height);
|
||||
loadLevelSource();
|
||||
m_pWorldSelectionList->commit();
|
||||
|
||||
m_btnDelete.m_yPos = m_btnBack.m_yPos = m_btnCreateNew.m_yPos = m_height - 28;
|
||||
m_btnDelete.m_width = m_btnBack.m_width = m_btnCreateNew.m_width = 84;
|
||||
m_btnDelete.m_height = m_btnBack.m_height = m_btnCreateNew.m_height = 24;
|
||||
|
||||
m_btnDelete.m_xPos = m_width / 2 - 130;
|
||||
m_btnCreateNew.m_xPos = m_width / 2 - 42;
|
||||
m_btnBack.m_xPos = m_width / 2 + 46;
|
||||
|
||||
m_buttons.push_back(&m_btnCreateNew);
|
||||
m_buttons.push_back(&m_btnBack);
|
||||
m_buttons.push_back(&m_btnDelete);
|
||||
|
||||
field_12C = Mouse::_buttonStates[1] == 0;
|
||||
|
||||
m_buttonTabList.push_back(&m_btnUnknown);
|
||||
m_buttonTabList.push_back(&m_btnDelete);
|
||||
m_buttonTabList.push_back(&m_btnCreateNew);
|
||||
m_buttonTabList.push_back(&m_btnBack);
|
||||
}
|
||||
|
||||
bool SelectWorldScreen::isInGameScreen()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void SelectWorldScreen::keyPressed(int code)
|
||||
{
|
||||
#ifndef ORIGINAL_CODE
|
||||
if (m_pMinecraft->m_options.m_keyBinds[Options::MENU_OK].value == code)
|
||||
m_pWorldSelectionList->selectItem(m_pWorldSelectionList->getItemAtPosition(m_width / 2, m_height / 2), false);
|
||||
|
||||
m_btnUnknown.field_36 = true;
|
||||
#endif
|
||||
|
||||
if (m_btnUnknown.field_36)
|
||||
{
|
||||
if (m_pMinecraft->m_options.m_keyBinds[Options::LEFT].value == code)
|
||||
m_pWorldSelectionList->stepLeft();
|
||||
|
||||
if (m_pMinecraft->m_options.m_keyBinds[Options::RIGHT].value == code)
|
||||
m_pWorldSelectionList->stepRight();
|
||||
}
|
||||
|
||||
Screen::keyPressed(code);
|
||||
}
|
||||
|
||||
static char g_SelectWorldFilterArray[] = { '/','\n','\r','\x09','\0','\xC','`','?','*','\\','<','>','|','"',':'};
|
||||
|
||||
void SelectWorldScreen::tick()
|
||||
{
|
||||
#ifndef ORIGINAL_CODE
|
||||
m_btnUnknown.field_36 = true;
|
||||
#endif
|
||||
|
||||
if (field_130 == 1)
|
||||
{
|
||||
// poll the user status to get details about the world name and seed
|
||||
int userInputStatus = m_pMinecraft->platform()->getUserInputStatus();
|
||||
|
||||
if (userInputStatus < 0)
|
||||
return;
|
||||
|
||||
if (userInputStatus != 1)
|
||||
{
|
||||
field_130 = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<std::string> userInput = m_pMinecraft->platform()->getUserInput();
|
||||
|
||||
std::string levelNickname = Util::stringTrim(userInput[0]);
|
||||
std::string levelUniqueName = levelNickname;
|
||||
|
||||
for (int i = 0; i < sizeof(g_SelectWorldFilterArray); i++)
|
||||
{
|
||||
std::string str;
|
||||
str.push_back(g_SelectWorldFilterArray[i]);
|
||||
Util::stringReplace(levelUniqueName, str, "");
|
||||
}
|
||||
|
||||
levelUniqueName = getUniqueLevelName(levelUniqueName);
|
||||
|
||||
int seed = int(getEpochTimeS());
|
||||
if (userInput.size() > 1)
|
||||
{
|
||||
std::string seedThing = Util::stringTrim(userInput[1]);
|
||||
if (!seedThing.empty())
|
||||
{
|
||||
int num;
|
||||
if (sscanf(seedThing.c_str(), "%d", &num) > 0)
|
||||
seed = num;
|
||||
else
|
||||
seed = Util::hashCode(seedThing);
|
||||
}
|
||||
}
|
||||
|
||||
m_pMinecraft->selectLevel(levelUniqueName, levelNickname, seed);
|
||||
m_pMinecraft->hostMultiplayer();
|
||||
m_pMinecraft->setScreen(new ProgressScreen);
|
||||
|
||||
// @BUG: Use of deallocated memory. SetScreen frees us
|
||||
#ifdef ORIGINAL_CODE
|
||||
field_130 = 0;
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
m_pWorldSelectionList->tick();
|
||||
if (m_pWorldSelectionList->field_90)
|
||||
{
|
||||
LevelSummary& ls = m_pWorldSelectionList->m_levelSummary;
|
||||
m_pMinecraft->selectLevel(ls.field_0, ls.field_18, 0);
|
||||
m_pMinecraft->hostMultiplayer();
|
||||
m_pMinecraft->setScreen(new ProgressScreen);
|
||||
return;
|
||||
}
|
||||
|
||||
// the level summary stuff is unused.
|
||||
LevelSummary ls;
|
||||
if (isIndexValid(m_pWorldSelectionList->m_selectedIndex))
|
||||
ls = m_pWorldSelectionList->m_items[m_pWorldSelectionList->m_selectedIndex];
|
||||
|
||||
m_btnDelete.m_bEnabled = isIndexValid(m_pWorldSelectionList->m_selectedIndex);
|
||||
}
|
||||
|
||||
void SelectWorldScreen::render(int mouseX, int mouseY, float f)
|
||||
{
|
||||
renderBackground();
|
||||
#ifndef ORIGINAL_CODE
|
||||
m_btnUnknown.field_36 = true;
|
||||
#endif
|
||||
m_pWorldSelectionList->setComponentSelected(m_btnUnknown.field_36);
|
||||
if (field_12C)
|
||||
{
|
||||
m_pWorldSelectionList->render(mouseX, mouseY, f);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pWorldSelectionList->render(0, 0, f);
|
||||
field_12C = Mouse::_buttonStates[1] == 0;
|
||||
}
|
||||
|
||||
Screen::render(mouseX, mouseY, f);
|
||||
|
||||
drawCenteredString(m_pMinecraft->m_pFont, "Select world", m_width / 2, 8, 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
bool SelectWorldScreen::handleBackEvent(bool b)
|
||||
{
|
||||
if (b)
|
||||
return true;
|
||||
|
||||
// @TODO: m_pMinecraft->cancelLocateMultiplayer();
|
||||
m_pMinecraft->setScreen(new StartMenuScreen);
|
||||
return true;
|
||||
}
|
||||
|
||||
void SelectWorldScreen::buttonClicked(Button* pButton)
|
||||
{
|
||||
if (pButton->field_30 == m_btnCreateNew.field_30)
|
||||
{
|
||||
#ifndef ORIGINAL_CODE
|
||||
m_pMinecraft->setScreen(new CreateWorldScreen);
|
||||
#else
|
||||
m_pMinecraft->platform()->showDialog(AppPlatform::DLG_CREATE_WORLD);
|
||||
m_pMinecraft->platform()->createUserInput();
|
||||
field_130 = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (pButton->field_30 == m_btnDelete.field_30)
|
||||
{
|
||||
LevelSummary ls(m_pWorldSelectionList->m_items[m_pWorldSelectionList->m_selectedIndex]);
|
||||
m_pMinecraft->setScreen(new DeleteWorldScreen(ls));
|
||||
}
|
||||
|
||||
if (pButton->field_30 == m_btnBack.field_30)
|
||||
{
|
||||
// @TODO: m_pMinecraft->cancelLocateMultiplayer();
|
||||
m_pMinecraft->setScreen(new StartMenuScreen);
|
||||
}
|
||||
|
||||
if (pButton->field_30 == m_btnUnknown.field_30)
|
||||
{
|
||||
m_pWorldSelectionList->selectItem(m_pWorldSelectionList->getItemAtPosition(m_width / 2, m_height / 2), false);
|
||||
}
|
||||
}
|
||||
|
||||
bool SelectWorldScreen::isIndexValid(int idx)
|
||||
{
|
||||
if (!m_pWorldSelectionList)
|
||||
return false;
|
||||
|
||||
if (idx < 0)
|
||||
return false;
|
||||
|
||||
if (idx >= m_pWorldSelectionList->getNumberOfItems())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string SelectWorldScreen::getUniqueLevelName(const std::string& in)
|
||||
{
|
||||
std::set<std::string> maps;
|
||||
|
||||
for (const auto& ls : m_levels)
|
||||
{
|
||||
maps.insert(ls.field_0);
|
||||
}
|
||||
|
||||
std::string out = in;
|
||||
while (maps.find(out) != maps.end())
|
||||
out += "-";
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
void SelectWorldScreen::loadLevelSource()
|
||||
{
|
||||
m_pMinecraft->getLevelSource()->getLevelList(m_levels);
|
||||
|
||||
std::sort(m_levels.begin(), m_levels.end());
|
||||
|
||||
for (const auto& level : m_levels)
|
||||
{
|
||||
if (level.field_0 == "_LastJoinedServer")
|
||||
continue;
|
||||
|
||||
m_pWorldSelectionList->m_items.push_back(level);
|
||||
}
|
||||
}
|
||||
41
source/gui/Screen/SelectWorldScreen.hpp
Normal file
41
source/gui/Screen/SelectWorldScreen.hpp
Normal file
@@ -0,0 +1,41 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Screen.hpp"
|
||||
#include "WorldSelectionList.hpp"
|
||||
|
||||
class SelectWorldScreen : public Screen
|
||||
{
|
||||
public:
|
||||
SelectWorldScreen();
|
||||
|
||||
void init() override;
|
||||
bool isInGameScreen() override;
|
||||
void keyPressed(int code) override;
|
||||
void tick() override;
|
||||
void render(int mouseX, int mouseY, float f) override;
|
||||
bool handleBackEvent(bool b) override;
|
||||
void buttonClicked(Button* pButton) override;
|
||||
|
||||
bool isIndexValid(int);
|
||||
std::string getUniqueLevelName(const std::string& in);
|
||||
void loadLevelSource();
|
||||
|
||||
public:
|
||||
Button m_btnDelete;
|
||||
Button m_btnCreateNew;
|
||||
Button m_btnBack;
|
||||
Button m_btnUnknown;
|
||||
WorldSelectionList* m_pWorldSelectionList = nullptr;
|
||||
std::vector<LevelSummary> m_levels;
|
||||
bool field_12C;
|
||||
int field_130 = 0;
|
||||
};
|
||||
|
||||
171
source/gui/Screen/StartMenuScreen.cpp
Normal file
171
source/gui/Screen/StartMenuScreen.cpp
Normal file
@@ -0,0 +1,171 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "StartMenuScreen.hpp"
|
||||
#include "InvalidLicenseScreen.hpp"
|
||||
#include "OptionsScreen.hpp"
|
||||
#include "ProgressScreen.hpp"
|
||||
#include "SelectWorldScreen.hpp"
|
||||
#include "JoinGameScreen.hpp"
|
||||
|
||||
StartMenuScreen::StartMenuScreen() :
|
||||
m_startButton (2, 0, 0, 160, 24, "Start Game"),
|
||||
m_joinButton (3, 0, 0, 160, 24, "Join Game"),
|
||||
m_optionsButton(4, 0, 0, 78, 22, "Options"),
|
||||
m_testButton (999, 0, 0, 78, 22, "Test"),
|
||||
m_buyButton (5, 0, 0, 78, 22, "Buy")
|
||||
//, m_testBox(1, 10, 10, 200, 16, "Insert some text...")
|
||||
{
|
||||
}
|
||||
|
||||
void StartMenuScreen::_updateLicense()
|
||||
{
|
||||
int licenseID = m_pMinecraft->getLicenseId();
|
||||
if (licenseID < 0)
|
||||
{
|
||||
m_optionsButton.m_bEnabled = false;
|
||||
m_startButton.m_bEnabled = false;
|
||||
m_joinButton.m_bEnabled = false;
|
||||
}
|
||||
else if (licenseID <= 1)
|
||||
{
|
||||
m_optionsButton.m_bEnabled = true;
|
||||
m_startButton.m_bEnabled = true;
|
||||
m_joinButton.m_bEnabled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pMinecraft->setScreen(new InvalidLicenseScreen(licenseID, m_pMinecraft->platform()->hasBuyButtonWhenInvalidLicense()));
|
||||
}
|
||||
}
|
||||
|
||||
void StartMenuScreen::buttonClicked(Button* pButton)
|
||||
{
|
||||
if (pButton->field_30 == m_startButton.field_30)
|
||||
{
|
||||
#if defined(DEMO)
|
||||
m_pMinecraft->selectLevel("_DemoLevel", "_DemoLevel", int(getEpochTimeS()));
|
||||
m_pMinecraft->hostMultiplayer();
|
||||
m_pMinecraft->setScreen(new ProgressScreen);
|
||||
#else
|
||||
m_pMinecraft->setScreen(new SelectWorldScreen);
|
||||
#endif
|
||||
}
|
||||
else if (pButton->field_30 == m_joinButton.field_30)
|
||||
{
|
||||
m_pMinecraft->locateMultiplayer();
|
||||
m_pMinecraft->setScreen(new JoinGameScreen);
|
||||
}
|
||||
else if (pButton->field_30 == m_buyButton.field_30)
|
||||
{
|
||||
m_pMinecraft->platform()->buyGame();
|
||||
}
|
||||
else if (pButton->field_30 == m_optionsButton.field_30)
|
||||
{
|
||||
m_pMinecraft->setScreen(new OptionsScreen);
|
||||
}
|
||||
}
|
||||
|
||||
void StartMenuScreen::init()
|
||||
{
|
||||
int yPos = m_height / 2;
|
||||
|
||||
m_joinButton.m_yPos = yPos + 25;
|
||||
m_startButton.m_yPos = yPos - 3;
|
||||
|
||||
yPos += 55;
|
||||
|
||||
m_optionsButton.m_yPos = yPos;
|
||||
m_testButton.m_yPos = yPos;
|
||||
m_buyButton.m_yPos = yPos;
|
||||
|
||||
m_startButton.m_xPos = (m_width - m_startButton.m_width) / 2;
|
||||
|
||||
int x1 = m_width - m_joinButton.m_width;
|
||||
|
||||
m_joinButton.m_xPos = x1 / 2;
|
||||
m_optionsButton.m_xPos = x1 / 2;
|
||||
m_buyButton.m_xPos = x1 / 2 + m_optionsButton.m_width + 4;
|
||||
m_testButton.m_xPos = x1 / 2 + m_optionsButton.m_width + 4;
|
||||
|
||||
// add the buttons to the screen:
|
||||
m_buttons.push_back(&m_startButton);
|
||||
m_buttonTabList.push_back(&m_startButton);
|
||||
m_buttons.push_back(&m_joinButton);
|
||||
m_buttonTabList.push_back(&m_joinButton);
|
||||
m_buttons.push_back(&m_optionsButton);
|
||||
m_buttonTabList.push_back(&m_optionsButton);
|
||||
|
||||
#ifdef DEMO
|
||||
m_buttons.push_back(&m_buyButton);
|
||||
m_buttonTabList.push_back(&m_buyButton);
|
||||
#endif
|
||||
|
||||
field_154 = "\xFFMojang AB";
|
||||
field_16C = m_width - 1 - m_pFont->width(field_154);
|
||||
|
||||
field_170 = "v0.1.0 alpha"
|
||||
#ifdef DEMO
|
||||
" (Demo)"
|
||||
#endif
|
||||
;
|
||||
|
||||
field_188 = (m_width - m_pFont->width(field_170)) / 2;
|
||||
|
||||
//m_testBox.init(m_pFont);
|
||||
//m_textInputs.push_back(&m_testBox);
|
||||
|
||||
_updateLicense();
|
||||
}
|
||||
|
||||
bool StartMenuScreen::isInGameScreen()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void StartMenuScreen::render(int a, int b, float c)
|
||||
{
|
||||
renderBackground();
|
||||
|
||||
Textures* tx = m_pMinecraft->m_pTextures;
|
||||
|
||||
int id = tx->loadTexture("gui/title.png", true);
|
||||
Texture *pTex = tx->getTemporaryTextureData(id);
|
||||
|
||||
if (pTex)
|
||||
{
|
||||
if (id != tx->m_currBoundTex)
|
||||
{
|
||||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
tx->m_currBoundTex = id;
|
||||
}
|
||||
|
||||
int left = (m_width - pTex->m_width) / 2;
|
||||
int width = pTex->m_width;
|
||||
int height = pTex->m_height;
|
||||
|
||||
Tesselator& t = Tesselator::instance;
|
||||
glColor4f(1, 1, 1, 1);
|
||||
t.begin();
|
||||
t.vertexUV(float(left), float(height + 4), field_4, 0.0f, 1.0f);
|
||||
t.vertexUV(float(left + width), float(height + 4), field_4, 1.0f, 1.0f);
|
||||
t.vertexUV(float(left + width), 4, field_4, 1.0f, 0.0f);
|
||||
t.vertexUV(float(left), 4, field_4, 0.0f, 0.0f);
|
||||
t.draw();
|
||||
}
|
||||
|
||||
drawString(m_pFont, field_170, field_188, 62, 0xFFCCCCCC);
|
||||
drawString(m_pFont, field_154, field_16C, m_height - 10, 0x00FFFFFF);
|
||||
|
||||
Screen::render(a, b, c);
|
||||
}
|
||||
|
||||
void StartMenuScreen::tick()
|
||||
{
|
||||
_updateLicense();
|
||||
}
|
||||
38
source/gui/Screen/StartMenuScreen.hpp
Normal file
38
source/gui/Screen/StartMenuScreen.hpp
Normal file
@@ -0,0 +1,38 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Screen.hpp"
|
||||
|
||||
class StartMenuScreen : public Screen
|
||||
{
|
||||
public:
|
||||
StartMenuScreen();
|
||||
void _updateLicense();
|
||||
|
||||
void init() override;
|
||||
void buttonClicked(Button*) override;
|
||||
bool isInGameScreen() override;
|
||||
void render(int, int, float) override;
|
||||
void tick() override;
|
||||
|
||||
private:
|
||||
Button m_startButton;
|
||||
Button m_joinButton;
|
||||
Button m_optionsButton;
|
||||
Button m_testButton;
|
||||
Button m_buyButton;
|
||||
std::string field_154;
|
||||
int field_16C;
|
||||
std::string field_170;
|
||||
int field_188;
|
||||
|
||||
//TextInputBox m_testBox;
|
||||
};
|
||||
|
||||
241
source/gui/ScrolledSelectionList.cpp
Normal file
241
source/gui/ScrolledSelectionList.cpp
Normal file
@@ -0,0 +1,241 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "ScrolledSelectionList.hpp"
|
||||
|
||||
#define C_ITEM_WIDTH (220)
|
||||
|
||||
ScrolledSelectionList::ScrolledSelectionList(Minecraft* minecraft, int a3, int a4, int a5, int a6, int a7) :
|
||||
m_pMinecraft(minecraft),
|
||||
field_C(float(a5)),
|
||||
field_10(float(a6)),
|
||||
m_itemHeight(a7),
|
||||
field_18(a3),
|
||||
field_1C(a4),
|
||||
field_20(float(a3))
|
||||
{
|
||||
}
|
||||
|
||||
void ScrolledSelectionList::setRenderSelection(bool b)
|
||||
{
|
||||
m_bRenderSelection = b;
|
||||
}
|
||||
|
||||
int ScrolledSelectionList::getMaxPosition()
|
||||
{
|
||||
return field_48 + m_itemHeight * getNumberOfItems();
|
||||
}
|
||||
|
||||
void ScrolledSelectionList::renderHeader(int a, int b, Tesselator& t)
|
||||
{
|
||||
}
|
||||
|
||||
void ScrolledSelectionList::renderDecorations(int a, int b)
|
||||
{
|
||||
}
|
||||
|
||||
void ScrolledSelectionList::clickedHeader(int x, int y)
|
||||
{
|
||||
}
|
||||
|
||||
int ScrolledSelectionList::getItemAtPosition(int x, int y)
|
||||
{
|
||||
if (x < field_18 / 2 - C_ITEM_WIDTH / 2)
|
||||
return -1;
|
||||
|
||||
if (x > field_18 / 2 + C_ITEM_WIDTH / 2)
|
||||
return -1;
|
||||
|
||||
return getItemAtYPositionRaw(transformY(y));
|
||||
}
|
||||
|
||||
void ScrolledSelectionList::capYPosition()
|
||||
{
|
||||
float maxY = float(getMaxPosition()) - (float(field_10 - field_C) - 4.0f);
|
||||
if (maxY < 0.0f)
|
||||
maxY *= 0.5f;
|
||||
|
||||
if (field_34 < 0.0f)
|
||||
field_34 = 0.0f;
|
||||
if (field_34 > maxY)
|
||||
field_34 = maxY;
|
||||
}
|
||||
|
||||
void ScrolledSelectionList::render(int mouseX, int mouseY, float f)
|
||||
{
|
||||
renderBackground();
|
||||
|
||||
int nItems = getNumberOfItems();
|
||||
if (Mouse::_buttonStates[1])
|
||||
{
|
||||
if (float(mouseY) >= field_C && float(mouseY) <= field_10 && mouseY != field_28)
|
||||
{
|
||||
int field_2C_old = field_2C;
|
||||
|
||||
if (field_2C == -1)
|
||||
{
|
||||
field_2C = 1;
|
||||
}
|
||||
else if (field_2C == 1)
|
||||
{
|
||||
field_3C = mouseY;
|
||||
field_40 = getTimeMs();
|
||||
}
|
||||
else if (field_2C == 0)
|
||||
{
|
||||
float diff = float(mouseY) - field_30;
|
||||
field_34 -= diff;
|
||||
field_38 += diff;
|
||||
}
|
||||
|
||||
if (field_2C_old >= 0)
|
||||
field_2C = 0;
|
||||
|
||||
field_28 = -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (field_2C >= 0)
|
||||
{
|
||||
if (fabsf(field_38) < 2.0f)
|
||||
field_38 = 0.0f;
|
||||
|
||||
if (getTimeMs() - field_40 < 300)
|
||||
{
|
||||
if (transformY(mouseY) / m_itemHeight >= 0 && m_itemHeight > abs(field_3C - mouseY))
|
||||
{
|
||||
selectItem(transformY(mouseY) / m_itemHeight, false);
|
||||
field_38 = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
field_2C = -1;
|
||||
field_34 -= field_38;
|
||||
}
|
||||
|
||||
field_30 = float(mouseY);
|
||||
field_38 *= 0.75f;
|
||||
capYPosition();
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
glDisable(GL_FOG);
|
||||
|
||||
m_pMinecraft->m_pTextures->loadAndBindTexture("gui/background.png");
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
Tesselator& t = Tesselator::instance;
|
||||
t.begin();
|
||||
t.color(0x202020);
|
||||
t.vertexUV(field_24, field_10, 0.0f, field_24 / 32.0f, (field_10 + float(int(field_34))) / 32.0f);
|
||||
t.vertexUV(field_20, field_10, 0.0f, field_20 / 32.0f, (field_10 + float(int(field_34))) / 32.0f);
|
||||
t.vertexUV(field_20, field_C, 0.0f, field_20 / 32.0f, (field_C + float(int(field_34))) / 32.0f);
|
||||
t.vertexUV(field_24, field_C, 0.0f, field_24 / 32.0f, (field_C + float(int(field_34))) / 32.0f);
|
||||
t.draw();
|
||||
|
||||
int itemX = field_18 / 2 - (C_ITEM_WIDTH - 4) / 2;
|
||||
int scrollY = int(field_C + 4 - float(int(field_34)));
|
||||
|
||||
if (field_45)
|
||||
renderHeader(itemX, scrollY, t);
|
||||
|
||||
for (int i = 0; i < nItems; i++)
|
||||
{
|
||||
float itemY = float(field_48 + scrollY + i * m_itemHeight);
|
||||
if (field_10 < itemY)
|
||||
continue;
|
||||
|
||||
float lowerY = itemY + m_itemHeight - 4;
|
||||
if (lowerY < field_C)
|
||||
continue;
|
||||
|
||||
if (m_bRenderSelection && isSelectedItem(i))
|
||||
{
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
t.begin();
|
||||
t.color(0x808080);
|
||||
t.vertexUV(float(field_18) / 2.0f - C_ITEM_WIDTH / 2.0f, lowerY + 2.0f, 0.0f, 0.0f, 1.0f);
|
||||
t.vertexUV(float(field_18) / 2.0f + C_ITEM_WIDTH / 2.0f, lowerY + 2.0f, 0.0f, 1.0f, 1.0f);
|
||||
t.vertexUV(float(field_18) / 2.0f + C_ITEM_WIDTH / 2.0f, itemY - 2.0f, 0.0f, 1.0f, 0.0f);
|
||||
t.vertexUV(float(field_18) / 2.0f - C_ITEM_WIDTH / 2.0f, itemY - 2.0f, 0.0f, 0.0f, 0.0f);
|
||||
t.color(0x000000);
|
||||
t.vertexUV(float(field_18) / 2.0f - C_ITEM_WIDTH / 2.0f + 1, lowerY + 1.0f, 0.0f, 0.0f, 1.0f);
|
||||
t.vertexUV(float(field_18) / 2.0f + C_ITEM_WIDTH / 2.0f - 1, lowerY + 1.0f, 0.0f, 1.0f, 1.0f);
|
||||
t.vertexUV(float(field_18) / 2.0f + C_ITEM_WIDTH / 2.0f - 1, itemY - 1.0f, 0.0f, 1.0f, 0.0f);
|
||||
t.vertexUV(float(field_18) / 2.0f - C_ITEM_WIDTH / 2.0f + 1, itemY - 1.0f, 0.0f, 0.0f, 0.0f);
|
||||
t.draw();
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
renderItem(i, itemX, int(itemY), int(m_itemHeight - 4.0f), t);
|
||||
}
|
||||
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
renderHoleBackground(0.0f, field_C, 255, 255);
|
||||
renderHoleBackground(field_10, float(field_1C), 255, 255);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glShadeModel(GL_SMOOTH);
|
||||
glDisable(GL_TEXTURE_2D);
|
||||
|
||||
t.begin();
|
||||
t.color(0, 0);
|
||||
t.vertexUV(field_24, field_C + 4.0f, 0.0f, 0.0f, 1.0f);
|
||||
t.vertexUV(field_20, field_C + 4.0f, 0.0f, 1.0f, 1.0f);
|
||||
t.color(0, 255);
|
||||
t.vertexUV(field_20, field_C, 0.0f, 1.0f, 0.0f);
|
||||
t.vertexUV(field_24, field_C, 0.0f, 0.0f, 0.0f);
|
||||
t.draw();
|
||||
|
||||
t.begin();
|
||||
t.color(0, 255);
|
||||
t.vertexUV(field_24, field_10, 0.0f, 0.0f, 1.0f);
|
||||
t.vertexUV(field_20, field_10, 0.0f, 1.0f, 1.0f);
|
||||
t.color(0, 0);
|
||||
t.vertexUV(field_20, field_10 - 4.0f, 0.0f, 1.0f, 0.0f);
|
||||
t.vertexUV(field_24, field_10 - 4.0f, 0.0f, 0.0f, 0.0f);
|
||||
t.draw();
|
||||
|
||||
renderDecorations(mouseX, mouseY);
|
||||
|
||||
glEnable(GL_TEXTURE_2D);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glShadeModel(GL_FLAT);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
void ScrolledSelectionList::renderHoleBackground(float a, float b, int c, int d)
|
||||
{
|
||||
m_pMinecraft->m_pTextures->loadAndBindTexture("gui/background.png");
|
||||
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
Tesselator& t = Tesselator::instance;
|
||||
t.begin();
|
||||
t.color(0x505050, d);
|
||||
t.vertexUV(0.0f, b, 0.0f, 0.0f, b / 32.0f);
|
||||
t.vertexUV(float(field_18), b, 0.0f, field_18 / 32.0f, b / 32.0f);
|
||||
t.color(0x505050, c);
|
||||
t.vertexUV(float(field_18), a, 0.0f, field_18 / 32.0f, a / 32.0f);
|
||||
t.vertexUV(0.0f, a, 0.0f, 0.0f, a / 32.0f);
|
||||
t.draw();
|
||||
}
|
||||
|
||||
void ScrolledSelectionList::setRenderHeader(bool b, int i)
|
||||
{
|
||||
field_45 = b;
|
||||
if (!b)
|
||||
i = 0;
|
||||
field_48 = i;
|
||||
}
|
||||
79
source/gui/ScrolledSelectionList.hpp
Normal file
79
source/gui/ScrolledSelectionList.hpp
Normal file
@@ -0,0 +1,79 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "GuiComponent.hpp"
|
||||
#include "Minecraft.hpp"
|
||||
|
||||
class ScrolledSelectionList : public GuiComponent
|
||||
{
|
||||
public:
|
||||
ScrolledSelectionList(Minecraft*, int, int, int, int, int);
|
||||
|
||||
virtual void setRenderSelection(bool);
|
||||
virtual int getNumberOfItems() = 0;
|
||||
virtual void selectItem(int, bool) = 0;
|
||||
virtual bool isSelectedItem(int) = 0;
|
||||
virtual int getMaxPosition();
|
||||
virtual void renderItem(int, int, int, int, Tesselator&) = 0;
|
||||
virtual void renderHeader(int, int, Tesselator&);
|
||||
virtual void renderBackground() = 0;
|
||||
virtual void renderDecorations(int, int);
|
||||
virtual void clickedHeader(int x, int y);
|
||||
virtual int getItemAtPosition(int x, int y);
|
||||
virtual void capYPosition();
|
||||
virtual void render(int mouseX, int mouseY, float f);
|
||||
virtual void renderHoleBackground(float, float, int, int);
|
||||
|
||||
void setRenderHeader(bool, int);
|
||||
|
||||
|
||||
// @NOTE: This is inlined.
|
||||
inline int getItemAtYPositionRaw(int y)
|
||||
{
|
||||
if (y < 0)
|
||||
return -1;
|
||||
|
||||
// @NOTE: redundant check
|
||||
int idx = y / m_itemHeight;
|
||||
if (idx < 0)
|
||||
return -1;
|
||||
|
||||
if (idx >= getNumberOfItems())
|
||||
return -1;
|
||||
|
||||
return idx;
|
||||
}
|
||||
// @NOTE: This is also inlined.
|
||||
inline int transformY(int y)
|
||||
{
|
||||
return int(y - field_C - field_48 + field_34 - 4.0f);
|
||||
}
|
||||
|
||||
public:
|
||||
Minecraft* m_pMinecraft;
|
||||
float field_C;
|
||||
float field_10;
|
||||
int m_itemHeight;
|
||||
int field_18;
|
||||
int field_1C;
|
||||
float field_20;
|
||||
float field_24 = 0.0f;
|
||||
int field_28;
|
||||
int field_2C = -2;
|
||||
float field_30 = 0.0f;
|
||||
float field_34 = 0.0f;
|
||||
float field_38 = 0.0f;
|
||||
int field_3C = -1;
|
||||
int field_40 = 0;
|
||||
bool m_bRenderSelection = true;
|
||||
bool field_45 = false;
|
||||
int field_48 = 0;
|
||||
};
|
||||
|
||||
33
source/gui/SmallButton.cpp
Normal file
33
source/gui/SmallButton.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "SmallButton.hpp"
|
||||
|
||||
// @NOTE: Used in the ConfirmScreen.
|
||||
// I reckon this was used in the OptionsScreen as well, since the button sizes are the same.
|
||||
|
||||
SmallButton::SmallButton(int id, int x, int y, const std::string& str) :
|
||||
Button(id, x, y, 150, 20, str)
|
||||
{
|
||||
}
|
||||
|
||||
SmallButton::SmallButton(int id, int x, int y, int width, int height, const std::string& str) :
|
||||
Button(id, x, y, width, height, str)
|
||||
{
|
||||
}
|
||||
|
||||
SmallButton::SmallButton(int id, int x, int y, Options::Option* pOption, const std::string& str) :
|
||||
Button(id, x, y, 150, 20, str),
|
||||
m_pOption(pOption)
|
||||
{
|
||||
}
|
||||
|
||||
Options::Option* SmallButton::getOption()
|
||||
{
|
||||
return m_pOption;
|
||||
}
|
||||
24
source/gui/SmallButton.hpp
Normal file
24
source/gui/SmallButton.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Button.hpp"
|
||||
|
||||
class SmallButton : public Button
|
||||
{
|
||||
public:
|
||||
SmallButton(int id, int x, int y, const std::string& str);
|
||||
SmallButton(int id, int x, int y, int width, int height, const std::string& str);
|
||||
SmallButton(int id, int x, int y, Options::Option* pOption, const std::string& str);
|
||||
Options::Option* getOption();
|
||||
|
||||
private:
|
||||
Options::Option* m_pOption = nullptr;
|
||||
};
|
||||
|
||||
271
source/gui/TextInputBox.cpp
Normal file
271
source/gui/TextInputBox.cpp
Normal file
@@ -0,0 +1,271 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "TextInputBox.hpp"
|
||||
#include "Minecraft.hpp"
|
||||
#ifndef ORIGINAL_CODE
|
||||
|
||||
TextInputBox::TextInputBox(int id, int x, int y) :
|
||||
TextInputBox(id, x, y, 200, 12, "", "")
|
||||
{
|
||||
}
|
||||
|
||||
TextInputBox::TextInputBox(int id, int x, int y, int width, int height) :
|
||||
TextInputBox(id, x, y, width, height, "", "")
|
||||
{
|
||||
}
|
||||
|
||||
TextInputBox::TextInputBox(int id, int x, int y, int width, int height, const std::string& placeholder) :
|
||||
TextInputBox(id, x, y, width, height, placeholder, "")
|
||||
{
|
||||
}
|
||||
|
||||
TextInputBox::TextInputBox(int id, int x, int y, int width, int height, const std::string& placeholder, const std::string& text) :
|
||||
m_ID(id),
|
||||
m_xPos(x),
|
||||
m_yPos(y),
|
||||
m_width(width),
|
||||
m_height(height),
|
||||
m_placeholder(placeholder),
|
||||
m_text(text)
|
||||
{
|
||||
}
|
||||
|
||||
void TextInputBox::init(Font* pFont)
|
||||
{
|
||||
m_pFont = pFont;
|
||||
}
|
||||
|
||||
void TextInputBox::setEnabled(bool bEnabled)
|
||||
{
|
||||
m_bEnabled = true;
|
||||
}
|
||||
|
||||
void TextInputBox::keyPressed(Minecraft* minecraft, int key)
|
||||
{
|
||||
if (!m_bFocused)
|
||||
return;
|
||||
|
||||
bool bShiftPressed = minecraft->platform()->shiftPressed();
|
||||
|
||||
char chr = '\0';
|
||||
if (key >= AKEYCODE_A && key <= AKEYCODE_Z)
|
||||
{
|
||||
chr = char((key - AKEYCODE_A) + (bShiftPressed ? 'A' : 'a'));
|
||||
}
|
||||
if (key >= AKEYCODE_0 && key <= AKEYCODE_9)
|
||||
{
|
||||
static const char shiftmap[] = { ')', '!', '@', '#', '$', '%', '^', '&', '*', '(' };
|
||||
chr = char(bShiftPressed ? shiftmap[key - AKEYCODE_0] : (key - AKEYCODE_0 + '0'));
|
||||
}
|
||||
switch (key)
|
||||
{
|
||||
case AKEYCODE_DEL:
|
||||
chr = '\b';
|
||||
break;
|
||||
case AKEYCODE_FORWARD_DEL:
|
||||
chr = '\001';
|
||||
break;
|
||||
case AKEYCODE_ARROW_LEFT:
|
||||
chr = '\002';
|
||||
break;
|
||||
case AKEYCODE_ARROW_RIGHT:
|
||||
chr = '\003';
|
||||
break;
|
||||
case AKEYCODE_SPACE:
|
||||
chr = ' ';
|
||||
break;
|
||||
case AKEYCODE_COMMA:
|
||||
chr = bShiftPressed ? '<' : ',';
|
||||
break;
|
||||
case AKEYCODE_PERIOD:
|
||||
chr = bShiftPressed ? '>' : '.';
|
||||
break;
|
||||
case AKEYCODE_PLUS:
|
||||
chr = bShiftPressed ? '+' : '=';
|
||||
break;
|
||||
case AKEYCODE_MINUS:
|
||||
chr = bShiftPressed ? '_' : '-';
|
||||
break;
|
||||
case AKEYCODE_SEMICOLON:
|
||||
chr = bShiftPressed ? ':' : ';';
|
||||
break;
|
||||
case AKEYCODE_SLASH:
|
||||
chr = bShiftPressed ? '?' : '/';
|
||||
break;
|
||||
case AKEYCODE_GRAVE:
|
||||
chr = bShiftPressed ? '~' : '`';
|
||||
break;
|
||||
case AKEYCODE_BACKSLASH:
|
||||
chr = bShiftPressed ? '|' : '\\';
|
||||
break;
|
||||
case AKEYCODE_APOSTROPHE:
|
||||
chr = bShiftPressed ? '"' : '\'';
|
||||
break;
|
||||
case AKEYCODE_LEFT_BRACKET:
|
||||
chr = bShiftPressed ? '{' : '[';
|
||||
break;
|
||||
case AKEYCODE_RIGHT_BRACKET:
|
||||
chr = bShiftPressed ? '}' : ']';
|
||||
break;
|
||||
}
|
||||
|
||||
if (chr)
|
||||
charPressed(chr);
|
||||
}
|
||||
|
||||
void TextInputBox::tick()
|
||||
{
|
||||
if (!m_lastFlashed)
|
||||
m_lastFlashed = getTimeMs();
|
||||
|
||||
if (m_bFocused)
|
||||
{
|
||||
if (getTimeMs() > m_lastFlashed + 500)
|
||||
{
|
||||
m_lastFlashed += 500;
|
||||
m_bCursorOn ^= 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_bCursorOn = false;
|
||||
}
|
||||
}
|
||||
|
||||
void TextInputBox::setFocused(bool b)
|
||||
{
|
||||
if (m_bFocused == b)
|
||||
return;
|
||||
|
||||
m_bFocused = b;
|
||||
if (b)
|
||||
{
|
||||
m_lastFlashed = getTimeMs();
|
||||
m_bCursorOn = true;
|
||||
m_insertHead = int(m_text.size());
|
||||
}
|
||||
}
|
||||
|
||||
void TextInputBox::onClick(int x, int y)
|
||||
{
|
||||
setFocused(clicked(x, y));
|
||||
}
|
||||
|
||||
void TextInputBox::charPressed(int k)
|
||||
{
|
||||
if (!m_bFocused)
|
||||
return;
|
||||
|
||||
if (k == '\b')
|
||||
{
|
||||
if (m_text.empty())
|
||||
return;
|
||||
|
||||
if (m_insertHead <= 0)
|
||||
return;
|
||||
|
||||
if (m_insertHead > int(m_text.size()))
|
||||
m_insertHead = int(m_text.size());
|
||||
|
||||
m_text.erase(m_text.begin() + m_insertHead - 1, m_text.begin() + m_insertHead);
|
||||
m_insertHead--;
|
||||
return;
|
||||
}
|
||||
|
||||
if (k == '\001') // delete
|
||||
{
|
||||
if (m_text.empty())
|
||||
return;
|
||||
|
||||
if (m_insertHead < 0)
|
||||
return;
|
||||
|
||||
if (m_insertHead >= int(m_text.size()))
|
||||
return;
|
||||
|
||||
m_text.erase(m_text.begin() + m_insertHead, m_text.begin() + m_insertHead + 1);
|
||||
return;
|
||||
}
|
||||
|
||||
if (k == '\002') // left
|
||||
{
|
||||
m_insertHead--;
|
||||
if (m_insertHead < 0)
|
||||
m_insertHead = 0;
|
||||
}
|
||||
|
||||
if (k == '\003') // right
|
||||
{
|
||||
m_insertHead++;
|
||||
if (!m_text.empty())
|
||||
{
|
||||
if (m_insertHead > int(m_text.size()))
|
||||
m_insertHead = int(m_text.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_insertHead = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (k == '\n' || k == '\r')
|
||||
{
|
||||
m_bFocused = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// other unrenderable character?
|
||||
if (k < ' ' || k > '~')
|
||||
return;
|
||||
|
||||
// note: the width will increase by the same amount no matter where K is appended
|
||||
int width = m_pFont->width(m_text + char(k));
|
||||
if (width < m_width - 2)
|
||||
{
|
||||
m_text.insert(m_text.begin() + m_insertHead, k);
|
||||
m_insertHead++;
|
||||
}
|
||||
}
|
||||
|
||||
void TextInputBox::render()
|
||||
{
|
||||
fill(m_xPos, m_yPos, m_xPos + m_width, m_yPos + m_height, 0xFFAAAAAA);
|
||||
fill(m_xPos + 1, m_yPos + 1, m_xPos + m_width - 1, m_yPos + m_height - 1, 0xFF000000);
|
||||
|
||||
int textYPos = (m_height - 8) / 2;
|
||||
|
||||
if (m_text.empty())
|
||||
drawString(m_pFont, m_placeholder, m_xPos + 2, m_yPos + 2, 0x404040);
|
||||
else
|
||||
drawString(m_pFont, m_text, m_xPos + 2, m_yPos + textYPos, 0xFFFFFF);
|
||||
|
||||
if (m_bCursorOn)
|
||||
{
|
||||
int xPos = 2;
|
||||
|
||||
std::string substr = m_text.substr(0, m_insertHead);
|
||||
xPos += m_pFont->width(substr);
|
||||
|
||||
drawString(m_pFont, "_", m_xPos + xPos, m_yPos + textYPos + 2, 0xFFFFFF);
|
||||
}
|
||||
}
|
||||
|
||||
bool TextInputBox::clicked(int xPos, int yPos)
|
||||
{
|
||||
if (!m_bEnabled) return false;
|
||||
|
||||
if (xPos < m_xPos) return false;
|
||||
if (yPos < m_yPos) return false;
|
||||
if (xPos >= m_xPos + m_width) return false;
|
||||
if (yPos >= m_yPos + m_height) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
54
source/gui/TextInputBox.hpp
Normal file
54
source/gui/TextInputBox.hpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Utils.hpp"
|
||||
#include "GuiComponent.hpp"
|
||||
|
||||
class Minecraft;
|
||||
|
||||
// @NOTE: This is NOT original Mojang code.
|
||||
|
||||
#ifndef ORIGINAL_CODE
|
||||
|
||||
class TextInputBox : public GuiComponent
|
||||
{
|
||||
public:
|
||||
TextInputBox(int id, int x, int y);
|
||||
TextInputBox(int id, int x, int y, int width, int height);
|
||||
TextInputBox(int id, int x, int y, int width, int height, const std::string& placeholder);
|
||||
TextInputBox(int id, int x, int y, int width, int height, const std::string& placeholder, const std::string& text);
|
||||
|
||||
void init(Font* pFont);
|
||||
void setEnabled(bool bEnabled);
|
||||
void keyPressed(Minecraft*, int key);
|
||||
void charPressed(int chr);
|
||||
void render();
|
||||
void tick();
|
||||
void setFocused(bool b);
|
||||
void onClick(int x, int y);
|
||||
bool clicked(int x, int y);
|
||||
|
||||
public:
|
||||
int m_ID = 0;
|
||||
int m_xPos = 0;
|
||||
int m_yPos = 0;
|
||||
int m_width = 0;
|
||||
int m_height = 0;
|
||||
std::string m_placeholder;
|
||||
std::string m_text;
|
||||
bool m_bFocused = false;
|
||||
bool m_bEnabled = true;
|
||||
bool m_bCursorOn = true;
|
||||
int m_insertHead = 0;
|
||||
int m_lastFlashed = 0;
|
||||
Font* m_pFont = nullptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
217
source/gui/WorldSelectionList.cpp
Normal file
217
source/gui/WorldSelectionList.cpp
Normal file
@@ -0,0 +1,217 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#include "WorldSelectionList.hpp"
|
||||
#include "Utils.hpp"
|
||||
|
||||
static float WorldSelectionList_Static1(float a, float b, float c, float d)
|
||||
{
|
||||
float x1 = 2 * (a / b), x2;
|
||||
|
||||
if (x1 < 1.0f)
|
||||
x2 = c + ((d - c) * 0.5f) * x1 * x1;
|
||||
else
|
||||
x2 = c + ((d - c) * -0.5f) * ((x1 - 1.0f) * (x1 - 3.0f) - 1.0f);
|
||||
|
||||
return x2;
|
||||
}
|
||||
|
||||
WorldSelectionList::WorldSelectionList(Minecraft* minecraft, int a, int b) :
|
||||
RolledSelectionList(minecraft, a, b, 0, a, 26, b - 32, 120)
|
||||
{
|
||||
field_68 = b;
|
||||
}
|
||||
|
||||
bool WorldSelectionList::capXPosition()
|
||||
{
|
||||
if (RolledSelectionList::capXPosition())
|
||||
{
|
||||
field_D8 = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void WorldSelectionList::tick()
|
||||
{
|
||||
RolledSelectionList::tick();
|
||||
field_D0++;
|
||||
if (Mouse::_buttonStates[1] || !field_28)
|
||||
return;
|
||||
|
||||
m_selectedIndex = -1;
|
||||
if (field_D8 == 1)
|
||||
{
|
||||
field_54 += 1.0f;
|
||||
if (field_54 != field_58)
|
||||
{
|
||||
tweenInited();
|
||||
return;
|
||||
}
|
||||
|
||||
field_D8 = 0;
|
||||
field_38 = 0.0f;
|
||||
field_34 = field_30 = field_60;
|
||||
m_selectedIndex = getItemAtPosition(field_18 / 2, field_1C / 2);
|
||||
return;
|
||||
}
|
||||
|
||||
float abs_field38 = Mth::abs(field_38);
|
||||
if (abs_field38 >= 5.0f)
|
||||
{
|
||||
field_38 *= 0.9f;
|
||||
return;
|
||||
}
|
||||
|
||||
field_38 *= 0.8f;
|
||||
if (abs_field38 < 1.0f && field_28 < 0)
|
||||
{
|
||||
float x1 = float((field_18 - m_itemWidth) / 2) + field_30;
|
||||
int x2 = getItemAtXPositionRaw(int(x1 - 10.0f * field_38));
|
||||
float x3 = float(m_itemWidth * x2) - x1;
|
||||
|
||||
if (x3 < -float(m_itemWidth / 2))
|
||||
x3 += float(m_itemWidth);
|
||||
|
||||
if (Mth::abs(x3) > 1.0f || abs_field38 >= 0.1f)
|
||||
{
|
||||
field_5C = field_30;
|
||||
field_60 = field_30 + x3;
|
||||
field_54 = 0.0f;
|
||||
field_D8 = 1;
|
||||
field_58 = float(Mth::Min(7, int(float(0.25f * Mth::abs(x3))) + 1));
|
||||
|
||||
tweenInited();
|
||||
return;
|
||||
}
|
||||
|
||||
m_selectedIndex = getItemAtPosition(field_18 / 2, field_1C / 2);
|
||||
}
|
||||
}
|
||||
|
||||
int WorldSelectionList::getNumberOfItems()
|
||||
{
|
||||
return int(m_items.size());
|
||||
}
|
||||
|
||||
void WorldSelectionList::selectItem(int index, bool b)
|
||||
{
|
||||
if (m_selectedIndex >= 0 && m_selectedIndex == index && !field_90)
|
||||
{
|
||||
field_90 = 1;
|
||||
m_levelSummary = m_items[index];
|
||||
}
|
||||
}
|
||||
|
||||
bool WorldSelectionList::isSelectedItem(int index)
|
||||
{
|
||||
return m_selectedIndex == index;
|
||||
}
|
||||
|
||||
float WorldSelectionList::getPos(float f)
|
||||
{
|
||||
if (field_D8 != 1)
|
||||
return RolledSelectionList::getPos(f);
|
||||
|
||||
return Lerp(WorldSelectionList_Static1(field_54, field_58, field_5C, field_60),
|
||||
WorldSelectionList_Static1(field_54 + 1.0f, field_58, field_5C, field_60),
|
||||
f);
|
||||
}
|
||||
|
||||
void WorldSelectionList::touched()
|
||||
{
|
||||
field_D8 = false;
|
||||
}
|
||||
|
||||
void WorldSelectionList::renderItem(int index, int xPos, int yPos, int width, Tesselator& t)
|
||||
{
|
||||
int xCenter = xPos + m_itemWidth / 2;
|
||||
float mult = Max(1.1f - 0.0055f * float(abs(field_18 / 2 - xCenter)), 0.2f);
|
||||
if (mult > 1.0f)
|
||||
mult = 1.0f;
|
||||
|
||||
int color1 = 0x010101 * int(mult * 255.0f);
|
||||
int color2 = 0x010101 * int(mult * 140.0f);
|
||||
|
||||
std::vector<std::string> details = m_vvs[index];
|
||||
|
||||
drawString(m_pMinecraft->m_pFont, details[0], xCenter + 5 - m_itemWidth / 2, yPos + 50, color1);
|
||||
drawString(m_pMinecraft->m_pFont, details[1], xCenter + 5 - m_itemWidth / 2, yPos + 60, color2);
|
||||
drawString(m_pMinecraft->m_pFont, details[2], xCenter + 5 - m_itemWidth / 2, yPos + 70, color2);
|
||||
|
||||
m_pMinecraft->m_pTextures->loadAndBindTexture(m_previewImages[index]);
|
||||
|
||||
// @NOTE: useless assignment of color
|
||||
t.color(0.3f, 1.0f, 0.2f);
|
||||
|
||||
t.begin();
|
||||
t.color(color1);
|
||||
float y = float(yPos) - 6.0f;
|
||||
t.vertexUV(float(xCenter - 32), y, this->field_4, 0.0f, 0.0f);
|
||||
t.vertexUV(float(xCenter - 32), y + 48.0f, this->field_4, 0.0f, 1.0f);
|
||||
t.vertexUV(float(xCenter + 32), y + 48.0f, this->field_4, 1.0f, 1.0f);
|
||||
t.vertexUV(float(xCenter + 32), y, this->field_4, 1.0f, 0.0f);
|
||||
t.draw();
|
||||
}
|
||||
|
||||
void WorldSelectionList::renderBackground()
|
||||
{
|
||||
}
|
||||
|
||||
void WorldSelectionList::commit()
|
||||
{
|
||||
for (const auto& item : m_items)
|
||||
{
|
||||
// @NOTE: this string stream crap is unused.
|
||||
// Weirdly Java Edition Beta 1.3 did not have world previews, so its interesting to see PE try
|
||||
std::stringstream ss;
|
||||
ss << item.field_18 << "/preview.png";
|
||||
|
||||
m_previewImages.push_back("gui/default_world.png");
|
||||
|
||||
std::vector<std::string> vs;
|
||||
vs.push_back(item.field_18);
|
||||
vs.push_back(m_pMinecraft->platform()->getDateString(item.field_30));
|
||||
vs.push_back(item.field_0);
|
||||
m_vvs.push_back(vs);
|
||||
}
|
||||
}
|
||||
|
||||
void WorldSelectionList::stepLeft()
|
||||
{
|
||||
if (m_selectedIndex <= 0)
|
||||
return;
|
||||
|
||||
field_5C = field_30;
|
||||
field_D8 = 1;
|
||||
field_60 = field_5C - float(m_itemWidth);
|
||||
field_54 = 0.0f;
|
||||
field_58 = 8.0f;
|
||||
tweenInited();
|
||||
}
|
||||
|
||||
void WorldSelectionList::stepRight()
|
||||
{
|
||||
if (m_selectedIndex < 0 || m_selectedIndex >= getNumberOfItems() - 1)
|
||||
return;
|
||||
|
||||
field_5C = field_30;
|
||||
field_D8 = 1;
|
||||
field_60 = field_5C + float(m_itemWidth);
|
||||
field_54 = 0.0f;
|
||||
field_58 = 8.0f;
|
||||
tweenInited();
|
||||
}
|
||||
|
||||
void WorldSelectionList::tweenInited()
|
||||
{
|
||||
field_38 =
|
||||
WorldSelectionList_Static1(field_54, field_58, field_5C, field_60) -
|
||||
WorldSelectionList_Static1(field_54 + 1.0f, field_58, field_5C, field_60);
|
||||
}
|
||||
50
source/gui/WorldSelectionList.hpp
Normal file
50
source/gui/WorldSelectionList.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/********************************************************************
|
||||
Minecraft: Pocket Edition - Decompilation Project
|
||||
Copyright (C) 2023 iProgramInCpp
|
||||
|
||||
The following code is licensed under the BSD 1 clause license.
|
||||
SPDX-License-Identifier: BSD-1-Clause
|
||||
********************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "RolledSelectionList.hpp"
|
||||
|
||||
class WorldSelectionList : public RolledSelectionList
|
||||
{
|
||||
public:
|
||||
WorldSelectionList(Minecraft*, int, int);
|
||||
|
||||
bool capXPosition() override;
|
||||
void tick() override;
|
||||
int getNumberOfItems() override;
|
||||
void selectItem(int, bool) override;
|
||||
bool isSelectedItem(int) override;
|
||||
float getPos(float) override;
|
||||
void touched() override;
|
||||
void renderItem(int, int, int, int, Tesselator&) override;
|
||||
void renderBackground() override;
|
||||
|
||||
void commit();
|
||||
void stepLeft();
|
||||
void stepRight();
|
||||
void tweenInited();
|
||||
|
||||
public:
|
||||
float field_54;
|
||||
float field_58;
|
||||
float field_5C;
|
||||
float field_60;
|
||||
int m_selectedIndex;
|
||||
int field_68;
|
||||
std::vector<LevelSummary> m_items;
|
||||
std::vector<std::vector<std::string> > m_vvs;
|
||||
std::vector<std::string> m_previewImages;
|
||||
bool field_90 = false;
|
||||
LevelSummary m_levelSummary;
|
||||
int field_CC = -1;
|
||||
int field_D0 = 0;
|
||||
int field_D4;
|
||||
int field_D8 = 0;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user