Ver código fonte

fix tools durability was not decreased when used

Kolja Strohm 9 meses atrás
pai
commit
b1b8def23e

+ 8 - 5
FactoryCraft/Axe.cpp

@@ -6,7 +6,7 @@ AxeToolItemType::AxeToolItemType() // TODO: add broken Axe
     : BasicToolItemType(ItemTypeEnum::AXE,
         "Axe",
         new AxeToolLevelUpRule(),
-        0,
+        ItemTypeEnum::AXE_BROKEN,
         ModelInfo("tools.m3/axe", "tools.ltdb/stoneaxe.png", 1))
 {}
 
@@ -60,7 +60,7 @@ AxeToolSkill::AxeToolSkill()
       maxXP(10.f)
 {}
 
-void AxeToolSkill::use(Entity* zActor, Item* zUsedItem, Block* zTarget)
+bool AxeToolSkill::use(Entity* zActor, Item* zUsedItem, Block* zTarget)
 {
     if (zActor->getStamina() > 0.0001f)
     {
@@ -74,17 +74,20 @@ void AxeToolSkill::use(Entity* zActor, Item* zUsedItem, Block* zTarget)
             zTarget->setHP(zTarget->getHP() - damage);
             xp += damage / 20;
             zActor->setStamina(zActor->getStamina() - 0.0001f);
-            zUsedItem->setHp(zUsedItem->getHp() - damage / 50);
+            zUsedItem->setDurability(zUsedItem->getDurability() - damage / 50);
         }
         else
         {
             zActor->setStamina(zActor->getStamina() - 0.0001f);
-            zUsedItem->setHp(zUsedItem->getHp() - 0.001f);
+            zUsedItem->setDurability(zUsedItem->getDurability() - 0.001f);
         }
+        return 1;
     }
+    return 0;
 }
 
-void AxeToolSkill::use(Entity* zActor, Item* zUsedItem, Entity* zTarget)
+bool AxeToolSkill::use(Entity* zActor, Item* zUsedItem, Entity* zTarget)
 {
     // an Axe can not be used on an entity
+    return 0;
 }

+ 2 - 2
FactoryCraft/Axe.h

@@ -34,8 +34,8 @@ private:
 
 public:
     AxeToolSkill();
-    void use(Entity* zActor, Item* zUsedItem, Block* zTarget) override;
-    void use(Entity* zActor, Item* zUsedItem, Entity* zTarget) override;
+    bool use(Entity* zActor, Item* zUsedItem, Block* zTarget) override;
+    bool use(Entity* zActor, Item* zUsedItem, Entity* zTarget) override;
 
     friend AxeToolItemType;
     friend AxeToolLevelUpRule;

+ 4 - 1
FactoryCraft/Block.cpp

@@ -187,7 +187,10 @@ void Block::sendModelInfo(NetworkMessage* zMessage)
     // overwritten by some blocks
 }
 
-void Block::interact(Item* zItem, Entity* zActor) {}
+bool Block::interact(Item* zItem, Entity* zActor)
+{
+    return false;
+}
 
 void Block::api(Framework::StreamReader* zRequest, NetworkMessage* zResponse)
 {

+ 1 - 1
FactoryCraft/Block.h

@@ -93,7 +93,7 @@ public:
     virtual void setNeighbourType(Direction dir, int type);
     virtual Framework::Text getTargetUIML();
     virtual void sendModelInfo(NetworkMessage* zMessage);
-    virtual void interact(Item* zItem, Entity *zActor);
+    virtual bool interact(Item* zItem, Entity* zActor);
     void api(Framework::StreamReader* zRequest, NetworkMessage* zResponse);
 
     bool isTickSource() const;

+ 2 - 1
FactoryCraft/Chest.cpp

@@ -70,7 +70,7 @@ bool Chest::onTick(TickQueue* zQueue, int numTicks, bool& blocked)
     return open;
 }
 
-void Chest::interact(Item* zItem, Entity* zActor)
+bool Chest::interact(Item* zItem, Entity* zActor)
 {
     lock();
     if (open)
@@ -128,6 +128,7 @@ void Chest::interact(Item* zItem, Entity* zActor)
         Game::INSTANCE->broadcastMessage(msg);
     }
     unlock();
+    return false; // item was not changed
 }
 
 void Chest::sendModelInfo(NetworkMessage* zMessage)

+ 1 - 1
FactoryCraft/Chest.h

@@ -19,6 +19,6 @@ protected:
 public:
     Chest(
         int typeId, ItemType* zTool, Framework::Vec3<int> pos, int dimensionId);
-    virtual void interact(Item* zItem, Entity* zActor) override;
+    virtual bool interact(Item* zItem, Entity* zActor) override;
     virtual void sendModelInfo(NetworkMessage* zMessage) override;
 };

+ 61 - 31
FactoryCraft/Entity.cpp

@@ -32,20 +32,27 @@ bool ActionTarget::isEntity(int entityId) const
     return this->entityId == entityId;
 }
 
-void ActionTarget::useItemSkillOnTarget(
+bool ActionTarget::useItemSkillOnTarget(
     Entity* zActor, ItemSkill* zItemSkill, Item* zUsedItem)
 {
     if (entityId >= 0)
     {
         Entity* target = Game::INSTANCE->zEntity(entityId);
-        if (target) zItemSkill->use(zActor, zUsedItem, target);
+        if (target)
+        {
+            return zItemSkill->use(zActor, zUsedItem, target);
+        }
     }
     else
     {
         Block* block = Game::INSTANCE->zRealBlockInstance(
             blockPos, zActor->getDimensionId());
-        if (block) zItemSkill->use(zActor, zUsedItem, block);
+        if (block)
+        {
+            return zItemSkill->use(zActor, zUsedItem, block);
+        }
     }
+    return 0;
 }
 
 void ActionTarget::interactItemSkillOnTarget(
@@ -82,7 +89,7 @@ void ActionTarget::interactItemSkillOnTarget(
     }
 }
 
-void ActionTarget::placeBlock(Entity* zActor, Item* zItem)
+bool ActionTarget::placeBlock(Entity* zActor, Item* zItem)
 {
     if (zActor->getStamina() > 0.2f)
     {
@@ -99,9 +106,11 @@ void ActionTarget::placeBlock(Entity* zActor, Item* zItem)
                     ->placeBlock(block->getPos(), block);
                 zItem->onPlaced();
                 zActor->setStamina(zActor->getStamina() - 0.2f);
+                return 1;
             }
         }
     }
+    return 0;
 }
 
 void ActionTarget::toMessage(
@@ -225,11 +234,11 @@ void Entity::onDeath()
         new EntityRemovedUpdate(id, dimensionId, location));
 }
 
