Add set_breath and get_breath to lua API.
authorRealBadAngel <mk@realbadangel.pl>
Fri, 19 Jul 2013 17:50:33 +0000 (19:50 +0200)
committerRealBadAngel <mk@realbadangel.pl>
Sat, 20 Jul 2013 18:34:11 +0000 (20:34 +0200)
14 files changed:
doc/lua_api.txt
src/client.cpp
src/client.h
src/clientserver.h
src/content_sao.cpp
src/content_sao.h
src/environment.cpp
src/environment.h
src/player.cpp
src/player.h
src/script/lua_api/l_object.cpp
src/script/lua_api/l_object.h
src/server.cpp
src/server.h

index 74b3d3ba5a72ebc141fb7a77ebe5e17820667604..6a4d198386aa149df60b246975ed19e6c5d230dd 100644 (file)
@@ -1547,6 +1547,11 @@ Player-only: (no-op for other objects)
 - get_look_yaw(): yaw in radians (wraps around pretty randomly as of now)
 - set_look_pitch(radians): sets look pitch
 - set_look_yaw(radians): sets look yaw
+- get_breath() : returns players breath
+- set_breath(value) : sets players breath
+    values: 0    player is drowning,
+            1-10 number of bubbles remain,
+            11   bubbles bar is not shown
 - set_inventory_formspec(formspec)
   ^ Redefine player's inventory form
   ^ Should usually be called in on_joinplayer
index c458684f60ca5e3a4a65df41973eb3fb2cfe9fbd..e5ba1485045ce59a027314218a592916f76fb9d5 100644 (file)
@@ -692,9 +692,14 @@ void Client::step(float dtime)
                                        m_client_event_queue.push_back(event);
                                }
                        }
+                       else if(event.type == CEE_PLAYER_BREATH)
+                       {
+                                       u16 breath = event.player_breath.amount;
+                                       sendBreath(breath);
+                       }
                }
        }
-       
+
        /*
                Print some info
        */
@@ -1579,6 +1584,15 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
                        m_client_event_queue.push_back(event);
                }
        }
+       else if(command == TOCLIENT_BREATH)
+       {
+               std::string datastring((char*)&data[2], datasize-2);
+               std::istringstream is(datastring, std::ios_base::binary);
+               Player *player = m_env.getLocalPlayer();
+               assert(player != NULL);
+               u16 breath = readU16(is);
+               player->setBreath(breath) ;
+       }
        else if(command == TOCLIENT_MOVE_PLAYER)
        {
                std::string datastring((char*)&data[2], datasize-2);
@@ -2359,6 +2373,20 @@ void Client::sendDamage(u8 damage)
        Send(0, data, true);
 }
 
+void Client::sendBreath(u16 breath)
+{
+       DSTACK(__FUNCTION_NAME);
+       std::ostringstream os(std::ios_base::binary);
+
+       writeU16(os, TOSERVER_BREATH);
+       writeU16(os, breath);
+       // Make data buffer
+       std::string s = os.str();
+       SharedBuffer<u8> data((u8*)s.c_str(), s.size());
+       // Send as reliable
+       Send(0, data, true);
+}
+
 void Client::sendRespawn()
 {
        DSTACK(__FUNCTION_NAME);
@@ -2694,7 +2722,7 @@ u16 Client::getBreath()
 {
        Player *player = m_env.getLocalPlayer();
        assert(player != NULL);
-       return player->breath;
+       return player->getBreath();
 }
 
 bool Client::getChatMessage(std::wstring &message)
index 0b69abf569ce89791ce53c436cc14dc6152f40b7..84cabf3f8c917014f7ad5353c49411c63d8b06ca 100644 (file)
@@ -306,6 +306,7 @@ public:
        void sendChangePassword(const std::wstring oldpassword,
                        const std::wstring newpassword);
        void sendDamage(u8 damage);
+       void sendBreath(u16 breath);
        void sendRespawn();
 
        ClientEnvironment& getEnv()
index a43baab23c6b29d84efa57d0b944d18b88c0deb4..a84d29a9020aa8c97a979be271c19c3932453fff 100644 (file)
@@ -488,6 +488,12 @@ enum ToClientCommand
                u16 len
                u8[len] value
        */
+
+       TOCLIENT_BREATH = 0x4e,
+       /*
+               u16 command
+               u16 breath
+       */
 };
 
 enum ToServerCommand
@@ -711,6 +717,12 @@ enum ToServerCommand
        /*
                u16 command
        */
+
+       TOSERVER_BREATH = 0x42,
+       /*
+               u16 command
+               u16 breath
+       */
 };
 
 #endif
