#include #include "CraftingGrid.h" #include "Globals.h" #include "DragController.h" #include "Game.h" #include "UIMLToolTip.h" using namespace Framework; CraftingGridElement::CraftingGridElement() : UIMLElement() {} //! prüft, ob dieses UIML Element für ein bestimmtes xml Element zuständig ist bool CraftingGridElement::isApplicableFor(Framework::XML::Element& element) { return element.getName().istGleich("craftingGrid"); } //! erstellt eine neue Zeichnung zu einem gegebenen xml Element Framework::Zeichnung* CraftingGridElement::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>(VecN({ (int)*first, (int)*second, (int)*third, (int)*forth })); first->release(); second->release(); third->release(); forth->release(); } return new CraftingGridView(element.getAttributeValue("id"), (int)element.getAttributeValue("rowSize"), (int)element.getAttributeValue("colSize"), (int)element.getAttributeValue("numOutputSlots"), target); } //! wendet die layout parameter zu einer Zeichnung an void CraftingGridElement::layout(Framework::XML::Element& element, Framework::Zeichnung& z, int pWidth, int pHeight, Framework::UIMLContainer& generalLayouter) { UIMLElement::layout(element, z, pWidth, pHeight, generalLayouter); } CraftingGridView::CraftingGridView(Text id, int rowSize, int colSize, int numOutputSlots, Either> target) : ZeichnungHintergrund(), rowSize(rowSize), colSize(colSize), numOutputSlots(numOutputSlots), target(target), slots(0), outputs(0), id(id), dragStartId(-1), dragStopId(-1), currentTooltipSlot(-1), requestetTooltipSlot(-1) { craft = uiFactory.createKnopf(uiFactory.initParam); craft->setPosition(rowSize * 60, 10); craft->setSize(40, 20); craft->setText("Craft"); craft->setMausEreignis([this](void* p, void* o, MausEreignis me) { if (me.id == ME_RLinks) { char* msg = new char[2 + (this->target.isA() ? 4 : 16)]; msg[0] = 7; // request crafting msg[1] = (char)this->target.isA(); if (msg[1]) *(int*)(msg + 2) = this->target.getA(); else { *(int*)(msg + 2) = this->target.getB()[0]; *(int*)(msg + 6) = this->target.getB()[1]; *(int*)(msg + 10) = this->target.getB()[2]; *(int*)(msg + 14) = this->target.getB()[3]; } World::INSTANCE->zClient()->sendPlayerAction(msg, 2 + (this->target.isA() ? 4 : 16)); delete[] msg; } return 1; }); setStyle(ZeichnungHintergrund::Style::Sichtbar | ZeichnungHintergrund::Style::Erlaubt); char* msg = new char[id.getLength() + 12 + 3]; msg[0] = 0; // request inventory tooltip msg[1] = (char)id.getLength(); memcpy(msg + 2, id.getText(), id.getLength()); msg[2 + id.getLength()] = (char)12; memcpy(msg + 3 + id.getLength(), "CraftingGrid", 12); World::INSTANCE->zClient()->inventoryAPIRequest(target, msg, id.getLength() + 12 + 3); delete[] msg; setNeedToolTipEvent([this](Zeichnung* z, Punkt p) { int slot = getSlotByLocalPos(p); if (currentTooltipSlot != slot) { this->setToolTipZ(0); currentTooltipSlot = -1; } else return; if (requestetTooltipSlot != slot) { requestetTooltipSlot = slot; char* msg = new char[this->id.getLength() + 6]; msg[0] = 2; // request inventory tooltip msg[1] = (char)this->id.getLength(); memcpy(msg + 2, this->id.getText(), this->id.getLength()); *(int*)(msg + 2 + this->id.getLength()) = slot; World::INSTANCE->zClient()->inventoryAPIRequest(this->target, msg, this->id.getLength() + 6); } }); } CraftingGridView::~CraftingGridView() { DragController* controller = ((Game*)(Menu*)menuRegister->get("game"))->zInventoryDragController(); if (controller->getCurrentDragContainer() == this) controller->stopDrag(); if (slots) slots->release(); if (outputs) outputs->release(); char* msg = new char[id.getLength() + 2]; msg[0] = 1; msg[1] = (char)id.getLength(); memcpy(msg + 2, id.getText(), id.getLength()); World::INSTANCE->zClient()->inventoryAPIRequest(target, msg, id.getLength() + 2); delete[] msg; craft->release(); } int CraftingGridView::getSlotByLocalPos(Punkt pos) { int x = 0; int y = 0; int rowCount = 0; int slot = 0; dragStopId = -1; if (slots) { for (SlotInfo info : *slots) { if (pos.x >= x && pos.x < x + 50 && pos.y >= y && pos.y < y + 50) return info.id; x += 60; if (++rowCount >= rowSize) { y += 60; x = 0; rowCount = 0; } slot++; } } return -1; } void CraftingGridView::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.hp = *(float*)(message += 4); info.maxHp = *(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.hp = *(float*)(message + 9); info.maxHp = *(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; } case 3: // receive tooltip uiml { int slotId = *(int*)(message + 1); if (slotId == requestetTooltipSlot) { short len = *(short*)(message + 5); char* uiml = new char[len + 1]; memcpy(uiml, message + 7, len); uiml[len] = 0; UIMLToolTip* tip = new UIMLToolTip(); tip->setUIML(uiml); setToolTipZ(tip); delete[] uiml; currentTooltipSlot = slotId; requestetTooltipSlot = -1; } break; } case 100: // set crafting result { Array* outputs = new Array(); int count = *(int*)(++message); for (int i = 0; i < count; i++) { SlotInfo info; info.id = i; info.itemCount = *(int*)(message += 4); if (info.itemCount > 0) { info.hp = *(float*)(message += 4); info.maxHp = *(float*)(message += 4); info.durability = *(float*)(message += 4); info.maxDurability = *(float*)(message += 4); info.zItem = itemIcons->z(*(int*)(message += 4)); } outputs->add(info); } postAction([this, outputs]() { if (this->outputs) this->outputs->release(); this->outputs = outputs; }); break; } } } bool CraftingGridView::tick(double tickVal) { return ZeichnungHintergrund::tick(tickVal); } void CraftingGridView::render(Bild& rObj) { ZeichnungHintergrund::render(rObj); if (!rObj.setDrawOptions(pos.x, pos.y, gr.x, gr.y)) return; int numRows = 1; if (slots) { int x = 0; int y = 0; int rowCount = 0; int index = 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; if (index < slots->getEintragAnzahl() - 1) numRows++; } index++; } } craft->render(rObj); rObj.fillRegion(rowSize * 60, gr.y / 2 - 5, 25, 10, 0xFF52525E); rObj.drawDreieck(Punkt(rowSize * 60 + 25, gr.y / 2 - 15), Punkt(rowSize * 60 + 40, gr.y / 2), Punkt(rowSize * 60 + 25, gr.y / 2 + 15), 0xFF52525E); if (outputs) { int x = rowSize * 60 + 50; int y = 0; int colCount = 0; for (SlotInfo info : *outputs) { info.render(x, y, rObj, dragStartId == info.id, dragStopId == info.id); y += 60; if (++colCount >= numRows) { x += 60; y = 0; colCount = 0; } } } rObj.releaseDrawOptions(); } void CraftingGridView::doMausEreignis(MausEreignis& me, bool userRet) { if (!slots) return; if (me.id == ME_Bewegung) { if (getSlotByLocalPos(Punkt(me.mx, me.my)) != currentTooltipSlot) { setToolTipZ(0); currentTooltipSlot = -1; } } craft->doPublicMausEreignis(me); 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; World::INSTANCE->zClient()->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> CraftingGridView::getInventoryTarget() const { return target; }