-void Entity::useItem(int typeId, Item* zItem, bool left)
+bool Entity::useItem(int typeId, ItemStack* zStack, bool left)
 {
     if (left)
     {
-        if (!zItem || zItem->isUsable())
+        if (!zStack || !zStack->zItem() || zStack->zItem()->isUsable())
         {
             cs.lock();
             if (target)
@@ -246,57 +255,77 @@ void Entity::useItem(int typeId, Item* zItem, bool left)
                 {
                     selected = zSkill(ItemTypeEnum::PLAYER_HAND);
                 }
-                target->useItemSkillOnTarget(this, selected, zItem);
+                bool result = target->useItemSkillOnTarget(this,
+                    selected,
+                    !zStack || zStack->getSize() > 1 ? 0
+                                                     : (Item*)zStack->zItem());
+                cs.unlock();
+                return result;
             }
             cs.unlock();
         }
-        else if (left)
+        else
         {
             useItem(ItemTypeEnum::PLAYER_HAND, 0, left);
         }
     }
     else
     {
-        if (zItem && zItem->isEatable())
+        if (zStack && zStack->zItem() && zStack->zItem()->isEatable()
+            && zStack->getSize() > 0)
         { // eat item
-            zItem->applyFoodEffects(this);
+            if (zStack->getSize() == 1)
+            {
+                return ((Item*)zStack->zItem())->applyFoodEffects(this);
+            }
+            else
+            {
+                if (zStack->zItem()->canApplyFoodEffectsFully(this))
+                {
+                    Item* item = zStack->extractFromStack();
+                    item->applyFoodEffects(this);
+                    item->release();
+                    return 1;
+                }
+            }
         }
-        else if (zItem && zItem->isPlaceable())
+        else if (zStack && zStack->zItem() && zStack->zItem()->isPlaceable()
+                 && zStack->getSize() > 0)
         { // place item
             if (placeBlockCooldown <= 0)
             {
                 cs.lock();
                 if (target)
                 {
-                    target->placeBlock(this, zItem);
+                    Item* item = zStack->extractFromStack();
+                    if (!target->placeBlock(this, item))
+                    {
+                        if (!zStack->addToStack(item))
+                        {
+                            Game::INSTANCE->spawnItem(
+                                location, dimensionId, new ItemStack(item, 1));
+                        }
+                        cs.unlock();
+                        return 0;
+                    }
+                    item->release();
                     placeBlockCooldown = 15;
+                    cs.unlock();
+                    return 1;
                 }
                 cs.unlock();
             }
         }
-        else if (!zItem || zItem->isUsable())
-        { // use item skill
-            cs.lock();
-            if (target)
-            {
-                ItemSkill* selected = zSkill(typeId);
-                if (!selected)
-                {
-                    selected
-                        = StaticRegistry<ItemType>::INSTANCE.zElement(typeId)
-                              ->createDefaultItemSkill();
-                    if (selected) skills.add(selected);
-                }
-                target->interactItemSkillOnTarget(this, selected, zItem);
-            }
-            cs.unlock();
-        }
     }
+    return 0;
 }
 
 void Entity::onTargetChange() {}
 
