Kaynağa Gözat

players con now move items from one inventory slot to another slot

Kolja Strohm 2 yıl önce
ebeveyn
işleme
86296fb435

+ 2 - 2
FactoryCraft/Block.cpp

@@ -239,9 +239,9 @@ BasicBlockItem::BasicBlockItem(const ItemType* zType, const BlockType* zPlacedBl
 	zBlockType = zPlacedBlockType;
 }
 
-bool BasicBlockItem::canBeStackedWith(Item* zItem) const
+bool BasicBlockItem::canBeStackedWith(const Item* zItem) const
 {
-	BasicBlockItem* item = dynamic_cast<BasicBlockItem*>(zItem);
+	const BasicBlockItem* item = dynamic_cast<const BasicBlockItem*>(zItem);
 	if (item)
 	{
 		return Item::canBeStackedWith(zItem) &&

+ 1 - 1
FactoryCraft/Block.h

@@ -107,7 +107,7 @@ protected:
 
 public:
 	BasicBlockItem(const ItemType* zType, const BlockType* zPlacedBlockType, const char* name);
-	virtual bool canBeStackedWith(Item* zItem) const override;
+	virtual bool canBeStackedWith(const Item* zItem) const override;
 
 	friend BasicBlockItemType;
 	friend BlockType;

+ 1 - 55
FactoryCraft/Entity.cpp

@@ -428,61 +428,7 @@ void Entity::tick(const Dimension* zDimension)
 }
 
 void Entity::api(Framework::StreamReader* zRequest, NetworkMessage* zResponse)
-{
-	char type;
-	zRequest->lese(&type, 1);
-	switch (type)
-	{
-	case 100: // 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);
-		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;
-	}
-	}
-}
+{}
 
 void Entity::onFall(float collisionSpeed)
 {

+ 35 - 0
FactoryCraft/Game.cpp

@@ -386,6 +386,30 @@ void Game::api(Framework::StreamReader* zRequest, GameClient* zOrigin)
 		}
 		break;
 	}
+	case 4:
+	{ // inventory
+		bool isEntity;
+		zRequest->lese((char*)&isEntity, 1);
+		Inventory* target;
+		if (isEntity)
+		{
+			int id;
+			zRequest->lese((char*)&id, 4);
+			target = zEntity(id);
+		}
+		else
+		{
+			int dim;
+			Vec3<int> pos;
+			zRequest->lese((char*)&dim, 4);
+			zRequest->lese((char*)&pos.x, 4);
+			zRequest->lese((char*)&pos.y, 4);
+			zRequest->lese((char*)&pos.z, 4);
+			target = zBlockAt(pos, dim);
+		}
+		if (target)
+			target->inventoryApi(zRequest, &response, zOrigin->zEntity());
+	}
 	default:
 		std::cout << "received unknown api request in game with type " << (int)type << "\n";
 	}
@@ -599,6 +623,17 @@ Entity* Game::zEntity(int id, int dimensionId) const
 	return 0;
 }
 
+Entity* Game::zEntity(int id) const
+{
+	for (Dimension* d : *dimensions)
+	{
+		Entity* e = d->zEntity(id);
+		if (e)
+			return e;
+	}
+	return 0;
+}
+
 Entity* Game::zNearestEntity(int dimensionId, Framework::Vec3<float> pos, std::function<bool(Entity*)> filter)
 {
 	Dimension* d = zDimension(dimensionId);

+ 1 - 0
FactoryCraft/Game.h

@@ -102,6 +102,7 @@ public:
 	int getNextEntityId();
 	WorldGenerator* zGenerator() const;
 	Entity* zEntity(int id, int dimensionId) const;
+	Entity* zEntity(int id) const;
 	Entity* zNearestEntity(int dimensionId, Framework::Vec3<float> pos, std::function<bool(Entity*)> filter);
 
 	static Game* INSTANCE;

+ 202 - 45
FactoryCraft/Inventory.cpp

@@ -1,7 +1,13 @@
+#include <InMemoryBuffer.h>
+
 #include "Inventory.h"
 #include "ItemFilter.h"
 #include "Constants.h"
 #include "Area.h"
+#include "NetworkMessage.h"
+#include "Entity.h"
+#include "Game.h"
+
 
 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)
 {
-	// 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())
 			{
-				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
 			{
-				while (sourceSlot && (!sourceSlot->zStack() || (zFilter && !zFilter->matchItem(sourceSlot->zStack()->zItem()))))
-					sourceSlot++;
-				if (!sourceSlot)
-					return;
 				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))
@@ -161,12 +159,18 @@ void InventoryInteraction::transaction(Inventory* zSource, Inventory* zTarget, I
 							if (count == 0)
 								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)
-{}
+{
+	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)
-{}
+{
+	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)
 {
@@ -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)
 {
 	if (itemCache)
@@ -501,7 +591,7 @@ ItemStack* Inventory::takeItemsOut(ItemSlot* zSlot, int count, Direction dir)
 		if (stack)
 		{
 			updateCache(zSlot, stack->zItem()->zItemType()->getId());
-			if(stack->getSize() > 0)
+			if (stack->getSize() > 0)
 				afterPullStack(zSlot, dir, stack->zItem(), stack->getSize());
 		}
 		return stack;
@@ -540,4 +630,71 @@ Framework::Iterator<ItemSlot*> Inventory::begin()
 Framework::Iterator<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;
+		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;
+	}
 }

