X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fenvironment.cpp;h=eea2646997c466989bfed37a05ae7ad43fb51e7a;hb=d1df09841d0eac7a88f638676b80ec848522cca5;hp=8103998c3c847d219caecc9bb40763b5ee44fe88;hpb=35ec3855f689cf2c6b1504a5813b7c3d9697ae14;p=dragonfireclient.git diff --git a/src/environment.cpp b/src/environment.cpp index 8103998c3..eea264699 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -17,6 +17,7 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include #include "environment.h" #include "filesys.h" #include "porting.h" @@ -31,43 +32,53 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "scripting_game.h" #include "nodedef.h" #include "nodemetadata.h" -#include "main.h" // For g_settings, g_profiler #include "gamedef.h" #ifndef SERVER #include "clientmap.h" #include "localplayer.h" +#include "mapblock_mesh.h" #include "event.h" #endif +#include "server.h" #include "daynightratio.h" #include "map.h" #include "emerge.h" #include "util/serialize.h" +#include "threading/mutex_auto_lock.h" #define PP(x) "("<<(x).X<<","<<(x).Y<<","<<(x).Z<<")" +#define LBM_NAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_:" + +// A number that is much smaller than the timeout for particle spawners should/could ever be +#define PARTICLE_SPAWNER_NO_EXPIRY -1024.f + Environment::Environment(): + m_time_of_day_speed(0), m_time_of_day(9000), m_time_of_day_f(9000./24000), - m_time_of_day_speed(0), - m_time_counter(0), + m_time_conversion_skew(0.0f), m_enable_day_night_ratio_override(false), m_day_night_ratio_override(0.0f) { + m_cache_enable_shaders = g_settings->getBool("enable_shaders"); + m_cache_active_block_mgmt_interval = g_settings->getFloat("active_block_mgmt_interval"); + m_cache_abm_interval = g_settings->getFloat("abm_interval"); + m_cache_nodetimer_interval = g_settings->getFloat("nodetimer_interval"); } Environment::~Environment() { // Deallocate players - for(std::list::iterator i = m_players.begin(); - i != m_players.end(); ++i) - { + for(std::vector::iterator i = m_players.begin(); + i != m_players.end(); ++i) { delete (*i); } } void Environment::addPlayer(Player *player) { - DSTACK(__FUNCTION_NAME); + DSTACK(FUNCTION_NAME); /* Check that peer_ids are unique. Also check that names are unique. @@ -75,35 +86,29 @@ void Environment::addPlayer(Player *player) */ // If peer id is non-zero, it has to be unique. if(player->peer_id != 0) - assert(getPlayer(player->peer_id) == NULL); + FATAL_ERROR_IF(getPlayer(player->peer_id) != NULL, "Peer id not unique"); // Name has to be unique. - assert(getPlayer(player->getName()) == NULL); + FATAL_ERROR_IF(getPlayer(player->getName()) != NULL, "Player name not unique"); // Add. m_players.push_back(player); } -void Environment::removePlayer(u16 peer_id) +void Environment::removePlayer(Player* player) { - DSTACK(__FUNCTION_NAME); - - for(std::list::iterator i = m_players.begin(); - i != m_players.end();) - { - Player *player = *i; - if(player->peer_id == peer_id) { - delete player; - i = m_players.erase(i); - } else { - ++i; + for (std::vector::iterator it = m_players.begin(); + it != m_players.end(); ++it) { + if ((*it) == player) { + delete *it; + m_players.erase(it); + return; } } } Player * Environment::getPlayer(u16 peer_id) { - for(std::list::iterator i = m_players.begin(); - i != m_players.end(); ++i) - { + for(std::vector::iterator i = m_players.begin(); + i != m_players.end(); ++i) { Player *player = *i; if(player->peer_id == peer_id) return player; @@ -113,9 +118,8 @@ Player * Environment::getPlayer(u16 peer_id) Player * Environment::getPlayer(const char *name) { - for(std::list::iterator i = m_players.begin(); - i != m_players.end(); ++i) - { + for(std::vector::iterator i = m_players.begin(); + i != m_players.end(); ++i) { Player *player = *i; if(strcmp(player->getName(), name) == 0) return player; @@ -125,15 +129,13 @@ Player * Environment::getPlayer(const char *name) Player * Environment::getRandomConnectedPlayer() { - std::list connected_players = getPlayers(true); + std::vector connected_players = getPlayers(true); u32 chosen_one = myrand() % connected_players.size(); u32 j = 0; - for(std::list::iterator + for(std::vector::iterator i = connected_players.begin(); - i != connected_players.end(); ++i) - { - if(j == chosen_one) - { + i != connected_players.end(); ++i) { + if(j == chosen_one) { Player *player = *i; return player; } @@ -144,17 +146,15 @@ Player * Environment::getRandomConnectedPlayer() Player * Environment::getNearestConnectedPlayer(v3f pos) { - std::list connected_players = getPlayers(true); + std::vector connected_players = getPlayers(true); f32 nearest_d = 0; Player *nearest_player = NULL; - for(std::list::iterator + for(std::vector::iterator i = connected_players.begin(); - i != connected_players.end(); ++i) - { + i != connected_players.end(); ++i) { Player *player = *i; f32 d = player->getPosition().getDistanceFrom(pos); - if(d < nearest_d || nearest_player == NULL) - { + if(d < nearest_d || nearest_player == NULL) { nearest_d = d; nearest_player = player; } @@ -162,22 +162,20 @@ Player * Environment::getNearestConnectedPlayer(v3f pos) return nearest_player; } -std::list Environment::getPlayers() +std::vector Environment::getPlayers() { return m_players; } -std::list Environment::getPlayers(bool ignore_disconnected) +std::vector Environment::getPlayers(bool ignore_disconnected) { - std::list newlist; - for(std::list::iterator + std::vector newlist; + for(std::vector::iterator i = m_players.begin(); - i != m_players.end(); ++i) - { + i != m_players.end(); ++i) { Player *player = *i; - - if(ignore_disconnected) - { + + if(ignore_disconnected) { // Ignore disconnected players if(player->peer_id == 0) continue; @@ -190,36 +188,91 @@ std::list Environment::getPlayers(bool ignore_disconnected) u32 Environment::getDayNightRatio() { - if(m_enable_day_night_ratio_override) + MutexAutoLock lock(this->m_time_lock); + if (m_enable_day_night_ratio_override) return m_day_night_ratio_override; - bool smooth = g_settings->getBool("enable_shaders"); - return time_to_daynight_ratio(m_time_of_day_f*24000, smooth); + return time_to_daynight_ratio(m_time_of_day_f * 24000, m_cache_enable_shaders); +} + +void Environment::setTimeOfDaySpeed(float speed) +{ + m_time_of_day_speed = speed; +} + +float Environment::getTimeOfDaySpeed() +{ + return m_time_of_day_speed; +} + +void Environment::setDayNightRatioOverride(bool enable, u32 value) +{ + MutexAutoLock lock(this->m_time_lock); + m_enable_day_night_ratio_override = enable; + m_day_night_ratio_override = value; +} + +void Environment::setTimeOfDay(u32 time) +{ + MutexAutoLock lock(this->m_time_lock); + if (m_time_of_day > time) + m_day_count++; + m_time_of_day = time; + m_time_of_day_f = (float)time / 24000.0; +} + +u32 Environment::getTimeOfDay() +{ + MutexAutoLock lock(this->m_time_lock); + return m_time_of_day; +} + +float Environment::getTimeOfDayF() +{ + MutexAutoLock lock(this->m_time_lock); + return m_time_of_day_f; } void Environment::stepTimeOfDay(float dtime) { - m_time_counter += dtime; - f32 speed = m_time_of_day_speed * 24000./(24.*3600); - u32 units = (u32)(m_time_counter*speed); - m_time_counter -= (f32)units / speed; + MutexAutoLock lock(this->m_time_lock); + + // Cached in order to prevent the two reads we do to give + // different results (can be written by code not under the lock) + f32 cached_time_of_day_speed = m_time_of_day_speed; + + f32 speed = cached_time_of_day_speed * 24000. / (24. * 3600); + m_time_conversion_skew += dtime; + u32 units = (u32)(m_time_conversion_skew * speed); bool sync_f = false; - if(units > 0){ + if (units > 0) { // Sync at overflow - if(m_time_of_day + units >= 24000) + if (m_time_of_day + units >= 24000) { sync_f = true; + m_day_count++; + } m_time_of_day = (m_time_of_day + units) % 24000; - if(sync_f) + if (sync_f) m_time_of_day_f = (float)m_time_of_day / 24000.0; } - if(!sync_f){ - m_time_of_day_f += m_time_of_day_speed/24/3600*dtime; - if(m_time_of_day_f > 1.0) + if (speed > 0) { + m_time_conversion_skew -= (f32)units / speed; + } + if (!sync_f) { + m_time_of_day_f += cached_time_of_day_speed / 24 / 3600 * dtime; + if (m_time_of_day_f > 1.0) m_time_of_day_f -= 1.0; - if(m_time_of_day_f < 0.0) + if (m_time_of_day_f < 0.0) m_time_of_day_f += 1.0; } } +u32 Environment::getDayCount() +{ + // Atomic counter + return m_day_count; +} + + /* ABMWithState */ @@ -236,6 +289,223 @@ ABMWithState::ABMWithState(ActiveBlockModifier *abm_): timer = myrand_range(minval, maxval); } +/* + LBMManager +*/ + +void LBMContentMapping::deleteContents() +{ + for (std::vector::iterator it = lbm_list.begin(); + it != lbm_list.end(); ++it) { + delete *it; + } +} + +void LBMContentMapping::addLBM(LoadingBlockModifierDef *lbm_def, IGameDef *gamedef) +{ + // Add the lbm_def to the LBMContentMapping. + // Unknown names get added to the global NameIdMapping. + INodeDefManager *nodedef = gamedef->ndef(); + + lbm_list.push_back(lbm_def); + + for (std::set::const_iterator it = lbm_def->trigger_contents.begin(); + it != lbm_def->trigger_contents.end(); ++it) { + std::set c_ids; + bool found = nodedef->getIds(*it, c_ids); + if (!found) { + content_t c_id = gamedef->allocateUnknownNodeId(*it); + if (c_id == CONTENT_IGNORE) { + // Seems it can't be allocated. + warningstream << "Could not internalize node name \"" << *it + << "\" while loading LBM \"" << lbm_def->name << "\"." << std::endl; + continue; + } + c_ids.insert(c_id); + } + + for (std::set::const_iterator iit = + c_ids.begin(); iit != c_ids.end(); ++iit) { + content_t c_id = *iit; + map[c_id].push_back(lbm_def); + } + } +} + +const std::vector * + LBMContentMapping::lookup(content_t c) const +{ + container_map::const_iterator it = map.find(c); + if (it == map.end()) + return NULL; + // This first dereferences the iterator, returning + // a std::vector + // reference, then we convert it to a pointer. + return &(it->second); +} + +LBMManager::~LBMManager() +{ + for (std::map::iterator it = + m_lbm_defs.begin(); it != m_lbm_defs.end(); ++it) { + delete it->second; + } + for (lbm_lookup_map::iterator it = m_lbm_lookup.begin(); + it != m_lbm_lookup.end(); ++it) { + (it->second).deleteContents(); + } +} + +void LBMManager::addLBMDef(LoadingBlockModifierDef *lbm_def) +{ + // Precondition, in query mode the map isn't used anymore + FATAL_ERROR_IF(m_query_mode == true, + "attempted to modify LBMManager in query mode"); + + if (!string_allowed(lbm_def->name, LBM_NAME_ALLOWED_CHARS)) { + throw ModError("Error adding LBM \"" + lbm_def->name + + "\": Does not follow naming conventions: " + "Only chararacters [a-z0-9_:] are allowed."); + } + + m_lbm_defs[lbm_def->name] = lbm_def; +} + +void LBMManager::loadIntroductionTimes(const std::string ×, + IGameDef *gamedef, u32 now) +{ + m_query_mode = true; + + // name -> time map. + // Storing it in a map first instead of + // handling the stuff directly in the loop + // removes all duplicate entries. + // TODO make this std::unordered_map + std::map introduction_times; + + /* + The introduction times string consists of name~time entries, + with each entry terminated by a semicolon. The time is decimal. + */ + + size_t idx = 0; + size_t idx_new; + while ((idx_new = times.find(";", idx)) != std::string::npos) { + std::string entry = times.substr(idx, idx_new - idx); + std::vector components = str_split(entry, '~'); + if (components.size() != 2) + throw SerializationError("Introduction times entry \"" + + entry + "\" requires exactly one '~'!"); + const std::string &name = components[0]; + u32 time = from_string(components[1]); + introduction_times[name] = time; + idx = idx_new + 1; + } + + // Put stuff from introduction_times into m_lbm_lookup + for (std::map::const_iterator it = introduction_times.begin(); + it != introduction_times.end(); ++it) { + const std::string &name = it->first; + u32 time = it->second; + + std::map::iterator def_it = + m_lbm_defs.find(name); + if (def_it == m_lbm_defs.end()) { + // This seems to be an LBM entry for + // an LBM we haven't loaded. Discard it. + continue; + } + LoadingBlockModifierDef *lbm_def = def_it->second; + if (lbm_def->run_at_every_load) { + // This seems to be an LBM entry for + // an LBM that runs at every load. + // Don't add it just yet. + continue; + } + + m_lbm_lookup[time].addLBM(lbm_def, gamedef); + + // Erase the entry so that we know later + // what elements didn't get put into m_lbm_lookup + m_lbm_defs.erase(name); + } + + // Now also add the elements from m_lbm_defs to m_lbm_lookup + // that weren't added in the previous step. + // They are introduced first time to this world, + // or are run at every load (introducement time hardcoded to U32_MAX). + + LBMContentMapping &lbms_we_introduce_now = m_lbm_lookup[now]; + LBMContentMapping &lbms_running_always = m_lbm_lookup[U32_MAX]; + + for (std::map::iterator it = + m_lbm_defs.begin(); it != m_lbm_defs.end(); ++it) { + if (it->second->run_at_every_load) { + lbms_running_always.addLBM(it->second, gamedef); + } else { + lbms_we_introduce_now.addLBM(it->second, gamedef); + } + } + + // Clear the list, so that we don't delete remaining elements + // twice in the destructor + m_lbm_defs.clear(); +} + +std::string LBMManager::createIntroductionTimesString() +{ + // Precondition, we must be in query mode + FATAL_ERROR_IF(m_query_mode == false, + "attempted to query on non fully set up LBMManager"); + + std::ostringstream oss; + for (lbm_lookup_map::iterator it = m_lbm_lookup.begin(); + it != m_lbm_lookup.end(); ++it) { + u32 time = it->first; + std::vector &lbm_list = it->second.lbm_list; + for (std::vector::iterator iit = lbm_list.begin(); + iit != lbm_list.end(); ++iit) { + // Don't add if the LBM runs at every load, + // then introducement time is hardcoded + // and doesn't need to be stored + if ((*iit)->run_at_every_load) + continue; + oss << (*iit)->name << "~" << time << ";"; + } + } + return oss.str(); +} + +void LBMManager::applyLBMs(ServerEnvironment *env, MapBlock *block, u32 stamp) +{ + // Precondition, we need m_lbm_lookup to be initialized + FATAL_ERROR_IF(m_query_mode == false, + "attempted to query on non fully set up LBMManager"); + v3s16 pos_of_block = block->getPosRelative(); + v3s16 pos; + MapNode n; + content_t c; + lbm_lookup_map::const_iterator it = getLBMsIntroducedAfter(stamp); + for (pos.X = 0; pos.X < MAP_BLOCKSIZE; pos.X++) + for (pos.Y = 0; pos.Y < MAP_BLOCKSIZE; pos.Y++) + for (pos.Z = 0; pos.Z < MAP_BLOCKSIZE; pos.Z++) + { + n = block->getNodeNoEx(pos); + c = n.getContent(); + for (LBMManager::lbm_lookup_map::const_iterator iit = it; + iit != m_lbm_lookup.end(); ++iit) { + const std::vector *lbm_list = + iit->second.lookup(c); + if (!lbm_list) + continue; + for (std::vector::const_iterator iit = + lbm_list->begin(); iit != lbm_list->end(); ++iit) { + (*iit)->trigger(env, pos + pos_of_block, n); + } + } + } +} + /* ActiveBlockList */ @@ -252,7 +522,7 @@ void fillRadiusBlock(v3s16 p0, s16 r, std::set &list) } } -void ActiveBlockList::update(std::list &active_positions, +void ActiveBlockList::update(std::vector &active_positions, s16 radius, std::set &blocks_removed, std::set &blocks_added) @@ -261,7 +531,7 @@ void ActiveBlockList::update(std::list &active_positions, Create the new list */ std::set newlist = m_forceloaded_list; - for(std::list::iterator i = active_positions.begin(); + for(std::vector::iterator i = active_positions.begin(); i != active_positions.end(); ++i) { fillRadiusBlock(*i, radius, newlist); @@ -310,14 +580,17 @@ void ActiveBlockList::update(std::list &active_positions, */ ServerEnvironment::ServerEnvironment(ServerMap *map, - GameScripting *scriptIface, IGameDef *gamedef): + GameScripting *scriptIface, IGameDef *gamedef, + const std::string &path_world) : m_map(map), m_script(scriptIface), m_gamedef(gamedef), + m_path_world(path_world), m_send_recommended_timer(0), m_active_block_interval_overload_skip(0), m_game_time(0), m_game_time_fraction_counter(0), + m_last_clear_objects_time(0), m_recommended_send_interval(0.1), m_max_lag_estimate(0.1) { @@ -336,7 +609,7 @@ ServerEnvironment::~ServerEnvironment() m_map->drop(); // Delete ActiveBlockModifiers - for(std::list::iterator + for(std::vector::iterator i = m_abms.begin(); i != m_abms.end(); ++i){ delete i->abm; } @@ -358,8 +631,8 @@ bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, float stepsize, v3s16 //calculate normalized direction vector v3f normalized_vector = v3f((pos2.X - pos1.X)/distance, - (pos2.Y - pos1.Y)/distance, - (pos2.Z - pos1.Z)/distance); + (pos2.Y - pos1.Y)/distance, + (pos2.Z - pos1.Z)/distance); //find out if there's a node on path between pos1 and pos2 for (float i = 1; i < distance; i += stepsize) { @@ -379,196 +652,87 @@ bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, float stepsize, v3s16 return true; } -void ServerEnvironment::serializePlayers(const std::string &savedir) +void ServerEnvironment::kickAllPlayers(AccessDeniedCode reason, + const std::string &str_reason, bool reconnect) { - std::string players_path = savedir + "/players"; - fs::CreateDir(players_path); - - std::set saved_players; - - std::vector player_files = fs::GetDirListing(players_path); - for(u32 i=0; icheckModified()) - { - // Open file and serialize - std::ostringstream ss(std::ios_base::binary); - player->serialize(ss); - if(!fs::safeWriteToFile(path, ss.str())) - { - infostream<<"Failed to write "<::iterator it = m_players.begin(); + it != m_players.end(); + ++it) { + ((Server*)m_gamedef)->DenyAccessVerCompliant((*it)->peer_id, + (*it)->protocol_version, (AccessDeniedCode)reason, + str_reason, reconnect); } +} - for(std::list::iterator i = m_players.begin(); - i != m_players.end(); ++i) - { - Player *player = *i; - if(saved_players.find(player) != saved_players.end()) - { - /*infostream<<"Player "<getName() - <<" was already saved."<getName(); - // Don't save unnamed player - if(playername == "") - { - //infostream<<"Not saving unnamed player."<getName()<<" to " - <serialize(ss); - if(!fs::safeWriteToFile(path, ss.str())) - { - infostream<<"Failed to write "<::iterator it = m_players.begin(); + it != m_players.end(); + ++it) { + RemotePlayer *player = static_cast(*it); + if (player->checkModified()) { + player->save(players_path); } } - - //infostream<<"Saved "< player_files = fs::GetDirListing(players_path); - for(u32 i=0; isave(players_path); +} - //infostream<<"Checking player file "<(getPlayer(playername.c_str())); + if (!player) { + player = new RemotePlayer(m_gamedef, ""); + newplayer = true; + } - if(!string_allowed(testplayer.getName(), PLAYERNAME_ALLOWED_CHARS)) - { - infostream<<"Not loading player with invalid name: " - <deSerialize(is, path); + is.close(); - // Load player - { - verbosestream<<"Reading player "<deSerialize(is, player_files[i].name); + if (player->getName() == playername) { + found = true; + break; } - if(newplayer) - { - addPlayer(player); - } + path = players_path + playername + itos(i); + } + + if (!found) { + infostream << "Player file for player " << playername + << " not found" << std::endl; + if (newplayer) + delete player; + return NULL; } + + if (newplayer) + addPlayer(player); + player->setModified(false); + return player; } -void ServerEnvironment::saveMeta(const std::string &savedir) +void ServerEnvironment::saveMeta() { - std::string path = savedir + "/env_meta.txt"; + std::string path = m_path_world + DIR_DELIM "env_meta.txt"; // Open file and serialize std::ostringstream ss(std::ios_base::binary); @@ -576,6 +740,11 @@ void ServerEnvironment::saveMeta(const std::string &savedir) Settings args; args.setU64("game_time", m_game_time); args.setU64("time_of_day", getTimeOfDay()); + args.setU64("last_clear_objects_time", m_last_clear_objects_time); + args.setU64("lbm_introduction_times_version", 1); + args.set("lbm_introduction_times", + m_lbm_mgr.createIntroductionTimesString()); + args.setU64("day_count", m_day_count); args.writeLines(ss); ss<<"EnvArgsEnd\n"; @@ -587,47 +756,61 @@ void ServerEnvironment::saveMeta(const std::string &savedir) } } -void ServerEnvironment::loadMeta(const std::string &savedir) +void ServerEnvironment::loadMeta() { - std::string path = savedir + "/env_meta.txt"; + std::string path = m_path_world + DIR_DELIM "env_meta.txt"; // Open file and deserialize std::ifstream is(path.c_str(), std::ios_base::binary); - if(is.good() == false) - { - infostream<<"ServerEnvironment::loadMeta(): Failed to open " - < > m_aabms; + std::map > m_aabms; public: - ABMHandler(std::list &abms, + ABMHandler(std::vector &abms, float dtime_s, ServerEnvironment *env, bool use_timers): m_env(env) @@ -651,8 +834,8 @@ class ABMHandler if(dtime_s < 0.001) return; INodeDefManager *ndef = env->getGameDef()->ndef(); - for(std::list::iterator - i = abms.begin(); i != abms.end(); ++i){ + for(std::vector::iterator + i = abms.begin(); i != abms.end(); ++i) { ActiveBlockModifier *abm = i->abm; float trigger_interval = abm->getTriggerInterval(); if(trigger_interval < 0.001) @@ -665,41 +848,45 @@ class ABMHandler i->timer -= trigger_interval; actual_interval = trigger_interval; } - float intervals = actual_interval / trigger_interval; - if(intervals == 0) - continue; float chance = abm->getTriggerChance(); if(chance == 0) chance = 1; ActiveABM aabm; aabm.abm = abm; - aabm.chance = chance / intervals; - if(aabm.chance == 0) - aabm.chance = 1; + if(abm->getSimpleCatchUp()) { + float intervals = actual_interval / trigger_interval; + if(intervals == 0) + continue; + aabm.chance = chance / intervals; + if(aabm.chance == 0) + aabm.chance = 1; + } else { + aabm.chance = chance; + } // Trigger neighbors std::set required_neighbors_s = abm->getRequiredNeighbors(); for(std::set::iterator i = required_neighbors_s.begin(); - i != required_neighbors_s.end(); i++) + i != required_neighbors_s.end(); ++i) { ndef->getIds(*i, aabm.required_neighbors); } // Trigger contents std::set contents_s = abm->getTriggerContents(); for(std::set::iterator - i = contents_s.begin(); i != contents_s.end(); i++) + i = contents_s.begin(); i != contents_s.end(); ++i) { std::set ids; ndef->getIds(*i, ids); for(std::set::const_iterator k = ids.begin(); - k != ids.end(); k++) + k != ids.end(); ++k) { content_t c = *k; - std::map >::iterator j; + std::map >::iterator j; j = m_aabms.find(c); if(j == m_aabms.end()){ - std::list aabmlist; + std::vector aabmlist; m_aabms[c] = aabmlist; j = m_aabms.find(c); } @@ -756,14 +943,13 @@ class ABMHandler content_t c = n.getContent(); v3s16 p = p0 + block->getPosRelative(); - std::map >::iterator j; + std::map >::iterator j; j = m_aabms.find(c); if(j == m_aabms.end()) continue; - for(std::list::iterator - i = j->second.begin(); i != j->second.end(); i++) - { + for(std::vector::iterator + i = j->second.begin(); i != j->second.end(); ++i) { if(myrand() % i->chance != 0) continue; @@ -818,34 +1004,43 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime) // Get time difference u32 dtime_s = 0; u32 stamp = block->getTimestamp(); - if(m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED) - dtime_s = m_game_time - block->getTimestamp(); + if (m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED) + dtime_s = m_game_time - stamp; dtime_s += additional_dtime; /*infostream<<"ServerEnvironment::activateBlock(): block timestamp: " <m_static_objects.m_stored.clear(); + // do not set changed flag to avoid unnecessary mapblock writes + } + // Set current time as timestamp block->setTimestampNoChangedFlag(m_game_time); /*infostream<<"ServerEnvironment::activateBlock(): block is " < elapsed_timers = + std::vector elapsed_timers = block->m_node_timers.step((float)dtime_s); - if(!elapsed_timers.empty()){ + if (!elapsed_timers.empty()) { MapNode n; - for(std::map::iterator + for (std::vector::iterator i = elapsed_timers.begin(); - i != elapsed_timers.end(); i++){ - n = block->getNodeNoEx(i->first); - v3s16 p = i->first + block->getPosRelative(); - if(m_script->node_on_timer(p,n,i->second.elapsed)) - block->setNodeTimer(i->first,NodeTimer(i->second.timeout,0)); + i != elapsed_timers.end(); ++i){ + n = block->getNodeNoEx(i->position); + v3s16 p = i->position + block->getPosRelative(); + if (m_script->node_on_timer(p, n, i->elapsed)) + block->setNodeTimer(NodeTimer(i->timeout, 0, i->position)); } } @@ -859,23 +1054,35 @@ void ServerEnvironment::addActiveBlockModifier(ActiveBlockModifier *abm) m_abms.push_back(ABMWithState(abm)); } +void ServerEnvironment::addLoadingBlockModifierDef(LoadingBlockModifierDef *lbm) +{ + m_lbm_mgr.addLBMDef(lbm); +} + bool ServerEnvironment::setNode(v3s16 p, const MapNode &n) { INodeDefManager *ndef = m_gamedef->ndef(); MapNode n_old = m_map->getNodeNoEx(p); + // Call destructor - if(ndef->get(n_old).has_on_destruct) + if (ndef->get(n_old).has_on_destruct) m_script->node_on_destruct(p, n_old); + // Replace node - bool succeeded = m_map->addNodeWithEvent(p, n); - if(!succeeded) + if (!m_map->addNodeWithEvent(p, n)) return false; + + // Update active VoxelManipulator if a mapgen thread + m_map->updateVManip(p); + // Call post-destructor - if(ndef->get(n_old).has_after_destruct) + if (ndef->get(n_old).has_after_destruct) m_script->node_after_destruct(p, n_old); + // Call constructor - if(ndef->get(n).has_on_construct) + if (ndef->get(n).has_on_construct) m_script->node_on_construct(p, n); + return true; } @@ -883,29 +1090,40 @@ bool ServerEnvironment::removeNode(v3s16 p) { INodeDefManager *ndef = m_gamedef->ndef(); MapNode n_old = m_map->getNodeNoEx(p); + // Call destructor - if(ndef->get(n_old).has_on_destruct) + if (ndef->get(n_old).has_on_destruct) m_script->node_on_destruct(p, n_old); + // Replace with air // This is slightly optimized compared to addNodeWithEvent(air) - bool succeeded = m_map->removeNodeWithEvent(p); - if(!succeeded) + if (!m_map->removeNodeWithEvent(p)) return false; + + // Update active VoxelManipulator if a mapgen thread + m_map->updateVManip(p); + // Call post-destructor - if(ndef->get(n_old).has_after_destruct) + if (ndef->get(n_old).has_after_destruct) m_script->node_after_destruct(p, n_old); + // Air doesn't require constructor return true; } bool ServerEnvironment::swapNode(v3s16 p, const MapNode &n) { - return m_map->addNodeWithEvent(p, n, false); + if (!m_map->addNodeWithEvent(p, n, false)) + return false; + + // Update active VoxelManipulator if a mapgen thread + m_map->updateVManip(p); + + return true; } -std::set ServerEnvironment::getObjectsInsideRadius(v3f pos, float radius) +void ServerEnvironment::getObjectsInsideRadius(std::vector &objects, v3f pos, float radius) { - std::set objects; for(std::map::iterator i = m_active_objects.begin(); i != m_active_objects.end(); ++i) @@ -915,36 +1133,34 @@ std::set ServerEnvironment::getObjectsInsideRadius(v3f pos, float radius) v3f objectpos = obj->getBasePosition(); if(objectpos.getDistanceFrom(pos) > radius) continue; - objects.insert(id); + objects.push_back(id); } - return objects; } -void ServerEnvironment::clearAllObjects() +void ServerEnvironment::clearObjects(ClearObjectsMode mode) { - infostream<<"ServerEnvironment::clearAllObjects(): " - <<"Removing all active objects"< objects_to_remove; - for(std::map::iterator + infostream << "ServerEnvironment::clearObjects(): " + << "Removing all active objects" << std::endl; + std::vector objects_to_remove; + for (std::map::iterator i = m_active_objects.begin(); - i != m_active_objects.end(); ++i) - { + i != m_active_objects.end(); ++i) { ServerActiveObject* obj = i->second; - if(obj->getType() == ACTIVEOBJECT_TYPE_PLAYER) + if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER) continue; u16 id = i->first; // Delete static object if block is loaded - if(obj->m_static_exists){ + if (obj->m_static_exists) { MapBlock *block = m_map->getBlockNoCreateNoEx(obj->m_static_block); - if(block){ + if (block) { block->m_static_objects.remove(id); block->raiseModified(MOD_STATE_WRITE_NEEDED, - "clearAllObjects"); + MOD_REASON_CLEAR_ALL_OBJECTS); obj->m_static_exists = false; } } // If known by some client, don't delete immediately - if(obj->m_known_by_count > 0){ + if (obj->m_known_by_count > 0) { obj->m_pending_deactivation = true; obj->m_removed = true; continue; @@ -956,110 +1172,119 @@ void ServerEnvironment::clearAllObjects() m_script->removeObjectReference(obj); // Delete active object - if(obj->environmentDeletes()) + if (obj->environmentDeletes()) delete obj; // Id to be removed from m_active_objects objects_to_remove.push_back(id); } + // Remove references from m_active_objects - for(std::list::iterator i = objects_to_remove.begin(); - i != objects_to_remove.end(); ++i) - { + for (std::vector::iterator i = objects_to_remove.begin(); + i != objects_to_remove.end(); ++i) { m_active_objects.erase(*i); } // Get list of loaded blocks - std::list loaded_blocks; - infostream<<"ServerEnvironment::clearAllObjects(): " - <<"Listing all loaded blocks"< loaded_blocks; + infostream << "ServerEnvironment::clearObjects(): " + << "Listing all loaded blocks" << std::endl; m_map->listAllLoadedBlocks(loaded_blocks); - infostream<<"ServerEnvironment::clearAllObjects(): " - <<"Done listing all loaded blocks: " - < loadable_blocks; - infostream<<"ServerEnvironment::clearAllObjects(): " - <<"Listing all loadable blocks"<listAllLoadableBlocks(loadable_blocks); - infostream<<"ServerEnvironment::clearAllObjects(): " - <<"Done listing all loadable blocks: " - < loadable_blocks; + if (mode == CLEAR_OBJECTS_MODE_FULL) { + infostream << "ServerEnvironment::clearObjects(): " + << "Listing all loadable blocks" << std::endl; + m_map->listAllLoadableBlocks(loadable_blocks); + infostream << "ServerEnvironment::clearObjects(): " + << "Done listing all loadable blocks: " + << loadable_blocks.size() << std::endl; + } else { + loadable_blocks = loaded_blocks; + } + + infostream << "ServerEnvironment::clearObjects(): " + << "Now clearing objects in " << loadable_blocks.size() + << " blocks" << std::endl; // Grab a reference on each loaded block to avoid unloading it - for(std::list::iterator i = loaded_blocks.begin(); - i != loaded_blocks.end(); ++i) - { + for (std::vector::iterator i = loaded_blocks.begin(); + i != loaded_blocks.end(); ++i) { v3s16 p = *i; MapBlock *block = m_map->getBlockNoCreateNoEx(p); - assert(block); + assert(block != NULL); block->refGrab(); } // Remove objects in all loadable blocks - u32 unload_interval = g_settings->getS32("max_clearobjects_extra_loaded_blocks"); - unload_interval = MYMAX(unload_interval, 1); + u32 unload_interval = U32_MAX; + if (mode == CLEAR_OBJECTS_MODE_FULL) { + unload_interval = g_settings->getS32("max_clearobjects_extra_loaded_blocks"); + unload_interval = MYMAX(unload_interval, 1); + } u32 report_interval = loadable_blocks.size() / 10; u32 num_blocks_checked = 0; u32 num_blocks_cleared = 0; u32 num_objs_cleared = 0; - for(std::list::iterator i = loadable_blocks.begin(); - i != loadable_blocks.end(); ++i) - { + for (std::vector::iterator i = loadable_blocks.begin(); + i != loadable_blocks.end(); ++i) { v3s16 p = *i; MapBlock *block = m_map->emergeBlock(p, false); - if(!block){ - errorstream<<"ServerEnvironment::clearAllObjects(): " - <<"Failed to emerge block "<m_static_objects.m_stored.size(); u32 num_active = block->m_static_objects.m_active.size(); - if(num_stored != 0 || num_active != 0){ + if (num_stored != 0 || num_active != 0) { block->m_static_objects.m_stored.clear(); block->m_static_objects.m_active.clear(); block->raiseModified(MOD_STATE_WRITE_NEEDED, - "clearAllObjects"); + MOD_REASON_CLEAR_ALL_OBJECTS); num_objs_cleared += num_stored + num_active; num_blocks_cleared++; } num_blocks_checked++; - if(report_interval != 0 && - num_blocks_checked % report_interval == 0){ + if (report_interval != 0 && + num_blocks_checked % report_interval == 0) { float percent = 100.0 * (float)num_blocks_checked / - loadable_blocks.size(); - infostream<<"ServerEnvironment::clearAllObjects(): " - <<"Cleared "<unloadUnreferencedBlocks(); } } m_map->unloadUnreferencedBlocks(); // Drop references that were added above - for(std::list::iterator i = loaded_blocks.begin(); - i != loaded_blocks.end(); ++i) - { + for (std::vector::iterator i = loaded_blocks.begin(); + i != loaded_blocks.end(); ++i) { v3s16 p = *i; MapBlock *block = m_map->getBlockNoCreateNoEx(p); assert(block); block->refDrop(); } - infostream<<"ServerEnvironment::clearAllObjects(): " - <<"Finished: Cleared "<getFloat("dedicated_server_step"); + static const float server_step = g_settings->getFloat("dedicated_server_step"); + m_recommended_send_interval = server_step; /* Increment game time @@ -1079,21 +1305,21 @@ void ServerEnvironment::step(float dtime) m_game_time += inc_i; m_game_time_fraction_counter -= (float)inc_i; } - + /* Handle players */ { ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_AVG); - for(std::list::iterator i = m_players.begin(); + for(std::vector::iterator i = m_players.begin(); i != m_players.end(); ++i) { Player *player = *i; - + // Ignore disconnected players if(player->peer_id == 0) continue; - + // Move player->move(dtime, this, 100*BS); } @@ -1102,30 +1328,29 @@ void ServerEnvironment::step(float dtime) /* Manage active block list */ - if(m_active_blocks_management_interval.step(dtime, 2.0)) - { - ScopeProfiler sp(g_profiler, "SEnv: manage act. block list avg /2s", SPT_AVG); + if (m_active_blocks_management_interval.step(dtime, m_cache_active_block_mgmt_interval)) { + ScopeProfiler sp(g_profiler, "SEnv: manage act. block list avg per interval", SPT_AVG); /* Get player block positions */ - std::list players_blockpos; - for(std::list::iterator + std::vector players_blockpos; + for(std::vector::iterator i = m_players.begin(); - i != m_players.end(); ++i) - { + i != m_players.end(); ++i) { Player *player = *i; // Ignore disconnected players if(player->peer_id == 0) continue; + v3s16 blockpos = getNodeBlockPos( floatToInt(player->getPosition(), BS)); players_blockpos.push_back(blockpos); } - + /* Update list of active blocks, collecting changes */ - const s16 active_block_range = g_settings->getS16("active_block_range"); + static const s16 active_block_range = g_settings->getS16("active_block_range"); std::set blocks_removed; std::set blocks_added; m_active_blocks.update(players_blockpos, active_block_range, @@ -1137,20 +1362,19 @@ void ServerEnvironment::step(float dtime) // Convert active objects that are no more in active blocks to static deactivateFarObjects(false); - + for(std::set::iterator i = blocks_removed.begin(); - i != blocks_removed.end(); ++i) - { + i != blocks_removed.end(); ++i) { v3s16 p = *i; /* infostream<<"Server: Block " << PP(p) << " became inactive"<getBlockNoCreateNoEx(p); if(block==NULL) continue; - + // Set current time as timestamp (and let it set ChangedFlag) block->setTimestamp(m_game_time); } @@ -1180,18 +1404,17 @@ void ServerEnvironment::step(float dtime) /* Mess around in active blocks */ - if(m_active_blocks_nodemetadata_interval.step(dtime, 1.0)) - { - ScopeProfiler sp(g_profiler, "SEnv: mess in act. blocks avg /1s", SPT_AVG); - - float dtime = 1.0; + if (m_active_blocks_nodemetadata_interval.step(dtime, m_cache_nodetimer_interval)) { + ScopeProfiler sp(g_profiler, "SEnv: mess in act. blocks avg per interval", SPT_AVG); + + float dtime = m_cache_nodetimer_interval; for(std::set::iterator i = m_active_blocks.m_list.begin(); i != m_active_blocks.m_list.end(); ++i) { v3s16 p = *i; - + /*infostream<<"Server: Block ("<resetUsageTimer(); - + // Set current time as timestamp block->setTimestampNoChangedFlag(m_game_time); // If time has changed much from the one on disk, // set block to be saved when it is unloaded if(block->getTimestamp() > block->getDiskTimestamp() + 60) block->raiseModified(MOD_STATE_WRITE_AT_UNLOAD, - "Timestamp older than 60s (step)"); + MOD_REASON_BLOCK_EXPIRED); // Run node timers - std::map elapsed_timers = + std::vector elapsed_timers = block->m_node_timers.step((float)dtime); - if(!elapsed_timers.empty()){ + if (!elapsed_timers.empty()) { MapNode n; - for(std::map::iterator + for (std::vector::iterator i = elapsed_timers.begin(); - i != elapsed_timers.end(); i++){ - n = block->getNodeNoEx(i->first); - p = i->first + block->getPosRelative(); - if(m_script->node_on_timer(p,n,i->second.elapsed)) - block->setNodeTimer(i->first,NodeTimer(i->second.timeout,0)); + i != elapsed_timers.end(); ++i) { + n = block->getNodeNoEx(i->position); + p = i->position + block->getPosRelative(); + if (m_script->node_on_timer(p, n, i->elapsed)) { + block->setNodeTimer(NodeTimer( + i->timeout, 0, i->position)); + } } } } } - - const float abm_interval = 1.0; - if(m_active_block_modifier_interval.step(dtime, abm_interval)) + + if (m_active_block_modifier_interval.step(dtime, m_cache_abm_interval)) do{ // breakable if(m_active_block_interval_overload_skip > 0){ ScopeProfiler sp(g_profiler, "SEnv: ABM overload skips"); m_active_block_interval_overload_skip--; break; } - ScopeProfiler sp(g_profiler, "SEnv: modify in blocks avg /1s", SPT_AVG); - TimeTaker timer("modify in active blocks"); - + ScopeProfiler sp(g_profiler, "SEnv: modify in blocks avg per interval", SPT_AVG); + TimeTaker timer("modify in active blocks per interval"); + // Initialize handling of ActiveBlockModifiers - ABMHandler abmhandler(m_abms, abm_interval, this, true); + ABMHandler abmhandler(m_abms, m_cache_abm_interval, this, true); for(std::set::iterator i = m_active_blocks.m_list.begin(); i != m_active_blocks.m_list.end(); ++i) { v3s16 p = *i; - + /*infostream<<"Server: Block ("<getBlockNoCreateNoEx(p); - if(block==NULL) + if(block == NULL) continue; - + // Set current time as timestamp block->setTimestampNoChangedFlag(m_game_time); @@ -1264,13 +1488,13 @@ void ServerEnvironment::step(float dtime) u32 time_ms = timer.stop(true); u32 max_time_ms = 200; if(time_ms > max_time_ms){ - infostream<<"WARNING: active block modifiers took " + warningstream<<"active block modifiers took " <avg("SEnv: num of objects", m_active_objects.size()); - + // This helps the objects to send data at the same time bool send_recommended = false; m_send_recommended_timer += dtime; @@ -1299,11 +1523,6 @@ void ServerEnvironment::step(float dtime) i != m_active_objects.end(); ++i) { ServerActiveObject* obj = i->second; - // Remove non-peaceful mobs on peaceful mode - if(g_settings->getBool("only_peaceful_mobs")){ - if(!obj->isPeaceful()) - obj->m_removed = true; - } // Don't step if is to be removed or stored statically if(obj->m_removed || obj->m_pending_deactivation) continue; @@ -1312,12 +1531,13 @@ void ServerEnvironment::step(float dtime) // Read messages from object while(!obj->m_messages_out.empty()) { - m_active_object_messages.push_back( - obj->m_messages_out.pop_front()); + m_active_object_messages.push( + obj->m_messages_out.front()); + obj->m_messages_out.pop(); } } } - + /* Manage active objects */ @@ -1329,6 +1549,49 @@ void ServerEnvironment::step(float dtime) */ removeRemovedObjects(); } + + /* + Manage particle spawner expiration + */ + if (m_particle_management_interval.step(dtime, 1.0)) { + for (std::map::iterator i = m_particle_spawners.begin(); + i != m_particle_spawners.end(); ) { + //non expiring spawners + if (i->second == PARTICLE_SPAWNER_NO_EXPIRY) { + ++i; + continue; + } + + i->second -= 1.0f; + if (i->second <= 0.f) + m_particle_spawners.erase(i++); + else + ++i; + } + } +} + +u32 ServerEnvironment::addParticleSpawner(float exptime) +{ + // Timers with lifetime 0 do not expire + float time = exptime > 0.f ? exptime : PARTICLE_SPAWNER_NO_EXPIRY; + + u32 id = 0; + for (;;) { // look for unused particlespawner id + id++; + std::map::iterator f; + f = m_particle_spawners.find(id); + if (f == m_particle_spawners.end()) { + m_particle_spawners[id] = time; + break; + } + } + return id; +} + +void ServerEnvironment::deleteParticleSpawner(u32 id) +{ + m_particle_spawners.erase(id); } ServerActiveObject* ServerEnvironment::getActiveObject(u16 id) @@ -1360,7 +1623,7 @@ u16 getFreeServerActiveObjectId( last_used_id ++; if(isFreeServerActiveObjectId(last_used_id, objects)) return last_used_id; - + if(last_used_id == startid) return 0; } @@ -1368,67 +1631,27 @@ u16 getFreeServerActiveObjectId( u16 ServerEnvironment::addActiveObject(ServerActiveObject *object) { - assert(object); + assert(object); // Pre-condition m_added_objects++; u16 id = addActiveObjectRaw(object, true, 0); return id; } -#if 0 -bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj) -{ - assert(obj); - - v3f objectpos = obj->getBasePosition(); - - // The block in which the object resides in - v3s16 blockpos_o = getNodeBlockPos(floatToInt(objectpos, BS)); - - /* - Update the static data - */ - - // Create new static object - std::string staticdata = obj->getStaticData(); - StaticObject s_obj(obj->getType(), objectpos, staticdata); - // Add to the block where the object is located in - v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS)); - // Get or generate the block - MapBlock *block = m_map->emergeBlock(blockpos); - - bool succeeded = false; - - if(block) - { - block->m_static_objects.insert(0, s_obj); - block->raiseModified(MOD_STATE_WRITE_AT_UNLOAD, - "addActiveObjectAsStatic"); - succeeded = true; - } - else{ - infostream<<"ServerEnvironment::addActiveObjectAsStatic: " - <<"Could not find or generate " - <<"a block for storing static object"<environmentDeletes()) - delete obj; - - return succeeded; -} -#endif - /* Finds out what new objects have been added to inside a radius around a position */ -void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius, +void ServerEnvironment::getAddedActiveObjects(Player *player, s16 radius, + s16 player_radius, std::set ¤t_objects, - std::set &added_objects) + std::queue &added_objects) { - v3f pos_f = intToFloat(pos, BS); f32 radius_f = radius * BS; + f32 player_radius_f = player_radius * BS; + + if (player_radius_f < 0) + player_radius_f = 0; + /* Go through the object list, - discard m_removed objects, @@ -1438,29 +1661,33 @@ void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius, */ for(std::map::iterator i = m_active_objects.begin(); - i != m_active_objects.end(); ++i) - { + i != m_active_objects.end(); ++i) { u16 id = i->first; + // Get object ServerActiveObject *object = i->second; if(object == NULL) continue; + // Discard if removed or deactivating if(object->m_removed || object->m_pending_deactivation) continue; - if(object->unlimitedTransferDistance() == false){ + + f32 distance_f = object->getBasePosition().getDistanceFrom(player->getPosition()); + if (object->getType() == ACTIVEOBJECT_TYPE_PLAYER) { // Discard if too far - f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f); - if(distance_f > radius_f) + if (distance_f > player_radius_f && player_radius_f != 0) continue; - } + } else if (distance_f > radius_f) + continue; + // Discard if already on current_objects std::set::iterator n; n = current_objects.find(id); if(n != current_objects.end()) continue; // Add to added_objects - added_objects.insert(id); + added_objects.push(id); } } @@ -1468,12 +1695,17 @@ void ServerEnvironment::getAddedActiveObjects(v3s16 pos, s16 radius, Finds out what objects have been removed from inside a radius around a position */ -void ServerEnvironment::getRemovedActiveObjects(v3s16 pos, s16 radius, +void ServerEnvironment::getRemovedActiveObjects(Player *player, s16 radius, + s16 player_radius, std::set ¤t_objects, - std::set &removed_objects) + std::queue &removed_objects) { - v3f pos_f = intToFloat(pos, BS); f32 radius_f = radius * BS; + f32 player_radius_f = player_radius * BS; + + if (player_radius_f < 0) + player_radius_f = 0; + /* Go through current_objects; object is removed if: - object is not found in m_active_objects (this is actually an @@ -1489,32 +1721,54 @@ void ServerEnvironment::getRemovedActiveObjects(v3s16 pos, s16 radius, u16 id = *i; ServerActiveObject *object = getActiveObject(id); - if(object == NULL){ - infostream<<"ServerEnvironment::getRemovedActiveObjects():" - <<" object in current_objects is NULL"<m_removed || object->m_pending_deactivation) - { - removed_objects.insert(id); + if (object->m_removed || object->m_pending_deactivation) { + removed_objects.push(id); continue; } - - // If transfer distance is unlimited, don't remove - if(object->unlimitedTransferDistance()) + + f32 distance_f = object->getBasePosition().getDistanceFrom(player->getPosition()); + if (object->getType() == ACTIVEOBJECT_TYPE_PLAYER) { + if (distance_f <= player_radius_f || player_radius_f == 0) + continue; + } else if (distance_f <= radius_f) continue; - f32 distance_f = object->getBasePosition().getDistanceFrom(pos_f); + // Object is no longer visible + removed_objects.push(id); + } +} - if(distance_f >= radius_f) - { - removed_objects.insert(id); +void ServerEnvironment::setStaticForActiveObjectsInBlock( + v3s16 blockpos, bool static_exists, v3s16 static_block) +{ + MapBlock *block = m_map->getBlockNoCreateNoEx(blockpos); + if (!block) + return; + + for (std::map::iterator + so_it = block->m_static_objects.m_active.begin(); + so_it != block->m_static_objects.m_active.end(); ++so_it) { + // Get the ServerActiveObject counterpart to this StaticObject + std::map::iterator ao_it; + ao_it = m_active_objects.find(so_it->first); + if (ao_it == m_active_objects.end()) { + // If this ever happens, there must be some kind of nasty bug. + errorstream << "ServerEnvironment::setStaticForObjectsInBlock(): " + "Object from MapBlock::m_static_objects::m_active not found " + "in m_active_objects"; continue; } - - // Not removed + + ServerActiveObject *sao = ao_it->second; + sao->m_static_exists = static_exists; + sao->m_static_block = static_block; } } @@ -1522,9 +1776,9 @@ ActiveObjectMessage ServerEnvironment::getActiveObjectMessage() { if(m_active_object_messages.empty()) return ActiveObjectMessage(0); - + ActiveObjectMessage message = m_active_object_messages.front(); - m_active_object_messages.pop_front(); + m_active_object_messages.pop(); return message; } @@ -1535,7 +1789,7 @@ ActiveObjectMessage ServerEnvironment::getActiveObjectMessage() u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, bool set_changed, u32 dtime_s) { - assert(object); + assert(object); // Pre-condition if(object->getId() == 0){ u16 new_id = getFreeServerActiveObjectId(m_active_objects); if(new_id == 0) @@ -1560,21 +1814,32 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, delete object; return 0; } + + if (objectpos_over_limit(object->getBasePosition())) { + v3f p = object->getBasePosition(); + errorstream << "ServerEnvironment::addActiveObjectRaw(): " + << "object position (" << p.X << "," << p.Y << "," << p.Z + << ") outside maximum range" << std::endl; + if (object->environmentDeletes()) + delete object; + return 0; + } + /*infostream<<"ServerEnvironment::addActiveObjectRaw(): " <<"added (id="<getId()<<")"<getId()] = object; - + verbosestream<<"ServerEnvironment::addActiveObjectRaw(): " <<"Added id="<getId()<<"; there are now " <addObjectReference(object); // Post-initialize object object->addedToEnvironment(dtime_s); - + // Add static data to block if(object->isStaticAllowed()) { @@ -1592,7 +1857,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, if(set_changed) block->raiseModified(MOD_STATE_WRITE_NEEDED, - "addActiveObjectRaw"); + MOD_REASON_ADD_ACTIVE_OBJECT_RAW); } else { v3s16 p = floatToInt(objectpos, BS); errorstream<<"ServerEnvironment::addActiveObjectRaw(): " @@ -1600,7 +1865,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, <<" statically (pos="<getId(); } @@ -1609,11 +1874,10 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, */ void ServerEnvironment::removeRemovedObjects() { - std::list objects_to_remove; + std::vector objects_to_remove; for(std::map::iterator i = m_active_objects.begin(); - i != m_active_objects.end(); ++i) - { + i != m_active_objects.end(); ++i) { u16 id = i->first; ServerActiveObject* obj = i->second; // This shouldn't happen but check it @@ -1642,7 +1906,7 @@ void ServerEnvironment::removeRemovedObjects() if (block) { block->m_static_objects.remove(id); block->raiseModified(MOD_STATE_WRITE_NEEDED, - "removeRemovedObjects/remove"); + MOD_REASON_REMOVE_OBJECTS_REMOVE); obj->m_static_exists = false; } else { infostream<<"Failed to emerge block from which an object to " @@ -1667,7 +1931,7 @@ void ServerEnvironment::removeRemovedObjects() block->m_static_objects.m_stored.push_back(i->second); block->m_static_objects.m_active.erase(id); block->raiseModified(MOD_STATE_WRITE_NEEDED, - "removeRemovedObjects/deactivate"); + MOD_REASON_REMOVE_OBJECTS_DEACTIVATE); } } else { infostream<<"Failed to emerge block from which an object to " @@ -1683,13 +1947,13 @@ void ServerEnvironment::removeRemovedObjects() // Delete if(obj->environmentDeletes()) delete obj; + // Id to be removed from m_active_objects objects_to_remove.push_back(id); } // Remove references from m_active_objects - for(std::list::iterator i = objects_to_remove.begin(); - i != objects_to_remove.end(); ++i) - { + for(std::vector::iterator i = objects_to_remove.begin(); + i != objects_to_remove.end(); ++i) { m_active_objects.erase(*i); } } @@ -1733,17 +1997,19 @@ static void print_hexdump(std::ostream &o, const std::string &data) */ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s) { - if(block==NULL) + if(block == NULL) return; + // Ignore if no stored objects (to not set changed flag) - if(block->m_static_objects.m_stored.size() == 0) + if(block->m_static_objects.m_stored.empty()) return; + verbosestream<<"ServerEnvironment::activateObjects(): " <<"activating objects of block "<getPos()) <<" ("<m_static_objects.m_stored.size() <<" objects)"<m_static_objects.m_stored.size() > g_settings->getU16("max_objects_per_block")); - if(large_amount){ + if (large_amount) { errorstream<<"suspiciously large amount of objects detected: " <m_static_objects.m_stored.size()<<" in " <getPos()) @@ -1751,32 +2017,28 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s) // Clear stored list block->m_static_objects.m_stored.clear(); block->raiseModified(MOD_STATE_WRITE_NEEDED, - "stored list cleared in activateObjects due to " - "large amount of objects"); + MOD_REASON_TOO_MANY_OBJECTS); return; } // Activate stored objects - std::list new_stored; - for(std::list::iterator + std::vector new_stored; + for (std::vector::iterator i = block->m_static_objects.m_stored.begin(); - i != block->m_static_objects.m_stored.end(); ++i) - { - /*infostream<<"Server: Creating an active object from " - <<"static data"<m_static_objects.m_stored.end(); ++i) { StaticObject &s_obj = *i; + // Create an active object from the data ServerActiveObject *obj = ServerActiveObject::create - (s_obj.type, this, 0, s_obj.pos, s_obj.data); + ((ActiveObjectType) s_obj.type, this, 0, s_obj.pos, s_obj.data); // If couldn't create object, store static data back. - if(obj==NULL) - { + if(obj == NULL) { errorstream<<"ServerEnvironment::activateObjects(): " <<"failed to create active object from static object " <<"in block "<m_static_objects.m_stored.clear(); // Add leftover failed stuff to stored list - for(std::list::iterator + for(std::vector::iterator i = new_stored.begin(); - i != new_stored.end(); ++i) - { + i != new_stored.end(); ++i) { StaticObject &s_obj = *i; block->m_static_objects.m_stored.push_back(s_obj); } @@ -1832,14 +2093,13 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s) */ void ServerEnvironment::deactivateFarObjects(bool force_delete) { - std::list objects_to_remove; + std::vector objects_to_remove; for(std::map::iterator i = m_active_objects.begin(); - i != m_active_objects.end(); ++i) - { + i != m_active_objects.end(); ++i) { ServerActiveObject* obj = i->second; assert(obj); - + // Do not deactivate if static data creation not allowed if(!force_delete && !obj->isStaticAllowed()) continue; @@ -1878,7 +2138,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) block->m_static_objects.insert(id, s_obj); obj->m_static_block = blockpos_o; block->raiseModified(MOD_STATE_WRITE_NEEDED, - "deactivateFarObjects: Static data moved in"); + MOD_REASON_STATIC_DATA_ADDED); // Delete from block where object was located block = m_map->emergeBlock(old_static_block, false); @@ -1891,7 +2151,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) } block->m_static_objects.remove(id); block->raiseModified(MOD_STATE_WRITE_NEEDED, - "deactivateFarObjects: Static data moved out"); + MOD_REASON_STATIC_DATA_REMOVED); continue; } @@ -1915,36 +2175,38 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) // Create new static object std::string staticdata_new = obj->getStaticData(); StaticObject s_obj(obj->getType(), objectpos, staticdata_new); - + bool stays_in_same_block = false; bool data_changed = true; - if(obj->m_static_exists){ - if(obj->m_static_block == blockpos_o) + if (obj->m_static_exists) { + if (obj->m_static_block == blockpos_o) stays_in_same_block = true; MapBlock *block = m_map->emergeBlock(obj->m_static_block, false); - - std::map::iterator n = + + if (block) { + std::map::iterator n = block->m_static_objects.m_active.find(id); - if(n != block->m_static_objects.m_active.end()){ - StaticObject static_old = n->second; + if (n != block->m_static_objects.m_active.end()) { + StaticObject static_old = n->second; - float save_movem = obj->getMinimumSavedMovement(); + float save_movem = obj->getMinimumSavedMovement(); - if(static_old.data == staticdata_new && - (static_old.pos - objectpos).getLength() < save_movem) - data_changed = false; - } else { - errorstream<<"ServerEnvironment::deactivateFarObjects(): " + if (static_old.data == staticdata_new && + (static_old.pos - objectpos).getLength() < save_movem) + data_changed = false; + } else { + errorstream<<"ServerEnvironment::deactivateFarObjects(): " <<"id="<m_static_block)<m_static_exists) { @@ -1956,8 +2218,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) // Only mark block as modified if data changed considerably if(shall_be_written) block->raiseModified(MOD_STATE_WRITE_NEEDED, - "deactivateFarObjects: Static data " - "changed considerably"); + MOD_REASON_STATIC_DATA_CHANGED); } } @@ -1992,20 +2253,19 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) // reason. Unsuccessful attempts have been made to find // said reason. if(id && block->m_static_objects.m_active.find(id) != block->m_static_objects.m_active.end()){ - infostream<<"ServerEnv: WARNING: Performing hack #83274" + warningstream<<"ServerEnv: Performing hack #83274" <m_static_objects.remove(id); } // Store static data u16 store_id = pending_delete ? id : 0; block->m_static_objects.insert(store_id, s_obj); - + // Only mark block as modified if data changed considerably if(shall_be_written) block->raiseModified(MOD_STATE_WRITE_NEEDED, - "deactivateFarObjects: Static data " - "changed considerably"); - + MOD_REASON_STATIC_DATA_CHANGED); + obj->m_static_exists = true; obj->m_static_block = block->getPos(); } @@ -2035,7 +2295,7 @@ void ServerEnvironment::deactivateFarObjects(bool force_delete) obj->m_pending_deactivation = true; continue; } - + verbosestream<<"ServerEnvironment::deactivateFarObjects(): " <<"object id="<::iterator i = objects_to_remove.begin(); - i != objects_to_remove.end(); ++i) - { + for(std::vector::iterator i = objects_to_remove.begin(); + i != objects_to_remove.end(); ++i) { m_active_objects.erase(*i); } } - #ifndef SERVER #include "clientsimpleobject.h" @@ -2079,7 +2337,7 @@ ClientEnvironment::ClientEnvironment(ClientMap *map, scene::ISceneManager *smgr, m_irr(irr) { char zero = 0; - memset(m_attachements, zero, sizeof(m_attachements)); + memset(attachement_parent_ids, zero, sizeof(attachement_parent_ids)); } ClientEnvironment::~ClientEnvironment() @@ -2092,9 +2350,8 @@ ClientEnvironment::~ClientEnvironment() delete i->second; } - for(std::list::iterator - i = m_simple_objects.begin(); i != m_simple_objects.end(); ++i) - { + for(std::vector::iterator + i = m_simple_objects.begin(); i != m_simple_objects.end(); ++i) { delete *i; } @@ -2114,21 +2371,21 @@ ClientMap & ClientEnvironment::getClientMap() void ClientEnvironment::addPlayer(Player *player) { - DSTACK(__FUNCTION_NAME); + DSTACK(FUNCTION_NAME); /* It is a failure if player is local and there already is a local player */ - assert(!(player->isLocal() == true && getLocalPlayer() != NULL)); + FATAL_ERROR_IF(player->isLocal() == true && getLocalPlayer() != NULL, + "Player is local but there is already a local player"); Environment::addPlayer(player); } LocalPlayer * ClientEnvironment::getLocalPlayer() { - for(std::list::iterator i = m_players.begin(); - i != m_players.end(); ++i) - { + for(std::vector::iterator i = m_players.begin(); + i != m_players.end(); ++i) { Player *player = *i; if(player->isLocal()) return (LocalPlayer*)player; @@ -2138,7 +2395,7 @@ LocalPlayer * ClientEnvironment::getLocalPlayer() void ClientEnvironment::step(float dtime) { - DSTACK(__FUNCTION_NAME); + DSTACK(FUNCTION_NAME); /* Step time of day */ stepTimeOfDay(dtime); @@ -2151,15 +2408,15 @@ void ClientEnvironment::step(float dtime) LocalPlayer *lplayer = getLocalPlayer(); assert(lplayer); // collision info queue - std::list player_collisions; - + std::vector player_collisions; + /* Get the speed the player is going */ bool is_climbing = lplayer->is_climbing; - + f32 player_speed = lplayer->getSpeed().getLength(); - + /* Maximum position increment */ @@ -2171,15 +2428,15 @@ void ClientEnvironment::step(float dtime) f32 dtime_max_increment = 1; if(player_speed > 0.001) dtime_max_increment = position_max_increment / player_speed; - + // Maximum time increment is 10ms or lower if(dtime_max_increment > 0.01) dtime_max_increment = 0.01; - + // Don't allow overly huge dtime if(dtime > 0.5) dtime = 0.5; - + f32 dtime_downcount = dtime; /* @@ -2207,11 +2464,11 @@ void ClientEnvironment::step(float dtime) */ dtime_downcount = 0; } - + /* Handle local player */ - + { // Apply physics if(free_move == false && is_climbing == false) @@ -2237,18 +2494,9 @@ void ClientEnvironment::step(float dtime) if(dl > lplayer->movement_liquid_fluidity_smooth) dl = lplayer->movement_liquid_fluidity_smooth; dl *= (lplayer->liquid_viscosity * viscosity_factor) + (1 - viscosity_factor); - + v3f d = d_wanted.normalize() * dl; speed += d; - -#if 0 // old code - if(speed.X > lplayer->movement_liquid_fluidity + lplayer->movement_liquid_fluidity_smooth) speed.X -= lplayer->movement_liquid_fluidity_smooth; - if(speed.X < -lplayer->movement_liquid_fluidity - lplayer->movement_liquid_fluidity_smooth) speed.X += lplayer->movement_liquid_fluidity_smooth; - if(speed.Y > lplayer->movement_liquid_fluidity + lplayer->movement_liquid_fluidity_smooth) speed.Y -= lplayer->movement_liquid_fluidity_smooth; - if(speed.Y < -lplayer->movement_liquid_fluidity - lplayer->movement_liquid_fluidity_smooth) speed.Y += lplayer->movement_liquid_fluidity_smooth; - if(speed.Z > lplayer->movement_liquid_fluidity + lplayer->movement_liquid_fluidity_smooth) speed.Z -= lplayer->movement_liquid_fluidity_smooth; - if(speed.Z < -lplayer->movement_liquid_fluidity - lplayer->movement_liquid_fluidity_smooth) speed.Z += lplayer->movement_liquid_fluidity_smooth; -#endif } lplayer->setSpeed(speed); @@ -2263,13 +2511,11 @@ void ClientEnvironment::step(float dtime) } } while(dtime_downcount > 0.001); - + //std::cout<<"Looped "<::iterator - i = player_collisions.begin(); - i != player_collisions.end(); ++i) - { + + for(std::vector::iterator i = player_collisions.begin(); + i != player_collisions.end(); ++i) { CollisionInfo &info = *i; v3f speed_diff = info.new_speed - info.old_speed;; // Handle only fall damage @@ -2302,14 +2548,14 @@ void ClientEnvironment::step(float dtime) } } } - + /* A quick draft of lava damage */ if(m_lava_hurt_interval.step(dtime, 1.0)) { v3f pf = lplayer->getPosition(); - + // Feet, middle and head v3s16 p1 = floatToInt(pf + v3f(0, BS*0.1, 0), BS); MapNode n1 = m_map->getNodeNoEx(p1); @@ -2325,7 +2571,7 @@ void ClientEnvironment::step(float dtime) m_gamedef->ndef()->get(n2).damage_per_second); damage_per_second = MYMAX(damage_per_second, m_gamedef->ndef()->get(n3).damage_per_second); - + if(damage_per_second != 0) { damageLocalPlayer(damage_per_second, true); @@ -2384,39 +2630,42 @@ void ClientEnvironment::step(float dtime) /* Stuff that can be done in an arbitarily large dtime */ - for(std::list::iterator i = m_players.begin(); - i != m_players.end(); ++i) - { + for(std::vector::iterator i = m_players.begin(); + i != m_players.end(); ++i) { Player *player = *i; - + /* Handle non-local players */ - if(player->isLocal() == false) - { + if(player->isLocal() == false) { // Move player->move(dtime, this, 100*BS); } - - // Update lighting on all players on client - float light = 1.0; - try{ - // Get node at head - v3s16 p = player->getLightPosition(); - MapNode n = m_map->getNode(p); - light = n.getLightBlendF1((float)getDayNightRatio()/1000, m_gamedef->ndef()); - } - catch(InvalidPositionException &e){ - light = blend_light_f1((float)getDayNightRatio()/1000, LIGHT_SUN, 0); - } - player->light = light; } - + + // Update lighting on local player (used for wield item) + u32 day_night_ratio = getDayNightRatio(); + { + // Get node at head + + // On InvalidPositionException, use this as default + // (day: LIGHT_SUN, night: 0) + MapNode node_at_lplayer(CONTENT_AIR, 0x0f, 0); + + v3s16 p = lplayer->getLightPosition(); + node_at_lplayer = m_map->getNodeNoEx(p); + + u16 light = getInteriorLight(node_at_lplayer, 0, m_gamedef->ndef()); + u8 day = light & 0xff; + u8 night = (light >> 8) & 0xff; + finalColorBlend(lplayer->light_color, day, night, day_night_ratio); + } + /* Step active objects and update lighting of them */ - + g_profiler->avg("CEnv: num of objects", m_active_objects.size()); bool update_lighting = m_active_object_light_update_interval.step(dtime, 0.21); for(std::map::iterator @@ -2431,15 +2680,16 @@ void ClientEnvironment::step(float dtime) { // Update lighting u8 light = 0; - try{ - // Get node at head - v3s16 p = obj->getLightPosition(); - MapNode n = m_map->getNode(p); - light = n.getLightBlend(getDayNightRatio(), m_gamedef->ndef()); - } - catch(InvalidPositionException &e){ - light = blend_light(getDayNightRatio(), LIGHT_SUN, 0); - } + bool pos_ok; + + // Get node at head + v3s16 p = obj->getLightPosition(); + MapNode n = m_map->getNodeNoEx(p, &pos_ok); + if (pos_ok) + light = n.getLightBlend(day_night_ratio, m_gamedef->ndef()); + else + light = blend_light(day_night_ratio, LIGHT_SUN, 0); + obj->updateLight(light); } } @@ -2448,25 +2698,36 @@ void ClientEnvironment::step(float dtime) Step and handle simple objects */ g_profiler->avg("CEnv: num of simple objects", m_simple_objects.size()); - for(std::list::iterator - i = m_simple_objects.begin(); i != m_simple_objects.end();) - { - ClientSimpleObject *simple = *i; - std::list::iterator cur = i; - ++i; + for(std::vector::iterator + i = m_simple_objects.begin(); i != m_simple_objects.end();) { + std::vector::iterator cur = i; + ClientSimpleObject *simple = *cur; + simple->step(dtime); - if(simple->m_to_be_removed){ + if(simple->m_to_be_removed) { delete simple; - m_simple_objects.erase(cur); + i = m_simple_objects.erase(cur); + } + else { + ++i; } } } - + void ClientEnvironment::addSimpleObject(ClientSimpleObject *simple) { m_simple_objects.push_back(simple); } +GenericCAO* ClientEnvironment::getGenericCAO(u16 id) +{ + ClientActiveObject *obj = getActiveObject(id); + if (obj && obj->getType() == ACTIVEOBJECT_TYPE_GENERIC) + return (GenericCAO*) obj; + else + return NULL; +} + ClientActiveObject* ClientEnvironment::getActiveObject(u16 id) { std::map::iterator n; @@ -2496,7 +2757,7 @@ u16 getFreeClientActiveObjectId( last_used_id ++; if(isFreeClientActiveObjectId(last_used_id, objects)) return last_used_id; - + if(last_used_id == startid) return 0; } @@ -2504,7 +2765,7 @@ u16 getFreeClientActiveObjectId( u16 ClientEnvironment::addActiveObject(ClientActiveObject *object) { - assert(object); + assert(object); // Pre-condition if(object->getId() == 0) { u16 new_id = getFreeClientActiveObjectId(m_active_objects); @@ -2530,15 +2791,16 @@ u16 ClientEnvironment::addActiveObject(ClientActiveObject *object) object->addToScene(m_smgr, m_texturesource, m_irr); { // Update lighting immediately u8 light = 0; - try{ - // Get node at head - v3s16 p = object->getLightPosition(); - MapNode n = m_map->getNode(p); + bool pos_ok; + + // Get node at head + v3s16 p = object->getLightPosition(); + MapNode n = m_map->getNodeNoEx(p, &pos_ok); + if (pos_ok) light = n.getLightBlend(getDayNightRatio(), m_gamedef->ndef()); - } - catch(InvalidPositionException &e){ + else light = blend_light(getDayNightRatio(), LIGHT_SUN, 0); - } + object->updateLight(light); } return object->getId(); @@ -2548,7 +2810,7 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type, const std::string &init_data) { ClientActiveObject* obj = - ClientActiveObject::create(type, m_gamedef, this); + ClientActiveObject::create((ActiveObjectType) type, m_gamedef, this); if(obj == NULL) { infostream<<"ClientEnvironment::addActiveObject(): " @@ -2556,7 +2818,7 @@ void ClientEnvironment::addActiveObject(u16 id, u8 type, <setId(id); try @@ -2592,28 +2854,23 @@ void ClientEnvironment::removeActiveObject(u16 id) m_active_objects.erase(id); } -void ClientEnvironment::processActiveObjectMessage(u16 id, - const std::string &data) +void ClientEnvironment::processActiveObjectMessage(u16 id, const std::string &data) { - ClientActiveObject* obj = getActiveObject(id); - if(obj == NULL) - { - infostream<<"ClientEnvironment::processActiveObjectMessage():" - <<" got message for id="<processMessage(data); - } - catch(SerializationError &e) - { + } catch (SerializationError &e) { errorstream<<"ClientEnvironment::processActiveObjectMessage():" - <<" id="<hp > damage) + + if (handle_hp) { + if (lplayer->hp > damage) lplayer->hp -= damage; else lplayer->hp = 0; @@ -2637,7 +2894,7 @@ void ClientEnvironment::damageLocalPlayer(u8 damage, bool handle_hp) event.type = CEE_PLAYER_DAMAGE; event.player_damage.amount = damage; event.player_damage.send_to_server = handle_hp; - m_client_event_queue.push_back(event); + m_client_event_queue.push(event); } void ClientEnvironment::updateLocalPlayerBreath(u16 breath) @@ -2645,13 +2902,13 @@ void ClientEnvironment::updateLocalPlayerBreath(u16 breath) ClientEnvEvent event; event.type = CEE_PLAYER_BREATH; event.player_breath.amount = breath; - m_client_event_queue.push_back(event); + m_client_event_queue.push(event); } /* Client likes to call these */ - + void ClientEnvironment::getActiveObjects(v3f origin, f32 max_d, std::vector &dest) { @@ -2679,11 +2936,9 @@ ClientEnvEvent ClientEnvironment::getClientEvent() event.type = CEE_NONE; else { event = m_client_event_queue.front(); - m_client_event_queue.pop_front(); + m_client_event_queue.pop(); } return event; } #endif // #ifndef SERVER - -