-void Entity::interact(Item* zItem, Entity* zActor) {}
+bool Entity::interact(Item* zItem, Entity* zActor)
+{
+    return false;
+}
 
 void Entity::addMovementFrame(MovementFrame& frame)
 {
@@ -333,7 +362,8 @@ void Entity::calculateTarget(Framework::Vec3<float> basePos,
     Direction dir = BOTTOM;
     while (true)
     {
-        if (getDefaultBlock(Game::INSTANCE->zBlockAt(Vec3<int>{px, py, pz}, dimensionId))
+        if (getDefaultBlock(
+                Game::INSTANCE->zBlockAt(Vec3<int>{px, py, pz}, dimensionId))
                 ->isInteractable(zItem))
         {
             if (!target || !target->isBlock({px, py, pz}, dir))

+ 4 - 4
FactoryCraft/Entity.h

@@ -29,11 +29,11 @@ public:
     bool isBlock(Framework::Vec3<int> blockPos, Direction blockSide) const;
     bool isEntity(int entityId) const;
 
-    void useItemSkillOnTarget(
+    bool useItemSkillOnTarget(
         Entity* zActor, ItemSkill* zItemSkill, Item* zUsedItem);
     void interactItemSkillOnTarget(
         Entity* zActor, ItemSkill* zItemSkill, Item* zUsedItem);
-    void placeBlock(Entity* zActor, Item* zItem);
+    bool placeBlock(Entity* zActor, Item* zItem);
 
     static void toMessage(
         const ActionTarget* zTarget, int dimensionId, NetworkMessage* zMsg);
@@ -82,7 +82,7 @@ protected:
         statusBarObservers;
 
     virtual void onDeath();
-    virtual void useItem(int typeId, Item* zItem, bool left);
+    virtual bool useItem(int typeId, ItemStack* zStack, bool left);
     Entity(int typeId,
         Framework::Vec3<float> location,
         int dimensionId,
@@ -105,7 +105,7 @@ public:
         Entity* zSource);
     virtual void onTargetChange();
 
-    virtual void interact(Item* zItem, Entity* zActor);
+    virtual bool interact(Item* zItem, Entity* zActor);
     virtual void onFall(float collisionSpeed);
     void setChatSecurityLevel(int level);
     void setPosition(Framework::Vec3<float> pos);

+ 16 - 6
FactoryCraft/Hoe.cpp

@@ -6,7 +6,7 @@ HoeToolItemType::HoeToolItemType() // TODO: add broken hoe
     : BasicToolItemType(ItemTypeEnum::HOE,
         "Hoe",
         new HoeToolLevelUpRule(),
-        0,
+        ItemTypeEnum::BROKEN_HOE,
         ModelInfo("tools.m3/hoe", "tools.ltdb/stonehoe.png", 1))
 {}
 
@@ -61,15 +61,16 @@ HoeToolSkill::HoeToolSkill()
       nextActionCounter(0)
 {}
 
-void HoeToolSkill::use(Entity* zActor, Item* zUsedItem, Block* zTarget)
+bool HoeToolSkill::use(Entity* zActor, Item* zUsedItem, Block* zTarget)
 {
     if (nextActionCounter == 0)
     {
-        if (zTarget->zBlockType()->getId() == BlockTypeEnum::DIRT)
+        if (zActor->getStamina() > 0.5f / (float)level)
         {
-            if (zActor->getStamina() > 0.5f / (float)level)
+            if (zTarget->zBlockType()->getId() == BlockTypeEnum::DIRT)
             {
-                zActor->setStamina(zActor->getStamina() - 0.5f / (float)level);
+                zActor->setStamina(
+                    zActor->getStamina() - 0.5f / (float)level);
                 zUsedItem->setDurability(zUsedItem->getDurability() - 0.5f);
                 Vec3<int> pos = zTarget->getPos();
                 int dimension = zTarget->getDimensionId();
@@ -80,13 +81,22 @@ void HoeToolSkill::use(Entity* zActor, Item* zUsedItem, Block* zTarget)
                 });
                 nextActionCounter = 20;
             }
+            else
+            {
+                zUsedItem->setDurability(
+                    zUsedItem->getDurability() - 0.5f / (float)level);
+                zActor->setStamina(zActor->getStamina() - 0.5f / (float)level);
+            }
+            return 1;
         }
     }
     else if (nextActionCounter > 0)
         nextActionCounter--;
+    return 0;
 }
 
-void HoeToolSkill::use(Entity* zActor, Item* zUsedItem, Entity* zTarget)
+bool HoeToolSkill::use(Entity* zActor, Item* zUsedItem, Entity* zTarget)
 {
     // a hoe can not be used on an entity
+    return 0;
 }

+ 2 - 2
FactoryCraft/Hoe.h

@@ -35,8 +35,8 @@ private:
 
 public:
     HoeToolSkill();
-    void use(Entity* zActor, Item* zUsedItem, Block* zTarget) override;
-    void use(Entity* zActor, Item* zUsedItem, Entity* zTarget) override;
+    bool use(Entity* zActor, Item* zUsedItem, Block* zTarget) override;
+    bool use(Entity* zActor, Item* zUsedItem, Entity* zTarget) override;
 
     friend HoeToolItemType;
     friend HoeToolLevelUpRule;

+ 18 - 15
FactoryCraft/Inventory.cpp

@@ -248,7 +248,8 @@ void MultipleInventoryLock::lock()
     }
 }
 
-Inventory::Inventory(const Framework::Vec3<float> location, int dimensionId, bool hasInventory)
+Inventory::Inventory(
+    const Framework::Vec3<float> location, int dimensionId, bool hasInventory)
     : ReferenceCounter(),
       nextSlotId(1),
       dimensionId(dimensionId),
@@ -351,24 +352,28 @@ void Inventory::afterPullStack(
 void Inventory::afterPushStack(
     ItemSlot* zSlot, Direction dir, const Item* zItem, int count)
 {
-    if (zSlot->getNumberOfItems() > 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);
-    }
-    else
+    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();
-        const Item* zItem = zSlot->zStack()->zItem();
         *(float*)(message + 9) = zItem->getHp();
         *(float*)(message + 13) = zItem->getMaxHp();
         *(float*)(message + 17) = zItem->getDurability();
@@ -381,8 +386,6 @@ void Inventory::afterPushStack(
         msg->setMessage(message, 30 + zItem->getName().getLength());
         notifyObservers(msg);
     }
-    for (auto call : afterPushStackCalls)
-        call(zSlot, dir, zItem, count);
 }
 
 void Inventory::loadInventory(Framework::StreamReader* zReader)

+ 1 - 0
FactoryCraft/Inventory.h

@@ -88,6 +88,7 @@ protected:
         ItemSlot* zSlot, Direction dir, const Item* zItem, int count);
     virtual void afterPushStack(
         ItemSlot* zSlot, Direction dir, const Item* zItem, int count);
+    virtual void updateSlot(ItemSlot* zSlot);
     virtual void loadInventory(Framework::StreamReader* zReader);
     virtual void saveInventory(Framework::StreamWriter* zWriter);
     void removeObserver(Entity* zSource, Framework::Text id);

+ 15 - 6
FactoryCraft/Item.cpp

@@ -20,7 +20,8 @@ Item::Item(int itemTypeId, const char* name)
       maxStackSize(50),
       name(name)
 {
-    foodEffect = [](Entity* e) {};
+    foodEffect = [](Item* i, Entity* e) { return false; };
+    foodEffectDestroysItemTest = [](const Item* i, Entity *e) { return false; };
 }
 
 void Item::setHp(float hp)
@@ -35,9 +36,11 @@ void Item::setDurability(float durability)
 
 void Item::tick() {}
 
-void Item::setFoodEffect(std::function<void(Entity*)> foodEffect)
+void Item::setFoodEffect(std::function<bool(Item*, Entity*)> foodEffect,
+    std::function<bool(const Item*, Entity*)> destroysItemTest)
 {
     this->foodEffect = foodEffect;
+    this->foodEffectDestroysItemTest = destroysItemTest;
 }
 
 const ItemType* Item::zItemType() const
@@ -139,9 +142,7 @@ Framework::Text Item::getTooltipUIML() const
 }
 
 void Item::applyInventoryEffects(Entity* zTarget)
-{
-    foodEffect(zTarget);
-}
+{}
 
 void Item::removeInventoryEffects(Entity* zTarget) {}
 
@@ -149,7 +150,15 @@ void Item::applyEquippedEffects(Entity* zTarget) {}
 
 void Item::removeEquippedEffects(Entity* zTarget) {}
 
-void Item::applyFoodEffects(Entity* zTarget) {}
+bool Item::applyFoodEffects(Entity* zTarget)
+{
+    return foodEffect(this, zTarget);
+}
+
+bool Item::canApplyFoodEffectsFully(Entity* zTarget) const
+{
+    return foodEffectDestroysItemTest(this, zTarget);
+}
 
 ItomJsonType::ItomJsonType()
     : TypeFactory()

+ 6 - 3
FactoryCraft/Item.h

@@ -25,7 +25,8 @@ protected:
     bool usable;
     int maxStackSize;
     Framework::Text name;
-    std::function<void(Entity*)> foodEffect;
+    std::function<bool(Item*, Entity*)> foodEffect;
+    std::function<bool(const Item*, Entity*)> foodEffectDestroysItemTest;
     Item(int itemTypeId, const char* name);
 
 public:
@@ -33,7 +34,8 @@ public:
     void setDurability(float durability);
     virtual void tick();
 
-    void setFoodEffect(std::function<void(Entity*)> foodEffect);
+    void setFoodEffect(std::function<bool(Item*, Entity*)> foodEffect,
+        std::function<bool(const Item*, Entity*)> destroysItemTest);
     const ItemType* zItemType() const;
     int getTypeId() const;
     const BlockType* zPlacedBlockType() const;
@@ -58,7 +60,8 @@ public:
     virtual void removeInventoryEffects(Entity* zTarget);
     virtual void applyEquippedEffects(Entity* zTarget);
     virtual void removeEquippedEffects(Entity* zTarget);
-    virtual void applyFoodEffects(Entity* zTarget);
+    virtual bool applyFoodEffects(Entity* zTarget);
+    virtual bool canApplyFoodEffectsFully(Entity* zTarget) const;
 
     friend ItemType;
 };

+ 20 - 10
FactoryCraft/ItemSkill.cpp

@@ -20,14 +20,14 @@ int ItemSkill::getTypeId()
     return itemTypeId;
 }
 
-void ItemSkill::interact(Entity* zActor, Item* zUsedItem, Block* zTarget)
+bool ItemSkill::interact(Entity* zActor, Item* zUsedItem, Block* zTarget)
 {
-    zTarget->interact(zUsedItem, zActor);
+    return zTarget->interact(zUsedItem, zActor);
 }
 