+ 8 - 1
FactoryCraft/Inventory.h

@@ -4,12 +4,15 @@
 #include <ReferenceCounter.h>
 #include <HashMap.h>
 #include <Critical.h>
+#include <ImmutablePair.h>
 
 #include "ItemSlot.h"
 #include "Area.h"
 
 class ItemFilter;
 class Inventory;
+class NetworkMessage;
+class Entity;
 
 class InventoryInteraction
 {
@@ -34,6 +37,7 @@ public:
 class Inventory : public virtual Framework::ReferenceCounter
 {
 private:
+	Framework::Array<Framework::ImmutablePair<int, Framework::Text>> observers;
 	Framework::RCArray<ItemSlot>* pullSlotsOrder;
 	Framework::RCArray<ItemSlot>* pushSlotsOrder;
 	Framework::HashMap<int, Framework::Array<ItemSlot*>*>* itemCache;
@@ -51,11 +55,13 @@ protected:
 	virtual void afterPushStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int count);
 	virtual void loadInventory(Framework::StreamReader* zReader);
 	virtual void saveInventory(Framework::StreamWriter* zWriter);
-	ItemSlot* zSlot(int id);
+	void notyObservers(NetworkMessage& msg);
+	void removeObserver(Entity* zSource, Framework::Text id);
 
 public:
 	Inventory(const Framework::Vec3<float> location, bool hasInventory);
 	virtual ~Inventory();
+	const ItemSlot* zSlot(int id) const;
 	void addSlot(ItemSlot* slot);
 	void localTransaction(Framework::Array< ItemSlot* >* zSourceSlots, Framework::Array< ItemSlot* >* zTargetSlots, ItemFilter* zFilter, int count, Direction outDir, Direction inDir);
 	ItemStack* takeItemsOut(ItemSlot* zSlot, int count, Direction dir);
@@ -65,6 +71,7 @@ public:
 	int numberOfAddableItems(const ItemStack* zStack, Direction dir) const;
 	Framework::Iterator<ItemSlot*> begin();
 	Framework::Iterator<ItemSlot*> end();
+	void inventoryApi(Framework::StreamReader* zRequest, NetworkMessage* zResponse, Entity* zSource);
 
 	friend InventoryInteraction;
 };

+ 1 - 1
FactoryCraft/Item.cpp

@@ -81,7 +81,7 @@ float Item::getMaxDamage() const
 	return maxDamage;
 }
 
