123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444 |
- #include "CraftingStorage.h"
- #include <InMemoryBuffer.h>
- #include "Game.h"
- #include "Inventory.h"
- #include "Item.h"
- #include "RecipieList.h"
- #include "RecipieLoader.h"
- #undef min
- #undef max
- 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) {
- Recipie* old = currentRecipie;
- calculateOutputPreview();
- if (old == currentRecipie)
- {
- NetworkMessage* message = new NetworkMessage();
- getOutputPreview(message);
- message->addressUIElement(id);
- Game::INSTANCE->sendMessage(message, zSource);
- }
- });
- }
- void BasicShapedCrafter::getOutputPreview(NetworkMessage* zMessage)
- {
- if (currentRecipie)
- {
- Framework::Array<ItemInfo> output = currentRecipie->getOutput();
- Framework::InMemoryBuffer buffer;
- int count = 0;
- for (const 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<RecipieInput>& inputs, 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++)
- {
- RecipieInput* i = inputs.z(h * width + w);
- ItemSlot* s
- = craftingInput.get((h + y) * this->width + (x + w));
- const Item* item = 0;
- if (s && s->zStack()
- && s->zStack()->getSize() >= i->getAmount())
- item = s->zStack()->zItem();
- wrong |= (item && !i->zFilter()) || (!item && i->zFilter());
- wrong |= item && i->zFilter()
- && !i->zFilter()->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::isAllAvailable(
- Framework::RCArray<RecipieInput>& inputs)
- {
- bool* used = new bool[craftingInput.getEintragAnzahl()];
- memset(used, 0, sizeof(bool) * craftingInput.getEintragAnzahl());
- for (RecipieInput* input : inputs)
- {
- bool found = 0;
- for (int i = 0; i < craftingInput.getEintragAnzahl(); i++)
- {
- if (used[i]) continue;
- ItemSlot* slot = craftingInput.get(i);
- if (slot && slot->zStack()
- && slot->zStack()->getSize() >= input->getAmount()
- && slot->zStack()->zItem()
- && input->zFilter()->matchItem(slot->zStack()->zItem()))
- {
- found = 1;
- used[i] = 1;
- break;
- }
- }
- if (!found)
- {
- delete[] used;
- return 0;
- }
- }
- delete[] used;
- return 1;
- }
- 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<RecipieInput>& inputs, int width, int height)
- {
- int beginX = this->width;
- int beginY = this->height;
- SourceSlotBlacklistFilter otherSlotsSource;
- TargetSlotBlacklistFilter otherSlotsTarget;
- 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);
- }
- otherSlotsSource.addBlackListSlotId(craftingInput.get(i)->getId());
- otherSlotsTarget.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, target->getNumberOfItems(), INSIDE);
- if (stack)
- {
- if (stack->getSize() > inputs.z(y * width + x)->getAmount())
- {
- ItemStack* overflow
- = stack->split(stack->getSize()
- - inputs.z(y * width + x)->getAmount());
- zInventory->unsaveAddItem(
- overflow, INSIDE, &otherSlotsTarget);
- if (overflow->getSize() > 0)
- {
- Game::INSTANCE->spawnItem(zInventory->getLocation(),
- zInventory->getDimensionId(),
- overflow);
- }
- else
- {
- overflow->release();
- }
- }
- if (stack->getSize() > 0 && stack->zItem())
- {
- ItemModifier* m = inputs.z(y * width + x)->zModifier();
- 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());
- if (broken)
- {
- ItemStack* brokenStack
- = new ItemStack(broken, stack->getSize());
- zInventory->unsaveAddItem(
- brokenStack, INSIDE, &otherSlotsTarget);
- if (brokenStack->getSize() > 0)
- {
- Game::INSTANCE->spawnItem(zInventory->getLocation(),
- zInventory->getDimensionId(),
- brokenStack);
- }
- else
- {
- brokenStack->release();
- }
- }
- stack->release();
- }
- else
- {
- zInventory->addItems(target, stack, INSIDE);
- if (stack->getSize() > 0)
- {
- Game::INSTANCE->spawnItem(zInventory->getLocation(),
- zInventory->getDimensionId(),
- stack);
- }
- else
- {
- stack->release();
- }
- }
- }
- ItemFilter* f = inputs.z(y * width + x)->zFilter();
- if (f)
- {
- if (target->isEmpty())
- {
- Framework::RCArray<ItemFilter> filters;
- filters.add(dynamic_cast<ItemFilter*>(f->getThis()));
- filters.add(
- dynamic_cast<ItemFilter*>(otherSlotsSource.getThis()));
- Framework::Array<ItemSlot*> tmp;
- tmp.add(target);
- CombinedItemFilter combinedFilter(
- filters, [](bool a, bool b) { return a && b; });
- zInventory->localTransaction(
- 0, &tmp, &combinedFilter, 1, NO_DIRECTION, INSIDE);
- }
- }
- }
- }
- return 1;
- }
- bool BasicShapedCrafter::consume(Framework::RCArray<RecipieInput>& inputs)
- {
- SourceSlotBlacklistFilter otherSlotsSource;
- TargetSlotBlacklistFilter otherSlotsTarget;
- for (int i = 0; i < craftingInput.getEintragAnzahl(); i++)
- {
- otherSlotsSource.addBlackListSlotId(craftingInput.get(i)->getId());
- otherSlotsTarget.addBlackListSlotId(craftingInput.get(i)->getId());
- }
- bool* used = new bool[craftingInput.getEintragAnzahl()];
- memset(used, 0, sizeof(bool) * craftingInput.getEintragAnzahl());
- for (int i = 0; i < inputs.getEintragAnzahl(); i++)
- {
- for (int j = 0; j < craftingInput.getEintragAnzahl(); j++)
- {
- if (used[j]) continue;
- ItemSlot* target = craftingInput.get(j);
- if (target && target->zStack()
- && target->zStack()->getSize() >= inputs.z(i)->getAmount()
- && target->zStack()->zItem()
- && inputs.z(i)->zFilter()->matchItem(target->zStack()->zItem()))
- {
- used[i] = 1;
- ItemStack* stack = zInventory->takeItemsOut(
- target, target->getNumberOfItems(), INSIDE);
- if (stack)
- {
- if (stack->getSize() > inputs.z(i)->getAmount())
- {
- ItemStack* overflow = stack->split(
- stack->getSize() - inputs.z(i)->getAmount());
- zInventory->unsaveAddItem(
- overflow, INSIDE, &otherSlotsTarget);
- if (overflow->getSize() > 0)
- {
- Game::INSTANCE->spawnItem(zInventory->getLocation(),
- zInventory->getDimensionId(),
- overflow);
- }
- else
- {
- overflow->release();
- }
- }
- if (stack->getSize() > 0 && stack->zItem())
- {
- ItemModifier* m = inputs.z(i)->zModifier();
- 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());
- if (broken)
- {
- ItemStack* brokenStack
- = new ItemStack(broken, stack->getSize());
- zInventory->unsaveAddItem(
- brokenStack, INSIDE, &otherSlotsTarget);
- if (brokenStack->getSize() > 0)
- {
- Game::INSTANCE->spawnItem(
- zInventory->getLocation(),
- zInventory->getDimensionId(),
- brokenStack);
- }
- else
- {
- brokenStack->release();
- }
- }
- stack->release();
- }
- else
- {
- zInventory->addItems(target, stack, INSIDE);
- if (stack->getSize() > 0)
- {
- Game::INSTANCE->spawnItem(zInventory->getLocation(),
- zInventory->getDimensionId(),
- stack);
- }
- else
- {
- stack->release();
- }
- }
- }
- ItemFilter* f = inputs.z(i)->zFilter();
- if (f)
- {
- if (target->isEmpty())
- {
- Framework::RCArray<ItemFilter> filters;
- filters.add(dynamic_cast<ItemFilter*>(f->getThis()));
- filters.add(dynamic_cast<ItemFilter*>(
- otherSlotsSource.getThis()));
- Framework::Array<ItemSlot*> tmp;
- tmp.add(target);
- CombinedItemFilter combinedFilter(
- filters, [](bool a, bool b) { return a && b; });
- zInventory->localTransaction(
- 0, &tmp, &combinedFilter, 1, NO_DIRECTION, INSIDE);
- }
- }
- break;
- }
- }
- }
- delete[] used;
- return 1;
- }
- void BasicShapedCrafter::addCraftingResult(ItemStack* stack)
- {
- TargetSlotBlacklistFilter otherSlotsTarget;
- for (int i = 0; i < craftingInput.getEintragAnzahl(); i++)
- otherSlotsTarget.addBlackListSlotId(craftingInput.get(i)->getId());
- zInventory->unsaveAddItem(stack, NO_DIRECTION, &otherSlotsTarget);
- }
- void BasicShapedCrafter::applyCurrentRecipie()
- {
- if (currentRecipie && currentRecipie->testApplicability(this))
- currentRecipie->apply(this);
- }
- void BasicShapedCrafter::calculateOutputPreview()
- {
- RecipieList* recipies
- = Game::INSTANCE->zRecipies()->zRecipieList(recipieList);
- if (recipies)
- {
- Recipie* recipie = recipies->zFirstRecipie(this);
- if (recipie != currentRecipie)
- {
- currentRecipie = recipie;
- NetworkMessage* message = new NetworkMessage();
- getOutputPreview(message);
- zInventory->notifyObservers(message);
- }
- }
- }
|