-void ItemSkill::interact(Entity* zActor, Item* zUsedItem, Entity* zTarget)
+bool ItemSkill::interact(Entity* zActor, Item* zUsedItem, Entity* zTarget)
 {
-    zTarget->interact(zUsedItem, zActor);
+    return zTarget->interact(zUsedItem, zActor);
 }
 
 BasicItemSkill::BasicItemSkill(int itemTypeId,
@@ -49,12 +49,22 @@ BasicItemSkill::BasicItemSkill(int itemTypeId,
       hungerModifier(hungerModifier)
 {}
 
-void BasicItemSkill::use(Entity* zActor, Item* zUsedItem, Block* zTarget) {}
+bool BasicItemSkill::use(Entity* zActor, Item* zUsedItem, Block* zTarget)
+{
+    return false;
+}
 
-void BasicItemSkill::use(Entity* zActor, Item* zUsedItem, Entity* zTarget) {}
+bool BasicItemSkill::use(Entity* zActor, Item* zUsedItem, Entity* zTarget)
+{
+    return false;
+}
 
-void BasicItemSkill::interact(Entity* zActor, Item* zUsedItem, Block* zTarget)
-{}
+bool BasicItemSkill::interact(Entity* zActor, Item* zUsedItem, Block* zTarget)
+{
+    return false;
+}
 
-void BasicItemSkill::interact(Entity* zActor, Item* zUsedItem, Entity* zTarget)
-{}
+bool BasicItemSkill::interact(Entity* zActor, Item* zUsedItem, Entity* zTarget)
+{
+    return false;
+}

+ 8 - 8
FactoryCraft/ItemSkill.h

@@ -25,10 +25,10 @@ private:
 
 public:
     ItemSkill(int itemTypeId);
-    virtual void use(Entity* zActor, Item* zUsedItem, Block* zTarget) = 0;
-    virtual void use(Entity* zActor, Item* zUsedItem, Entity* zTarget) = 0;
-    virtual void interact(Entity* zActor, Item* zUsedItem, Block* zTarget);
-    virtual void interact(Entity* zActor, Item* zUsedItem, Entity* zTarget);
+    virtual bool use(Entity* zActor, Item* zUsedItem, Block* zTarget) = 0;
+    virtual bool use(Entity* zActor, Item* zUsedItem, Entity* zTarget) = 0;
+    virtual bool interact(Entity* zActor, Item* zUsedItem, Block* zTarget);
+    virtual bool interact(Entity* zActor, Item* zUsedItem, Entity* zTarget);
     const ItemType* zSkillType();
     int getTypeId();
 };
@@ -55,11 +55,11 @@ protected:
         float xpIncrease = 1.1f);
 
 public:
-    virtual void use(Entity* zActor, Item* zUsedItem, Block* zTarget) override;
-    virtual void use(Entity* zActor, Item* zUsedItem, Entity* zTarget) override;
-    virtual void interact(
+    virtual bool use(Entity* zActor, Item* zUsedItem, Block* zTarget) override;
+    virtual bool use(Entity* zActor, Item* zUsedItem, Entity* zTarget) override;
+    virtual bool interact(
         Entity* zActor, Item* zUsedItem, Block* zTarget) override;
-    virtual void interact(
+    virtual bool interact(
         Entity* zActor, Item* zUsedItem, Entity* zTarget) override;
 
     friend ItemType;

+ 8 - 0
FactoryCraft/ItemSlot.cpp

@@ -71,6 +71,14 @@ void ItemSlot::addItems(ItemStack* zStack, Direction dir)
     }
 }
 
