#include #include #include "InventoryView.h" #include "Globals.h" #include "DragController.h" #include "Globals.h" #include "Game.h" using namespace Framework; InventoryElement::InventoryElement() : UIMLElement() {} //! prüft, ob dieses UIML Element für ein bestimmtes xml Element zuständig ist bool InventoryElement::isApplicableFor(Framework::XML::Element& element) { return element.getName().istGleich("inventory"); } //! erstellt eine neue Zeichnung zu einem gegebenen xml Element Framework::Zeichnung* InventoryElement::parseElement(Framework::XML::Element& element, Framework::UIMLContainer& generalFactory) { Text targetValue = element.getAttributeValue("target"); Vec3 blockPos(0, 0, 0); Framework::Either> target((int)targetValue); if (targetValue.hat(',')) { Text* first = targetValue.getTeilText(0, targetValue.positionVon(",", 0) + 1); Text* second = targetValue.getTeilText(targetValue.positionVon(",", 0) + 1, targetValue.positionVon(",", 1)); Text* third = targetValue.getTeilText(targetValue.positionVon(",", 1) + 1, targetValue.positionVon(",", 2)); Text* forth = targetValue.getTeilText(targetValue.positionVon(",", 2) + 1); target = Framework::Either>(Framework::VecN({ (int)*first, (int)*second, (int)*third, (int)*forth })); first->release(); second->release(); third->release(); forth->release(); } return new InventoryView(element.getAttributeValue("id"), target, (int)element.getAttributeValue("rowSize"), element.getAttributeValue("slotNameFilter")); } //! wendet die layout parameter zu einer Zeichnung an void InventoryElement::layout(Framework::XML::Element& element, Framework::Zeichnung& z, int pWidth, int pHeight, Framework::UIMLContainer& generalLayouter) { UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter); } void SlotInfo::render(int x, int y, Framework::Bild& rObj, bool selected, bool lightBackground) { TextRenderer tr; tr.setSchriftZ(dynamic_cast(uiFactory.initParam.schrift->getThis())); tr.setSchriftSize(12); rObj.fillRegion(x, y, 52, 52, selected ? 0xFFFFFFFF : 0xFF52525E); rObj.fillRegion(x + 1, y + 1, 50, 50, lightBackground ? 0xFF42424E : 0xFF222222); if (itemCount > 0) { rObj.alphaBild(x + 1, y + 1, 50, 50, *zItem); if (damage < maxDamage) { rObj.fillRegion(x + 1, y + 47, 50, 2, 0xFF000000); rObj.fillRegion(x + 1, y + 47, (int)((damage / maxDamage) * 50), 2, 0xFFFF0000); } if (durability < maxDurability) { rObj.fillRegion(x + 1, y + 49, 50, 2, 0xFF000000); rObj.fillRegion(x + 1, y + 49, (int)((durability / maxDurability) * 50), 2, 0xFF00FF00); } const char* units[] = { "", "K", "M", "G", "T", "P" }; int i = 0; for (; i < 6 && itemCount > 1024; i++) itemCount = itemCount / 1024; Text count = itemCount; count += units[i]; tr.renderText(x + 45 - tr.getTextBreite(count), y + 45 - tr.getTextHeight(count), count, rObj, 0xFFFFFFFF); } } InventoryView::InventoryView(Text id, Either> target, int rowSize, Text slotNameFilter) : ZeichnungHintergrund(), rowSize(rowSize), target(target), slotNameFilter(slotNameFilter), id(id), slots(0), dragStartId(-1), dragStopId(-1) { setStyle(ZeichnungHintergrund::Style::Sichtbar | ZeichnungHintergrund::Style::Erlaubt); char* msg = new char[id.getLength() + slotNameFilter.getLength() + 3]; msg[0] = 0; msg[1] = (char)id.getLength(); memcpy(msg + 2, id.getText(), id.getLength()); msg[2 + id.getLength()] = (char)slotNameFilter.getLength(); memcpy(msg + 3 + id.getLength(), slotNameFilter.getText(), slotNameFilter.getLength()); network->zFactoryClient()->inventoryAPIRequest(target, msg, id.getLength() + slotNameFilter.getLength() + 3); delete[] msg; } InventoryView::~InventoryView() { DragController* controller = ((Game*)(Menu*)menuRegister->get("game"))->zInventoryDragController(); if (controller->getCurrentDragContainer() == this) controller->stopDrag(); if (slots) slots->release(); char* msg = new char[id.getLength() + 2]; msg[0] = 1; msg[1] = (char)id.getLength(); memcpy(msg + 2, id.getText(), id.getLength()); network->zFactoryClient()->inventoryAPIRequest(target, msg, id.getLength() + 2); delete[] msg; } void InventoryView::api(char* message) { switch (message[0]) { case 0: // send inventory content { Array* slots = new Array(); int count = *(int*)(++message); for (int i = 0; i < count; i++) { SlotInfo info; info.id = *(int*)(message += 4); info.itemCount = *(int*)(message += 4); if (info.itemCount > 0) { info.damage = *(float*)(message += 4); info.maxDamage = *(float*)(message += 4); info.durability = *(float*)(message += 4); info.maxDurability = *(float*)(message += 4); info.zItem = itemIcons->z(*(int*)(message += 4)); } slots->add(info); } postAction([this, slots]() { if (this->slots) this->slots->release(); this->slots = slots; }); break; } case 1: // set count of items { if (!slots) return; int id = *(int*)(message + 1); int count = *(int*)(message + 5); for (int i = 0; i < slots->getEintragAnzahl(); i++) { if (slots->get(i).id == id) { SlotInfo info = slots->get(i); info.itemCount = count; if (info.itemCount == 0) { DragController* controller = ((Game*)(Menu*)menuRegister->get("game"))->zInventoryDragController(); if (controller && controller->getCurrentDragContainer() == this && controller->getCurrentDaragElement() == info.id) { controller->stopDrag(); } } slots->set(info, i); break; } } break; } case 2: // add new stack { if (!slots) return; int id = *(int*)(message + 1); for (int i = 0; i < slots->getEintragAnzahl(); i++) { if (slots->get(i).id == id) { SlotInfo info = slots->get(i); info.itemCount = *(int*)(message + 5); info.damage = *(float*)(message + 9); info.maxDamage = *(float*)(message + 13); info.durability = *(float*)(message + 17); info.maxDurability = *(float*)(message + 21); info.zItem = itemIcons->z(*(int*)(message + 25)); slots->set(info, i); break; } } break; } } } bool InventoryView::tick(double tickVal) { return ZeichnungHintergrund::tick(tickVal); } void InventoryView::render(Bild& rObj) { ZeichnungHintergrund::render(rObj); if (!rObj.setDrawOptions(pos.x, pos.y, gr.x, gr.y)) return; if (slots) { int x = 0; int y = 0; int rowCount = 0; for (SlotInfo info : *slots) { info.render(x, y, rObj, dragStartId == info.id, dragStopId == info.id); x += 60; if (++rowCount >= rowSize) { y += 60; x = 0; rowCount = 0; } } } rObj.releaseDrawOptions(); } void InventoryView::doMausEreignis(MausEreignis& me, bool userRet) { if (!slots) return; DragController* controller = ((Game*)(Menu*)menuRegister->get("game"))->zInventoryDragController(); int x = 0; int y = 0; int rowCount = 0; int slot = 0; dragStopId = -1; for (SlotInfo info : *slots) { if (me.mx >= x && me.mx < x + 50 && me.my >= y && me.my < y + 50) { if (me.id == ME_RLinks) { if (!controller->getCurrentDragContainer() && info.itemCount > 0) { controller->beginDrag(this, info.id, info.zItem, [this]() { dragStartId = -1; }); dragStartId = info.id; } else if (controller->getCurrentDragContainer()) { // request to transfer items from source to target slot Framework::Either> source = controller->getCurrentDragContainer()->getInventoryTarget(); int len = 2 + (source.isA() ? 4 : 16) + 5 + (target.isA() ? 4 : 16) + 4; char* msg = new char[len]; int index = 0; msg[index++] = 6; msg[index++] = (char)source.isA(); if (source.isA()) { *(int*)(msg + index) = source.getA(); index += 4; } else { *(int*)(msg + index) = source.getB()[0]; *(int*)(msg + index + 4) = source.getB()[1]; *(int*)(msg + index + 8) = source.getB()[2]; *(int*)(msg + index + 12) = source.getB()[3]; index += 16; } *(int*)(msg + index) = controller->getCurrentDaragElement(); index += 4; msg[index++] = target.isA(); if (target.isA()) { *(int*)(msg + index) = target.getA(); index += 4; } else { *(int*)(msg + index) = target.getB()[0]; *(int*)(msg + index + 4) = target.getB()[1]; *(int*)(msg + index + 8) = target.getB()[2]; *(int*)(msg + index + 12) = target.getB()[3]; index += 16; } *(int*)(msg + index) = info.id; network->zFactoryClient()->sendPlayerAction(msg, len); delete[] msg; } } else { if (controller->getCurrentDragContainer() && (controller->getCurrentDragContainer() != this || controller->getCurrentDaragElement() != info.id)) { dragStopId = info.id; } } break; } x += 60; if (++rowCount >= rowSize) { y += 60; x = 0; rowCount = 0; } slot++; } ZeichnungHintergrund::doMausEreignis(me, userRet); } Framework::Either> InventoryView::getInventoryTarget() const { return target; }