- 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
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
*/
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);
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);
{
Player *player = m_env.getLocalPlayer();
assert(player != NULL);
- return player->breath;
+ return player->getBreath();
}
bool Client::getChatMessage(std::wstring &message)
void sendChangePassword(const std::wstring oldpassword,
const std::wstring newpassword);
void sendDamage(u8 damage);
+ void sendBreath(u16 breath);
void sendRespawn();
ClientEnvironment& getEnv()
u16 len
u8[len] value
*/
+
+ TOCLIENT_BREATH = 0x4e,
+ /*
+ u16 command
+ u16 breath
+ */
};
enum ToServerCommand
/*
u16 command
*/
+
+ TOSERVER_BREATH = 0x42,
+ /*
+ u16 command
+ u16 breath
+ */
};
#endif
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),
}
}
+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;
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);
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;
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);
}
}
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);
+ }
}
}
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
*/
enum ClientEnvEventType
{
CEE_NONE,
- CEE_PLAYER_DAMAGE
+ CEE_PLAYER_DAMAGE,
+ CEE_PLAYER_BREATH
};
struct ClientEnvEvent
u8 amount;
bool send_to_server;
} player_damage;
+ struct{
+ u16 amount;
+ } player_breath;
};
};
*/
void damageLocalPlayer(u8 damage, bool handle_hp=true);
+ void updateLocalPlayerBreath(u16 breath);
/*
Client likes to call these
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),
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);
}
}catch(SettingNotFoundException &e){
hp = 20;
}
+ try{
+ m_breath = args.getS32("breath");
+ }catch(SettingNotFoundException &e){
+ m_breath = 11;
+ }
inventory.deSerialize(is);
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;
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;
IGameDef *m_gamedef;
char m_name[PLAYERNAME_SIZE];
+ u16 m_breath;
f32 m_pitch;
f32 m_yaw;
v3f m_speed;
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)
{
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),
// 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);
SendPlayerHP(client->peer_id);
}
+ /*
+ Send player breath if changed
+ */
+ if(playersao->m_breath_not_sent){
+ SendPlayerBreath(client->peer_id);
+ }
+
/*
Send player inventories if necessary
*/
if(g_settings->getBool("enable_damage"))
SendPlayerHP(peer_id);
+ // Send Breath
+ SendPlayerBreath(peer_id);
+
// Send detached inventories
sendDetachedInventories(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)
{
/*
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)
{
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);
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,
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);