+void ItemSlot::update() {
+    if (items && items->getSize() == 0)
+    {
+		items->release();
+		items = 0;
+	}
+}
+
 int ItemSlot::numberOfAddableItems(const ItemStack* zStack, Direction dir) const
 {
     if ((dir | allowedPushSides) == allowedPushSides)

+ 1 - 0
FactoryCraft/ItemSlot.h

@@ -43,6 +43,7 @@ public:
 
     ItemStack* takeItemsOut(int count, Direction dir);
     void addItems(ItemStack* zStack, Direction dir);
+    void update();
 
     int numberOfAddableItems(const ItemStack* zStack, Direction dir) const;
     const ItemStack* zStack() const;

+ 8 - 0
FactoryCraft/ItemType.cpp

@@ -147,6 +147,14 @@ void ItemType::saveItemSkill(
 
 Item* ItemType::breakItem(const Item* zItem) const
 {
+    if (brokenTypeId)
+    {
+        const ItemType *type = StaticRegistry<ItemType>::INSTANCE.zElement(brokenTypeId);
+        if (type)
+        {
+            return type->createItem();
+        }
+    }
     return 0;
 }
 

+ 44 - 66
FactoryCraft/Player.cpp

@@ -5,7 +5,6 @@
 #include "PlayerHand.h"
 #include "QuestDialog.h"
 
-
 Player::Player(Framework::Vec3<float> location, int dimensionId, int entityId)
     : Entity(EntityTypeEnum::PLAYER, location, dimensionId, entityId),
       BasicShapedCrafter(3, 3, this, "inventory")
@@ -87,82 +86,61 @@ Framework::Text Player::getPlayerGUI()
 
 void Player::useItemSlot(ItemSlot* zSlot, bool left)
 {
-    if (zSlot->zStack())
+    if (Entity::useItem(zSlot->zStack() && zSlot->zStack()->zItem()
+                            ? zSlot->zStack()->zItem()->getTypeId()
+                            : ItemTypeEnum::PLAYER_HAND,
+            (ItemStack*)zSlot->zStack(),
+            left))
     {
-        ItemStack* stack = takeItemsOut(zSlot, 1, NO_DIRECTION);
-        if (stack)
+        zSlot->update();
+        if (zSlot->zStack())
         {
-            Item* item = stack->extractFromStack();
-            Entity::useItem(item->getTypeId(), item, left);
-            if (item->getHp() > 0)
+            if (zSlot->zStack()->zItem()->getDurability() <= 0)
             {
-                if (item->getDurability() > 0)
-                { // put used item back
-                    stack->addToStack(item);
-                    if (!zSlot->numberOfAddableItems(stack, NO_DIRECTION))
-                    { // move other items to other space
-                        ItemStack* oldItems = takeItemsOut(
-                            zSlot, zSlot->zStack()->getSize(), NO_DIRECTION);
-                        addItems(zSlot, stack, NO_DIRECTION);
-                        addItems(oldItems, NO_DIRECTION, 0);
-                        if (oldItems->getSize() > 0)
-                        {
-                            Game::INSTANCE->spawnItem(
-                                getLocation(), getDimensionId(), oldItems);
-                        }
-                        else
-                        {
-                            oldItems->release();
-                        }
-                    }
-                    else
-                        addItems(zSlot, stack, NO_DIRECTION);
-                }
-                else
-                { // item is broken
-                    // move other items of the same type to the slot
-                    Array<ItemSlot*> fromSlots;
-                    for (ItemSlot* slot : *this)
+                ItemStack* stack = zSlot->takeItemsOut(
+                    zSlot->getNumberOfItems(), NO_DIRECTION);
+                Item* broken
+                    = stack->zItem()->zItemType()->breakItem(stack->zItem());
+                if (broken)
+                {
+                    ItemStack* newStack
+                        = new ItemStack(broken, stack->getSize());
+                    zSlot->addItems(newStack, NO_DIRECTION);
+                    if (newStack->getSize() > 0)
                     {
-                        if (slot != zSlot) fromSlots.add(slot);
+                        Game::INSTANCE->spawnItem(
+                            getLocation(), getDimensionId(), newStack);
                     }
-                    Array<ItemSlot*> targetSlots;
-                    targetSlots.add(zSlot);
-                    TypeItemFilter filter(item->zItemType());
-                    localTransaction(&fromSlots,
-                        &targetSlots,
-                        &filter,
-                        zSlot->getFreeSpace(),
-                        NO_DIRECTION,
-                        NO_DIRECTION);
-                    // place broken item in inventory
-                    const ItemType* brokenType
-                        = item->zItemType()->zBrokenItemType();
-                    if (brokenType)
+                    else
                     {
-                        Item* broken = item->zItemType()->breakItem(item);
-                        if (broken)
-                        {
-                            stack->addToStack(broken);
-                            addItems(stack, NO_DIRECTION, 0);
-                            if (stack->getSize() > 0)
-                            {
-                                Game::INSTANCE->spawnItem(getLocation(),
-                                    getDimensionId(),
-                                    dynamic_cast<ItemStack*>(stack->getThis()));
-                            }
-                        }
+                        newStack->release();
                     }
-                    item->release();
                 }
+                stack->release();
+            }
+            else if (zSlot->zStack()->zItem()->getHp() <= 0)
+            {
+                ItemStack* stack = zSlot->takeItemsOut(
+                    zSlot->getNumberOfItems(), NO_DIRECTION);
+                Array<ItemSlot*> fromSlots;
+                for (ItemSlot* slot : *this)
+                {
+                    if (slot != zSlot) fromSlots.add(slot);
+                }
+                Array<ItemSlot*> targetSlots;
+                targetSlots.add(zSlot);
+                TypeItemFilter filter(stack->zItem()->zItemType());
+                localTransaction(&fromSlots,
+                    &targetSlots,
+                    &filter,
+                    zSlot->getFreeSpace(),
+                    NO_DIRECTION,
+                    NO_DIRECTION);
+                stack->release();
             }
-            else
-                item->release();
-            stack->release();
         }
+        updateSlot(zSlot);
     }
-    else
-        Entity::useItem(ItemTypeEnum::PLAYER_HAND, 0, left); // hand usage
 }
 
 void Player::setName(Framework::Text name)

+ 4 - 2
FactoryCraft/PlayerHand.cpp

@@ -46,7 +46,7 @@ PlayerHandSkill::PlayerHandSkill()
     : ItemSkill(ItemTypeEnum::PLAYER_HAND)
 {}
 
-void PlayerHandSkill::use(Entity* zActor, Item* zUsedItem, Block* zTarget)
+bool PlayerHandSkill::use(Entity* zActor, Item* zUsedItem, Block* zTarget)
 {
     if (zActor->getStamina() > 0.001f)
     {
@@ -61,9 +61,11 @@ void PlayerHandSkill::use(Entity* zActor, Item* zUsedItem, Block* zTarget)
             zActor->setHP(zActor->getCurrentHP() - 0.01f);
         }
     }
+    return false; // item was not changed
 }
 
-void PlayerHandSkill::use(Entity* zActor, Item* zUsedItem, Entity* zTarget)
+bool PlayerHandSkill::use(Entity* zActor, Item* zUsedItem, Entity* zTarget)
 {
     // TODO: make damage on the entity
+    return false; // item was not changed
 }

+ 2 - 2
FactoryCraft/PlayerHand.h

@@ -28,6 +28,6 @@ class PlayerHandSkill : public ItemSkill
 {
 public:
     PlayerHandSkill();
-    void use(Entity* zActor, Item* zUsedItem, Block* zTarget) override;
-    void use(Entity* zActor, Item* zUsedItem, Entity* zTarget) override;
+    bool use(Entity* zActor, Item* zUsedItem, Block* zTarget) override;
+    bool use(Entity* zActor, Item* zUsedItem, Entity* zTarget) override;
 };

+ 8 - 5
FactoryCraft/Shovel.cpp

@@ -5,7 +5,7 @@ ShovelToolItemType::ShovelToolItemType() // TODO: add broken Shovel
     : BasicToolItemType(ItemTypeEnum::SHOVEL,
         "Shovel",
         new ShovelToolLevelUpRule(),
-        0,
+        ItemTypeEnum::SHOVEL_BROKEN,
         ModelInfo("tools.m3/shovel", "tools.ltdb/stonehoe.png", 1)) // use same texture as hoe
 {}
 
@@ -59,7 +59,7 @@ ShovelToolSkill::ShovelToolSkill()
       maxXP(10.f)
 {}
 
-void ShovelToolSkill::use(Entity* zActor, Item* zUsedItem, Block* zTarget)
+bool ShovelToolSkill::use(Entity* zActor, Item* zUsedItem, Block* zTarget)
 {
     if (zActor->getStamina() > 0.0001f)
     {
@@ -72,17 +72,20 @@ void ShovelToolSkill::use(Entity* zActor, Item* zUsedItem, Block* zTarget)
             zTarget->setHP(zTarget->getHP() - damage);
             xp += damage / 20;
             zActor->setStamina(zActor->getStamina() - 0.0001f);
-            zUsedItem->setHp(zUsedItem->getHp() - damage / 50);
+            zUsedItem->setDurability(zUsedItem->getDurability() - damage / 50);
         }
         else
         {
             zActor->setStamina(zActor->getStamina() - 0.0001f);
-            zUsedItem->setHp(zUsedItem->getHp() - 0.001f);
+            zUsedItem->setDurability(zUsedItem->getDurability() - 0.001f);
         }
+        return true;
     }
+    return false;
 }
 
-void ShovelToolSkill::use(Entity* zActor, Item* zUsedItem, Entity* zTarget)
+bool ShovelToolSkill::use(Entity* zActor, Item* zUsedItem, Entity* zTarget)
 {
     // an Shovel can not be used on an entity
+    return 0;
 }

+ 2 - 2
FactoryCraft/Shovel.h

@@ -33,8 +33,8 @@ private:
 
 public:
     ShovelToolSkill();
-    void use(Entity* zActor, Item* zUsedItem, Block* zTarget) override;
-    void use(Entity* zActor, Item* zUsedItem, Entity* zTarget) override;
+    bool use(Entity* zActor, Item* zUsedItem, Block* zTarget) override;
+    bool use(Entity* zActor, Item* zUsedItem, Entity* zTarget) override;
 
     friend ShovelToolItemType;
     friend ShovelToolLevelUpRule;

+ 29 - 10
FactoryCraft/StaticInitializerOrder.cpp

@@ -17,10 +17,10 @@
 #include "Player.h"
 // item skills
 #include "Axe.h"
-#include "Hoe.h"
-#include "Shovel.h"
 #include "BasicItems.h"
+#include "Hoe.h"
 #include "PlayerHand.h"
+#include "Shovel.h"
 // world updates
 #include "AddEntityUpdate.h"
 #include "EntityRemovedUpdate.h"
@@ -283,7 +283,8 @@ void initializeBlockTypes()
     (new FluidBlockType(BlockTypeEnum::WATER,
          ModelInfo("fluid", "fluids.ltdb/water.png", 6),
          "Water",
-         0xFF2323BF, Vec3<float>(0.8f, 0.8f, 0.95f)))
+         0xFF2323BF,
+         Vec3<float>(0.8f, 0.8f, 0.95f)))
         ->initializeDefault();
     (new BasicBlockType(BlockTypeEnum::CRAFTING_TABLE,
          ItemTypeEnum::CRAFTING_TABLE,
@@ -596,12 +597,30 @@ void initializeItemTypes()
                 1,
                 0,
                 50);
-            item->setFoodEffect([](Entity* zEntity) {
-                zEntity->setHunger(zEntity->getHunger() + 0.5f);
-                zEntity->setThirst(
-                    zEntity->getThirst() + 1.f); // TODO: remove thirst addition
-                                                 // when drinkable water exists
-            });
+            item->setFoodEffect(
+                [](Item* zItem, Entity* zEntity) {
+                    float added = zItem->getHp() / 2.f;
+                    if (zEntity->getHunger() + added > zEntity->getMaxHunger())
+                    {
+                        added = zEntity->getMaxHunger() - zEntity->getHunger();
+                    }
+                    zEntity->setHunger(zEntity->getHunger() + added);
+                    zEntity->setThirst(
+                        zEntity->getThirst()
+                        + added * 2); // TODO: remove thirst addition
+                                      // when drinkable water exists
+                    zItem->setHp(zItem->getHp() - added * 2.f);
+                    return added != 0.f;
+                },
+                [](const Item* zItem, Entity* zEntity) {
+                    float addable = zItem->getHp() / 2.f;
+                    if (zEntity->getHunger() + addable
+                        > zEntity->getMaxHunger())
+                    {
+                        return 0;
+                    }
+                    return 1;
+                });
             return item;
         }));
 