-bool Item::canBeStackedWith(Item* zItem) const
+bool Item::canBeStackedWith(const Item* zItem) const
 {
 	return zType == zItem->zType && damage == 0 &&
 		zItem->damage == 0 &&

+ 1 - 1
FactoryCraft/Item.h

@@ -40,7 +40,7 @@ public:
 	float getMaxDurability() const;
 	int getMaxStackSize() const;
 	float getMaxDamage() const;
-	virtual bool canBeStackedWith(Item* zItem) const;
+	virtual bool canBeStackedWith(const Item* zItem) const;
 	virtual void onPlaced();
 
 	virtual void applyInventoryEffects(Entity* zTarget);

+ 33 - 0
FactoryCraft/ItemFilter.cpp

@@ -1,12 +1,28 @@
 #include "ItemFilter.h"
 #include "ItemType.h"
 #include "Item.h"
+#include "ItemSlot.h"
 
 
 ItemFilter::ItemFilter()
 	: ReferenceCounter()
 {}
 
+bool ItemFilter::matchItem(const Item* zItem) const
+{
+	return 1;
+}
+
+bool ItemFilter::matchSourceSlot(ItemSlot* zSlot) const
+{
+	return zSlot->zStack() ? matchItem(zSlot->zStack()->zItem()) : 0;
+}
+
+bool ItemFilter::matchTargetSlot(ItemSlot* zSlot) const
+{
+	return 1;
+}
+
 
 CombinedItemFilter::CombinedItemFilter(ItemFilter* filterA, ItemFilter* filterB, std::function<bool(bool, bool)> op)
 	: ItemFilter(),
@@ -39,4 +55,21 @@ TypeItemFilter::TypeItemFilter(const ItemType* zType)
 bool TypeItemFilter::matchItem(const Item* zItem) const
 {
 	return zItem->zItemType() == zType;
+}
+
+
+SpecificSlotFilter::SpecificSlotFilter(int sourceSlotId, int targetSlotId)
+	: ItemFilter(),
+	sourceSlotId(sourceSlotId),
+	targetSlotId(targetSlotId)
+{}
+
+bool SpecificSlotFilter::matchSourceSlot(ItemSlot* zSlot) const
+{
+	return sourceSlotId == zSlot->getId();
+}
+
+bool SpecificSlotFilter::matchTargetSlot(ItemSlot* zSlot) const
+{
+	return targetSlotId == zSlot->getId();
 }

+ 18 - 1
FactoryCraft/ItemFilter.h

@@ -5,12 +5,15 @@
 
 class Item;
 class ItemType;
+class ItemSlot;
 
 class ItemFilter : public virtual Framework::ReferenceCounter
 {
 public:
 	ItemFilter();
-	virtual bool matchItem(const Item* zItem) const = 0;
+	virtual bool matchItem(const Item* zItem) const;
+	virtual bool matchSourceSlot(ItemSlot* zSlot) const;
+	virtual bool matchTargetSlot(ItemSlot* zSlot) const;
 };
 
 class CombinedItemFilter : public ItemFilter
@@ -42,3 +45,17 @@ public:
 	bool matchItem(const Item* zItem) const override;
 };
 
+
+class SpecificSlotFilter : public ItemFilter
+{
+private:
+	int sourceSlotId;
+	int targetSlotId;
+
+public:
+	SpecificSlotFilter(int sourceSlotId, int targetSlotId);
+	bool matchSourceSlot(ItemSlot* zSlot) const override;
+	bool matchTargetSlot(ItemSlot* zSlot) const override;
+};
+
+

+ 7 - 0
FactoryCraft/NetworkMessage.cpp

