Просмотр исходного кода

use new gui element to display player status bars

Kolja Strohm 1 год назад
Родитель
Сommit
165d385238

+ 1 - 1
FactoryCraft/CraftingStorage.cpp

@@ -242,7 +242,7 @@ void BasicShapedCrafter::calculateOutputPreview()
             currentRecipie = recipie;
             NetworkMessage* message = new NetworkMessage();
             getOutputPreview(message);
-            zInventory->notyObservers(message);
+            zInventory->notifyObservers(message);
         }
     }
 }

+ 173 - 5
FactoryCraft/Entity.cpp

@@ -23,7 +23,8 @@ bool ActionTarget::isBlock(
     Framework::Vec3<int> blockPos, Direction blockSide) const
 {
     return this->entityId == -1 && this->blockPos == blockPos
-        && (this->targetBlockSide == targetBlockSide || blockSide == NO_DIRECTION);
+        && (this->targetBlockSide == targetBlockSide
+            || blockSide == NO_DIRECTION);
 }
 
 bool ActionTarget::isEntity(int entityId) const
@@ -102,8 +103,8 @@ void ActionTarget::toMessage(
             *(int*)(message + 10) = zTarget->blockPos.z;
             *(int*)(message + 14) = zTarget->targetBlockSide;
             short len = (short)targetUIML.getLength();
-			*(short*)(message + 18) = len;
-			memcpy(message + 20, targetUIML.getText(), len);
+            *(short*)(message + 18) = len;
+            memcpy(message + 20, targetUIML.getText(), len);
             zMsg->setMessage(message, 18 + len + 2);
         }
     }
@@ -373,6 +374,62 @@ void Entity::calculateTarget(
     }
 }
 
+void Entity::removeStatusBarObserver(Entity* zSource, Framework::Text id)
+{
+    cs.lock();
+    int index = 0;
+    for (auto observer : statusBarObservers)
+    {
+        if (observer.getFirst() == zSource->getId()
+            && observer.getSecond().istGleich(id))
+        {
+            statusBarObservers.remove(index);
+            break;
+        }
+        index++;
+    }
+    cs.unlock();
+}
+
+void Entity::addStatusBarObserver(Entity* zSource, Framework::Text id)
+{
+    cs.lock();
+    for (auto observer : statusBarObservers)
+    {
+        if (observer.getFirst() == zSource->getId()
+            && observer.getSecond().istGleich(id))
+        {
+            cs.unlock();
+            return;
+        }
+    }
+    statusBarObservers.add(ImmutablePair<int, Text>(zSource->getId(), id));
+    cs.unlock();
+}
+
+void Entity::notifyStatusBarObservers(NetworkMessage* msg)
+{
+    cs.lock();
+    int index = 0;
+    Array<int> toDelete;
+    for (auto observer : statusBarObservers)
+    {
+        Entity* e = Game::INSTANCE->zEntity(observer.getFirst());
+        if (e)
+        {
+            msg->addressGui(observer.getSecond());
+            Game::INSTANCE->sendMessage(msg->clone(), e);
+        }
+        else
+            toDelete.add(index, 0);
+        index++;
+    }
+    for (int i : toDelete)
+        statusBarObservers.remove(i);
+    cs.unlock();
+    msg->release();
+}
+
 void Entity::prepareTick(const Dimension* zDimension) {}
 
 void Entity::tick(const Dimension* zDimension)
@@ -413,13 +470,76 @@ void Entity::tick(const Dimension* zDimension)
                 }
             }
             if (currentFrame.duration > 0) movements.set(currentFrame, 0);
+            if (getStamina() <= getMaxStamina() - 0.0025f)
+            {
+                if (getThirst() > 0 && getHunger() > 0)
+                {
+                    setStamina(getStamina() + 0.0025f);
+                    setHunger(getHunger() - 0.0005f);
+                    setThirst(getThirst() - 0.0015f);
+                }
+            }
+        }
+        else
+        {
+            if (getStamina() <= getMaxStamina() - 0.005f)
+            {
+                if (getThirst() > 0 && getHunger() > 0)
+                {
+                    setStamina(getStamina() + 0.005f);
+                    setHunger(getHunger() - 0.001f);
+                    setThirst(getThirst() - 0.003f);
+                }
+            }
         }
     }
     time.messungStart();
 }
 