@@ -657,7 +676,7 @@ void initializeEntityTypes()
 
 void initializeDimensions()
 {
-    //new OverworldDimension();
+    // new OverworldDimension();
 }
 
 void initializeMultiblockTypes()

+ 29 - 0
Windows Version/data/quests/quests.json

@@ -29,6 +29,35 @@
             ]
           }
         ]
+      },
+      {
+        "questId": "tutorial_2",
+        "questName": "Inventory",
+        "description": "Your inventory shows you all the items you currently have.\nYou can open it by pressing the tab key on your keyboard.\nIn your inventory you can also combine items to to create new once.\n",
+        "imagePath": "data/images/gui_icons.ltdb/questdialog.png",
+        "requiredQuestIds": [ [ "tutorial_1" ] ],
+        "requirements": [
+          {
+            "id": "1",
+            "description": "Open your inventory",
+            "type": "open_dialog",
+            "dialogId": "player_inventory"
+          }
+        ],
+        "rewards": [
+          {
+            "rewardId": "1",
+            "type": "give_items",
+            "items": [
+              {
+                "item": {
+                  "type": "WoodenStick"
+                },
+                "count": 10
+              }
+            ]
+          }
+        ]
       }
     ]
   }

+ 0 - 216
enc_temp_folder/9b5d8d394bbd57f419062a24c115732/QuestReward.cpp