@@ -30,6 +30,7 @@ NetworkMessage::~NetworkMessage()
 
 void NetworkMessage::adressChunck(Chunk* zChunk)
 {
+	delete[] adress;
 	adressLength = 10;
 	adress = new char[adressLength];
 	adress[0] = 1; // dimension response
@@ -44,6 +45,7 @@ void NetworkMessage::adressChunck(Chunk* zChunk)
 
 void NetworkMessage::adressEntity(Entity* zEntity)
 {
+	delete[] adress;
 	adressLength = 6;
 	adress = new char[adressLength];
 	adress[0] = 1; // dimension response
@@ -56,6 +58,7 @@ void NetworkMessage::adressEntity(Entity* zEntity)
 
 void NetworkMessage::adressBlock(Block* zBlock)
 {
+	delete[] adress;
 	adressLength = 14;
 	adress = new char[adressLength];
 	adress[0] = 1; // dimension response
@@ -71,6 +74,7 @@ void NetworkMessage::adressBlock(Block* zBlock)
 
 void NetworkMessage::openDialog(Framework::Text dialogName)
 {
+	delete[] adress;
 	adressLength = (char)(4 + dialogName.getLength());
 	adress = new char[adressLength];
 	adress[0] = 2; // gui message
@@ -81,6 +85,7 @@ void NetworkMessage::openDialog(Framework::Text dialogName)
 
 void NetworkMessage::adressGui(Framework::Text elementId)
 {
+	delete[] adress;
 	adressLength = (char)(4 + elementId.getLength());
 	adress = new char[adressLength];
 	adress[0] = 2; // gui message
@@ -91,6 +96,8 @@ void NetworkMessage::adressGui(Framework::Text elementId)
 
 void NetworkMessage::setMessage(char* msg, int length, bool deleteMsg)
 {
+	if (msgDelete)
+		delete[] message;
 	message = msg;
 	msgLength = length;
 	msgDelete = deleteMsg;

+ 50 - 58
FactoryCraft/Player.cpp

@@ -33,64 +33,6 @@ Player::Player(Framework::Vec3<float> location, int dimensionId, int entityId)
 	targetDistanceLimit = 4;
 }
 
-void Player::afterPullStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int count)
-{
-	for (auto slot : itemBar)
-	{
-		if (slot == zSlot)
-		{
-			NetworkMessage msg;
-			msg.adressGui("gui_item_bar");
-			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);
-			Game::INSTANCE->sendMessage(&msg, this);
-			return;
-		}
-	}
-}
-
-void Player::afterPushStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int count)
-{
-	for (auto slot : itemBar)
-	{
-		if (slot == zSlot)
-		{
-			if (zSlot->getNumberOfItems() > count)
-			{
-				NetworkMessage msg;
-				msg.adressGui("gui_item_bar");
-				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);
-				Game::INSTANCE->sendMessage(&msg, this);
-			}
-			else
-			{
-				NetworkMessage msg;
-				msg.adressGui("gui_item_bar");
-				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);
-				Game::INSTANCE->sendMessage(&msg, this);
-			}
-			return;
-		}
-	}
-}
-
 void Player::onTargetChange()
 {
 	NetworkMessage msg;
@@ -386,6 +328,56 @@ void Player::playerApi(Framework::StreamReader* zRequest, NetworkMessage* zRespo
 		zResponse->setMessage(msg, msgSize, 1);
 		break;
 	}
+	case 6:
+	{ // inventory transaction
+		bool isEntity;
+		zRequest->lese((char*)&isEntity, 1);
+		Inventory* source;
+		if (isEntity)
+		{
+			int id;
+			zRequest->lese((char*)&id, 4);
+			source = Game::INSTANCE->zEntity(id, getCurrentDimensionId());
+		}
+		else
+		{
+			int dim;
+			Framework::Vec3<int> pos;
+			zRequest->lese((char*)&dim, 4);
+			zRequest->lese((char*)&pos.x, 4);
+			zRequest->lese((char*)&pos.y, 4);
+			zRequest->lese((char*)&pos.z, 4);
+			source = Game::INSTANCE->zBlockAt(pos, dim);
+		}
+		int sourceSlotId;
+		zRequest->lese((char*)&sourceSlotId, 4);
+		zRequest->lese((char*)&isEntity, 1);
+		Inventory* target;
+		if (isEntity)
+		{
+			int id;
+			zRequest->lese((char*)&id, 4);
+			target = Game::INSTANCE->zEntity(id, getCurrentDimensionId());
+		}
+		else
+		{
+			int dim;
+			Framework::Vec3<int> pos;
+			zRequest->lese((char*)&dim, 4);
+			zRequest->lese((char*)&pos.x, 4);
+			zRequest->lese((char*)&pos.y, 4);
+			zRequest->lese((char*)&pos.z, 4);
+			target = Game::INSTANCE->zBlockAt(pos, dim);
+		}
+		if (source && target)
+		{
+			int targetSlotId;
+			zRequest->lese((char*)&targetSlotId, 4);
+			SpecificSlotFilter filter(sourceSlotId, targetSlotId);
+			source->interactWith(target, Direction::NO_DIRECTION).pushItems(source->zSlot(sourceSlotId)->getNumberOfItems(), &filter);
+		}
+		break;
+	}
 	}
 }
 

+ 0 - 2
FactoryCraft/Player.h

@@ -36,8 +36,6 @@ private:
 	void useItemSlot(ItemSlot* zSlot);
 	Player(Framework::Vec3<float> location, int dimensionId, int entityId);
 
-	virtual void afterPullStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int count) override;
-	virtual void afterPushStack(ItemSlot* zSlot, Direction dir, const Item* zItem, int count) override;
 	virtual void onTargetChange() override;
 	Framework::Text getInventoryUIML();
 	Framework::Text getPlayerGUI();