index cc02a743146264f939141fe889e12fff628788be..993859f1c6e6ebb32e0141c7c5d807e78d6a9c0e 100644 (file)
@@ -935,6 +935,7 @@ PlayerSAO::PlayerSAO(ServerEnvironment *env_, Player *player_, u16 peer_id_,
        m_moved(false),
        m_inventory_not_sent(false),
        m_hp_not_sent(false),
+       m_breath_not_sent(false),
        m_wielded_item_not_sent(false),
        m_physics_override_speed(1),
        m_physics_override_jump(1),
@@ -1370,6 +1371,16 @@ void PlayerSAO::setHP(s16 hp)
        }
 }
 
+u16 PlayerSAO::getBreath() const
+{
+       return m_player->getBreath();
+}
+
+void PlayerSAO::setBreath(u16 breath)
+{
+       m_player->setBreath(breath);
+}
+
 void PlayerSAO::setArmorGroups(const ItemGroupList &armor_groups)
 {
        m_armor_groups = armor_groups;
index dca02bb00ba5e2e6cbb55b56072fe182f0a8e87f..bfce83d02fd1d9a3c8c9da8e2af79aecf23bbc46 100644 (file)
@@ -162,7 +162,8 @@ public:
        void rightClick(ServerActiveObject *clicker);
        s16 getHP() const;
        void setHP(s16 hp);
-       
+       u16 getBreath() const;
+       void setBreath(u16 breath);
        void setArmorGroups(const ItemGroupList &armor_groups);
        void setAnimation(v2f frame_range, float frame_speed, float frame_blend);
        void setBonePosition(std::string bone, v3f position, v3f rotation);
@@ -282,6 +283,7 @@ public:
        bool m_moved;
        bool m_inventory_not_sent;
        bool m_hp_not_sent;
+       bool m_breath_not_sent;
        bool m_wielded_item_not_sent;
 
        float m_physics_override_speed;
index cd87839847236f28b310f8c10007e7a3b7a87a52..57fdfd7e577d4b293ff1729bdb8892280c7b8e39 100644 (file)
@@ -2242,15 +2242,19 @@ void ClientEnvironment::step(float dtime)
                v3s16 p = floatToInt(pf + v3f(0, BS*1.6, 0), BS);
                MapNode n = m_map->getNodeNoEx(p);
                ContentFeatures c = m_gamedef->ndef()->get(n);
-
-               if(c.isLiquid() && c.drowning){
-                       if(lplayer->breath > 10)
-                               lplayer->breath = 11;
-                       if(lplayer->breath > 0)
-                               lplayer->breath -= 1;
+               if(c.isLiquid() && c.drowning && lplayer->hp > 0){
+                       u16 breath = lplayer->getBreath();
+                       if(breath > 10){
+                               breath = 11;
+                       }
+                       if(breath > 0){
+                               breath -= 1;
+                       }
+                       lplayer->setBreath(breath);
+                       updateLocalPlayerBreath(breath);
                }
 
-               if(lplayer->breath == 0){
+               if(lplayer->getBreath() == 0){
                        damageLocalPlayer(1, true);
                }
        }
@@ -2262,10 +2266,16 @@ void ClientEnvironment::step(float dtime)
                v3s16 p = floatToInt(pf + v3f(0, BS*1.6, 0), BS);
                MapNode n = m_map->getNodeNoEx(p);
                ContentFeatures c = m_gamedef->ndef()->get(n);
-
-               if(!c.isLiquid() || !c.drowning){
-                       if(lplayer->breath <= 10)
-                               lplayer->breath += 1;
+               if (!lplayer->hp){
+                       lplayer->setBreath(11);
+               }
+               else if(!c.isLiquid() || !c.drowning){
+                       u16 breath = lplayer->getBreath();
+                       if(breath <= 10){
+                               breath += 1;
+                               lplayer->setBreath(breath);
+                               updateLocalPlayerBreath(breath);
+                       }
                }
        }
 
@@ -2528,6 +2538,14 @@ void ClientEnvironment::damageLocalPlayer(u8 damage, bool handle_hp)
        m_client_event_queue.push_back(event);
 }
 
+void ClientEnvironment::updateLocalPlayerBreath(u16 breath)
+{
+       ClientEnvEvent event;
+       event.type = CEE_PLAYER_BREATH;
+       event.player_breath.amount = breath;
+       m_client_event_queue.push_back(event);
+}
+
 /*
        Client likes to call these
 */
index ac479999cf748d29a09f5a18e72b74afd64dc7be..e175d70d9d2c81ec0c4a2ad43ed683b1c0559b42 100644 (file)
@@ -395,7 +395,8 @@ class ClientSimpleObject;
 enum ClientEnvEventType
 {
        CEE_NONE,
-       CEE_PLAYER_DAMAGE
+       CEE_PLAYER_DAMAGE,
+       CEE_PLAYER_BREATH
 };
 
 struct ClientEnvEvent
@@ -408,6 +409,9 @@ struct ClientEnvEvent
                        u8 amount;
                        bool send_to_server;
                } player_damage;