@@ -1,216 +0,0 @@
-#include "QuestReward.h"
-
-#include <Fenster.h>
-
-#include "Entity.h"
-#include "Game.h"
-#include "Player.h"
-
-QuestReward::QuestReward(Framework::Text rewardId)
-    : ReferenceCounter(),
-      rewardId(rewardId)
-{}
-
-bool QuestReward::validateSettings(
-    Framework::XML::Element* zParent, QuestStorage* zStorage)
-{
-    return true;
-}
-
-void QuestReward::api(Framework::StreamReader* message,
-    Framework::XML::Element* zParent,
-    QuestStorage* zStorage)
-{}
-
-const Framework::Text& QuestReward::getRewardId() const
-{
-    return rewardId;
-}
-
-ItemStackInfo::ItemStackInfo(Item* item, int count)
-    : ReferenceCounter(),
-      item(item),
-      count(count)
-{}
-
-ItemStackInfo::~ItemStackInfo()
-{
-    item->release();
-}
-
-Item* ItemStackInfo::zItem() const
-{
-    return item;
-}
-
-int ItemStackInfo::getCount() const
-{
-    return count;
-}
-
-ItemStackInfoType::ItemStackInfoType()
-    : TypeFactory<ItemStackInfo>()
-{}
-
-ItemStackInfo* ItemStackInfoType::fromJson(
-    Framework::JSON::JSONValue* zJson) const
-{
-    return new ItemStackInfo(Game::INSTANCE->zTypeRegistry()->fromJson<Item>(
-                                 zJson->asObject()->zValue("item")),
-        (int)zJson->asObject()->zValue("count")->asNumber()->getNumber());
-}
-
-Framework::JSON::JSONValue* ItemStackInfoType::toJson(
-    ItemStackInfo* zObject) const
-{
-    Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
-    result->addValue(
-        "item", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zItem()));
-    result->addValue(
-        "count", new Framework::JSON::JSONNumber((double)zObject->getCount()));
-    return result;
-}
-
-Framework::JSON::Validator::JSONValidator*
-ItemStackInfoType::getValidator() const
-{
-    return Framework::JSON::Validator::JSONValidator::buildForObject()
-        ->withRequiredAttribute(
-            "item", Game::INSTANCE->zTypeRegistry()->getValidator<Item>())
-        ->withRequiredNumber("count")
-        ->withDefault(1.0)
-        ->whichIsGreaterOrEqual(1.0)
-        ->finishNumber()
-        ->finishObject();
-}
-
-QuestRewardGiveItems::QuestRewardGiveItems(Framework::Text rewardId)
-    : QuestReward(rewardId)
-{}
-
-void QuestRewardGiveItems::giveReward(Framework::XML::Element* zParent,
-    QuestStorage* zStorage,
-    Entity* zTargetEntity)
-{
-    Player *p = dynamic_cast<Player*>(zTargetEntity);
-    if (p)
-    {
-        zStorage->putValue(
-            (Framework::Text("reward_") += rewardId) += "_given_to",
-            new Framework::JSON::JSONString(p->getName()));
-    }
-    for (ItemStackInfo* info : items)
-    {
-        ItemStack* stack = new ItemStack(
-            dynamic_cast<Item*>(info->zItem()->getThis()), info->getCount());
-        zTargetEntity->unsaveAddItem(stack, Direction::NO_DIRECTION, 0);
-        if (stack->getSize() > 0)
-        {
-            Game::INSTANCE->spawnItem(zTargetEntity->getLocation(),
-                zTargetEntity->getDimensionId(),
-                stack);
-        }
-        else
-        {
-            stack->release();
-        }
-    }
-}
-
-void QuestRewardGiveItems::addRewardUIML(Framework::XML::Element* zParent,
-    QuestStorage* zStorage,
-    Framework::Text onClickPrefix)
-{
-    Framework::XML::Element* container
-        = new Framework::XML::Element("<frame width=\"100%\" height=\"auto\" "
-                                      "display=\"column\" gap=\"10\"/>");
-    container->setAttribute("style",
-        Framework::Text() += (Framework::Fenster::Style::Sichtbar
-                              | Framework::Fenster::Style::Erlaubt));
-    container->setAttribute("id", Framework::Text("reward_") += rewardId);
-    container->addChild(new Framework::XML::Element(
-        "<text width=\"auto\" height=\"auto\">Item Reward:</text>"));
-    for (ItemStackInfo* info : items)
-    {
-        auto stack = new Framework::XML::Element(
-            "<itemStack width=\"50\" height=\"50\"/>");
-        stack->setAttribute(
-            "id", (Framework::Text("reward_") += rewardId) += "_item_stack");
-        stack->setAttribute("count", info->getCount());
-        stack->setAttribute("type", info->zItem()->getTypeId());
-        stack->addChild(
-            new Framework::XML::Element(info->zItem()->getTooltipUIML()));
-        auto text = new Framework::XML::Element(
-            "<text margin-left=\"10\" width=\"auto\" height=\"auto\"/>");
-        text->setText((Framework::Text(info->getCount()) += " ")
-                      += info->zItem()->getName());
-        text->setAttribute("align-left", stack->getAttributeValue("id"));
-        text->setAttribute("align-y", stack->getAttributeValue("id"));
-        container->addChild(stack);
-        container->addChild(text);
-        if (zStorage->containsKey( (Framework::Text("reward_") += rewardId) += "_given_to"))
-		{
-			auto givenTo = new Framework::XML::Element(
-				"<text width=\"auto\" height=\"auto\"/>");
-            auto name = zStorage->zValue(
-				(Framework::Text("reward_") += rewardId) += "_given_to")->asString();
-            givenTo->setText((Framework::Text("Given to: ") += name->getString()));
-            givenTo->setAttribute("align-top", text->getAttributeValue("id"));
-            givenTo->setAttribute("align-x", text->getAttributeValue("id"));
-            container->addChild(givenTo);
-		}
-    }
-    zParent->addChild(container);
-}
-
-QuestRewardGiveItemsType::QuestRewardGiveItemsType()
-    : SubTypeFactory<QuestReward, QuestRewardGiveItems>()
-{}
-
-QuestRewardGiveItems* QuestRewardGiveItemsType::fromJson(
-    Framework::JSON::JSONObject* zJson) const
-{
-    QuestRewardGiveItems* result = new QuestRewardGiveItems(
-        zJson->zValue("rewardId")->asString()->getString());
-    Framework::JSON::JSONArray* itemsJson = zJson->zValue("items")->asArray();
-    for (Framework::JSON::JSONValue* itemJson : *itemsJson)
-    {
-        result->items.add(
-            Game::INSTANCE->zTypeRegistry()->fromJson<ItemStackInfo>(itemJson));
-    }
-    return result;
-}
-
-Framework::JSON::JSONObject* QuestRewardGiveItemsType::toJson(
-    QuestRewardGiveItems* zObject) const
-{
-    Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
-    result->addValue(
-        "rewardId", new Framework::JSON::JSONString(zObject->getRewardId()));
-    Framework::JSON::JSONArray* itemsJson = new Framework::JSON::JSONArray();
-    for (ItemStackInfo* item : zObject->items)
-    {
-        itemsJson->addValue(Game::INSTANCE->zTypeRegistry()->toJson(item));
-    }
-    result->addValue("items", itemsJson);
-    return result;
-}
-
-Framework::JSON::Validator::JSONValidator*
-QuestRewardGiveItemsType::getValidator(
-    Framework::JSON::Validator::ObjectValidationBuilder<
-        Framework::JSON::Validator::JSONValidator>* builder) const
-{
-    return builder->withRequiredString("rewardId")
-        ->finishString()
-        ->withRequiredArray("items")
-        ->addAcceptedTypeInArray(
-            Game::INSTANCE->zTypeRegistry()->getValidator<ItemStackInfo>())
-        ->finishArray()
-        ->finishObject();
-}
-
-Framework::Text QuestRewardGiveItemsType::getTypeToken() const
-{
-    return "give_items";
-}

+ 0 - 218
enc_temp_folder/f12bb5e05c148783c3dcfcb42ea2394/QuestReward.cpp