-void Entity::api(Framework::StreamReader* zRequest, NetworkMessage* zResponse)
-{}
+void Entity::api(Framework::StreamReader* zRequest,
+    NetworkMessage* zResponse,
+    Entity* zSource)
+{
+    char type;
+    zRequest->lese(&type, 1);
+    switch (type)
+    {
+    case 0: // request status bar state
+        {
+            char len;
+            zRequest->lese(&len, 1);
+            char* guiId = new char[(int)len + 1];
+            zRequest->lese(guiId, len);
+            guiId[(int)len] = 0;
+            zResponse->addressGui(guiId);
+            addStatusBarObserver(zSource, guiId);
+            char* msg = new char[33];
+            msg[0] = 0;
+            *(float*)(msg + 1) = getMaxHP();
+            *(float*)(msg + 5) = getCurrentHP();
+            *(float*)(msg + 9) = getMaxStamina();
+            *(float*)(msg + 13) = getStamina();
+            *(float*)(msg + 17) = getMaxHunger();
+            *(float*)(msg + 21) = getHunger();
+            *(float*)(msg + 25) = getMaxThirst();
+            *(float*)(msg + 29) = getThirst();
+            zResponse->setMessage(msg, 33);
+            delete[] guiId;
+            break;
+        }
+    case 1: // remove status bar observer
+        {
+            char len;
+            zRequest->lese(&len, 1);
+            char* guiId = new char[(int)len + 1];
+            zRequest->lese(guiId, len);
+            guiId[(int)len] = 0;
+            removeStatusBarObserver(zSource, guiId);
+            delete[] guiId;
+            break;
+        }
+    }
+}
 
 void Entity::onFall(float collisionSpeed)
 {
@@ -434,6 +554,54 @@ void Entity::setPosition(Framework::Vec3<float> pos)
     location = pos;
 }
 
