| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012 |
- #include "Inventory.h"
- #include <InMemoryBuffer.h>
- #include "Area.h"
- #include "Constants.h"
- #include "Entity.h"
- #include "Game.h"
- #include "ItemFilter.h"
- #include "ItemSlot.h"
- #include "ItemStack.h"
- #include "ItemType.h"
- #include "NetworkMessage.h"
- #include "UIMLBuilder.h"
- using namespace Framework;
- InventoryInteraction::InventoryInteraction(
- Inventory* current, Inventory* other, Direction dir)
- : current(current),
- other(other),
- dir(dir)
- {
- lock();
- }
- InventoryInteraction::InventoryInteraction(
- const InventoryInteraction& interaction)
- : InventoryInteraction(
- interaction.current, interaction.other, interaction.dir)
- {}
- InventoryInteraction::~InventoryInteraction()
- {
- unlock();
- }
- void InventoryInteraction::lock()
- {
- if (!current || !other) return;
- if (current->location.x < other->location.x)
- {
- current->cs.lock();
- other->cs.lock();
- return;
- }
- else if (current->location.x == other->location.x)
- {
- if (current->location.y < other->location.y)
- {
- current->cs.lock();
- other->cs.lock();
- return;
- }
- else if (current->location.y == other->location.y)
- {
- if (current->location.z < other->location.z)
- {
- current->cs.lock();
- other->cs.lock();
- return;
- }
- }
- }
- other->cs.lock();
- current->cs.lock();
- }
- void InventoryInteraction::unlock()
- {
- if (!current || !other) return;
- if (current->location.x < other->location.x)
- {
- current->cs.unlock();
- other->cs.unlock();
- return;
- }
- else if (current->location.x == other->location.x)
- {
- if (current->location.y < other->location.y)
- {
- current->cs.unlock();
- other->cs.unlock();
- return;
- }
- else if (current->location.y == other->location.y)
- {
- if (current->location.z < other->location.z)
- {
- current->cs.unlock();
- other->cs.unlock();
- return;
- }
- }
- }
- other->cs.unlock();
- current->cs.unlock();
- }
- void InventoryInteraction::transaction(Inventory* zSource,
- Inventory* zTarget,
- ItemFilter* zFilter,
- Direction sourceView,
- Direction targetView,
- int count)
- {
- for (auto sourceSlot = zSource->pullSlotsOrder->begin(); sourceSlot;)
- {
- while (sourceSlot
- && (sourceSlot->getNumberOfItems() == 0
- || (zFilter && !zFilter->matchSourceSlot(sourceSlot))))
- sourceSlot++;
- if (!sourceSlot) break;
- // TODO: use target cache ot get list of slots that already contains the
- // source item
- bool needNext = 1;
- for (auto targetSlot = zTarget->pushSlotsOrder->begin(); targetSlot;)
- {
- while (targetSlot
- && (targetSlot->isFull()
- || (zFilter && !zFilter->matchTargetSlot(targetSlot))))
- targetSlot++;
- if (!targetSlot) break;
- needNext &= !Inventory::unsafeMove(zSource,
- zTarget,
- sourceSlot,
- targetSlot,
- sourceView,
- targetView,
- count);
- if (count == 0) return;
- if (sourceSlot->getNumberOfItems() == 0) break;
- }
- if (needNext) sourceSlot++;
- }
- }
- InventoryInteraction& InventoryInteraction::operator=(
- const InventoryInteraction& data)
- {
- if (&data == this) return *this;
- unlock();
- current = data.current;
- other = data.other;
- dir = data.dir;
- lock();
- return *this;
- }
- void InventoryInteraction::endInteraction()
- {
- unlock();
- current = 0;
- other = 0;
- }
- void InventoryInteraction::pullItems(int count, ItemFilter* zFilter)
- {
- if (!current || !other) return;
- transaction(other, current, zFilter, getOppositeDirection(dir), dir, count);
- }
- void InventoryInteraction::pushItems(int count, ItemFilter* zFilter)
- {
- if (!current || !other) return;
- transaction(current, other, zFilter, dir, getOppositeDirection(dir), count);
- }
- MultipleInventoryLock::MultipleInventoryLock(Inventory** inventories, int count)
- : inventories(new Inventory*[count]),
- count(count),
- locked(0)
- {
- // sort given inventories in locking order
- bool* used = new bool[count];
- memset(used, 0, count);
- // TODO: use a performant sorting algorithm
- for (int i = 0; i < count; i++)
- {
- Inventory* min = 0;
- int minJ = 0;
- for (int j = 0; j < count; j++)
- {
- if (!used[j])
- {
- if (!min)
- {
- min = inventories[j];
- minJ = j;
- continue;
- }
- if (inventories[j]->location.x < min->location.x)
- {
- min = inventories[j];
- minJ = j;
- continue;
- }
- if (inventories[j]->location.x == min->location.x)
- {
- if (inventories[j]->location.y < min->location.y)
- {
- min = inventories[j];
- minJ = j;
- continue;
- }
- if (inventories[j]->location.y == min->location.y)
- {
- if (inventories[j]->location.z < min->location.z)
- {
- min = inventories[j];
- minJ = j;
- continue;
- }
- }
- }
- }
- }
- this->inventories[i] = min;
- used[minJ] = 1;
- }
- lock();
- delete[] used;
- }
- MultipleInventoryLock::~MultipleInventoryLock()
- {
- unlock();
- delete[] inventories;
- }
- void MultipleInventoryLock::unlock()
- {
- if (locked)
- {
- locked = 0;
- for (int i = count - 1; i >= 0; i--)
- {
- inventories[i]->cs.unlock();
- }
- }
- }
- void MultipleInventoryLock::lock()
- {
- if (!locked)
- {
- locked = 1;
- for (int i = 0; i < count; i++)
- {
- inventories[i]->cs.lock();
- }
- }
- }
- Inventory::Inventory(
- const Framework::Vec3<float> location, int dimensionId, bool hasInventory)
- : ReferenceCounter(),
- nextSlotId(1),
- dimensionId(dimensionId),
- location(location)
- {
- if (hasInventory)
- {
- pullSlotsOrder = new Framework::RCArray<ItemSlot>();
- pushSlotsOrder = new Framework::RCArray<ItemSlot>();
- itemCache = new Framework::HashMap<int, Framework::Array<ItemSlot*>*>(
- ITEM_CACHE_SIZE, [](int key) { return key; });
- }
- else
- {
- pullSlotsOrder = 0;
- pushSlotsOrder = 0;
- itemCache = 0;
- }
- }
- Inventory::~Inventory()
- {
- if (pullSlotsOrder) pullSlotsOrder->release();
- if (pushSlotsOrder) pushSlotsOrder->release();
- if (itemCache) itemCache->release();
- }
- void Inventory::updateCache(ItemSlot* zSlot, int beforeKey)
- {
- if (!itemCache) return;
- int key
- = zSlot->zStack() ? zSlot->zStack()->zItem()->zItemType()->getId() : -1;
- if (key == beforeKey) return;
- if (beforeKey >= 0)
- {
- auto tmp = itemCache->safeGet(key, 0);
- if (tmp) tmp->removeValue(zSlot);
- }
- if (zSlot->zStack())
- {
- auto tmp = itemCache->safeGet(key, 0);
- if (!tmp)
- {
- tmp = new Array<ItemSlot*>();
- itemCache->put(key, tmp);
- }
- tmp->add(zSlot, 0);
- }
- }
- void Inventory::addSlot(ItemSlot* slot)
- {
- cs.lock();
- ((ItemSlotIDSetter*)slot)->setId(nextSlotId++);
- int pullPrio = slot->getPullPriority();
- int pushPrio = slot->getPushPriority();
- int index = 0;
- for (auto stack : *pullSlotsOrder)
- {
- if (stack->getPullPriority() > pullPrio) break;
- index++;
- }
- pullSlotsOrder->add(dynamic_cast<ItemSlot*>(slot->getThis()), index);
- index = 0;
- for (auto stack : *pushSlotsOrder)
- {
- if (stack->getPushPriority() > pushPrio) break;
- index++;
- }
- pushSlotsOrder->add(slot, index);
- updateCache(slot, -1);
- cs.unlock();
- }
- int Inventory::countAccessableItems(ItemFilter* zFilter, Direction dir) const
- {
- int count = 0;
- if (itemCache)
- {
- for (auto slot : *pullSlotsOrder)
- {
- if (slot->getNumberOfItems() > 0
- && (!zFilter || zFilter->matchSourceSlot(slot)))
- {
- if (allowPullStack(slot, dir))
- {
- count += slot->getNumberOfItems();
- }
- }
- }
- }
- return count;
- }
- bool Inventory::allowPullStack(ItemSlot* zSlot, Direction dir) const
- {
- return pullSlotsOrder != 0;
- }
- bool Inventory::allowPushStack(
- ItemSlot* zSlot, Direction dir, const Item* zItem, int& count) const
- {
- return pushSlotsOrder != 0;
- }
- void Inventory::afterPullStack(
- ItemSlot* zSlot, Direction dir, const Item* zItem, int count)
- {
- NetworkMessage* msg = new NetworkMessage();
- char* message = new char[9];
- message[0] = 1; // set count of items
- *(int*)(message + 1) = zSlot->getId();
- *(int*)(message + 5) = zSlot->getNumberOfItems();
- msg->setMessage(message, 9);
- notifyObservers(msg);
- for (auto call : afterPullStackCalls)
- call(zSlot, dir, zItem, count);
- }
- void Inventory::afterPushStack(
- ItemSlot* zSlot, Direction dir, const Item* zItem, int count)
- {
- updateSlot(zSlot);
- for (auto call : afterPushStackCalls)
- call(zSlot, dir, zItem, count);
- }
- void Inventory::updateSlot(ItemSlot* zSlot)
- {
- NetworkMessage* msg = new NetworkMessage();
- char* message = new char[9];
- message[0] = 1; // set count of items
- *(int*)(message + 1) = zSlot->getId();
- *(int*)(message + 5) = 0;
- msg->setMessage(message, 9);
- notifyObservers(msg);
- if (zSlot->getNumberOfItems() > 0)
- {
- const Item* zItem = zSlot->zStack()->zItem();
- NetworkMessage* msg = new NetworkMessage();
- char* message = new char[30 + zItem->getName().getLength()];
- message[0] = 2; // add new stack
- *(int*)(message + 1) = zSlot->getId();
- *(int*)(message + 5) = zSlot->getNumberOfItems();
- *(float*)(message + 9) = zItem->getHp();
- *(float*)(message + 13) = zItem->getMaxHp();
- *(float*)(message + 17) = zItem->getDurability();
- *(float*)(message + 21) = zItem->getMaxDurability();
- *(int*)(message + 25) = zItem->zItemType()->getId();
- *(message + 29) = (char)zItem->getName().getLength();
- memcpy(message + 30,
- zItem->getName().getText(),
- zItem->getName().getLength());
- msg->setMessage(message, 30 + zItem->getName().getLength());
- notifyObservers(msg);
- }
- }
- void Inventory::loadInventory(Framework::StreamReader* zReader)
- {
- if (itemCache)
- {
- for (auto stack : *pushSlotsOrder)
- {
- int size = 0;
- zReader->lese((char*)&size, 4);
- if (size != 0)
- {
- int id = 0;
- zReader->lese((char*)&id, 4);
- Item* item = Game::INSTANCE->zItemType(id)->loadItem(zReader);
- stack->addItems(new ItemStack(item, size), NO_DIRECTION);
- }
- }
- }
- }
- void Inventory::saveInventory(Framework::StreamWriter* zWriter)
- {
- if (itemCache)
- {
- for (auto slot : *pushSlotsOrder)
- {
- const ItemStack* stack = slot->zStack();
- int value = 0;
- if (!stack || !stack->zItem())
- {
- zWriter->schreibe((char*)&value, 4);
- }
- else
- {
- value = stack->getSize();
- zWriter->schreibe((char*)&value, 4);
- value = stack->zItem()->zItemType()->getId();
- zWriter->schreibe((char*)&value, 4);
- stack->zItem()->zItemType()->saveItem(stack->zItem(), zWriter);
- }
- }
- }
- }
- void Inventory::notifyObservers(NetworkMessage* msg)
- {
- observable.notifyObservers(msg);
- }
- void Inventory::lock()
- {
- cs.lock();
- }
- void Inventory::unlock()
- {
- cs.unlock();
- }
- const ItemSlot* Inventory::zSlot(int id) const
- {
- if (itemCache)
- {
- for (auto slot : *pushSlotsOrder)
- {
- if (slot->getId() == id) return slot;
- }
- }
- return 0;
- }
- void Inventory::localTransaction(Array<ItemSlot*>* zSourceSlots,
- Array<ItemSlot*>* zTargetSlots,
- ItemFilter* zFilter,
- int count,
- Direction outDir,
- Direction inDir)
- {
- if (itemCache)
- {
- cs.lock();
- auto sourceSlot
- = zSourceSlots ? zSourceSlots->begin() : pullSlotsOrder->begin();
- while (true)
- {
- while (sourceSlot
- && (sourceSlot->getNumberOfItems() == 0
- || (zFilter && !zFilter->matchSourceSlot(sourceSlot))))
- sourceSlot++;
- if (!sourceSlot)
- {
- cs.unlock();
- return;
- }
- bool needNext = 1;
- for (auto targetSlot = zTargetSlots->begin(); targetSlot;)
- {
- while (
- targetSlot
- && (targetSlot->isFull()
- || (zFilter && !zFilter->matchTargetSlot(targetSlot))))
- targetSlot++;
- if (!targetSlot) break;
- needNext &= !Inventory::unsafeMove(
- this, this, sourceSlot, targetSlot, outDir, inDir, count);
- if (count == 0)
- {
- cs.unlock();
- return;
- }
- if (sourceSlot->getNumberOfItems() == 0) break;
- }
- if (needNext) sourceSlot++;
- }
- cs.unlock();
- }
- }
- void Inventory::addItems(ItemStack* zItems, Direction dir, ItemFilter* zFilter)
- {
- if (itemCache && zItems && zItems->getSize() > 0)
- {
- cs.lock();
- for (auto targetSlot = pushSlotsOrder->begin(); targetSlot;
- targetSlot++)
- {
- if (!targetSlot->isFull()
- && (!zFilter || zFilter->matchTargetSlot(targetSlot)))
- {
- if (targetSlot->zStack())
- {
- if (targetSlot->zStack()->zItem()->canBeStackedWith(
- zItems->zItem()))
- {
- int number = MIN(targetSlot->numberOfAddableItems(
- zItems->zItem(), dir),
- zItems->getSize());
- int tmp = number;
- if (number > 0
- && allowPushStack(
- targetSlot, dir, zItems->zItem(), tmp))
- {
- number = MIN(number, tmp);
- ItemStack* stack = zItems->split(number);
- if (stack)
- {
- targetSlot->addItems(stack, dir);
- afterPushStack(targetSlot,
- dir,
- targetSlot->zStack()->zItem(),
- number);
- if (stack->getSize()) throw stack;
- stack->release();
- if (!zItems->getSize()) break;
- }
- }
- }
- }
- else
- {
- int number = MIN(
- targetSlot->numberOfAddableItems(zItems->zItem(), dir),
- zItems->getSize());
- int tmp = number;
- if (number > 0
- && allowPushStack(
- targetSlot, dir, zItems->zItem(), tmp))
- {
- number = MIN(number, tmp);
- ItemStack* stack = zItems->split(number);
- if (stack)
- {
- targetSlot->addItems(stack, dir);
- updateCache(targetSlot, -1);
- afterPushStack(targetSlot,
- dir,
- targetSlot->zStack()->zItem(),
- number);
- if (stack->getSize()) throw stack;
- stack->release();
- if (!zItems->getSize()) break;
- }
- }
- }
- }
- }
- cs.unlock();
- }
- }
- void Inventory::addItems(ItemSlot* zSlot, ItemStack* zItems, Direction dir)
- {
- if (zSlot->zStack()
- && !zSlot->zStack()->zItem()->canBeStackedWith(zItems->zItem()))
- return;
- bool needUpdate = !zSlot->zStack();
- int number = MIN(
- zSlot->numberOfAddableItems(zItems->zItem(), dir), zItems->getSize());
- int tmp = number;
- if (number > 0 && allowPushStack(zSlot, dir, zItems->zItem(), tmp))
- {
- number = MIN(number, tmp);
- ItemStack* stack = zItems->split(number);
- if (stack)
- {
- zSlot->addItems(stack, dir);
- if (needUpdate) updateCache(zSlot, -1);
- afterPushStack(zSlot, dir, zSlot->zStack()->zItem(), number);
- if (stack->getSize()) throw stack;
- stack->release();
- }
- }
- }
- ItemStack* Inventory::takeItemsOut(ItemSlot* zSlot, int count, Direction dir)
- {
- if (allowPullStack(zSlot, dir))
- {
- ItemStack* stack = zSlot->takeItemsOut(count, dir);
- if (stack)
- {
- updateCache(zSlot, stack->zItem()->zItemType()->getId());
- if (stack->getSize() > 0)
- afterPullStack(zSlot, dir, stack->zItem(), stack->getSize());
- }
- return stack;
- }
- return 0;
- }
- InventoryInteraction Inventory::interactWith(
- Inventory* zInventory, Direction dir)
- {
- return InventoryInteraction(this, zInventory, dir);
- }
- void Inventory::unsaveAddItem(
- ItemStack* zStack, Direction dir, ItemFilter* zFilter)
- {
- addItems(zStack, dir, zFilter);
- }
- int Inventory::numberOfAddableItems(const Item* zItem, Direction dir) const
- {
- int count = 0;
- for (auto targetSlot = pushSlotsOrder->begin(); targetSlot; targetSlot++)
- {
- int maxCount = targetSlot->numberOfAddableItems(zItem, dir);
- int allowed = maxCount;
- if (allowPushStack(targetSlot, dir, zItem, allowed))
- count += MIN(maxCount, allowed);
- }
- return count;
- }
- int Inventory::numberOfAddableItems(
- const Item* zItem, Direction dir, const Framework::Text& slotName) const
- {
- int count = 0;
- for (auto targetSlot = pushSlotsOrder->begin(); targetSlot; targetSlot++)
- {
- if (targetSlot->getName().istGleich(slotName))
- {
- int maxCount = targetSlot->numberOfAddableItems(zItem, dir);
- int allowed = maxCount;
- if (allowPushStack(targetSlot, dir, zItem, allowed))
- count += MIN(maxCount, allowed);
- }
- }
- return count;
- }
- bool Inventory::isAllAvailable(Framework::RCArray<RecipieInput>& inputs,
- const Framework::Text& slotName) const
- {
- int* used = new int[pullSlotsOrder->getEintragAnzahl()];
- memset(used, 0, sizeof(int) * pullSlotsOrder->getEintragAnzahl());
- for (RecipieInput* input : inputs)
- {
- int found = 0;
- for (int i = 0; i < pullSlotsOrder->getEintragAnzahl(); i++)
- {
- ItemSlot* slot = pullSlotsOrder->get(i);
- if (slot && slot->zStack() && slot->zStack()->zItem()
- && slot->getNumberOfItems() > used[i]
- && slot->getName().istGleich(slotName)
- && input->zFilter()->matchItem(slot->zStack()->zItem()))
- {
- int usable = slot->getNumberOfItems() - used[i];
- if (found + usable >= input->getAmount())
- {
- used[i] += input->getAmount() - found;
- found = input->getAmount();
- break;
- }
- else
- {
- used[i] += usable;
- found += usable;
- }
- }
- }
- if (found < input->getAmount())
- {
- delete[] used;
- return 0;
- }
- }
- delete[] used;
- return 1;
- }
- void Inventory::consume(
- Framework::RCArray<RecipieInput>& inputs, const Framework::Text& slotName)
- {
- for (RecipieInput* input : inputs)
- {
- int consumed = 0;
- for (int i = 0; i < pullSlotsOrder->getEintragAnzahl(); i++)
- {
- ItemSlot* slot = pullSlotsOrder->get(i);
- if (slot && slot->zStack() && slot->zStack()->zItem()
- && slot->getName().istGleich(slotName)
- && input->zFilter()->matchItem(slot->zStack()->zItem()))
- {
- if (consumed + slot->getNumberOfItems() >= input->getAmount())
- {
- takeItemsOut(
- slot, input->getAmount() - consumed, NO_DIRECTION)
- ->release();
- consumed = input->getAmount();
- break;
- }
- else
- {
- consumed += slot->getNumberOfItems();
- takeItemsOut(slot, slot->getNumberOfItems(), NO_DIRECTION)
- ->release();
- }
- }
- }
- }
- }
- Framework::ArrayIterator<ItemSlot*> Inventory::begin()
- {
- return pullSlotsOrder->begin();
- }
- Framework::ArrayIterator<ItemSlot*> Inventory::end()
- {
- return pullSlotsOrder->end();
- }
- void Inventory::inventoryApi(Framework::StreamReader* zRequest,
- NetworkMessage* zResponse,
- Entity* zSource)
- {
- char type;
- zRequest->lese(&type, 1);
- switch (type)
- {
- case 0: // request inventory
- {
- char idLen;
- zRequest->lese(&idLen, 1);
- char* id = new char[idLen + 1];
- zRequest->lese(id, idLen);
- id[(int)idLen] = 0;
- int processor;
- zRequest->lese((char*)&processor, 4);
- zResponse->addressUIElement(id, processor);
- observable.addObserver(zSource, id, processor);
- delete[] id;
- char filterLen;
- zRequest->lese(&filterLen, 1);
- char* filter = new char[filterLen + 1];
- if (filterLen) zRequest->lese(filter, filterLen);
- filter[(int)filterLen] = 0;
- InMemoryBuffer buffer;
- int count = 0;
- for (ItemSlot* slot : *this)
- {
- if (filterLen == 0 || slot->getName().istGleich(filter))
- {
- count++;
- int id = slot->getId();
- buffer.schreibe((char*)&id, 4);
- int itemCount = slot->getNumberOfItems();
- buffer.schreibe((char*)&itemCount, 4);
- if (itemCount > 0)
- {
- float f = slot->zStack()->zItem()->getHp();
- buffer.schreibe((char*)&f, 4);
- f = slot->zStack()->zItem()->getMaxHp();
- buffer.schreibe((char*)&f, 4);
- f = slot->zStack()->zItem()->getDurability();
- buffer.schreibe((char*)&f, 4);
- f = slot->zStack()->zItem()->getMaxDurability();
- buffer.schreibe((char*)&f, 4);
- int id = slot->zStack()->zItem()->zItemType()->getId();
- buffer.schreibe((char*)&id, 4);
- char len = (char)slot->zStack()
- ->zItem()
- ->getName()
- .getLength();
- buffer.schreibe((char*)&len, 1);
- buffer.schreibe(
- slot->zStack()->zItem()->getName().getText(),
- slot->zStack()->zItem()->getName().getLength());
- }
- }
- }
- delete[] filter;
- char* msg = new char[5 + buffer.getSize()];
- msg[0] = 0;
- *(int*)(msg + 1) = count;
- buffer.lese(msg + 5, (int)buffer.getSize());
- zResponse->setMessage(msg, 5 + (int)buffer.getSize());
- break;
- }
- case 1: // remove Observer
- {
- char idLen;
- zRequest->lese(&idLen, 1);
- char* id = new char[idLen + 1];
- zRequest->lese(id, idLen);
- id[(int)idLen] = 0;
- int processor;
- zRequest->lese((char*)&processor, 4);
- observable.removeObserver(zSource, id, processor);
- delete[] id;
- break;
- }
- case 2: // request item tooltip
- {
- char idLen;
- zRequest->lese(&idLen, 1);
- char* id = new char[idLen + 1];
- zRequest->lese(id, idLen);
- id[(int)idLen] = 0;
- int processor;
- zRequest->lese((char*)&processor, 4);
- zResponse->addressUIElement(id, processor);
- delete[] id;
- int slotId;
- zRequest->lese((char*)&slotId, 4);
- Text uiml;
- for (ItemSlot* slot : *pullSlotsOrder)
- {
- if (slot->getId() == slotId)
- {
- if (slot->zStack() && slot->zStack()->zItem())
- {
- Framework::XML::Element* element
- = slot->zStack()
- ->zItem()
- ->getTooltipUIML()
- ->build();
- uiml = element->toString();
- element->release();
- }
- }
- }
- short len = (short)uiml.getLength();
- char* buffer = new char[uiml.getLength() + 7];
- buffer[0] = 3;
- *(int*)(buffer + 1) = slotId;
- *(short*)(buffer + 5) = len;
- memcpy(buffer + 7, uiml, len);
- zResponse->setMessage(buffer, len + 7);
- break;
- }
- }
- }
- void Inventory::registerAfterPullStackCall(std::function<void(
- ItemSlot* zSlot, Direction dir, const Item* zItem, int count)> call)
- {
- afterPullStackCalls.add(call);
- }
- void Inventory::registerAfterPushStackCall(std::function<void(
- ItemSlot* zSlot, Direction dir, const Item* zItem, int count)> call)
- {
- afterPushStackCalls.add(call);
- }
- void Inventory::registerObserverAddedCall(
- std::function<void(Entity* zSource, Framework::Text id, int processor)>
- call)
- {
- observable.registerOnObserverAddedCall(call);
- }
- int Inventory::getDimensionId() const
- {
- return dimensionId;
- }
- Framework::Vec3<float> Inventory::getLocation() const
- {
- return location;
- }
- bool Inventory::unsafeMove(Inventory* zSource,
- Inventory* zTarget,
- ArrayIterator<ItemSlot*>& sourceSlot,
- ArrayIterator<ItemSlot*>& targetSlot,
- Direction outDir,
- Direction inDir,
- int& count)
- {
- if (targetSlot->zStack())
- {
- if (sourceSlot->zStack()->zItem()->canBeStackedWith(
- targetSlot->zStack()->zItem()))
- {
- int number = MIN(targetSlot->numberOfAddableItems(
- sourceSlot->zStack()->zItem(), outDir),
- count);
- int tmp = number;
- if (number > 0 && zSource->allowPullStack(sourceSlot, outDir)
- && zTarget->allowPushStack(
- targetSlot, inDir, sourceSlot->zStack()->zItem(), tmp))
- {
- number = MIN(number, tmp);
- ItemStack* stack = sourceSlot->takeItemsOut(number, outDir);
- if (stack)
- {
- targetSlot->addItems(stack, inDir);
- zSource->updateCache(sourceSlot,
- targetSlot->zStack()->zItem()->zItemType()->getId());
- zSource->afterPullStack(sourceSlot,
- outDir,
- targetSlot->zStack()->zItem(),
- number);
- zTarget->afterPushStack(targetSlot,
- inDir,
- targetSlot->zStack()->zItem(),
- number);
- if (stack->getSize()) throw stack;
- stack->release();
- count -= number;
- return 1;
- }
- else
- targetSlot++;
- }
- else
- targetSlot++;
- }
- else
- targetSlot++;
- }
- else
- {
- int number = MIN(targetSlot->numberOfAddableItems(
- sourceSlot->zStack()->zItem(), outDir),
- count);
- int tmp = number;
- if (number > 0 && zSource->allowPullStack(sourceSlot, outDir)
- && zTarget->allowPushStack(
- targetSlot, inDir, sourceSlot->zStack()->zItem(), tmp))
- {
- number = MIN(number, tmp);
- if (number > 0)
- {
- ItemStack* stack = sourceSlot->takeItemsOut(number, outDir);
- if (stack)
- {
- targetSlot->addItems(stack, inDir);
- zSource->updateCache(sourceSlot,
- targetSlot->zStack()->zItem()->zItemType()->getId());
- zTarget->updateCache(targetSlot, -1);
- zSource->afterPullStack(sourceSlot,
- outDir,
- targetSlot->zStack()->zItem(),
- number);
- zTarget->afterPushStack(targetSlot,
- inDir,
- targetSlot->zStack()->zItem(),
- number);
- if (stack->getSize()) throw stack;
- stack->release();
- count -= number;
- return 1;
- }
- else
- targetSlot++;
- }
- else
- targetSlot++;
- }
- else
- targetSlot++;
- }
- return 0;
- }
|