123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230 |
- #include <InMemoryBuffer.h>
- #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<int>::max(), std::numeric_limits<int>::max(), INSIDE, INSIDE, 0);
- zInventory->addSlot(slot);
- craftingInput.add(slot);
- }
- std::function<void(ItemSlot* zSlot, Direction dir, const Item* zItem, int count)> 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<ItemInfo> 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.hp;
- buffer.schreibe((char*)&f, 4);
- f = slot.maxHp;
- 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<ItemFilter>& 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<ItemFilter>& filters, Framework::RCArray<ItemModifier>& modfiers, int width, int height)
- {
- int beginX = this->width;
- int beginY = this->height;
- SourceSlotBlacklistFilter otherSlots;
- for (int i = 0; i < craftingInput.getEintragAnzahl(); i++)
- {
- if (!craftingInput.get(i)->isEmpty())
- {
- int x = i % this->width;
- int y = i / this->width;
- beginX = MIN(beginX, x);
- beginY = MIN(beginY, y);
- }
- otherSlots.addBlackListSlotId(craftingInput.get(i)->getId());
- }
- for (int x = 0; x < width; x++)
- {
- for (int y = 0; y < height; y++)
- {
- ItemSlot* target = craftingInput.get((y + beginY) * this->width + x + beginX);
- ItemStack* stack = zInventory->takeItemsOut(target, 1, INSIDE);
- if (stack)
- {
- if (stack->getSize() > 0 && stack->zItem())
- {
- ItemModifier* m = modfiers.z(y * width + x);
- if (m)
- m->applyOn((Item*)stack->zItem());
- }
- if (stack->zItem()->getHp() == 0)
- stack->release();
- else if (stack->zItem()->getDurability() == 0)
- {
- Item* broken = stack->zItem()->zItemType()->breakItem(stack->zItem());
- stack->release();
- if (broken)
- {
- ItemStack* brokenStack = new ItemStack(broken, 1);
- zInventory->unsaveAddItem(brokenStack, INSIDE);
- // TODO: if brokenStack is not empty spawn an item entity
- brokenStack->release();
- }
- }
- else
- {
- // TODO: transfer all items from target to other slots or drop them
- zInventory->addItems(target, stack, INSIDE);
- // TODO: if stack is not empty spawn an item entity
- }
- }
- ItemFilter* f = filters.z(y * width + x);
- if (f)
- {
- if (target->isEmpty())
- {
- Framework::Array< ItemSlot*> tmp;
- tmp.add(target);
- CombinedItemFilter combinedFilter(dynamic_cast<ItemFilter*>(f->getThis()), dynamic_cast<ItemFilter*>(otherSlots.getThis()), [](bool a, bool b)
- {
- return a && b;
- });
- zInventory->localTransaction(0, &tmp, &combinedFilter, 1, NO_DIRECTION, INSIDE);
- }
- }
- }
- }
- return 1;
- }
- void BasicShapedCrafter::addCraftingResult(ItemStack* stack)
- {
- zInventory->unsaveAddItem(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);
- }
- }
- }
|