+void Entity::setHP(float hp)
+{
+    currentHP = MIN(MAX(hp, 0), maxHP);
+    NetworkMessage* msg = new NetworkMessage();
+    char* message = new char[9];
+    message[0] = 1;
+    *(float*)(message + 1) = getMaxHP();
+    *(float*)(message + 5) = getCurrentHP();
+    msg->setMessage(message, 9);
+    notifyStatusBarObservers(msg);
+}
+
+void Entity::setStamina(float stamina)
+{
+    this->stamina = MIN(MAX(stamina, 0), maxStamina);
+    NetworkMessage* msg = new NetworkMessage();
+    char* message = new char[9];
+    message[0] = 2;
+    *(float*)(message + 1) = getMaxStamina();
+    *(float*)(message + 5) = getStamina();
+    msg->setMessage(message, 9);
+    notifyStatusBarObservers(msg);
+}
+
+void Entity::setHunger(float hunger)
+{
+    this->hunger = MIN(MAX(hunger, 0), maxHunger);
+    NetworkMessage* msg = new NetworkMessage();
+    char* message = new char[9];
+    message[0] = 3;
+    *(float*)(message + 1) = getMaxHunger();
+    *(float*)(message + 5) = getHunger();
+    msg->setMessage(message, 9);
+    notifyStatusBarObservers(msg);
+}
+
+void Entity::setThirst(float thirst)
+{
+    this->thirst = MIN(MAX(thirst, 0), maxThirst);
+    NetworkMessage* msg = new NetworkMessage();
+    char* message = new char[9];
+    message[0] = 4;
+    *(float*)(message + 1) = getMaxThirst();
+    *(float*)(message + 5) = getThirst();
+    msg->setMessage(message, 9);
+    notifyStatusBarObservers(msg);
+}
+
 float Entity::getMaxHP() const
 {
     return maxHP;

+ 17 - 6
FactoryCraft/Entity.h

@@ -48,14 +48,16 @@ struct MovementFrame
 
 class Entity : public Inventory
 {
+private:
+    float stamina;
+    float hunger;
+    float currentHP;
+    float thirst;
+
 protected:
     float maxHP;
-    float currentHP;
-    float stamina;
     float maxStamina;
-    float hunger;
     float maxHunger;
-    float thirst;
     float maxThirst;
     float targetDistanceLimit;
     float maxMovementSpeed;
@@ -73,6 +75,8 @@ protected:
     Framework::ZeitMesser time;
     Framework::Array<MovementFrame> movements;
     Framework::Critical cs;
+    Framework::Array<Framework::ImmutablePair<int, Framework::Text>>
+        statusBarObservers;
 
     virtual void onDeath();
     virtual void useItem(int typeId, Item* zItem);
@@ -83,17 +87,24 @@ protected:
     void addMovementFrame(MovementFrame& frame);
     void calculateTarget(
         Framework::Vec3<float> basePos, Framework::Vec3<float> direction);
+    void removeStatusBarObserver(Entity* zSource, Framework::Text id);
+    void addStatusBarObserver(Entity* zSource, Framework::Text id);
+    void notifyStatusBarObservers(NetworkMessage* msg);
 
 public:
     virtual void prepareTick(const Dimension* zDimension);
     virtual void tick(const Dimension* zDimension);
 
-    virtual void api(
-        Framework::StreamReader* zRequest, NetworkMessage* zResponse);
+    virtual void api(Framework::StreamReader* zRequest,
+        NetworkMessage* zResponse, Entity* zSource);
     virtual void onTargetChange();
 
     virtual void onFall(float collisionSpeed);
     void setPosition(Framework::Vec3<float> pos);
+    void setHP(float hp);
+    void setStamina(float stamina);
+    void setHunger(float hunger);
+    void setThirst(float thirst);
     float getMaxHP() const;
     float getCurrentHP() const;
     float getStamina() const;

+ 1 - 1
FactoryCraft/Game.cpp

@@ -485,7 +485,7 @@ void Game::api(Framework::InMemoryBuffer* zRequest, GameClient* zOrigin)
                 Entity* entity = dim->zEntity(id);
                 if (entity)
                 {
-                    entity->api(zRequest, response);
+                    entity->api(zRequest, response, zOrigin->zEntity());
                     break;
                 }
             }

+ 4 - 4
FactoryCraft/Inventory.cpp

@@ -256,7 +256,7 @@ void Inventory::afterPullStack(
     *(int*)(message + 1) = zSlot->getId();
     *(int*)(message + 5) = zSlot->getNumberOfItems();
     msg->setMessage(message, 9);
-    notyObservers(msg);
+    notifyObservers(msg);
     for (auto call : afterPullStackCalls)
         call(zSlot, dir, zItem, count);
 }
@@ -272,7 +272,7 @@ void Inventory::afterPushStack(
         *(int*)(message + 1) = zSlot->getId();
         *(int*)(message + 5) = zSlot->getNumberOfItems();
         msg->setMessage(message, 9);
-        notyObservers(msg);
+        notifyObservers(msg);
     }
     else
     {
@@ -288,7 +288,7 @@ void Inventory::afterPushStack(
         *(float*)(message + 21) = zItem->getMaxDurability();
         *(int*)(message + 25) = zItem->zItemType()->getId();
         msg->setMessage(message, 29);
-        notyObservers(msg);
+        notifyObservers(msg);
     }
     for (auto call : afterPushStackCalls)
         call(zSlot, dir, zItem, count);
@@ -339,7 +339,7 @@ void Inventory::saveInventory(Framework::StreamWriter* zWriter)
     }
 }
 