+               struct{
+                       u16 amount;
+               } player_breath;
        };
 };
 
@@ -462,6 +466,7 @@ public:
        */
 
        void damageLocalPlayer(u8 damage, bool handle_hp=true);
+       void updateLocalPlayerBreath(u16 breath);
 
        /*
                Client likes to call these
index 2a7a3084c760e345dc56ad858e955a38148465c5..8028fe6afb57d5cb7e750bb04d268b554fea2e31 100644 (file)
@@ -36,10 +36,10 @@ Player::Player(IGameDef *gamedef):
        camera_barely_in_ceiling(false),
        inventory(gamedef->idef()),
        hp(PLAYER_MAX_HP),
-       breath(-1),
        peer_id(PEER_ID_INEXISTENT),
 // protected
        m_gamedef(gamedef),
+       m_breath(-1),
        m_pitch(0),
        m_yaw(0),
        m_speed(0,0,0),
@@ -177,11 +177,12 @@ void Player::serialize(std::ostream &os)
        args.setFloat("yaw", m_yaw);
        args.setV3F("position", m_position);
        args.setS32("hp", hp);
+       args.setS32("breath", m_breath);
 
        args.writeLines(os);
 
        os<<"PlayerArgsEnd\n";
-       
+
        inventory.serialize(os);
 }
 
@@ -213,6 +214,11 @@ void Player::deSerialize(std::istream &is, std::string playername)
        }catch(SettingNotFoundException &e){
                hp = 20;
        }
+       try{
+               m_breath = args.getS32("breath");
+       }catch(SettingNotFoundException &e){
+               m_breath = 11;
+       }
 
        inventory.deSerialize(is);
 
index 60645a60f55f9a1329dc4f3b4c5e146d8638ee54..7ddc40b370356ea42dc2af7ec1503b0da58880ce 100644 (file)
@@ -160,6 +160,16 @@ public:
                return m_yaw;
        }
 
+       u16 getBreath()
+       {
+               return m_breath;
+       }
+
+       virtual void setBreath(u16 breath)
+       {
+               m_breath = breath;
+       }
+
        f32 getRadPitch()
        {
                return -1.0 * m_pitch * core::DEGTORAD;
@@ -249,13 +259,12 @@ public:
        float physics_override_gravity;
 
        u16 hp;
-       u16 breath;
 
        float hurt_tilt_timer;
        float hurt_tilt_strength;
 
        u16 peer_id;
-       
+
        std::string inventory_formspec;
        
        PlayerControl control;
@@ -274,6 +283,7 @@ protected:
        IGameDef *m_gamedef;
 
        char m_name[PLAYERNAME_SIZE];
+       u16 m_breath;
        f32 m_pitch;
        f32 m_yaw;
        v3f m_speed;
index f90b59285bdde7de38a9c71888cb70f472b83c5f..ee24789c5a54e548ca9f9d4c77f4dd31c29549e8 100644 (file)
@@ -702,6 +702,33 @@ int ObjectRef::l_set_look_yaw(lua_State *L)
        return 1;
 }
 
+// set_breath(self, breath)
+int ObjectRef::l_set_breath(lua_State *L)
+{
+       NO_MAP_LOCK_REQUIRED;
+       ObjectRef *ref = checkobject(L, 1);
+       PlayerSAO* co = getplayersao(ref);
+       if(co == NULL) return 0;
+       u16 breath = luaL_checknumber(L, 2);
+       // Do it
+       co->setBreath(breath);
+       co->m_breath_not_sent = true;
+       return 0;
+}
+
+// get_breath(self)
+int ObjectRef::l_get_breath(lua_State *L)
+{
+       NO_MAP_LOCK_REQUIRED;
+       ObjectRef *ref = checkobject(L, 1);
+       PlayerSAO* co = getplayersao(ref);
+       if(co == NULL) return 0;
+       // Do it
+       u16 breath = co->getBreath();
+       lua_pushinteger (L, breath);
+       return 1;
+}
+
 // set_inventory_formspec(self, formspec)
 int ObjectRef::l_set_inventory_formspec(lua_State *L)
 {
@@ -1098,6 +1125,8 @@ const luaL_reg ObjectRef::methods[] = {
        luamethod(ObjectRef, get_look_yaw),
        luamethod(ObjectRef, set_look_yaw),
        luamethod(ObjectRef, set_look_pitch),
+       luamethod(ObjectRef, get_breath),
+       luamethod(ObjectRef, set_breath),
        luamethod(ObjectRef, set_inventory_formspec),
        luamethod(ObjectRef, get_inventory_formspec),
        luamethod(ObjectRef, get_player_control),
index 57dac0e6486eea17fdd08223c3d572bfd7c646be..a826384421153a12f60662c767f2dc021c87fbfe 100644 (file)
@@ -179,6 +179,12 @@ private:
        // set_look_yaw(self, radians)
        static int l_set_look_yaw(lua_State *L);
 
+       // set_breath(self, breath)
+       static int l_set_breath(lua_State *L);
+
+       // get_breath(self, breath)
+       static int l_get_breath(lua_State *L);
+
        // set_inventory_formspec(self, formspec)
        static int l_set_inventory_formspec(lua_State *L);
 
index 955858c70217f74c543946ef0517398459ede2d5..3bba193da5365c903a4d297d9ee9afba6a669369 100644 (file)
@@ -1139,6 +1139,13 @@ void Server::AsyncRunStep()
                                        SendPlayerHP(client->peer_id);
                        }
 
+                       /*
+                               Send player breath if changed
+                       */
+                       if(playersao->m_breath_not_sent){
+                               SendPlayerBreath(client->peer_id);
+                       }
+
                        /*
                                Send player inventories if necessary
                        */