@@ -1,218 +0,0 @@
-#include "QuestReward.h"
-
-#include <Fenster.h>
-
-#include "Entity.h"
-#include "Game.h"
-#include "Player.h"
-
-QuestReward::QuestReward(Framework::Text rewardId)
-    : ReferenceCounter(),
-      rewardId(rewardId)
-{}
-
-bool QuestReward::validateSettings(
-    Framework::XML::Element* zParent, QuestStorage* zStorage)
-{
-    return true;
-}
-
-void QuestReward::api(Framework::StreamReader* message,
-    Framework::XML::Element* zParent,
-    QuestStorage* zStorage)
-{}
-
-const Framework::Text& QuestReward::getRewardId() const
-{
-    return rewardId;
-}
-
-ItemStackInfo::ItemStackInfo(Item* item, int count)
-    : ReferenceCounter(),
-      item(item),
-      count(count)
-{}
-
-ItemStackInfo::~ItemStackInfo()
-{
-    item->release();
-}
-
-Item* ItemStackInfo::zItem() const
-{
-    return item;
-}
-
-int ItemStackInfo::getCount() const
-{
-    return count;
-}
-
-ItemStackInfoType::ItemStackInfoType()
-    : TypeFactory<ItemStackInfo>()
-{}
-
-ItemStackInfo* ItemStackInfoType::fromJson(
-    Framework::JSON::JSONValue* zJson) const
-{
-    return new ItemStackInfo(Game::INSTANCE->zTypeRegistry()->fromJson<Item>(
-                                 zJson->asObject()->zValue("item")),
-        (int)zJson->asObject()->zValue("count")->asNumber()->getNumber());
-}
-
-Framework::JSON::JSONValue* ItemStackInfoType::toJson(
-    ItemStackInfo* zObject) const
-{
-    Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
-    result->addValue(
-        "item", Game::INSTANCE->zTypeRegistry()->toJson(zObject->zItem()));
-    result->addValue(
-        "count", new Framework::JSON::JSONNumber((double)zObject->getCount()));
-    return result;
-}
-
-Framework::JSON::Validator::JSONValidator*
-ItemStackInfoType::getValidator() const
-{
-    return Framework::JSON::Validator::JSONValidator::buildForObject()
-        ->withRequiredAttribute(
-            "item", Game::INSTANCE->zTypeRegistry()->getValidator<Item>())
-        ->withRequiredNumber("count")
-        ->withDefault(1.0)
-        ->whichIsGreaterOrEqual(1.0)
-        ->finishNumber()
-        ->finishObject();
-}
-
-QuestRewardGiveItems::QuestRewardGiveItems(Framework::Text rewardId)
-    : QuestReward(rewardId)
-{}
-
-void QuestRewardGiveItems::giveReward(Framework::XML::Element* zParent,
-    QuestStorage* zStorage,
-    Entity* zTargetEntity)
-{
-    Player *p = dynamic_cast<Player*>(zTargetEntity);
-    if (p)
-    {
-        zStorage->putValue(
-            (Framework::Text("reward_") += rewardId) += "_given_to",
-            new Framework::JSON::JSONString(p->getName()));
-    }
-    for (ItemStackInfo* info : items)
-    {
-        ItemStack* stack = new ItemStack(
-            dynamic_cast<Item*>(info->zItem()->getThis()), info->getCount());
-        zTargetEntity->unsaveAddItem(stack, Direction::NO_DIRECTION, 0);
-        if (stack->getSize() > 0)
-        {
-            Game::INSTANCE->spawnItem(zTargetEntity->getLocation(),
-                zTargetEntity->getDimensionId(),
-                stack);
-        }
-        else
-        {
-            stack->release();
-        }
-    }
-}
-
-void QuestRewardGiveItems::addRewardUIML(Framework::XML::Element* zParent,
-    QuestStorage* zStorage,
-    Framework::Text onClickPrefix)
-{
-    Framework::XML::Element* container
-        = new Framework::XML::Element("<frame width=\"100%\" height=\"auto\" "
-                                      "display=\"column\" gap=\"10\"/>");
-    container->setAttribute("style",
-        Framework::Text() += (Framework::Fenster::Style::Sichtbar
-                              | Framework::Fenster::Style::Erlaubt));
-    container->setAttribute("id", Framework::Text("reward_") += rewardId);
-    container->addChild(new Framework::XML::Element(
-        "<text width=\"auto\" height=\"auto\">Item Reward:</text>"));
-    for (ItemStackInfo* info : items)
-    {
-        auto stack = new Framework::XML::Element(
-            "<itemStack width=\"50\" height=\"50\"/>");
-        stack->setAttribute(
-            "id", (Framework::Text("reward_") += rewardId) += "_item_stack");
-        stack->setAttribute("count", info->getCount());
-        stack->setAttribute("type", info->zItem()->getTypeId());
-        stack->addChild(
-            new Framework::XML::Element(info->zItem()->getTooltipUIML()));
-        auto text = new Framework::XML::Element(
-            "<text margin-left=\"10\" width=\"auto\" height=\"auto\"/>");
-        text->setAttribute(
-            "id", (Framework::Text("reward_") += rewardId) += "_item_description");
-        text->setText((Framework::Text(info->getCount()) += " ")
-                      += info->zItem()->getName());
-        text->setAttribute("align-left", stack->getAttributeValue("id"));
-        text->setAttribute("align-y", stack->getAttributeValue("id"));
-        container->addChild(stack);
-        container->addChild(text);
-        if (zStorage->containsKey( (Framework::Text("reward_") += rewardId) += "_given_to"))
-		{
-			auto givenTo = new Framework::XML::Element(
-				"<text width=\"auto\" height=\"auto\"/>");
-            auto name = zStorage->zValue(
-				(Framework::Text("reward_") += rewardId) += "_given_to")->asString();
-            givenTo->setText((Framework::Text("Given to: ") += name->getString()));
-            givenTo->setAttribute("align-top", text->getAttributeValue("id"));
-            givenTo->setAttribute("align-x", text->getAttributeValue("id"));
-            container->addChild(givenTo);
-		}
-    }
-    zParent->addChild(container);
-}
-
-QuestRewardGiveItemsType::QuestRewardGiveItemsType()
-    : SubTypeFactory<QuestReward, QuestRewardGiveItems>()
-{}
-
-QuestRewardGiveItems* QuestRewardGiveItemsType::fromJson(
-    Framework::JSON::JSONObject* zJson) const
-{
-    QuestRewardGiveItems* result = new QuestRewardGiveItems(
-        zJson->zValue("rewardId")->asString()->getString());
-    Framework::JSON::JSONArray* itemsJson = zJson->zValue("items")->asArray();
-    for (Framework::JSON::JSONValue* itemJson : *itemsJson)
-    {
-        result->items.add(
-            Game::INSTANCE->zTypeRegistry()->fromJson<ItemStackInfo>(itemJson));
-    }
-    return result;
-}
-
-Framework::JSON::JSONObject* QuestRewardGiveItemsType::toJson(
-    QuestRewardGiveItems* zObject) const
-{
-    Framework::JSON::JSONObject* result = new Framework::JSON::JSONObject();
-    result->addValue(
-        "rewardId", new Framework::JSON::JSONString(zObject->getRewardId()));
-    Framework::JSON::JSONArray* itemsJson = new Framework::JSON::JSONArray();
-    for (ItemStackInfo* item : zObject->items)
-    {
-        itemsJson->addValue(Game::INSTANCE->zTypeRegistry()->toJson(item));
-    }
-    result->addValue("items", itemsJson);
-    return result;
-}
-
-Framework::JSON::Validator::JSONValidator*
-QuestRewardGiveItemsType::getValidator(
-    Framework::JSON::Validator::ObjectValidationBuilder<
-        Framework::JSON::Validator::JSONValidator>* builder) const
-{
-    return builder->withRequiredString("rewardId")
-        ->finishString()
-        ->withRequiredArray("items")
-        ->addAcceptedTypeInArray(
-            Game::INSTANCE->zTypeRegistry()->getValidator<ItemStackInfo>())
-        ->finishArray()
-        ->finishObject();
-}
-
-Framework::Text QuestRewardGiveItemsType::getTypeToken() const
-{
-    return "give_items";
-}