diff --git a/src/environment.cpp b/src/environment.cpp index bc246f66c..514aa918a 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -603,8 +603,9 @@ void ServerEnvironment::kickAllPlayers(AccessDeniedCode reason, { for (std::vector::iterator it = m_players.begin(); it != m_players.end(); ++it) { - ((Server*)m_gamedef)->DenyAccessVerCompliant((*it)->peer_id, - (*it)->protocol_version, reason, str_reason, reconnect); + RemotePlayer *player = dynamic_cast(*it); + ((Server*)m_gamedef)->DenyAccessVerCompliant(player->peer_id, + player->protocol_version, reason, str_reason, reconnect); } } @@ -618,7 +619,7 @@ void ServerEnvironment::saveLoadedPlayers() ++it) { RemotePlayer *player = static_cast(*it); if (player->checkModified()) { - player->save(players_path); + player->save(players_path, m_gamedef); } } } @@ -628,7 +629,7 @@ void ServerEnvironment::savePlayer(RemotePlayer *player) std::string players_path = m_path_world + DIR_DELIM "players"; fs::CreateDir(players_path); - player->save(players_path); + player->save(players_path, m_gamedef); } RemotePlayer *ServerEnvironment::loadPlayer(const std::string &playername) @@ -640,7 +641,7 @@ RemotePlayer *ServerEnvironment::loadPlayer(const std::string &playername) RemotePlayer *player = getPlayer(playername.c_str()); if (!player) { - player = new RemotePlayer(m_gamedef, ""); + player = new RemotePlayer("", m_gamedef->idef()); newplayer = true; } @@ -2300,15 +2301,14 @@ LocalPlayer *ClientEnvironment::getPlayer(const char* name) return dynamic_cast(Environment::getPlayer(name)); } -void ClientEnvironment::addPlayer(Player *player) +void ClientEnvironment::addPlayer(LocalPlayer *player) { DSTACK(FUNCTION_NAME); /* - It is a failure if player is local and there already is a local - player + It is a failure if already is a local player */ - FATAL_ERROR_IF(player->isLocal() && getLocalPlayer() != NULL, - "Player is local but there is already a local player"); + FATAL_ERROR_IF(getLocalPlayer() != NULL, + "Player is local but there is already a local player"); Environment::addPlayer(player); } @@ -2563,7 +2563,7 @@ void ClientEnvironment::step(float dtime) */ for (std::vector::iterator i = m_players.begin(); i != m_players.end(); ++i) { - LocalPlayer *player = dynamic_cast(*i); + Player *player = *i; assert(player); /* diff --git a/src/environment.h b/src/environment.h index 99066c367..7ed38ad5d 100644 --- a/src/environment.h +++ b/src/environment.h @@ -579,7 +579,7 @@ public: void step(f32 dtime); - virtual void addPlayer(Player *player); + virtual void addPlayer(LocalPlayer *player); LocalPlayer * getLocalPlayer(); /* diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 732ca8acf..bc242a59d 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -26,16 +26,29 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include "environment.h" #include "map.h" -#include "util/numeric.h" +#include "client.h" /* LocalPlayer */ -LocalPlayer::LocalPlayer(IGameDef *gamedef, const char *name): - Player(gamedef, name), +LocalPlayer::LocalPlayer(Client *gamedef, const char *name): + Player(name, gamedef->idef()), parent(0), + got_teleported(false), isAttached(false), + touching_ground(false), + in_liquid(false), + in_liquid_stable(false), + liquid_viscosity(0), + is_climbing(false), + swimming_vertical(false), + // Movement overrides are multipliers and must be 1 by default + physics_override_speed(1.0f), + physics_override_jump(1.0f), + physics_override_gravity(1.0f), + physics_override_sneak(true), + physics_override_sneak_glitch(true), overridePosition(v3f(0,0,0)), last_position(v3f(0,0,0)), last_speed(v3f(0,0,0)), @@ -47,6 +60,8 @@ LocalPlayer::LocalPlayer(IGameDef *gamedef, const char *name): hotbar_image(""), hotbar_selected_image(""), light_color(255,255,255,255), + hurt_tilt_timer(0.0f), + hurt_tilt_strength(0.0f), m_sneak_node(32767,32767,32767), m_sneak_node_exists(false), m_need_to_get_new_sneak_node(true), @@ -54,7 +69,8 @@ LocalPlayer::LocalPlayer(IGameDef *gamedef, const char *name): m_old_node_below(32767,32767,32767), m_old_node_below_type("air"), m_can_jump(false), - m_cao(NULL) + m_cao(NULL), + m_gamedef(gamedef) { // Initialize hp to 0, so that no hearts will be shown if server // doesn't support health points diff --git a/src/localplayer.h b/src/localplayer.h index 8897adc5e..182b51d4d 100644 --- a/src/localplayer.h +++ b/src/localplayer.h @@ -21,8 +21,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #define LOCALPLAYER_HEADER #include "player.h" +#include "environment.h" #include +class Client; class Environment; class GenericCAO; class ClientActiveObject; @@ -32,7 +34,7 @@ enum LocalPlayerAnimations {NO_ANIM, WALK_ANIM, DIG_ANIM, WD_ANIM}; // no local class LocalPlayer : public Player { public: - LocalPlayer(IGameDef *gamedef, const char *name); + LocalPlayer(Client *gamedef, const char *name); virtual ~LocalPlayer(); bool isLocal() const @@ -42,7 +44,23 @@ public: ClientActiveObject *parent; + bool got_teleported; bool isAttached; + bool touching_ground; + // This oscillates so that the player jumps a bit above the surface + bool in_liquid; + // This is more stable and defines the maximum speed of the player + bool in_liquid_stable; + // Gets the viscosity of water to calculate friction + u8 liquid_viscosity; + bool is_climbing; + bool swimming_vertical; + + float physics_override_speed; + float physics_override_jump; + float physics_override_gravity; + bool physics_override_sneak; + bool physics_override_sneak_glitch; v3f overridePosition; @@ -71,6 +89,9 @@ public: video::SColor light_color; + float hurt_tilt_timer; + float hurt_tilt_strength; + GenericCAO* getCAO() const { return m_cao; } @@ -102,6 +123,7 @@ private: bool m_can_jump; GenericCAO* m_cao; + Client *m_gamedef; }; #endif diff --git a/src/player.cpp b/src/player.cpp index fd72d63b6..c0d367134 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -32,31 +32,19 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "porting.h" // strlcpy -Player::Player(IGameDef *gamedef, const char *name): - got_teleported(false), - touching_ground(false), - in_liquid(false), - in_liquid_stable(false), - liquid_viscosity(0), - is_climbing(false), - swimming_vertical(false), +Player::Player(const char *name, IItemDefManager *idef): camera_barely_in_ceiling(false), - inventory(gamedef->idef()), + inventory(idef), hp(PLAYER_MAX_HP), - hurt_tilt_timer(0), - hurt_tilt_strength(0), - protocol_version(0), peer_id(PEER_ID_INEXISTENT), keyPressed(0), // protected - m_gamedef(gamedef), m_breath(PLAYER_MAX_BREATH), 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.75,BS*0.30), - m_dirty(false) + m_collisionbox(-BS*0.30,0.0,-BS*0.30,BS*0.30,BS*1.75,BS*0.30) { strlcpy(m_name, name, PLAYERNAME_SIZE); @@ -92,13 +80,6 @@ Player::Player(IGameDef *gamedef, const char *name): movement_gravity = 9.81 * BS; local_animation_speed = 0.0; - // Movement overrides are multipliers and must be 1 by default - physics_override_speed = 1; - physics_override_jump = 1; - physics_override_gravity = 1; - physics_override_sneak = true; - physics_override_sneak_glitch = true; - hud_flags = HUD_FLAG_HOTBAR_VISIBLE | HUD_FLAG_HEALTHBAR_VISIBLE | HUD_FLAG_CROSSHAIR_VISIBLE | HUD_FLAG_WIELDITEM_VISIBLE | @@ -117,70 +98,6 @@ v3s16 Player::getLightPosition() const return floatToInt(m_position + v3f(0,BS+BS/2,0), BS); } -void Player::serialize(std::ostream &os) -{ - // 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.setS32("breath", m_breath); - - args.writeLines(os); - - os<<"PlayerArgsEnd\n"; - - inventory.serialize(os); -} - -void Player::deSerialize(std::istream &is, std::string playername) -{ - Settings args; - - if (!args.parseConfigLines(is, "PlayerArgsEnd")) { - throw SerializationError("PlayerArgsEnd of player " + - playername + " not found!"); - } - - m_dirty = true; - //args.getS32("version"); // Version field value not used - std::string name = args.get("name"); - strlcpy(m_name, name.c_str(), PLAYERNAME_SIZE); - setPitch(args.getFloat("pitch")); - setYaw(args.getFloat("yaw")); - setPosition(args.getV3F("position")); - try{ - hp = args.getS32("hp"); - }catch(SettingNotFoundException &e) { - hp = PLAYER_MAX_HP; - } - try{ - m_breath = args.getS32("breath"); - }catch(SettingNotFoundException &e) { - m_breath = PLAYER_MAX_BREATH; - } - - 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()); - } - } -} - u32 Player::addHud(HudElement *toadd) { MutexAutoLock lock(m_mutex); @@ -227,17 +144,24 @@ void Player::clearHud() } } +/* + RemotePlayer +*/ // static config cache for remoteplayer bool RemotePlayer::m_setting_cache_loaded = false; float RemotePlayer::m_setting_chat_message_limit_per_10sec = 0.0f; u16 RemotePlayer::m_setting_chat_message_limit_trigger_kick = 0; -RemotePlayer::RemotePlayer(IGameDef *gamedef, const char *name): - Player(gamedef, name), +RemotePlayer::RemotePlayer(const char *name, IItemDefManager *idef): + Player(name, idef), + protocol_version(0), m_sao(NULL), + m_dirty(false), m_last_chat_message_sent(time(NULL)), m_chat_message_allowance(5.0f), - m_message_rate_overhead(0) + m_message_rate_overhead(0), + hud_hotbar_image(""), + hud_hotbar_selected_image("") { if (!RemotePlayer::m_setting_cache_loaded) { RemotePlayer::m_setting_chat_message_limit_per_10sec = @@ -260,7 +184,7 @@ RemotePlayer::RemotePlayer(IGameDef *gamedef, const char *name): movement_gravity = g_settings->getFloat("movement_gravity") * BS; } -void RemotePlayer::save(std::string savedir) +void RemotePlayer::save(std::string savedir, IGameDef *gamedef) { /* * We have to open all possible player files in the players directory @@ -269,7 +193,7 @@ void RemotePlayer::save(std::string savedir) */ // A player to deserialize files into to check their names - RemotePlayer testplayer(m_gamedef, ""); + RemotePlayer testplayer("", gamedef->idef()); savedir += DIR_DELIM; std::string path = savedir + m_name; @@ -309,11 +233,75 @@ void RemotePlayer::save(std::string savedir) return; } -/* - RemotePlayer -*/ +void RemotePlayer::deSerialize(std::istream &is, const std::string &playername) +{ + Settings args; + + if (!args.parseConfigLines(is, "PlayerArgsEnd")) { + throw SerializationError("PlayerArgsEnd of player " + + playername + " not found!"); + } + + m_dirty = true; + //args.getS32("version"); // Version field value not used + std::string name = args.get("name"); + strlcpy(m_name, name.c_str(), PLAYERNAME_SIZE); + setPitch(args.getFloat("pitch")); + setYaw(args.getFloat("yaw")); + setPosition(args.getV3F("position")); + try{ + hp = args.getS32("hp"); + }catch(SettingNotFoundException &e) { + hp = PLAYER_MAX_HP; + } + try{ + m_breath = args.getS32("breath"); + }catch(SettingNotFoundException &e) { + m_breath = PLAYER_MAX_BREATH; + } + + 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()); + } + } +} + +void RemotePlayer::serialize(std::ostream &os) +{ + // 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.setS32("breath", m_breath); + + args.writeLines(os); + + os<<"PlayerArgsEnd\n"; + + inventory.serialize(os); +} + void RemotePlayer::setPosition(const v3f &position) { + if (position != m_position) + m_dirty = true; + Player::setPosition(position); if(m_sao) m_sao->setBasePosition(position); diff --git a/src/player.h b/src/player.h index fbd88fc71..1980a86a3 100644 --- a/src/player.h +++ b/src/player.h @@ -112,7 +112,7 @@ class Player { public: - Player(IGameDef *gamedef, const char *name); + Player(const char *name, IItemDefManager *idef); virtual ~Player() = 0; virtual void move(f32 dtime, Environment *env, f32 pos_max_d) @@ -151,80 +151,32 @@ public: virtual void setPosition(const v3f &position) { - if (position != m_position) - m_dirty = true; m_position = position; } - void setPitch(f32 pitch) + virtual void setPitch(f32 pitch) { - if (pitch != m_pitch) - m_dirty = true; m_pitch = pitch; } virtual void setYaw(f32 yaw) { - if (yaw != m_yaw) - m_dirty = true; m_yaw = yaw; } - f32 getPitch() - { - return m_pitch; - } + f32 getPitch() const { return m_pitch; } + f32 getYaw() const { return m_yaw; } + u16 getBreath() const { return m_breath; } - f32 getYaw() - { - return m_yaw; - } + virtual void setBreath(u16 breath) { m_breath = breath; } - u16 getBreath() - { - return m_breath; - } + f32 getRadPitch() const { return m_pitch * core::DEGTORAD; } + f32 getRadYaw() const { return m_yaw * core::DEGTORAD; } + const char *getName() const { return m_name; } + aabb3f getCollisionbox() const { return m_collisionbox; } - virtual void setBreath(u16 breath) + u32 getFreeHudID() { - if (breath != m_breath) - m_dirty = true; - m_breath = breath; - } - - // Deprecated - f32 getRadPitchDep() - { - return -1.0 * m_pitch * core::DEGTORAD; - } - - // Deprecated - f32 getRadYawDep() - { - return (m_yaw + 90.) * core::DEGTORAD; - } - - f32 getRadPitch() - { - return m_pitch * core::DEGTORAD; - } - - f32 getRadYaw() - { - return m_yaw * core::DEGTORAD; - } - - const char *getName() const - { - return m_name; - } - - aabb3f getCollisionbox() - { - return m_collisionbox; - } - - u32 getFreeHudID() { size_t size = hud.size(); for (size_t i = 0; i != size; i++) { if (!hud[i]) @@ -233,41 +185,6 @@ public: return size; } - void setHotbarImage(const std::string &name) - { - hud_hotbar_image = name; - } - - std::string getHotbarImage() - { - return hud_hotbar_image; - } - - void setHotbarSelectedImage(const std::string &name) - { - hud_hotbar_selected_image = name; - } - - std::string getHotbarSelectedImage() { - return hud_hotbar_selected_image; - } - - void setSky(const video::SColor &bgcolor, const std::string &type, - const std::vector ¶ms) - { - m_sky_bgcolor = bgcolor; - m_sky_type = type; - m_sky_params = params; - } - - void getSky(video::SColor *bgcolor, std::string *type, - std::vector *params) - { - *bgcolor = m_sky_bgcolor; - *type = m_sky_type; - *params = m_sky_params; - } - void setLocalAnimations(v2s32 frames[4], float frame_speed) { for (int i = 0; i < 4; i++) @@ -282,49 +199,8 @@ public: *frame_speed = local_animation_speed; } - virtual bool isLocal() const - { - return false; - } + virtual bool isLocal() const { return false; } - virtual void setPlayerSAO(PlayerSAO *sao) - { - FATAL_ERROR("FIXME"); - } - - /* - serialize() writes a bunch of text that can contain - any characters except a '\0', and such an ending that - deSerialize stops reading exactly at the right point. - */ - void serialize(std::ostream &os); - void deSerialize(std::istream &is, std::string playername); - - bool checkModified() const - { - return m_dirty || inventory.checkModified(); - } - - void setModified(const bool x) - { - m_dirty = x; - if (!x) - inventory.setModified(x); - } - - // Use a function, if isDead can be defined by other conditions - bool isDead() { return hp == 0; } - - bool got_teleported; - bool touching_ground; - // This oscillates so that the player jumps a bit above the surface - bool in_liquid; - // This is more stable and defines the maximum speed of the player - bool in_liquid_stable; - // Gets the viscosity of water to calculate friction - u8 liquid_viscosity; - bool is_climbing; - bool swimming_vertical; bool camera_barely_in_ceiling; v3f eye_offset_first; v3f eye_offset_third; @@ -344,21 +220,11 @@ public: f32 movement_liquid_sink; f32 movement_gravity; - float physics_override_speed; - float physics_override_jump; - float physics_override_gravity; - bool physics_override_sneak; - bool physics_override_sneak_glitch; - v2s32 local_animations[4]; float local_animation_speed; u16 hp; - float hurt_tilt_timer; - float hurt_tilt_strength; - - u16 protocol_version; u16 peer_id; std::string inventory_formspec; @@ -368,7 +234,6 @@ public: u32 keyPressed; - HudElement* getHud(u32 id); u32 addHud(HudElement* hud); HudElement* removeHud(u32 id); @@ -376,11 +241,7 @@ public: u32 hud_flags; s32 hud_hotbar_itemcount; - std::string hud_hotbar_image; - std::string hud_hotbar_selected_image; protected: - IGameDef *m_gamedef; - char m_name[PLAYERNAME_SIZE]; u16 m_breath; f32 m_pitch; @@ -389,13 +250,7 @@ protected: v3f m_position; aabb3f m_collisionbox; - bool m_dirty; - std::vector hud; - - std::string m_sky_type; - video::SColor m_sky_bgcolor; - std::vector m_sky_params; private: // Protect some critical areas // hud for example can be modified by EmergeThread @@ -414,15 +269,14 @@ enum RemotePlayerChatResult { class RemotePlayer : public Player { public: - RemotePlayer(IGameDef *gamedef, const char *name); + RemotePlayer(const char *name, IItemDefManager *idef); virtual ~RemotePlayer() {} - void save(std::string savedir); + void save(std::string savedir, IGameDef *gamedef); + void deSerialize(std::istream &is, const std::string &playername); - PlayerSAO *getPlayerSAO() - { return m_sao; } - void setPlayerSAO(PlayerSAO *sao) - { m_sao = sao; } + PlayerSAO *getPlayerSAO() { return m_sao; } + void setPlayerSAO(PlayerSAO *sao) { m_sao = sao; } void setPosition(const v3f &position); const RemotePlayerChatResult canSendChatMessage(); @@ -446,8 +300,92 @@ public: *ratio = m_day_night_ratio; } + // Use a function, if isDead can be defined by other conditions + bool isDead() const { return hp == 0; } + + void setHotbarImage(const std::string &name) + { + hud_hotbar_image = name; + } + + std::string getHotbarImage() const + { + return hud_hotbar_image; + } + + void setHotbarSelectedImage(const std::string &name) + { + hud_hotbar_selected_image = name; + } + + const std::string &getHotbarSelectedImage() const + { + return hud_hotbar_selected_image; + } + + // Deprecated + f32 getRadPitchDep() const { return -1.0 * m_pitch * core::DEGTORAD; } + + // Deprecated + f32 getRadYawDep() const { return (m_yaw + 90.) * core::DEGTORAD; } + + void setSky(const video::SColor &bgcolor, const std::string &type, + const std::vector ¶ms) + { + m_sky_bgcolor = bgcolor; + m_sky_type = type; + m_sky_params = params; + } + + void getSky(video::SColor *bgcolor, std::string *type, + std::vector *params) + { + *bgcolor = m_sky_bgcolor; + *type = m_sky_type; + *params = m_sky_params; + } + + bool checkModified() const { return m_dirty || inventory.checkModified(); } + + void setModified(const bool x) + { + m_dirty = x; + if (!x) + inventory.setModified(x); + } + + virtual void setBreath(u16 breath) + { + if (breath != m_breath) + m_dirty = true; + Player::setBreath(breath); + } + + virtual void setPitch(f32 pitch) + { + if (pitch != m_pitch) + m_dirty = true; + Player::setPitch(pitch); + } + + virtual void setYaw(f32 yaw) + { + if (yaw != m_yaw) + m_dirty = true; + Player::setYaw(yaw); + } + + u16 protocol_version; private: + /* + serialize() writes a bunch of text that can contain + any characters except a '\0', and such an ending that + deSerialize stops reading exactly at the right point. + */ + void serialize(std::ostream &os); + PlayerSAO *m_sao; + bool m_dirty; static bool m_setting_cache_loaded; static float m_setting_chat_message_limit_per_10sec; @@ -459,6 +397,12 @@ private: bool m_day_night_ratio_do_override; float m_day_night_ratio; + std::string hud_hotbar_image; + std::string hud_hotbar_selected_image; + + std::string m_sky_type; + video::SColor m_sky_bgcolor; + std::vector m_sky_params; }; #endif diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 74b33da37..a1f83919c 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -1600,7 +1600,7 @@ int ObjectRef::l_hud_get_hotbar_selected_image(lua_State *L) if (player == NULL) return 0; - std::string name = getServer(L)->hudGetHotbarSelectedImage(player); + const std::string &name = getServer(L)->hudGetHotbarSelectedImage(player); lua_pushlstring(L, name.c_str(), name.size()); return 1; } diff --git a/src/server.cpp b/src/server.cpp index edd97e225..71e71f43e 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1108,7 +1108,7 @@ PlayerSAO* Server::StageTwoClientInit(u16 peer_id) SendPlayerBreath(peer_id); // Show death screen if necessary - if(player->isDead()) + if (player->isDead()) SendDeathscreen(peer_id, false, v3f(0,0,0)); // Note things in chat if not in simple singleplayer mode @@ -3080,14 +3080,6 @@ void Server::hudSetHotbarSelectedImage(RemotePlayer *player, std::string name) SendHUDSetParam(player->peer_id, HUD_PARAM_HOTBAR_SELECTED_IMAGE, name); } -std::string Server::hudGetHotbarSelectedImage(RemotePlayer *player) -{ - if (!player) - return ""; - - return player->getHotbarSelectedImage(); -} - bool Server::setLocalPlayerAnimations(RemotePlayer *player, v2s32 animation_frames[4], f32 frame_speed) { @@ -3408,11 +3400,10 @@ PlayerSAO* Server::emergePlayer(const char *name, u16 peer_id, u16 proto_version /* Try to get an existing player */ - RemotePlayer *player = static_cast(m_env->getPlayer(name)); + RemotePlayer *player = m_env->getPlayer(name); // If player is already connected, cancel - if(player != NULL && player->peer_id != 0) - { + if (player != NULL && player->peer_id != 0) { infostream<<"emergePlayer(): Player already connected"<getPlayer(peer_id) != NULL) - { + if (m_env->getPlayer(peer_id) != NULL) { infostream<<"emergePlayer(): Player with wrong name but same" " peer_id already exists"<(m_env->loadPlayer(name)); + player = m_env->loadPlayer(name); } // Create player if it doesn't exist if (!player) { newplayer = true; - player = new RemotePlayer(this, name); + player = new RemotePlayer(name, this->idef()); // Set player position infostream<<"Server: Finding spawn place for player \"" <getHotbarSelectedImage(); + } inline Address getPeerAddress(u16 peer_id) { return m_con.GetPeerAddress(peer_id); }