@@ -2105,6 +2112,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                if(g_settings->getBool("enable_damage"))
                        SendPlayerHP(peer_id);
 
+               // Send Breath
+               SendPlayerBreath(peer_id);
+
                // Send detached inventories
                sendDetachedInventories(peer_id);
 
@@ -2583,6 +2593,13 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                SendPlayerHP(peer_id);
                }
        }
+       else if(command == TOSERVER_BREATH)
+       {
+               std::string datastring((char*)&data[2], datasize-2);
+               std::istringstream is(datastring, std::ios_base::binary);
+               u16 breath = readU16(is);
+               playersao->setBreath(breath);
+       }
        else if(command == TOSERVER_PASSWORD)
        {
                /*
@@ -3326,6 +3343,21 @@ void Server::SendHP(con::Connection &con, u16 peer_id, u8 hp)
        con.Send(peer_id, 0, data, true);
 }
 
+void Server::SendBreath(con::Connection &con, u16 peer_id, u16 breath)
+{
+       DSTACK(__FUNCTION_NAME);
+       std::ostringstream os(std::ios_base::binary);
+
+       writeU16(os, TOCLIENT_BREATH);
+       writeU16(os, breath);
+
+       // Make data buffer
+       std::string s = os.str();
+       SharedBuffer<u8> data((u8*)s.c_str(), s.size());
+       // Send as reliable
+       con.Send(peer_id, 0, data, true);
+}
+
 void Server::SendAccessDenied(con::Connection &con, u16 peer_id,
                const std::wstring &reason)
 {
@@ -3755,6 +3787,15 @@ void Server::SendPlayerHP(u16 peer_id)
        SendHP(m_con, peer_id, playersao->getHP());
 }
 
+void Server::SendPlayerBreath(u16 peer_id)
+{
+       DSTACK(__FUNCTION_NAME);
+       PlayerSAO *playersao = getPlayerSAO(peer_id);
+       assert(playersao);
+       playersao->m_breath_not_sent = false;
+       SendBreath(m_con, peer_id, playersao->getBreath());
+}
+
 void Server::SendMovePlayer(u16 peer_id)
 {
        DSTACK(__FUNCTION_NAME);
index edc5c4895d71fd1fa8f1b0b8cdd93d4034945b50..65762d901d1184d218c1d2411e11b730dffcf0ca 100644 (file)
@@ -557,6 +557,7 @@ private:
 
        static void SendMovement(con::Connection &con, u16 peer_id);
        static void SendHP(con::Connection &con, u16 peer_id, u8 hp);
+       static void SendBreath(con::Connection &con, u16 peer_id, u16 breath);
        static void SendAccessDenied(con::Connection &con, u16 peer_id,
                        const std::wstring &reason);
        static void SendDeathscreen(con::Connection &con, u16 peer_id,
@@ -578,6 +579,7 @@ private:
        void SendChatMessage(u16 peer_id, const std::wstring &message);
        void BroadcastChatMessage(const std::wstring &message);
        void SendPlayerHP(u16 peer_id);
+       void SendPlayerBreath(u16 peer_id);
        void SendMovePlayer(u16 peer_id);
        void SendPlayerPrivileges(u16 peer_id);
        void SendPlayerInventoryFormspec(u16 peer_id);