*/
#include "player.h"
+
+#include "threading/mutex_auto_lock.h"
+#include "util/numeric.h"
#include "hud.h"
#include "constants.h"
#include "gamedef.h"
-#include "connection.h" // PEER_ID_INEXISTENT
#include "settings.h"
-#include "content_sao.h"
-#include "util/numeric.h"
+#include "log.h"
+#include "porting.h" // strlcpy
+
-Player::Player(IGameDef *gamedef):
- touching_ground(false),
- in_liquid(false),
- in_liquid_stable(false),
- liquid_viscosity(0),
- is_climbing(false),
- swimming_vertical(false),
- camera_barely_in_ceiling(false),
- inventory(gamedef->idef()),
- hp(PLAYER_MAX_HP),
- peer_id(PEER_ID_INEXISTENT),
-// protected
- m_gamedef(gamedef),
- m_pitch(0),
- m_yaw(0),
- m_speed(0,0,0),
- m_position(0,0,0),
- m_collisionbox(-BS*0.30,0.0,-BS*0.30,BS*0.30,BS*1.55,BS*0.30)
+Player::Player(const char *name, IItemDefManager *idef):
+ inventory(idef)
{
- updateName("<not set>");
+ strlcpy(m_name, name, PLAYERNAME_SIZE);
+
inventory.clear();
inventory.addList("main", PLAYER_INVENTORY_SIZE);
InventoryList *craft = inventory.addList("craft", 9);
craft->setWidth(3);
inventory.addList("craftpreview", 1);
inventory.addList("craftresult", 1);
+ inventory.setModified(false);
// Can be redefined via Lua
- inventory_formspec = "size[8,7.5]"
+ inventory_formspec = "size[8,7.5]"
//"image[1,0.6;1,2;player.png]"
"list[current_player;main;0,3.5;8,4;]"
"list[current_player;craft;3,0;3,3;]"
+ "listring[]"
"list[current_player;craftpreview;7,1;1,1;]";
- // Initialize movement settings at default values, so movement can work if the server fails to send them
- movement_acceleration_default = 3 * BS;
- movement_acceleration_air = 2 * BS;
- movement_acceleration_fast = 10 * BS;
- movement_speed_walk = 4 * BS;
- movement_speed_crouch = 1.35 * BS;
- movement_speed_fast = 20 * BS;
- movement_speed_climb = 2 * BS;
- movement_speed_jump = 6.5 * BS;
- movement_liquid_fluidity = 1 * BS;
- movement_liquid_fluidity_smooth = 0.5 * BS;
- movement_liquid_sink = 10 * BS;
- movement_gravity = 9.81 * BS;
-
- // Movement overrides are multipliers and must be 1 by default
- physics_override_speed = 1;
- physics_override_jump = 1;
- physics_override_gravity = 1;
-
- hud_flags = HUD_DRAW_HOTBAR
- | HUD_DRAW_HEALTHBAR
- | HUD_DRAW_CROSSHAIR
- | HUD_DRAW_WIELDITEM;
+ // Initialize movement settings at default values, so movement can work
+ // if the server fails to send them
+ movement_acceleration_default = 3 * BS;
+ movement_acceleration_air = 2 * BS;
+ movement_acceleration_fast = 10 * BS;
+ movement_speed_walk = 4 * BS;
+ movement_speed_crouch = 1.35 * BS;
+ movement_speed_fast = 20 * BS;
+ movement_speed_climb = 2 * BS;
+ movement_speed_jump = 6.5 * BS;
+ movement_liquid_fluidity = 1 * BS;
+ movement_liquid_fluidity_smooth = 0.5 * BS;
+ movement_liquid_sink = 10 * BS;
+ movement_gravity = 9.81 * BS;
+ local_animation_speed = 0.0;
+
+ hud_flags =
+ HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE |
+ HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE |
+ HUD_FLAG_BREATHBAR_VISIBLE | HUD_FLAG_MINIMAP_VISIBLE |
+ HUD_FLAG_MINIMAP_RADAR_VISIBLE;
+
+ hud_hotbar_itemcount = HUD_HOTBAR_ITEMCOUNT_DEFAULT;
+
+ m_player_settings.readGlobalSettings();
+ // Register player setting callbacks
+ for (const std::string &name : m_player_settings.setting_names)
+ g_settings->registerChangedCallback(name,
+ &Player::settingsChangedCallback, &m_player_settings);
}
Player::~Player()
{
+ // m_player_settings becomes invalid, remove callbacks
+ for (const std::string &name : m_player_settings.setting_names)
+ g_settings->deregisterChangedCallback(name,
+ &Player::settingsChangedCallback, &m_player_settings);
+ clearHud();
}
-// Horizontal acceleration (X and Z), Y direction is ignored
-void Player::accelerateHorizontal(v3f target_speed, f32 max_increase)
+void Player::setWieldIndex(u16 index)
{
- if(max_increase == 0)
- return;
-
- v3f d_wanted = target_speed - m_speed;
- d_wanted.Y = 0;
- f32 dl = d_wanted.getLength();
- if(dl > max_increase)
- dl = max_increase;
-
- v3f d = d_wanted.normalize() * dl;
-
- m_speed.X += d.X;
- m_speed.Z += d.Z;
-
-#if 0 // old code
- if(m_speed.X < target_speed.X - max_increase)
- m_speed.X += max_increase;
- else if(m_speed.X > target_speed.X + max_increase)
- m_speed.X -= max_increase;
- else if(m_speed.X < target_speed.X)
- m_speed.X = target_speed.X;
- else if(m_speed.X > target_speed.X)
- m_speed.X = target_speed.X;
-
- if(m_speed.Z < target_speed.Z - max_increase)
- m_speed.Z += max_increase;
- else if(m_speed.Z > target_speed.Z + max_increase)
- m_speed.Z -= max_increase;
- else if(m_speed.Z < target_speed.Z)
- m_speed.Z = target_speed.Z;
- else if(m_speed.Z > target_speed.Z)
- m_speed.Z = target_speed.Z;
-#endif
+ const InventoryList *mlist = inventory.getList("main");
+ m_wield_index = MYMIN(index, mlist ? mlist->getSize() : 0);
}
-// Vertical acceleration (Y), X and Z directions are ignored
-void Player::accelerateVertical(v3f target_speed, f32 max_increase)
+ItemStack &Player::getWieldedItem(ItemStack *selected, ItemStack *hand) const
{
- if(max_increase == 0)
- return;
-
- f32 d_wanted = target_speed.Y - m_speed.Y;
- if(d_wanted > max_increase)
- d_wanted = max_increase;
- else if(d_wanted < -max_increase)
- d_wanted = -max_increase;
-
- m_speed.Y += d_wanted;
-
-#if 0 // old code
- if(m_speed.Y < target_speed.Y - max_increase)
- m_speed.Y += max_increase;
- else if(m_speed.Y > target_speed.Y + max_increase)
- m_speed.Y -= max_increase;
- else if(m_speed.Y < target_speed.Y)
- m_speed.Y = target_speed.Y;
- else if(m_speed.Y > target_speed.Y)
- m_speed.Y = target_speed.Y;
-#endif
-}
+ assert(selected);
-v3s16 Player::getLightPosition() const
-{
- return floatToInt(m_position + v3f(0,BS+BS/2,0), BS);
+ const InventoryList *mlist = inventory.getList("main"); // TODO: Make this generic
+ const InventoryList *hlist = inventory.getList("hand");
+
+ if (mlist && m_wield_index < mlist->getSize())
+ *selected = mlist->getItem(m_wield_index);
+
+ if (hand && hlist)
+ *hand = hlist->getItem(0);
+
+ // Return effective tool item
+ return (hand && selected->name.empty()) ? *hand : *selected;
}
-void Player::serialize(std::ostream &os)
+u32 Player::addHud(HudElement *toadd)
{
- // Utilize a Settings object for storing values
- Settings args;
- args.setS32("version", 1);
- args.set("name", m_name);
- //args.set("password", m_password);
- args.setFloat("pitch", m_pitch);
- args.setFloat("yaw", m_yaw);
- args.setV3F("position", m_position);
- args.setS32("hp", hp);
-
- args.writeLines(os);
-
- os<<"PlayerArgsEnd\n";
-
- inventory.serialize(os);
+ MutexAutoLock lock(m_mutex);
+
+ u32 id = getFreeHudID();
+
+ if (id < hud.size())
+ hud[id] = toadd;
+ else
+ hud.push_back(toadd);
+
+ return id;
}
-void Player::deSerialize(std::istream &is)
+HudElement* Player::getHud(u32 id)
{
- Settings args;
-
- for(;;)
- {
- if(is.eof())
- throw SerializationError
- ("Player::deSerialize(): PlayerArgsEnd not found");
- std::string line;
- std::getline(is, line);
- std::string trimmedline = trim(line);
- if(trimmedline == "PlayerArgsEnd")
- break;
- args.parseConfigLine(line);
- }
+ MutexAutoLock lock(m_mutex);
- //args.getS32("version"); // Version field value not used
- std::string name = args.get("name");
- updateName(name.c_str());
- setPitch(args.getFloat("pitch"));
- setYaw(args.getFloat("yaw"));
- setPosition(args.getV3F("position"));
- try{
- hp = args.getS32("hp");
- }catch(SettingNotFoundException &e){
- hp = 20;
- }
+ if (id < hud.size())
+ return hud[id];
- inventory.deSerialize(is);
-
- if(inventory.getList("craftpreview") == NULL)
- {
- // Convert players without craftpreview
- inventory.addList("craftpreview", 1);
-
- bool craftresult_is_preview = true;
- if(args.exists("craftresult_is_preview"))
- craftresult_is_preview = args.getBool("craftresult_is_preview");
- if(craftresult_is_preview)
- {
- // Clear craftresult
- inventory.getList("craftresult")->changeItem(0, ItemStack());
- }
- }
+ return NULL;
}
-/*
- RemotePlayer
-*/
+HudElement* Player::removeHud(u32 id)
+{
+ MutexAutoLock lock(m_mutex);
+ HudElement* retval = NULL;
+ if (id < hud.size()) {
+ retval = hud[id];
+ hud[id] = NULL;
+ }
+ return retval;
+}
+void Player::clearHud()
+{
+ MutexAutoLock lock(m_mutex);
+ while(!hud.empty()) {
+ delete hud.back();
+ hud.pop_back();
+ }
+}
+void PlayerSettings::readGlobalSettings()
+{
+ free_move = g_settings->getBool("free_move");
+ pitch_move = g_settings->getBool("pitch_move");
+ fast_move = g_settings->getBool("fast_move");
+ continuous_forward = g_settings->getBool("continuous_forward");
+ always_fly_fast = g_settings->getBool("always_fly_fast");
+ aux1_descends = g_settings->getBool("aux1_descends");
+ noclip = g_settings->getBool("noclip");
+ autojump = g_settings->getBool("autojump");
+}
-void RemotePlayer::setPosition(const v3f &position)
+void Player::settingsChangedCallback(const std::string &name, void *data)
{
- Player::setPosition(position);
- if(m_sao)
- m_sao->setBasePosition(position);
+ ((PlayerSettings *)data)->readGlobalSettings();
}