Files
minecraft-pe-0.6.1/src/client/gui/screens/ArmorScreen.cpp
2026-03-02 22:04:18 +03:00

371 lines
10 KiB
C++
Executable File

#include "ArmorScreen.h"
#include "../Screen.h"
#include "../components/NinePatch.h"
#include "../../Minecraft.h"
#include "../../player/LocalPlayer.h"
#include "../../renderer/Tesselator.h"
#include "../../renderer/entity/ItemRenderer.h"
#include "../../../world/item/Item.h"
#include "../../../world/item/ItemCategory.h"
#include "../../../world/entity/player/Inventory.h"
#include "../../../world/entity/item/ItemEntity.h"
#include "../../../world/level/Level.h"
#include "../../../network/RakNetInstance.h"
#include "../../renderer/entity/EntityRenderDispatcher.h"
#include "../../../world/item/ArmorItem.h"
static void setIfNotSet(bool& ref, bool condition) {
ref = (ref || condition);
}
const int descFrameWidth = 100;
const int rgbActive = 0xfff0f0f0;
const int rgbInactive = 0xc0635558;
const int rgbInactiveShadow = 0xc0aaaaaa;
#ifdef __APPLE__
static const float BorderPixels = 4;
#ifdef DEMO_MODE
static const float BlockPixels = 22;
#else
static const float BlockPixels = 22;
#endif
#else
static const float BorderPixels = 4;
static const float BlockPixels = 24;
#endif
static const int ItemSize = (int)(BlockPixels + 2*BorderPixels);
static const int Bx = 10; // Border Frame width
static const int By = 6; // Border Frame height
ArmorScreen::ArmorScreen():
inventoryPane(NULL),
btnArmor0(0),
btnArmor1(1),
btnArmor2(2),
btnArmor3(3),
btnClose(4, ""),
bHeader (5, "Armor"),
guiBackground(NULL),
guiSlot(NULL),
guiPaneFrame(NULL),
guiPlayerBg(NULL),
doRecreatePane(false),
descWidth(90)
//guiSlotItem(NULL),
//guiSlotItemSelected(NULL)
{
//LOGI("Creating ArmorScreen with %p, %d\n", furnace, furnace->runningId);
}
ArmorScreen::~ArmorScreen() {
delete inventoryPane;
delete guiBackground;
delete guiSlot;
delete guiPaneFrame;
delete guiPlayerBg;
}
void ArmorScreen::init() {
super::init();
player = minecraft->player;
ImageDef def;
def.name = "gui/spritesheet.png";
def.x = 0;
def.y = 1;
def.width = def.height = 18;
def.setSrc(IntRectangle(60, 0, 18, 18));
btnClose.setImageDef(def, true);
btnClose.scaleWhenPressed = false;
buttons.push_back(&bHeader);
buttons.push_back(&btnClose);
armorButtons[0] = &btnArmor0;
armorButtons[1] = &btnArmor1;
armorButtons[2] = &btnArmor2;
armorButtons[3] = &btnArmor3;
for (int i = 0; i < NUM_ARMORBUTTONS; ++i)
buttons.push_back(armorButtons[i]);
// GUI - nine patches
NinePatchFactory builder(minecraft->textures, "gui/spritesheet.png");
guiBackground = builder.createSymmetrical(IntRectangle(0, 0, 16, 16), 4, 4);
guiSlot = builder.createSymmetrical(IntRectangle(0, 32, 8, 8), 3, 3, 20, 20);
guiPaneFrame = builder.createSymmetrical(IntRectangle(28, 42, 4, 4), 1, 1)->setExcluded(1 << 4);
guiPlayerBg = builder.createSymmetrical(IntRectangle(0, 20, 8, 8), 3, 3);
updateItems();
}
void ArmorScreen::setupPositions() {
// Left - Categories
bHeader.x = bHeader.y = 0;
bHeader.width = width;// - bDone.w;
btnClose.width = btnClose.height = 19;
btnClose.x = width - btnClose.width;
btnClose.y = 0;
// Inventory pane
const int maxWidth = (int)(width/1.8f) - Bx - Bx;
const int InventoryColumns = maxWidth / ItemSize;
const int realWidth = InventoryColumns * ItemSize;
const int paneWidth = realWidth + Bx + Bx;
const int realBx = (paneWidth - realWidth) / 2;
inventoryPaneRect = IntRectangle(realBx,
#ifdef __APPLE__
26 + By - ((width==240)?1:0), realWidth, ((width==240)?1:0) + height-By-By-28);
#else
26 + By, realWidth, height-By-By-28);
#endif
for (int i = 0; i < NUM_ARMORBUTTONS; ++i) {
Button& b = *armorButtons[i];
b.x = paneWidth;
b.y = inventoryPaneRect.y + 24 * i;
b.width = 20;
b.height = 20;
}
guiPlayerBgRect.y = inventoryPaneRect.y;
int xx = armorButtons[0]->x + armorButtons[0]->width;
int xw = width - xx;
guiPlayerBgRect.x = xx + xw / 10;
guiPlayerBgRect.w = xw - (xw / 10) * 2;
guiPlayerBgRect.h = inventoryPaneRect.h;
guiPaneFrame->setSize((float)inventoryPaneRect.w + 2, (float)inventoryPaneRect.h + 2);
guiPlayerBg->setSize((float)guiPlayerBgRect.w, (float)guiPlayerBgRect.h);
guiBackground->setSize((float)width, (float)height);
updateItems();
setupInventoryPane();
}
void ArmorScreen::tick() {
if (inventoryPane)
inventoryPane->tick();
if (doRecreatePane) {
updateItems();
setupInventoryPane();
doRecreatePane = false;
}
}
void ArmorScreen::handleRenderPane(Touch::InventoryPane* pane, Tesselator& t, int xm, int ym, float a) {
if (pane) {
pane->render(xm, ym, a);
guiPaneFrame->draw(t, (float)(pane->rect.x - 1), (float)(pane->rect.y - 1));
}
}
void ArmorScreen::render(int xm, int ym, float a) {
//renderBackground();
Tesselator& t = Tesselator::instance;
t.addOffset(0, 0, -500);
guiBackground->draw(t, 0, 0);
t.addOffset(0, 0, 500);
glEnable2(GL_ALPHA_TEST);
// Buttons (Left side + crafting)
super::render(xm, ym, a);
handleRenderPane(inventoryPane, t, xm, ym, a);
t.colorABGR(0xffffffff);
glColor4f2(1, 1, 1, 1);
t.addOffset(0, 0, -490);
guiPlayerBg->draw(t, (float)guiPlayerBgRect.x, (float)guiPlayerBgRect.y);
t.addOffset(0, 0, 490);
renderPlayer((float)(guiPlayerBgRect.x + guiPlayerBgRect.w / 2), 0.85f * height);
for (int i = 0; i < NUM_ARMORBUTTONS; ++i) {
drawSlotItemAt(t, i, player->getArmor(i), armorButtons[i]->x, armorButtons[i]->y);
}
glDisable2(GL_ALPHA_TEST);
}
void ArmorScreen::buttonClicked(Button* button) {
if (button == &btnClose) {
minecraft->setScreen(NULL);
}
if (button->id >= 0 && button->id <= 3) {
takeAndClearSlot(button->id);
}
}
bool ArmorScreen::addItem(const Touch::InventoryPane* forPane, int itemIndex) {
const ItemInstance* instance = armorItems[itemIndex];
if (!ItemInstance::isArmorItem(instance))
return false;
ArmorItem* item = (ArmorItem*) instance->getItem();
ItemInstance* old = player->getArmor(item->slot);
ItemInstance oldArmor;
if (ItemInstance::isArmorItem(old)) {
oldArmor = *old;
}
player->setArmor(item->slot, instance);
player->inventory->removeItem(instance);
//@attn: this is hugely important
armorItems[itemIndex] = NULL;
if (!oldArmor.isNull()) {
if (!player->inventory->add(&oldArmor)) {
player->drop(new ItemInstance(oldArmor), false);
}
}
doRecreatePane = true;
return true;
}
bool ArmorScreen::isAllowed( int slot ) {
return true;
}
bool ArmorScreen::renderGameBehind() {
return false;
}
std::vector<const ItemInstance*> ArmorScreen::getItems( const Touch::InventoryPane* forPane ) {
return armorItems;
}
void ArmorScreen::updateItems() {
armorItems.clear();
for (int i = Inventory::MAX_SELECTION_SIZE; i < minecraft->player->inventory->getContainerSize(); ++i) {
ItemInstance* item = minecraft->player->inventory->getItem(i);
if (ItemInstance::isArmorItem(item))
armorItems.push_back(item);
}
}
bool ArmorScreen::canMoveToSlot(int slot, const ItemInstance* item) {
return ItemInstance::isArmorItem(item)
&& ((ArmorItem*)item)->slot == slot;
}
void ArmorScreen::setupInventoryPane() {
// IntRectangle(0, 0, 100, 100)
if (inventoryPane) delete inventoryPane;
inventoryPane = new Touch::InventoryPane(this, minecraft, inventoryPaneRect, inventoryPaneRect.w, BorderPixels, armorItems.size(), ItemSize, (int)BorderPixels);
inventoryPane->fillMarginX = 0;
inventoryPane->fillMarginY = 0;
//LOGI("Creating new pane: %d %p\n", inventoryItems.size(), inventoryPane);
}
void ArmorScreen::drawSlotItemAt( Tesselator& t, int slot, const ItemInstance* item, int x, int y)
{
float xx = (float)x;
float yy = (float)y;
guiSlot->draw(t, xx, yy);
if (item && !item->isNull()) {
ItemRenderer::renderGuiItem(minecraft->font, minecraft->textures, item, xx + 2, yy, true);
glDisable2(GL_TEXTURE_2D);
ItemRenderer::renderGuiItemDecorations(item, xx + 2, yy + 3);
glEnable2(GL_TEXTURE_2D);
//minecraft->gui.renderSlotText(item, xx + 3, yy + 3, true, true);
} else {
minecraft->textures->loadAndBindTexture("gui/items.png");
blit(x + 2, y, 15 * 16, slot * 16, 16, 16, 16, 16);
}
}
void ArmorScreen::takeAndClearSlot( int slot ) {
ItemInstance* item = player->getArmor(slot);
if (!item)
return;
int oldSize = minecraft->player->inventory->getNumEmptySlots();
if (!minecraft->player->inventory->add(item))
minecraft->player->drop(new ItemInstance(*item), false);
player->setArmor(slot, NULL);
int newSize = minecraft->player->inventory->getNumEmptySlots();
setIfNotSet(doRecreatePane, newSize != oldSize);
}
void ArmorScreen::renderPlayer(float xo, float yo) {
// Push GL and player state
glPushMatrix();
glTranslatef(xo, yo, -200);
float ss = 45;
glScalef(-ss, ss, ss);
glRotatef(180, 0, 0, 1);
//glDisable(GL_DEPTH_TEST);
Player* player = (Player*) minecraft->player;
float oybr = player->yBodyRot;
float oyr = player->yRot;
float oxr = player->xRot;
float t = getTimeS();
float xd = 10 * Mth::sin(t);//(xo + 51) - xm;
float yd = 10 * Mth::cos(t * 0.05f);//(yo + 75 - 50) - ym;
glRotatef(45 + 90, 0, 1, 0);
glRotatef(-45 - 90, 0, 1, 0);
const float xtan = Mth::atan(xd / 40.0f) * +20;
const float ytan = Mth::atan(yd / 40.0f) * -20;
glRotatef(ytan, 1, 0, 0);
player->yBodyRot = xtan;
player->yRot = xtan + xtan;
player->xRot = ytan;
glTranslatef(0, player->heightOffset, 0);
// Push walking anim
float oldWAP = player->walkAnimPos;
float oldWAS = player->walkAnimSpeed;
float oldWASO = player->walkAnimSpeedO;
// Set new walking anim
player->walkAnimSpeedO = player->walkAnimSpeed = 0.25f;
player->walkAnimPos = getTimeS() * player->walkAnimSpeed * SharedConstants::TicksPerSecond;
EntityRenderDispatcher* rd = EntityRenderDispatcher::getInstance();
rd->playerRotY = 180;
rd->render(player, 0, 0, 0, 0, 1);
// Pop walking anim
player->walkAnimPos = oldWAP;
player->walkAnimSpeed = oldWAS;
player->walkAnimSpeedO = oldWASO;
//glEnable(GL_DEPTH_TEST);
// Pop GL and player state
player->yBodyRot = oybr;
player->yRot = oyr;
player->xRot = oxr;
glPopMatrix();
}