Ver código fonte

items can now be crafted with the crafting grid uiml element

Kolja Strohm 2 anos atrás
pai
commit
072b69b5b7

+ 300 - 6
FactoryCraft/CraftingGrid.cpp

@@ -1,6 +1,9 @@
 #include <XML.h>
 
 #include "CraftingGrid.h"
+#include "Globals.h"
+#include "DragController.h"
+#include "Game.h"
 
 using namespace Framework;
 
@@ -11,7 +14,7 @@ CraftingGridElement::CraftingGridElement()
 //! 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("inventory");
+	return element.getName().istGleich("craftingGrid");
 }
 
 //! erstellt eine neue Zeichnung zu einem gegebenen xml Element
@@ -32,7 +35,7 @@ Framework::Zeichnung* CraftingGridElement::parseElement(Framework::XML::Element&
 		third->release();
 		forth->release();
 	}
-	return new CraftingGridView((int)element.getAttributeValue("rowSize"), (int)element.getAttributeValue("colSize"), (int)element.getAttributeValue("numOutputSlots"), target);
+	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
@@ -42,17 +45,176 @@ void CraftingGridElement::layout(Framework::XML::Element& element, Framework::Ze
 }
 
 
-CraftingGridView::CraftingGridView(int rowSize, int colSize, int numOutputSlots, Either<int, VecN<int, 4>> target)
+CraftingGridView::CraftingGridView(Text id, int rowSize, int colSize, int numOutputSlots, Either<int, VecN<int, 4>> target)
 	: ZeichnungHintergrund(),
 	rowSize(rowSize),
 	colSize(colSize),
 	numOutputSlots(numOutputSlots),
-	target(target)
-{}
+	target(target),
+	slots(0),
+	outputs(0),
+	id(id),
+	dragStartId(-1),
+	dragStopId(-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];
+				}
+				network->zFactoryClient()->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 content
+	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);
+	network->zFactoryClient()->inventoryAPIRequest(target, msg, id.getLength() + 12 + 3);
+	delete[] msg;
+}
 
-void CraftingGridView::api(char* message)
+CraftingGridView::~CraftingGridView()
 {
+	DragController<InventoryDragSource, int>* 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());
+	network->zFactoryClient()->inventoryAPIRequest(target, msg, id.getLength() + 2);
+	delete[] msg;
+	craft->release();
+}
 
+void CraftingGridView::api(char* message)
+{
+	switch (message[0])
+	{
+	case 0:
+		// send inventory content
+	{
+		Array<SlotInfo>* slots = new Array<SlotInfo>();
+		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
+	{
+		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<InventoryDragSource, int>* 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
+	{
+		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;
+	}
+	case 100: // set crafting result
+	{
+		Array<SlotInfo>* outputs = new Array<SlotInfo>();
+		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.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));
+			}
+			outputs->add(info);
+		}
+		postAction([this, outputs]()
+			{
+				if (this->outputs)
+					this->outputs->release();
+				this->outputs = outputs;
+			});
+		break;
+	}
+	}
 }
 
 bool CraftingGridView::tick(double tickVal)
@@ -63,9 +225,141 @@ bool CraftingGridView::tick(double 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)
 {
+	craft->doPublicMausEreignis(me);
+	DragController<InventoryDragSource, int>* 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<int, Framework::VecN<int, 4>> 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<int, Framework::VecN<int, 4>> CraftingGridView::getInventoryTarget() const
+{
+	return target;
 }

+ 14 - 4
FactoryCraft/CraftingGrid.h

@@ -1,11 +1,13 @@
 #pragma once
 
-#include "NetworkAPIProcessor.h"
-
 #include <UIMLView.h>
 #include <Either.h>
 #include <VecN.h>
 
+#include "NetworkAPIProcessor.h"
+#include "InventoryView.h"
+
+
 class CraftingGridElement : public Framework::UIMLElement
 {
 public:
@@ -18,7 +20,7 @@ public:
 	void layout(Framework::XML::Element& element, Framework::Zeichnung& z, int pWidth, int pHeight, Framework::UIMLContainer& generalLayouter) override;
 };
 
-class CraftingGridView : public Framework::ZeichnungHintergrund, public NetworkAPIProcessor
+class CraftingGridView : public Framework::ZeichnungHintergrund, public NetworkAPIProcessor, public InventoryDragSource
 {
 private:
 	int rowSize;
@@ -26,11 +28,19 @@ private:
 	int numOutputSlots;
 	// entity id or block position
 	Framework::Either<int, Framework::VecN<int, 4>> target;
+	Framework::Array<SlotInfo>* slots;
+	Framework::Array<SlotInfo>* outputs;
+	Framework::Text id;
+	int dragStartId;
+	int dragStopId;
+	Framework::Knopf* craft;
 
 public:
-	CraftingGridView(int rowSize, int colSize, int numOutputSlots, Framework::Either<int, Framework::VecN<int, 4>> target);
+	CraftingGridView(Framework::Text id, int rowSize, int colSize, int numOutputSlots, Framework::Either<int, Framework::VecN<int, 4>> target);
+	~CraftingGridView();
 	void api(char* message) override;
 	bool tick(double tickVal) override;
 	void render(Framework::Bild& rObj) override;
 	void doMausEreignis(Framework::MausEreignis& me, bool userRet) override;
+	Framework::Either<int, Framework::VecN<int, 4>> getInventoryTarget() const override;
 };

+ 8 - 12
FactoryCraft/InventoryView.cpp

@@ -88,18 +88,15 @@ InventoryView::InventoryView(Text id, Either<int, VecN<int, 4>> target, int rowS
 	dragStartId(-1),
 	dragStopId(-1)
 {
-	if (target.isA())
-	{
-		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;
-	}
 	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()
@@ -113,7 +110,6 @@ InventoryView::~InventoryView()
 	msg[0] = 1;
 	msg[1] = (char)id.getLength();
 	memcpy(msg + 2, id.getText(), id.getLength());
-	msg[2 + id.getLength()] = (char)slotNameFilter.getLength();
 	network->zFactoryClient()->inventoryAPIRequest(target, msg, id.getLength() + 2);
 	delete[] msg;
 }