Browse Source

add gravity

Kolja Strohm 4 tháng trước cách đây
mục cha
commit
7159c5191b

+ 5 - 0
FactoryCraft/AddEntityUpdate.cpp

@@ -31,7 +31,12 @@ void AddEntityUpdate::write(Framework::StreamWriter* zWriter)
     zWriter->schreibe((char*)&pos.z, 4);
     float maxSpeed = entity->getMaxSpeed();
     zWriter->schreibe((char*)&maxSpeed, 4);
+    float gravityMultiplier = entity->getGravityMultiplier();
+    zWriter->schreibe((char*)&gravityMultiplier, 4);
+    float jumpSpeed = entity->getJumpSpeed();
+    zWriter->schreibe((char*)&jumpSpeed, 4);
     bool special = !entity->hasDefaultModel();
     zWriter->schreibe((char*)&special, 1);
     if (special) entity->zSpecialModel()->writeTo(zWriter);
+
 }

+ 12 - 0
FactoryCraft/Block.cpp

@@ -113,6 +113,18 @@ void Block::broadcastMessage(NetworkMessage* message)
     }
 }
 
+void Block::broadcastPassableSpeedModifierChange()
+{
+    NetworkMessage* message = new NetworkMessage();
+    message->addressBlock(this);
+    char* msg = new char[6];
+    msg[0] = 3;
+    msg[1] = passable;
+    *(float*)(msg + 2) = speedModifier;
+    message->setMessage(msg, 6);
+    broadcastMessage(message);
+}
+
 void Block::tick(TickQueue* zQueue)
 {
     if (wasTicked) return;

+ 1 - 0
FactoryCraft/Block.h

@@ -74,6 +74,7 @@ protected:
     virtual void onDialogClosed(Framework::Text dialogId);
     void broadcastModelInfoChange();
     void broadcastMessage(NetworkMessage* message);
+    void broadcastPassableSpeedModifierChange();
 
 public:
     Block(int typeId,

+ 57 - 16
FactoryCraft/Chunk.cpp

@@ -478,6 +478,7 @@ void Chunk::initializeLightning()
 Framework::Either<Block*, int> Chunk::zBlockAt(
     Framework::Vec3<int> location) const
 {
+    if (location.z < 0 || location.z >= WORLD_HEIGHT) return 0;
     int index = Chunk::index(location);
     assert(index < CHUNK_SIZE * CHUNK_SIZE * WORLD_HEIGHT);
     if (blocks[index])
@@ -670,13 +671,37 @@ void Chunk::putBlockTypeAt(Framework::Vec3<int> location, int type)
 void Chunk::sendBlockInfo(Framework::Vec3<int> location)
 {
     int index = Chunk::index(location);
-    char* msg = new char[9];
+    char* msg = new char[14];
     msg[0] = 0; // set block
-    *(int*)(msg + 1) = index;
-    *(int*)(msg + 5) = blockIds[index];
+    *(unsigned short*)(msg + 1) = blockIds[index];
+    *(int*)(msg + 3) = index;
+    char state = 0;
+    const BlockType* type = Game::INSTANCE->zBlockType(blockIds[index]);
+    if (type->isFluid())
+    {
+        state |= 1;
+    }
+    if ((blocks[index] && blocks[index]->isPassable())
+        || (type->zDefault()->isPassable()))
+    {
+        state |= 2;
+    }
+    msg[7] = state;
+    if ((state | 1) == state)
+    {
+        FluidBlock* fluidBlock = dynamic_cast<FluidBlock*>(blocks[index]);
+        msg[8] = fluidBlock ? fluidBlock->getFlowOptions() : 0;
+        msg[9] = fluidBlock ? fluidBlock->getDistanceToSource() : 0;
+    }
+    if ((state | 2) == state)
+    {
+        *(float*)(msg + 10) = blocks[index]
+                                ? blocks[index]->getSpeedModifier()
+                                : type->zDefault()->getSpeedModifier();
+    }
     NetworkMessage* message = new NetworkMessage();
     message->addressChunck(this);
-    message->setMessage(msg, 9);
+    message->setMessage(msg, 14);
     notifyObservers(message);
     if (blocks[index])
     {
@@ -874,26 +899,42 @@ void Chunk::sendToClient(Framework::StreamWriter* zWriter)
             for (int z = 0; z < WORLD_HEIGHT; z++)
             {
                 int index = Chunk::index({x, y, z});
-                if (isVisible(index)
-                    && Game::INSTANCE->zBlockType(blockIds[index])
-                           ->doesNeedClientInstance())
+                const BlockType* type
+                    = Game::INSTANCE->zBlockType(blockIds[index]);
+                if (isVisible(index) && type->doesNeedClientInstance())
                 {
-                    unsigned short blockType = blocks[index]
-                                                 ? (unsigned short)blocks[index]
-                                                       ->zBlockType()
-                                                       ->getId()
-                                                 : blockIds[index];
-                    zWriter->schreibe((char*)&blockType, 2);
+                    zWriter->schreibe((char*)&blockIds[index], 2);
                     zWriter->schreibe((char*)&index, 4);
-                    if (Game::INSTANCE->zBlockType(blockIds[index])->isFluid())
+                    char state = 0;
+                    if (type->isFluid())
+                    {
+                        state |= 1;
+                    }
+                    if ((blocks[index] && blocks[index]->isPassable())
+                        || (type->zDefault()->isPassable()))
+                    {
+                        state |= 2;
+                    }
+                    zWriter->schreibe((char*)&state, 1);
+                    if ((state | 1) == state)
                     {
                         FluidBlock* fluidBlock
                             = dynamic_cast<FluidBlock*>(blocks[index]);
-                        char data = fluidBlock->getFlowOptions();
+                        char data
+                            = fluidBlock ? fluidBlock->getFlowOptions() : 0;
                         zWriter->schreibe(&data, 1);
-                        data = fluidBlock->getDistanceToSource();
+                        data = fluidBlock ? fluidBlock->getDistanceToSource()
+                                          : 0;
                         zWriter->schreibe(&data, 1);
                     }
+                    if ((state | 2) == state)
+                    {
+                        float speedModifier
+                            = blocks[index]
+                                ? blocks[index]->getSpeedModifier()
+                                : type->zDefault()->getSpeedModifier();
+                        zWriter->schreibe((char*)&speedModifier, 4);
+                    }
                 }
             }
         }

+ 21 - 2
FactoryCraft/Entity.cpp

@@ -224,6 +224,7 @@ Entity::Entity(
       typeId(typeId),
       removed(0),
       gravityMultiplier(1.f),
+      jumpSpeed(0.f),
       id(entityId),
       placeBlockCooldown(0)
 {}
@@ -705,9 +706,9 @@ void Entity::api(Framework::StreamReader* zRequest,
 
 void Entity::onFall(float collisionSpeed)
 {
-    if (collisionSpeed > 5)
+    if (collisionSpeed > 10)
     {
-        // TODO: take damage
+        setHP(getCurrentHP() - (collisionSpeed - 10.f) / 2.5f);
     }
 }
 
@@ -731,6 +732,10 @@ void Entity::setHP(float hp)
     *(float*)(message + 5) = getCurrentHP();
     msg->setMessage(message, 9);
     notifyStatusBarObservers(msg);
+    if (currentHP == 0)
+    {
+         onDeath();
+    }
 }
 
 void Entity::setStamina(float stamina)
@@ -769,6 +774,10 @@ void Entity::setThirst(float thirst)
     notifyStatusBarObservers(msg);
 }
 
+void Entity::setGravityMultiplier(float multiplier) {
+	gravityMultiplier = multiplier;
+}
+
 float Entity::getMaxHP() const
 {
     return maxHP;
@@ -829,6 +838,16 @@ float Entity::getGravityMultiplier() const
     return gravityMultiplier;
 }
 
+float Entity::getJumpSpeed() const
+{
+    return jumpSpeed;
+}
+
+void Entity::setJumpSpeed(float speed)
+{
+    jumpSpeed = speed;
+}
+
 bool Entity::isRemoved() const
 {
     return removed;

+ 4 - 0
FactoryCraft/Entity.h

@@ -73,6 +73,7 @@ protected:
     int typeId;
     bool removed;
     float gravityMultiplier;
+    float jumpSpeed;
     int id;
     int placeBlockCooldown;
     Framework::ZeitMesser time;
@@ -113,6 +114,8 @@ public:
     void setStamina(float stamina);
     void setHunger(float hunger);
     void setThirst(float thirst);
+    void setGravityMultiplier(float multiplier);
+    void setJumpSpeed(float speed);
     float getMaxHP() const;
     float getCurrentHP() const;
     float getStamina() const;
@@ -125,6 +128,7 @@ public:
     Framework::Vec3<float> getFaceDir() const;
     Framework::Vec3<float> getPosition() const;
     float getGravityMultiplier() const;
+    float getJumpSpeed() const;
     bool isRemoved() const;
     const EntityType* zType() const;
     const ActionTarget* zTarget() const;

+ 4 - 0
FactoryCraft/EntityType.cpp

@@ -39,6 +39,8 @@ void EntityType::loadSuperEntity(
     zReader->lese((char*)&zEntity->location.x, 4);
     zReader->lese((char*)&zEntity->location.y, 4);
     zReader->lese((char*)&zEntity->location.z, 4);
+    zReader->lese((char*)&zEntity->gravityMultiplier, 4);
+    zReader->lese((char*)&zEntity->jumpSpeed, 4);
     if (zEntity->target) delete zEntity->target;
     zEntity->target = ActionTarget::load(zReader);
     // load item skills
@@ -79,6 +81,8 @@ void EntityType::saveSuperEntity(
     zWriter->schreibe((char*)&zEntity->location.x, 4);
     zWriter->schreibe((char*)&zEntity->location.y, 4);
     zWriter->schreibe((char*)&zEntity->location.z, 4);
+    zWriter->schreibe((char*)&zEntity->gravityMultiplier, 4);
+    zWriter->schreibe((char*)&zEntity->jumpSpeed, 4);
     ActionTarget::save(zEntity->target, zWriter);
     // save item skills
     int skillCount = zEntity->skills.getEintragAnzahl();

+ 10 - 1
FactoryCraft/Game.cpp

@@ -158,13 +158,22 @@ void GameClient::reply()
     other.unlock();
     if (first)
     {
-        foreground.lock();
+        foreground.lock(); 
         int id = zPlayer->getId();
         client->zForegroundWriter()->schreibe(
             (char*)&Message::POSITION_UPDATE, 1);
         client->zForegroundWriter()->schreibe((char*)&id, 4);
         id = zPlayer->getDimensionId();
         client->zForegroundWriter()->schreibe((char*)&id, 4);
+        client->zForegroundWriter()->schreibe((char*)&Message::API_MESSAGE, 1);
+        int len = 10;
+        client->zForegroundWriter()->schreibe((char*)&len, 4);
+        client->zForegroundWriter()->schreibe("\1", 1);
+        client->zForegroundWriter()->schreibe((char*)&id, 4);
+        client->zForegroundWriter()->schreibe("\6", 1);
+        float gravity = Game::INSTANCE->zDimension(zPlayer->getDimensionId())
+                            ->getGravity();
+        client->zForegroundWriter()->schreibe((char*)&gravity, 4);
         foreground.unlock();
         first = 0;
     }

+ 19 - 49
FactoryCraft/Player.cpp

@@ -2,6 +2,7 @@
 
 #include "ArrayUtils.h"
 #include "Block.h"
+#include "Chat.h"
 #include "Game.h"
 #include "ItemFilter.h"
 #include "ItemStack.h"
@@ -34,6 +35,7 @@ Player::Player(Framework::Vec3<float> location, int dimensionId, int entityId)
     setStamina(10);
     setHunger(10);
     setThirst(10);
+    setJumpSpeed(5.f);
     keyState = 0;
     jumping = 0;
     faceOffset = {0.f, 0.f, 1.5f};
@@ -349,53 +351,11 @@ void Player::playerApi(
                 new QuestDialog(getId()));
             break;
         }
-    case 10: // request quest graph
+    case 10: // fall damage
         {
-            /*
-            unsigned char length;
-            zRequest->lese((char*)&length, 1);
-            char* collectionName = new char[length + 1];
-            zRequest->lese(collectionName, length);
-            collectionName[length] = 0;
-            Framework::Text uiml
-                = Game::INSTANCE->zQuestManager()->getQuestGraphUIML(
-                    this, collectionName);
-            delete[] collectionName;
-            zRequest->lese((char*)&length, 1);
-            char* guiId = new char[(int)length + 1];
-            zRequest->lese(guiId, length);
-            guiId[(int)length] = 0;
-            zResponse->addressGui(guiId);
-            delete[] guiId;
-            int msgSize = 4 + uiml.getLength();
-            char* msg = new char[msgSize];
-            *(int*)msg = uiml.getLength();
-            memcpy(msg + 4, uiml.getText(), uiml.getLength());
-            zResponse->setMessage(msg, msgSize);*/
-            break;
-        }
-    case 11: // request quest view
-        {
-            /* unsigned char length;
-            zRequest->lese((char*)&length, 1);
-            char* questName = new char[length + 1];
-            zRequest->lese(questName, length);
-            questName[length] = 0;
-            Framework::Text uiml
-                = Game::INSTANCE->zQuestManager()->getQuestViewUIML(
-                    this, questName);
-            delete[] questName;
-            zRequest->lese((char*)&length, 1);
-            char* guiId = new char[(int)length + 1];
-            zRequest->lese(guiId, length);
-            guiId[(int)length] = 0;
-            zResponse->addressGui(guiId);
-            delete[] guiId;
-            int msgSize = 4 + uiml.getLength();
-            char* msg = new char[msgSize];
-            *(int*)msg = uiml.getLength();
-            memcpy(msg + 4, uiml.getText(), uiml.getLength());
-            zResponse->setMessage(msg, msgSize);*/
+            float speed = 0.f;
+            zRequest->lese((char*)&speed, 4);
+            onFall(speed);
             break;
         }
     }
@@ -404,13 +364,23 @@ void Player::playerApi(
 void Player::onFall(float collisionSpeed)
 {
     Entity::onFall(collisionSpeed);
-    gravityMultiplier = 1.f;
-    jumping = 0;
+    // TODO: check validity
+}
+
+void Player::onDeath()
+{
+    this->setHP(this->getMaxHP());
+    Game::INSTANCE->zChat()->broadcastMessage(
+        name + " died!", Chat::CHANNEL_INFO);
+    // TODO: respown
 }
 
 PlayerEntityType::PlayerEntityType()
     : EntityType("Player",
-        new ModelInfo("player", toArray("player.ltdb/player.png", 6), 0, 1.f))
+        new ModelInfo("entities.m3/player",
+            toArray("entities.ltdb/player.png", 6),
+            0,
+            1.f))
 {}
 
 void PlayerEntityType::loadSuperEntity(

+ 1 - 0
FactoryCraft/Player.h

@@ -42,6 +42,7 @@ public:
     void playerApi(
         Framework::StreamReader* zRequest, NetworkMessage* zResponse);
     void onFall(float collisionSpeed) override;
+    void onDeath() override;
 
     friend PlayerEntityType;
 };