#include #include "CraftingStorage.h" #include "Game.h" #include "Inventory.h" #include "Item.h" BasicShapedCrafter::BasicShapedCrafter(int width, int height, Inventory* zInventory, Framework::Text recipieList) : zInventory(zInventory), currentRecipie(0), recipieList(recipieList), width(width), height(height) { for (int i = 0; i < width * height; i++) { ItemSlot* slot = new ItemSlot("CraftingGrid", 1, std::numeric_limits::max(), std::numeric_limits::max(), INSIDE, INSIDE, 0); zInventory->addSlot(slot); craftingInput.add(slot); } std::function onChange = [this, recipieList](ItemSlot* zSlot, Direction dir, const Item* zItem, int count) { if (!zSlot->getName().istGleich("CraftingGrid")) return; calculateOutputPreview(); }; zInventory->registerAfterPullStackCall(onChange); zInventory->registerAfterPushStackCall(onChange); zInventory->registerObserverAddedCall([this](Entity* zSource, Framework::Text id) { ShapedRecipie* old = currentRecipie; calculateOutputPreview(); if (old == currentRecipie) { NetworkMessage* message = new NetworkMessage(); getOutputPreview(message); message->addressGui(id); Game::INSTANCE->sendMessage(message, zSource); } }); } void BasicShapedCrafter::getOutputPreview(NetworkMessage* zMessage) { if (currentRecipie) { Framework::Array output = currentRecipie->getOutput(this); Framework::InMemoryBuffer buffer; int count = 0; for (ItemInfo slot : output) { count++; int itemCount = slot.count; buffer.schreibe((char*)&itemCount, 4); if (itemCount > 0) { float f = slot.damage; buffer.schreibe((char*)&f, 4); f = slot.maxDamage; buffer.schreibe((char*)&f, 4); f = slot.durability; buffer.schreibe((char*)&f, 4); f = slot.maxDurability; buffer.schreibe((char*)&f, 4); int id = slot.type; buffer.schreibe((char*)&id, 4); } } char* msg = new char[5 + buffer.getSize()]; msg[0] = 100; // set crafting result *(int*)(msg + 1) = count; buffer.lese(msg + 5, (int)buffer.getSize()); zMessage->setMessage(msg, 5 + (int)buffer.getSize()); } else { char* msg = new char[5]; msg[0] = 100; // set crafting result *(int*)(msg + 1) = 0; zMessage->setMessage(msg, 5); } } bool BasicShapedCrafter::isAllAvailable(Framework::RCArray& filters, int width, int height) { for (int x = 0; x <= this->width - width; x++) { for (int y = 0; y <= this->height - height; y++) { bool wrong = 0; for (int w = 0; w < width; w++) { for (int h = 0; h < height; h++) { ItemFilter* f = filters.z(h * width + w); ItemSlot* s = craftingInput.get((h + y) * this->width + (x + w)); const Item* item = 0; if (s && s->zStack()) item = s->zStack()->zItem(); wrong |= (item && !f) || (!item && f); wrong |= item && f && !f->matchItem(item); if (wrong) break; } if (wrong) break; } if (!wrong) { int i = 0; for (ItemSlot* slot : craftingInput) { int w = i % this->width; int h = i / this->width; if ((w < x || w >= x + width || h < y || h >= y + height) && slot->zStack()) return 0; // more items then needed are in crafting grid i++; } return 1; } } } return 0; } bool BasicShapedCrafter::hasFreeSpace(const Item* zItem, int amount) { ItemStack* stack = new ItemStack(zItem->zItemType()->cloneItem(zItem), amount); int addable = zInventory->numberOfAddableItems(stack, NO_DIRECTION); stack->release(); return addable >= amount; } bool BasicShapedCrafter::consume(Framework::RCArray& filters, int width, int height) { for (ItemSlot* slot : craftingInput) { if (slot && slot->zStack()) { ItemStack* stack = zInventory->takeItemsOut(slot, 1, INSIDE); if (stack) stack->release(); } } for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { ItemFilter* f = filters.z(x * width + y); if (f) { ItemSlot* target = craftingInput.get(x * this->width + y); Framework::Array< ItemSlot*> tmp; tmp.add(target); zInventory->localTransaction(0, &tmp, f, 1, NO_DIRECTION, INSIDE); } } } return 1; } void BasicShapedCrafter::addCraftingResult(ItemStack* stack) { zInventory->addItems(stack, NO_DIRECTION); } void BasicShapedCrafter::applyCurrentRecipie() { if (currentRecipie && currentRecipie->testApplicability(this)) currentRecipie->apply(this); } void BasicShapedCrafter::calculateOutputPreview() { ShapedRecipieList* recipies = Game::INSTANCE->getRecipies().zShapedRecipieList(recipieList); if (recipies) { ShapedRecipie* recipie = recipies->zFirstRecipie(this); if (recipie != currentRecipie) { currentRecipie = recipie; NetworkMessage* message = new NetworkMessage(); getOutputPreview(message); zInventory->notyObservers(message); } } }