|
@@ -1,7 +1,13 @@
|
|
|
|
+#include <InMemoryBuffer.h>
|
|
|
|
+
|
|
#include "Inventory.h"
|
|
#include "Inventory.h"
|
|
#include "ItemFilter.h"
|
|
#include "ItemFilter.h"
|
|
#include "Constants.h"
|
|
#include "Constants.h"
|
|
#include "Area.h"
|
|
#include "Area.h"
|
|
|
|
+#include "NetworkMessage.h"
|
|
|
|
+#include "Entity.h"
|
|
|
|
+#include "Game.h"
|
|
|
|
+
|
|
|
|
|
|
using namespace Framework;
|
|
using namespace Framework;
|
|
|
|
|
|
@@ -86,59 +92,51 @@ void InventoryInteraction::unlock()
|
|
|
|
|
|
void InventoryInteraction::transaction(Inventory* zSource, Inventory* zTarget, ItemFilter* zFilter, Direction sourceView, Direction targetView, int count)
|
|
void InventoryInteraction::transaction(Inventory* zSource, Inventory* zTarget, ItemFilter* zFilter, Direction sourceView, Direction targetView, int count)
|
|
{
|
|
{
|
|
- // TODO: rewrite this such that for each source slot all target slots are looped trough
|
|
|
|
- auto sourceSlot = zSource->pullSlotsOrder->begin();
|
|
|
|
- for (auto targetSlot = zTarget->pushSlotsOrder->begin(); targetSlot; )
|
|
|
|
|
|
+ for (auto sourceSlot = zSource->pullSlotsOrder->begin(); sourceSlot; )
|
|
{
|
|
{
|
|
- int amount = count;
|
|
|
|
- if (!targetSlot->isFull())
|
|
|
|
|
|
+ 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
|
|
|
|
+ for (auto targetSlot = zTarget->pushSlotsOrder->begin(); targetSlot; )
|
|
{
|
|
{
|
|
|
|
+ while (targetSlot && (targetSlot->isFull() || (zFilter && !zFilter->matchTargetSlot(targetSlot))))
|
|
|
|
+ targetSlot++;
|
|
|
|
+ if (!targetSlot) break;
|
|
if (targetSlot->zStack())
|
|
if (targetSlot->zStack())
|
|
{
|
|
{
|
|
- Array<ItemSlot*>* zSurceListe = zSource->itemCache->safeGet(targetSlot->zStack()->zItem()->zItemType()->getId(), 0);
|
|
|
|
- if (zSurceListe)
|
|
|
|
|
|
+ if (sourceSlot->zStack()->zItem()->canBeStackedWith(targetSlot->zStack()->zItem()))
|
|
{
|
|
{
|
|
- Array<int> toDelete;
|
|
|
|
- int index = 0;
|
|
|
|
- for (auto sourceSlot = zSurceListe->begin(); sourceSlot; sourceSlot++, index++)
|
|
|
|
|
|
+ int number = MIN(targetSlot->numberOfAddableItems(sourceSlot->zStack(), sourceView), count);
|
|
|
|
+ int tmp = number;
|
|
|
|
+ if (number > 0 && zSource->allowPullStack(sourceSlot, sourceView) && zTarget->allowPushStack(targetSlot, targetView, sourceSlot->zStack()->zItem(), tmp))
|
|
{
|
|
{
|
|
- if (zFilter && !zFilter->matchItem(sourceSlot->zStack()->zItem()))
|
|
|
|
- continue;
|
|
|
|
- int number = MIN(targetSlot->numberOfAddableItems(sourceSlot->zStack(), sourceView), count);
|
|
|
|
- int tmp = number;
|
|
|
|
- if (number > 0 && zSource->allowPullStack(sourceSlot, sourceView) && zTarget->allowPushStack(targetSlot, targetView, sourceSlot->zStack()->zItem(), tmp))
|
|
|
|
|
|
+ number = MIN(number, tmp);
|
|
|
|
+ ItemStack* stack = sourceSlot->takeItemsOut(number, dir);
|
|
|
|
+ if (stack)
|
|
{
|
|
{
|
|
- number = MIN(number, tmp);
|
|
|
|
- ItemStack* stack = sourceSlot->takeItemsOut(number, dir);
|
|
|
|
- if (stack)
|
|
|
|
- {
|
|
|
|
- if (!sourceSlot->zStack())
|
|
|
|
- toDelete.add(index, 0);
|
|
|
|
- targetSlot->addItems(stack, dir);
|
|
|
|
- zSource->updateCache(sourceSlot, targetSlot->zStack()->zItem()->zItemType()->getId());
|
|
|
|
- zSource->afterPullStack(sourceSlot, sourceView, targetSlot->zStack()->zItem(), number);
|
|
|
|
- zTarget->afterPushStack(targetSlot, targetView, targetSlot->zStack()->zItem(), number);
|
|
|
|
- if (stack->getSize())
|
|
|
|
- throw stack;
|
|
|
|
- stack->release();
|
|
|
|
- count -= number;
|
|
|
|
- if (count == 0)
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
|
|
+ targetSlot->addItems(stack, dir);
|
|
|
|
+ zSource->updateCache(sourceSlot, targetSlot->zStack()->zItem()->zItemType()->getId());
|
|
|
|
+ zSource->afterPullStack(sourceSlot, sourceView, targetSlot->zStack()->zItem(), number);
|
|
|
|
+ zTarget->afterPushStack(targetSlot, targetView, targetSlot->zStack()->zItem(), number);
|
|
|
|
+ if (stack->getSize())
|
|
|
|
+ throw stack;
|
|
|
|
+ stack->release();
|
|
|
|
+ count -= number;
|
|
|
|
+ if (count == 0)
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
|
|
+ else
|
|
|
|
+ targetSlot++;
|
|
}
|
|
}
|
|
- for (auto indexToDelete = toDelete.begin(); indexToDelete; indexToDelete++)
|
|
|
|
- zSurceListe->remove(indexToDelete);
|
|
|
|
- if (count == 0)
|
|
|
|
- return;
|
|
|
|
|
|
+ else
|
|
|
|
+ targetSlot++;
|
|
}
|
|
}
|
|
|
|
+ else
|
|
|
|
+ targetSlot++;
|
|
}
|
|
}
|
|
else
|
|
else
|
|
{
|
|
{
|
|
- while (sourceSlot && (!sourceSlot->zStack() || (zFilter && !zFilter->matchItem(sourceSlot->zStack()->zItem()))))
|
|
|
|
- sourceSlot++;
|
|
|
|
- if (!sourceSlot)
|
|
|
|
- return;
|
|
|
|
int number = MIN(targetSlot->numberOfAddableItems(sourceSlot->zStack(), sourceView), count);
|
|
int number = MIN(targetSlot->numberOfAddableItems(sourceSlot->zStack(), sourceView), count);
|
|
int tmp = number;
|
|
int tmp = number;
|
|
if (number > 0 && zSource->allowPullStack(sourceSlot, sourceView) && zTarget->allowPushStack(targetSlot, targetView, sourceSlot->zStack()->zItem(), tmp))
|
|
if (number > 0 && zSource->allowPullStack(sourceSlot, sourceView) && zTarget->allowPushStack(targetSlot, targetView, sourceSlot->zStack()->zItem(), tmp))
|
|
@@ -161,12 +159,18 @@ void InventoryInteraction::transaction(Inventory* zSource, Inventory* zTarget, I
|
|
if (count == 0)
|
|
if (count == 0)
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
+ else
|
|
|
|
+ targetSlot++;
|
|
}
|
|
}
|
|
|
|
+ else
|
|
|
|
+ targetSlot++;
|
|
}
|
|
}
|
|
|
|
+ else
|
|
|
|
+ targetSlot++;
|
|
}
|
|
}
|
|
|
|
+ if (sourceSlot->getNumberOfItems() == 0)
|
|
|
|
+ break;
|
|
}
|
|
}
|
|
- if (amount == count || targetSlot->isFull())
|
|
|
|
- targetSlot++;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -293,10 +297,45 @@ bool Inventory::allowPushStack(ItemSlot* zSlot, Direction dir, const Item* zItem
|
|
}
|
|
}
|
|
|
|
|
|
void Inventory::afterPullStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int count)
|
|
void Inventory::afterPullStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int count)
|
|
-{}
|
|
|
|
|
|
+{
|
|
|
|
+ NetworkMessage msg;
|
|
|
|
+ char message[9];
|
|
|
|
+ message[0] = 1; // set count of items
|
|
|
|
+ *(int*)(message + 1) = zSlot->getId();
|
|
|
|
+ *(int*)(message + 5) = zSlot->getNumberOfItems();
|
|
|
|
+ msg.setMessage(message, 9, 0);
|
|
|
|
+ notyObservers(msg);
|
|
|
|
+}
|
|
|
|
|
|
void Inventory::afterPushStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int count)
|
|
void Inventory::afterPushStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int count)
|
|
-{}
|
|
|
|
|
|
+{
|
|
|
|
+ if (zSlot->getNumberOfItems() > count)
|
|
|
|
+ {
|
|
|
|
+ NetworkMessage msg;
|
|
|
|
+ char message[9];
|
|
|
|
+ message[0] = 1; // set count of items
|
|
|
|
+ *(int*)(message + 1) = zSlot->getId();
|
|
|
|
+ *(int*)(message + 5) = zSlot->getNumberOfItems();
|
|
|
|
+ msg.setMessage(message, 9, 0);
|
|
|
|
+ notyObservers(msg);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ {
|
|
|
|
+ NetworkMessage msg;
|
|
|
|
+ char message[29];
|
|
|
|
+ message[0] = 2; // add new stack
|
|
|
|
+ *(int*)(message + 1) = zSlot->getId();
|
|
|
|
+ *(int*)(message + 5) = zSlot->getNumberOfItems();
|
|
|
|
+ const Item* zItem = zSlot->zStack()->zItem();
|
|
|
|
+ *(float*)(message + 9) = zItem->getDamage();
|
|
|
|
+ *(float*)(message + 13) = zItem->getMaxDamage();
|
|
|
|
+ *(float*)(message + 17) = zItem->getDurability();
|
|
|
|
+ *(float*)(message + 21) = zItem->getMaxDurability();
|
|
|
|
+ *(int*)(message + 25) = zItem->zItemType()->getId();
|
|
|
|
+ msg.setMessage(message, 29, 0);
|
|
|
|
+ notyObservers(msg);
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
|
|
void Inventory::loadInventory(Framework::StreamReader* zReader)
|
|
void Inventory::loadInventory(Framework::StreamReader* zReader)
|
|
{
|
|
{
|
|
@@ -341,6 +380,57 @@ void Inventory::saveInventory(Framework::StreamWriter* zWriter)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+void Inventory::notyObservers(NetworkMessage& msg)
|
|
|
|
+{
|
|
|
|
+ cs.lock();
|
|
|
|
+ int index = 0;
|
|
|
|
+ Array<int> toDelete;
|
|
|
|
+ for (auto observer : observers)
|
|
|
|
+ {
|
|
|
|
+ Entity* e = Game::INSTANCE->zEntity(observer.getFirst());
|
|
|
|
+ if (e)
|
|
|
|
+ {
|
|
|
|
+ msg.adressGui(observer.getSecond());
|
|
|
|
+ Game::INSTANCE->sendMessage(&msg, e);
|
|
|
|
+ }
|
|
|
|
+ else
|
|
|
|
+ toDelete.add(index, 0);
|
|
|
|
+ index++;
|
|
|
|
+ }
|
|
|
|
+ for (int i : toDelete)
|
|
|
|
+ observers.remove(i);
|
|
|
|
+ cs.unlock();
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void Inventory::removeObserver(Entity* zSource, Framework::Text id)
|
|
|
|
+{
|
|
|
|
+ cs.lock();
|
|
|
|
+ int index = 0;
|
|
|
|
+ for (auto observer : observers)
|
|
|
|
+ {
|
|
|
|
+ if (observer.getFirst() == zSource->getId() && observer.getSecond().istGleich(id))
|
|
|
|
+ {
|
|
|
|
+ observers.remove(index);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+ index++;
|
|
|
|
+ }
|
|
|
|
+ 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)
|
|
void Inventory::localTransaction(Array< ItemSlot* >* zSourceSlots, Array< ItemSlot* >* zTargetSlots, ItemFilter* zFilter, int count, Direction outDir, Direction inDir)
|
|
{
|
|
{
|
|
if (itemCache)
|
|
if (itemCache)
|
|
@@ -501,7 +591,7 @@ ItemStack* Inventory::takeItemsOut(ItemSlot* zSlot, int count, Direction dir)
|
|
if (stack)
|
|
if (stack)
|
|
{
|
|
{
|
|
updateCache(zSlot, stack->zItem()->zItemType()->getId());
|
|
updateCache(zSlot, stack->zItem()->zItemType()->getId());
|
|
- if(stack->getSize() > 0)
|
|
|
|
|
|
+ if (stack->getSize() > 0)
|
|
afterPullStack(zSlot, dir, stack->zItem(), stack->getSize());
|
|
afterPullStack(zSlot, dir, stack->zItem(), stack->getSize());
|
|
}
|
|
}
|
|
return stack;
|
|
return stack;
|
|
@@ -540,4 +630,71 @@ Framework::Iterator<ItemSlot*> Inventory::begin()
|
|
Framework::Iterator<ItemSlot*> Inventory::end()
|
|
Framework::Iterator<ItemSlot*> Inventory::end()
|
|
{
|
|
{
|
|
return pullSlotsOrder->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;
|
|
|
|
+ zResponse->adressGui(id);
|
|
|
|
+ observers.add(ImmutablePair<int, Text>(zSource->getId(), id));
|
|
|
|
+ delete[] id;
|
|
|
|
+ char filterLen;
|
|
|
|
+ zRequest->lese(&filterLen, 1);
|
|
|
|
+ char* filter = new char[filterLen + 1];
|
|
|
|
+ zRequest->lese(filter, filterLen);
|
|
|
|
+ filter[(int)filterLen] = 0;
|
|
|
|
+ InMemoryBuffer buffer;
|
|
|
|
+ int count = 0;
|
|
|
|
+ for (ItemSlot* slot : *this)
|
|
|
|
+ {
|
|
|
|
+ if (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()->getDamage();
|
|
|
|
+ buffer.schreibe((char*)&f, 4);
|
|
|
|
+ f = slot->zStack()->zItem()->getMaxDamage();
|
|
|
|
+ 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);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ 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(), 1);
|
|
|
|
+ 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;
|
|
|
|
+ removeObserver(zSource, id);
|
|
|
|
+ delete[] id;
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
}
|
|
}
|