-void Inventory::notyObservers(NetworkMessage* msg)
+void Inventory::notifyObservers(NetworkMessage* msg)
 {
     cs.lock();
     int index = 0;

+ 1 - 1
FactoryCraft/Inventory.h

@@ -78,7 +78,7 @@ protected:
 public:
     Inventory(const Framework::Vec3<float> location, bool hasInventory);
     virtual ~Inventory();
-    void notyObservers(NetworkMessage* msg);
+    void notifyObservers(NetworkMessage* msg);
     const ItemSlot* zSlot(int id) const;
     void addSlot(ItemSlot* slot);
     void localTransaction(Framework::Array<ItemSlot*>* zSourceSlots,

+ 5 - 5
FactoryCraft/ItemEntity.cpp

@@ -10,13 +10,13 @@ ItemEntity::ItemEntity(
     addSlot(slot);
     faceOffset = {0.f, 0.f, 0.f};
     maxHP = 10;
-    currentHP = 10;
-    stamina = 10;
     maxStamina = 10;
-    hunger = 10;
     maxHunger = 10;
-    thirst = 10;
     maxThirst = 10;
+    setHP(10);
+    setStamina(10);
+    setHunger(10);
+    setThirst(10);
     targetDistanceLimit = 4;
     maxMovementSpeed = 1;
 }
@@ -73,7 +73,7 @@ void ItemEntity::tick(const Dimension* zDimension)
 
 void ItemEntity::onFall(float collisionSpeed)
 {
-    if (collisionSpeed >= 50.f) this->currentHP = 0;
+    if (collisionSpeed >= 50.f) this->setHP(0);
 }
 
 bool ItemEntity::hasDefaultModel() const

+ 9 - 4
FactoryCraft/Player.cpp

@@ -22,13 +22,13 @@ Player::Player(Framework::Vec3<float> location, int dimensionId, int entityId)
     }
     leftHandPosition = 0;
     maxHP = 10;
-    currentHP = 10;
-    stamina = 10;
     maxStamina = 10;
-    hunger = 10;
     maxHunger = 10;
-    thirst = 10;
     maxThirst = 10;
+    setHP(10);
+    setStamina(10);
+    setHunger(10);
+    setThirst(10);
     keyState = 0;
     jumping = 0;
     faceOffset = {0.f, 0.f, 1.5f};
@@ -84,6 +84,11 @@ Framework::Text Player::getPlayerGUI()
            "height=\"52\" rowSize=\"10\" slotNameFilter=\"ItemBar\" target=\"";
     result += getId();
     result += "\"/>";
+    result
+        += "<statusBars id=\"gui_status_bars\" margin-bottom=\"9\" "
+           "align-bottom=\"gui_item_bar\" align-left=\"center\" target=\"";
+    result += getId();
+    result += "\"/>";
 
     result += "</gui>";
     return result;

+ 8 - 1
FactoryCraft/PlayerHand.cpp

@@ -1,6 +1,7 @@
 #include "PlayerHand.h"
 
 #include "Block.h"
+#include "Entity.h"
 
 PlayerHandItemType::PlayerHandItemType()
     : ItemType(ItemTypeEnum::PLAYER_HAND,
@@ -47,10 +48,16 @@ PlayerHandSkill::PlayerHandSkill()
 
 void PlayerHandSkill::use(Entity* zActor, Item* zUsedItem, Block* zTarget)
 {
-    if (zTarget && zTarget->getHardness() <= 1)
+    if (zTarget && zTarget->getHardness() <= 1 && zActor->getStamina() > 0.01f)
     {
+        zActor->setStamina(zActor->getStamina() - 0.001f);
         zTarget->setHP(zTarget->getHP() - 1 / (zTarget->getHardness() + 1));
     }
+    else
+    {
+        zActor->setStamina(zActor->getStamina() - 0.001f);
+        zActor->setHP(zActor->getCurrentHP() - 0.01f);
+    }
 }
 
 void PlayerHandSkill::use(Entity* zActor, Item* zUsedItem, Entity* zTarget)

+ 7 - 0
FactoryCraft/StoneTool.cpp

@@ -1,6 +1,7 @@
 #include "StoneTool.h"
 
 #include "Block.h"
+#include "Player.h"
 
 StoneToolItemType::StoneToolItemType()
     : ItemType(ItemTypeEnum::STONE_TOOL,
@@ -80,8 +81,14 @@ void StoneToolSkill::use(Entity* zActor, Item* zUsedItem, Block* zTarget)
             = (1 + ((float)level / 10.f)) / (zTarget->getHardness() + 1);
         zTarget->setHP(zTarget->getHP() - damage);
         xp += damage / 20;
+        zActor->setStamina(zActor->getStamina() - 0.0001f);
         zUsedItem->setHp(zUsedItem->getHp() - damage / 50);
     }
+    else
+    {
+        zActor->setStamina(zActor->getStamina() - 0.0001f);
+        zUsedItem->setHp(zUsedItem->getHp() - 0.001f);
+    }
 }
 
 void StoneToolSkill::use(Entity* zActor, Item* zUsedItem, Entity* zTarget)