X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;ds=inline;f=src%2Fserverenvironment.cpp;h=ae0f397eeedfc2cc12f250f2fcc11e360cb911b4;hb=359a940dde0d0d85b288c8af6b10bccbd021f9c1;hp=2fb12692b75406a1cd470f4e80a5c2a3d79fdcf8;hpb=bb1c71158613c1f17c57e53ad489b076a11e3828;p=dragonfireclient.git diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index 2fb12692b..ae0f397ee 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_sao.h" #include "settings.h" #include "log.h" +#include "mapblock.h" #include "nodedef.h" #include "nodemetadata.h" #include "gamedef.h" @@ -36,12 +37,13 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "threading/mutex_auto_lock.h" #include "filesys.h" #include "gameparams.h" -#include "database-dummy.h" -#include "database-files.h" -#include "database-sqlite3.h" +#include "database/database-dummy.h" +#include "database/database-files.h" +#include "database/database-sqlite3.h" #if USE_POSTGRESQL -#include "database-postgresql.h" +#include "database/database-postgresql.h" #endif +#include #define LBM_NAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyz0123456789_:" @@ -78,12 +80,12 @@ void LBMContentMapping::addLBM(LoadingBlockModifierDef *lbm_def, IGameDef *gamed { // Add the lbm_def to the LBMContentMapping. // Unknown names get added to the global NameIdMapping. - INodeDefManager *nodedef = gamedef->ndef(); + const NodeDefManager *nodedef = gamedef->ndef(); lbm_list.push_back(lbm_def); for (const std::string &nodeTrigger: lbm_def->trigger_contents) { - std::set c_ids; + std::vector c_ids; bool found = nodedef->getIds(nodeTrigger, c_ids); if (!found) { content_t c_id = gamedef->allocateUnknownNodeId(nodeTrigger); @@ -93,7 +95,7 @@ void LBMContentMapping::addLBM(LoadingBlockModifierDef *lbm_def, IGameDef *gamed << "\" while loading LBM \"" << lbm_def->name << "\"." << std::endl; continue; } - c_ids.insert(c_id); + c_ids.push_back(c_id); } for (content_t c_id : c_ids) { @@ -128,7 +130,7 @@ LBMManager::~LBMManager() void LBMManager::addLBMDef(LoadingBlockModifierDef *lbm_def) { // Precondition, in query mode the map isn't used anymore - FATAL_ERROR_IF(m_query_mode == true, + FATAL_ERROR_IF(m_query_mode, "attempted to modify LBMManager in query mode"); if (!string_allowed(lbm_def->name, LBM_NAME_ALLOWED_CHARS)) { @@ -159,7 +161,7 @@ void LBMManager::loadIntroductionTimes(const std::string ×, size_t idx = 0; size_t idx_new; - while ((idx_new = times.find(";", idx)) != std::string::npos) { + 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) @@ -223,7 +225,7 @@ void LBMManager::loadIntroductionTimes(const std::string ×, std::string LBMManager::createIntroductionTimesString() { // Precondition, we must be in query mode - FATAL_ERROR_IF(m_query_mode == false, + FATAL_ERROR_IF(!m_query_mode, "attempted to query on non fully set up LBMManager"); std::ostringstream oss; @@ -245,7 +247,7 @@ std::string LBMManager::createIntroductionTimesString() 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, + FATAL_ERROR_IF(!m_query_mode, "attempted to query on non fully set up LBMManager"); v3s16 pos_of_block = block->getPosRelative(); v3s16 pos; @@ -290,8 +292,27 @@ void fillRadiusBlock(v3s16 p0, s16 r, std::set &list) } } -void ActiveBlockList::update(std::vector &active_positions, - s16 radius, +void fillViewConeBlock(v3s16 p0, + const s16 r, + const v3f camera_pos, + const v3f camera_dir, + const float camera_fov, + std::set &list) +{ + v3s16 p; + const s16 r_nodes = r * BS * MAP_BLOCKSIZE; + for (p.X = p0.X - r; p.X <= p0.X+r; p.X++) + for (p.Y = p0.Y - r; p.Y <= p0.Y+r; p.Y++) + for (p.Z = p0.Z - r; p.Z <= p0.Z+r; p.Z++) { + if (isBlockInSight(p, camera_pos, camera_dir, camera_fov, r_nodes)) { + list.insert(p); + } + } +} + +void ActiveBlockList::update(std::vector &active_players, + s16 active_block_range, + s16 active_object_range, std::set &blocks_removed, std::set &blocks_added) { @@ -299,22 +320,34 @@ void ActiveBlockList::update(std::vector &active_positions, Create the new list */ std::set newlist = m_forceloaded_list; - for(std::vector::iterator i = active_positions.begin(); - i != active_positions.end(); ++i) - { - fillRadiusBlock(*i, radius, newlist); + m_abm_list = m_forceloaded_list; + for (const PlayerSAO *playersao : active_players) { + v3s16 pos = getNodeBlockPos(floatToInt(playersao->getBasePosition(), BS)); + fillRadiusBlock(pos, active_block_range, m_abm_list); + fillRadiusBlock(pos, active_block_range, newlist); + + s16 player_ao_range = std::min(active_object_range, playersao->getWantedRange()); + // only do this if this would add blocks + if (player_ao_range > active_block_range) { + v3f camera_dir = v3f(0,0,1); + camera_dir.rotateYZBy(playersao->getPitch()); + camera_dir.rotateXZBy(playersao->getYaw()); + fillViewConeBlock(pos, + player_ao_range, + playersao->getEyePosition(), + camera_dir, + playersao->getFov(), + newlist); + } } /* Find out which blocks on the old list are not on the new list */ // Go through old list - for(std::set::iterator i = m_list.begin(); - i != m_list.end(); ++i) - { - v3s16 p = *i; + for (v3s16 p : m_list) { // If not on new list, it's been removed - if(newlist.find(p) == newlist.end()) + if (newlist.find(p) == newlist.end()) blocks_removed.insert(p); } @@ -322,10 +355,7 @@ void ActiveBlockList::update(std::vector &active_positions, Find out which blocks on the new list are not on the old list */ // Go through new list - for(std::set::iterator i = newlist.begin(); - i != newlist.end(); ++i) - { - v3s16 p = *i; + for (v3s16 p : newlist) { // If not on old list, it's been added if(m_list.find(p) == m_list.end()) blocks_added.insert(p); @@ -335,10 +365,7 @@ void ActiveBlockList::update(std::vector &active_positions, Update m_list */ m_list.clear(); - for(std::set::iterator i = newlist.begin(); - i != newlist.end(); ++i) - { - v3s16 p = *i; + for (v3s16 p : newlist) { m_list.insert(p); } } @@ -374,7 +401,7 @@ ServerEnvironment::ServerEnvironment(ServerMap *map, } } - std::string name = ""; + std::string name; conf.getNoEx("player_backend", name); m_player_database = openPlayerDatabase(name, path_world, conf); } @@ -392,15 +419,13 @@ ServerEnvironment::~ServerEnvironment() m_map->drop(); // Delete ActiveBlockModifiers - for (std::vector::iterator - i = m_abms.begin(); i != m_abms.end(); ++i){ - delete i->abm; + for (ABMWithState &m_abm : m_abms) { + delete m_abm.abm; } // Deallocate players - for (std::vector::iterator i = m_players.begin(); - i != m_players.end(); ++i) { - delete (*i); + for (RemotePlayer *m_player : m_players) { + delete m_player; } delete m_player_database; @@ -416,12 +441,10 @@ ServerMap & ServerEnvironment::getServerMap() return *m_map; } -RemotePlayer *ServerEnvironment::getPlayer(const u16 peer_id) +RemotePlayer *ServerEnvironment::getPlayer(const session_t peer_id) { - for (std::vector::iterator i = m_players.begin(); - i != m_players.end(); ++i) { - RemotePlayer *player = *i; - if (player->peer_id == peer_id) + for (RemotePlayer *player : m_players) { + if (player->getPeerId() == peer_id) return player; } return NULL; @@ -429,9 +452,7 @@ RemotePlayer *ServerEnvironment::getPlayer(const u16 peer_id) RemotePlayer *ServerEnvironment::getPlayer(const char* name) { - for (std::vector::iterator i = m_players.begin(); - i != m_players.end(); ++i) { - RemotePlayer *player = *i; + for (RemotePlayer *player : m_players) { if (strcmp(player->getName(), name) == 0) return player; } @@ -440,15 +461,14 @@ RemotePlayer *ServerEnvironment::getPlayer(const char* name) void ServerEnvironment::addPlayer(RemotePlayer *player) { - DSTACK(FUNCTION_NAME); /* Check that peer_ids are unique. Also check that names are unique. Exception: there can be multiple players with peer_id=0 */ // If peer id is non-zero, it has to be unique. - if (player->peer_id != 0) - FATAL_ERROR_IF(getPlayer(player->peer_id) != NULL, "Peer id not unique"); + if (player->getPeerId() != PEER_ID_INEXISTENT) + FATAL_ERROR_IF(getPlayer(player->getPeerId()) != NULL, "Peer id not unique"); // Name has to be unique. FATAL_ERROR_IF(getPlayer(player->getName()) != NULL, "Player name not unique"); // Add. @@ -472,40 +492,29 @@ bool ServerEnvironment::removePlayerFromDatabase(const std::string &name) return m_player_database->removePlayer(name); } -bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, float stepsize, v3s16 *p) +bool ServerEnvironment::line_of_sight(v3f pos1, v3f pos2, v3s16 *p) { - float distance = pos1.getDistanceFrom(pos2); - - //calculate normalized direction vector - v3f normalized_vector = v3f((pos2.X - pos1.X)/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) { - v3s16 pos = floatToInt(v3f(normalized_vector.X * i, - normalized_vector.Y * i, - normalized_vector.Z * i) +pos1,BS); - - MapNode n = getMap().getNodeNoEx(pos); - - if(n.param0 != CONTENT_AIR) { - if (p) { - *p = pos; - } + // Iterate trough nodes on the line + voxalgo::VoxelLineIterator iterator(pos1 / BS, (pos2 - pos1) / BS); + do { + MapNode n = getMap().getNodeNoEx(iterator.m_current_node_pos); + + // Return non-air + if (n.param0 != CONTENT_AIR) { + if (p) + *p = iterator.m_current_node_pos; return false; } - } + iterator.next(); + } while (iterator.m_current_index <= iterator.m_last_index); return true; } void ServerEnvironment::kickAllPlayers(AccessDeniedCode reason, const std::string &str_reason, bool reconnect) { - for (std::vector::iterator it = m_players.begin(); - it != m_players.end(); ++it) { - RemotePlayer *player = dynamic_cast(*it); - m_server->DenyAccessVerCompliant(player->peer_id, + for (RemotePlayer *player : m_players) { + m_server->DenyAccessVerCompliant(player->getPeerId(), player->protocol_version, reason, str_reason, reconnect); } } @@ -515,15 +524,13 @@ void ServerEnvironment::saveLoadedPlayers() std::string players_path = m_path_world + DIR_DELIM + "players"; fs::CreateDir(players_path); - for (std::vector::iterator it = m_players.begin(); - it != m_players.end(); - ++it) { - if ((*it)->checkModified() || - ((*it)->getPlayerSAO() && (*it)->getPlayerSAO()->extendedAttributesModified())) { + for (RemotePlayer *player : m_players) { + if (player->checkModified() || (player->getPlayerSAO() && + player->getPlayerSAO()->extendedAttributesModified())) { try { - m_player_database->savePlayer(*it); + m_player_database->savePlayer(player); } catch (DatabaseException &e) { - errorstream << "Failed to save player " << (*it)->getName() << " exception: " + errorstream << "Failed to save player " << player->getName() << " exception: " << e.what() << std::endl; throw; } @@ -543,7 +550,7 @@ void ServerEnvironment::savePlayer(RemotePlayer *player) } PlayerSAO *ServerEnvironment::loadPlayer(RemotePlayer *player, bool *new_player, - u16 peer_id, bool is_singleplayer) + session_t peer_id, bool is_singleplayer) { PlayerSAO *playersao = new PlayerSAO(this, player, peer_id, is_singleplayer); // Create player if it doesn't exist @@ -560,8 +567,7 @@ PlayerSAO *ServerEnvironment::loadPlayer(RemotePlayer *player, bool *new_player, // If the player exists, ensure that they respawn inside legal bounds // This fixes an assert crash when the player can't be added // to the environment - ServerMap &map = getServerMap(); - if (map.getMapgenParams()->saoPosOverLimit(playersao->getBasePosition())) { + if (objectpos_over_limit(playersao->getBasePosition())) { actionstream << "Respawn position for player \"" << player->getName() << "\" outside limits, resetting" << std::endl; playersao->setBasePosition(m_server->findSpawnPos()); @@ -640,7 +646,7 @@ void ServerEnvironment::loadMeta() // If missing, do as if clearObjects was never called args.getU64("last_clear_objects_time") : 0; - std::string lbm_introduction_times = ""; + std::string lbm_introduction_times; try { u64 ver = args.getU64("lbm_introduction_times_version"); if (ver == 1) { @@ -667,7 +673,8 @@ struct ActiveABM { ActiveBlockModifier *abm; int chance; - std::set required_neighbors; + std::vector required_neighbors; + bool check_required_neighbors; // false if required_neighbors is known to be empty }; class ABMHandler @@ -683,19 +690,18 @@ class ABMHandler { if(dtime_s < 0.001) return; - INodeDefManager *ndef = env->getGameDef()->ndef(); - for(std::vector::iterator - i = abms.begin(); i != abms.end(); ++i) { - ActiveBlockModifier *abm = i->abm; + const NodeDefManager *ndef = env->getGameDef()->ndef(); + for (ABMWithState &abmws : abms) { + ActiveBlockModifier *abm = abmws.abm; float trigger_interval = abm->getTriggerInterval(); if(trigger_interval < 0.001) trigger_interval = 0.001; float actual_interval = dtime_s; if(use_timers){ - i->timer += dtime_s; - if(i->timer < trigger_interval) + abmws.timer += dtime_s; + if(abmws.timer < trigger_interval) continue; - i->timer -= trigger_interval; + abmws.timer -= trigger_interval; actual_interval = trigger_interval; } float chance = abm->getTriggerChance(); @@ -715,22 +721,19 @@ class ABMHandler } // Trigger neighbors - const std::set &required_neighbors_s = + const std::vector &required_neighbors_s = abm->getRequiredNeighbors(); - for (std::set::iterator rn = required_neighbors_s.begin(); - rn != required_neighbors_s.end(); ++rn) { - ndef->getIds(*rn, aabm.required_neighbors); + for (const std::string &required_neighbor_s : required_neighbors_s) { + ndef->getIds(required_neighbor_s, aabm.required_neighbors); } + aabm.check_required_neighbors = !required_neighbors_s.empty(); // Trigger contents - const std::set &contents_s = abm->getTriggerContents(); - for (std::set::iterator cs = contents_s.begin(); - cs != contents_s.end(); ++cs) { - std::set ids; - ndef->getIds(*cs, ids); - for (std::set::const_iterator k = ids.begin(); - k != ids.end(); ++k) { - content_t c = *k; + const std::vector &contents_s = abm->getTriggerContents(); + for (const std::string &content_s : contents_s) { + std::vector ids; + ndef->getIds(content_s, ids); + for (content_t c : ids) { if (c >= m_aabms.size()) m_aabms.resize(c + 256, NULL); if (!m_aabms[c]) @@ -743,8 +746,8 @@ class ABMHandler ~ABMHandler() { - for (size_t i = 0; i < m_aabms.size(); i++) - delete m_aabms[i]; + for (auto &aabms : m_aabms) + delete aabms; } // Find out how many objects the given block and its neighbours contain. @@ -798,14 +801,12 @@ class ABMHandler continue; v3s16 p = p0 + block->getPosRelative(); - for(std::vector::iterator - i = m_aabms[c]->begin(); i != m_aabms[c]->end(); ++i) { - if(myrand() % i->chance != 0) + for (ActiveABM &aabm : *m_aabms[c]) { + if (myrand() % aabm.chance != 0) continue; // Check neighbors - if(!i->required_neighbors.empty()) - { + if (aabm.check_required_neighbors) { v3s16 p1; for(p1.X = p0.X-1; p1.X <= p0.X+1; p1.X++) for(p1.Y = p0.Y-1; p1.Y <= p0.Y+1; p1.Y++) @@ -824,11 +825,8 @@ class ABMHandler MapNode n = map->getNodeNoEx(p1 + block->getPosRelative()); c = n.getContent(); } - std::set::const_iterator k; - k = i->required_neighbors.find(c); - if(k != i->required_neighbors.end()){ + if (CONTAINS(aabm.required_neighbors, c)) goto neighbor_found; - } } // No required neighbor found continue; @@ -836,8 +834,8 @@ class ABMHandler neighbor_found: // Call all the trigger variations - i->abm->trigger(m_env, p, n); - i->abm->trigger(m_env, p, n, + aabm.abm->trigger(m_env, p, n); + aabm.abm->trigger(m_env, p, n, active_object_count, active_object_count_wider); // Count surrounding objects again if the abms added any @@ -893,24 +891,19 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime) block->m_node_timers.step((float)dtime_s); if (!elapsed_timers.empty()) { MapNode n; - for (std::vector::iterator - i = elapsed_timers.begin(); - 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)); + for (const NodeTimer &elapsed_timer : elapsed_timers) { + n = block->getNodeNoEx(elapsed_timer.position); + v3s16 p = elapsed_timer.position + block->getPosRelative(); + if (m_script->node_on_timer(p, n, elapsed_timer.elapsed)) + block->setNodeTimer(NodeTimer(elapsed_timer.timeout, 0, + elapsed_timer.position)); } } - - /* Handle ActiveBlockModifiers */ - ABMHandler abmhandler(m_abms, dtime_s, this, false); - abmhandler.apply(block); } void ServerEnvironment::addActiveBlockModifier(ActiveBlockModifier *abm) { - m_abms.push_back(ABMWithState(abm)); + m_abms.emplace_back(abm); } void ServerEnvironment::addLoadingBlockModifierDef(LoadingBlockModifierDef *lbm) @@ -920,11 +913,13 @@ void ServerEnvironment::addLoadingBlockModifierDef(LoadingBlockModifierDef *lbm) bool ServerEnvironment::setNode(v3s16 p, const MapNode &n) { - INodeDefManager *ndef = m_server->ndef(); + const NodeDefManager *ndef = m_server->ndef(); MapNode n_old = m_map->getNodeNoEx(p); + const ContentFeatures &cf_old = ndef->get(n_old); + // Call destructor - if (ndef->get(n_old).has_on_destruct) + if (cf_old.has_on_destruct) m_script->node_on_destruct(p, n_old); // Replace node @@ -935,11 +930,15 @@ bool ServerEnvironment::setNode(v3s16 p, const MapNode &n) m_map->updateVManip(p); // Call post-destructor - if (ndef->get(n_old).has_after_destruct) + if (cf_old.has_after_destruct) m_script->node_after_destruct(p, n_old); + // Retrieve node content features + // if new node is same as old, reuse old definition to prevent a lookup + const ContentFeatures &cf_new = n_old == n ? cf_old : ndef->get(n); + // Call constructor - if (ndef->get(n).has_on_construct) + if (cf_new.has_on_construct) m_script->node_on_construct(p, n); return true; @@ -947,7 +946,7 @@ bool ServerEnvironment::setNode(v3s16 p, const MapNode &n) bool ServerEnvironment::removeNode(v3s16 p) { - INodeDefManager *ndef = m_server->ndef(); + const NodeDefManager *ndef = m_server->ndef(); MapNode n_old = m_map->getNodeNoEx(p); // Call destructor @@ -984,10 +983,9 @@ bool ServerEnvironment::swapNode(v3s16 p, const MapNode &n) void ServerEnvironment::getObjectsInsideRadius(std::vector &objects, v3f pos, float radius) { - for (ServerActiveObjectMap::iterator i = m_active_objects.begin(); - i != m_active_objects.end(); ++i) { - ServerActiveObject* obj = i->second; - u16 id = i->first; + for (auto &activeObject : m_active_objects) { + ServerActiveObject* obj = activeObject.second; + u16 id = activeObject.first; v3f objectpos = obj->getBasePosition(); if (objectpos.getDistanceFrom(pos) > radius) continue; @@ -1000,26 +998,18 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode) infostream << "ServerEnvironment::clearObjects(): " << "Removing all active objects" << std::endl; std::vector objects_to_remove; - for (ServerActiveObjectMap::iterator i = m_active_objects.begin(); - i != m_active_objects.end(); ++i) { - ServerActiveObject* obj = i->second; + for (auto &it : m_active_objects) { + u16 id = it.first; + ServerActiveObject* obj = it.second; if (obj->getType() == ACTIVEOBJECT_TYPE_PLAYER) continue; - u16 id = i->first; + // Delete static object if block is loaded - if (obj->m_static_exists) { - MapBlock *block = m_map->getBlockNoCreateNoEx(obj->m_static_block); - if (block) { - block->m_static_objects.remove(id); - block->raiseModified(MOD_STATE_WRITE_NEEDED, - MOD_REASON_CLEAR_ALL_OBJECTS); - obj->m_static_exists = false; - } - } + deleteStaticFromBlock(obj, id, MOD_REASON_CLEAR_ALL_OBJECTS, true); + // If known by some client, don't delete immediately if (obj->m_known_by_count > 0) { - obj->m_pending_deactivation = true; - obj->m_removed = true; + obj->m_pending_removal = true; continue; } @@ -1036,9 +1026,8 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode) } // Remove references from m_active_objects - for (std::vector::iterator i = objects_to_remove.begin(); - i != objects_to_remove.end(); ++i) { - m_active_objects.erase(*i); + for (u16 i : objects_to_remove) { + m_active_objects.erase(i); } // Get list of loaded blocks @@ -1063,14 +1052,12 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode) loadable_blocks = loaded_blocks; } - infostream << "ServerEnvironment::clearObjects(): " + actionstream << "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::vector::iterator i = loaded_blocks.begin(); - i != loaded_blocks.end(); ++i) { - v3s16 p = *i; + for (v3s16 p : loaded_blocks) { MapBlock *block = m_map->getBlockNoCreateNoEx(p); assert(block != NULL); block->refGrab(); @@ -1086,7 +1073,7 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode) u32 num_blocks_checked = 0; u32 num_blocks_cleared = 0; u32 num_objs_cleared = 0; - for (std::vector::iterator i = loadable_blocks.begin(); + for (auto i = loadable_blocks.begin(); i != loadable_blocks.end(); ++i) { v3s16 p = *i; MapBlock *block = m_map->emergeBlock(p, false); @@ -1111,7 +1098,7 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode) num_blocks_checked % report_interval == 0) { float percent = 100.0 * (float)num_blocks_checked / loadable_blocks.size(); - infostream << "ServerEnvironment::clearObjects(): " + actionstream << "ServerEnvironment::clearObjects(): " << "Cleared " << num_objs_cleared << " objects" << " in " << num_blocks_cleared << " blocks (" << percent << "%)" << std::endl; @@ -1123,9 +1110,7 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode) m_map->unloadUnreferencedBlocks(); // Drop references that were added above - for (std::vector::iterator i = loaded_blocks.begin(); - i != loaded_blocks.end(); ++i) { - v3s16 p = *i; + for (v3s16 p : loaded_blocks) { MapBlock *block = m_map->getBlockNoCreateNoEx(p); assert(block); block->refDrop(); @@ -1133,17 +1118,13 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode) m_last_clear_objects_time = m_game_time; - infostream << "ServerEnvironment::clearObjects(): " + actionstream << "ServerEnvironment::clearObjects(): " << "Finished: Cleared " << num_objs_cleared << " objects" << " in " << num_blocks_cleared << " blocks" << std::endl; } void ServerEnvironment::step(float dtime) { - DSTACK(FUNCTION_NAME); - - //TimeTaker timer("ServerEnv step"); - /* Step time of day */ stepTimeOfDay(dtime); @@ -1171,7 +1152,7 @@ void ServerEnvironment::step(float dtime) ScopeProfiler sp(g_profiler, "SEnv: handle players avg", SPT_AVG); for (RemotePlayer *player : m_players) { // Ignore disconnected players - if (player->peer_id == 0) + if (player->getPeerId() == PEER_ID_INEXISTENT) continue; // Move @@ -1187,27 +1168,30 @@ void ServerEnvironment::step(float dtime) /* Get player block positions */ - std::vector players_blockpos; + std::vector players; for (RemotePlayer *player: m_players) { // Ignore disconnected players - if (player->peer_id == 0) + if (player->getPeerId() == PEER_ID_INEXISTENT) continue; PlayerSAO *playersao = player->getPlayerSAO(); assert(playersao); - players_blockpos.push_back( - getNodeBlockPos(floatToInt(playersao->getBasePosition(), BS))); + players.push_back(playersao); } /* Update list of active blocks, collecting changes */ + // use active_object_send_range_blocks since that is max distance + // for active objects sent the client anyway + static thread_local const s16 active_object_range = + g_settings->getS16("active_object_send_range_blocks"); static thread_local 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, + m_active_blocks.update(players, active_block_range, active_object_range, blocks_removed, blocks_added); /* @@ -1234,6 +1218,7 @@ void ServerEnvironment::step(float dtime) MapBlock *block = m_map->getBlockOrEmerge(p); if (!block) { m_active_blocks.m_list.erase(p); + m_active_blocks.m_abm_list.erase(p); continue; } @@ -1295,7 +1280,7 @@ void ServerEnvironment::step(float dtime) // Initialize handling of ActiveBlockModifiers ABMHandler abmhandler(m_abms, m_cache_abm_interval, this, true); - for (const v3s16 &p : m_active_blocks.m_list) { + for (const v3s16 &p : m_active_blocks.m_abm_list) { MapBlock *block = m_map->getBlockNoCreateNoEx(p); if (!block) continue; @@ -1340,19 +1325,16 @@ void ServerEnvironment::step(float dtime) send_recommended = true; } - for (ServerActiveObjectMap::iterator i = m_active_objects.begin(); - i != m_active_objects.end(); ++i) { - ServerActiveObject* obj = i->second; - // Don't step if is to be removed or stored statically - if(obj->m_removed || obj->m_pending_deactivation) + for (auto &ao_it : m_active_objects) { + ServerActiveObject* obj = ao_it.second; + if (obj->isGone()) continue; + // Step object obj->step(dtime, send_recommended); // Read messages from object - while(!obj->m_messages_out.empty()) - { - m_active_object_messages.push( - obj->m_messages_out.front()); + while (!obj->m_messages_out.empty()) { + m_active_object_messages.push(obj->m_messages_out.front()); obj->m_messages_out.pop(); } } @@ -1363,9 +1345,6 @@ void ServerEnvironment::step(float dtime) */ if (m_object_management_interval.step(dtime, 0.5)) { ScopeProfiler sp(g_profiler, "SEnv: remove removed objs avg /.5s", SPT_AVG); - /* - Remove objects that satisfy (m_removed && m_known_by_count==0) - */ removeRemovedObjects(); } @@ -1485,22 +1464,20 @@ void ServerEnvironment::getAddedActiveObjects(PlayerSAO *playersao, s16 radius, player_radius_f = 0; /* Go through the object list, - - discard m_removed objects, + - discard removed/deactivated objects, - discard objects that are too far away, - discard objects that are found in current_objects. - add remaining objects to added_objects */ - for (ServerActiveObjectMap::iterator i = m_active_objects.begin(); - i != m_active_objects.end(); ++i) { - u16 id = i->first; + for (auto &ao_it : m_active_objects) { + u16 id = ao_it.first; // Get object - ServerActiveObject *object = i->second; + ServerActiveObject *object = ao_it.second; if (object == NULL) continue; - // Discard if removed or deactivating - if(object->m_removed || object->m_pending_deactivation) + if (object->isGone()) continue; f32 distance_f = object->getBasePosition(). @@ -1539,16 +1516,12 @@ void ServerEnvironment::getRemovedActiveObjects(PlayerSAO *playersao, s16 radius /* Go through current_objects; object is removed if: - object is not found in m_active_objects (this is actually an - error condition; objects should be set m_removed=true and removed - only after all clients have been informed about removal), or - - object has m_removed=true, or + error condition; objects should be removed only after all clients + have been informed about removal), or + - object is to be removed or deactivated, or - object is too far away */ - for(std::set::iterator - i = current_objects.begin(); - i != current_objects.end(); ++i) - { - u16 id = *i; + for (u16 id : current_objects) { ServerActiveObject *object = getActiveObject(id); if (object == NULL) { @@ -1558,7 +1531,7 @@ void ServerEnvironment::getRemovedActiveObjects(PlayerSAO *playersao, s16 radius continue; } - if (object->m_removed || object->m_pending_deactivation) { + if (object->isGone()) { removed_objects.push(id); continue; } @@ -1582,11 +1555,9 @@ void ServerEnvironment::setStaticForActiveObjectsInBlock( 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) { + for (auto &so_it : block->m_static_objects.m_active) { // Get the ServerActiveObject counterpart to this StaticObject - ServerActiveObjectMap::const_iterator ao_it = m_active_objects.find(so_it->first); + ServerActiveObjectMap::const_iterator 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(): " @@ -1620,8 +1591,8 @@ void ServerEnvironment::getSelectedActiveObjects( shootline_on_map.getLength() + 10.0f); const v3f line_vector = shootline_on_map.getVector(); - for (u32 i = 0; i < objectIds.size(); i++) { - ServerActiveObject* obj = getActiveObject(objectIds[i]); + for (u16 objectId : objectIds) { + ServerActiveObject* obj = getActiveObject(objectId); aabb3f selection_box; if (!obj->getSelectionBox(&selection_box)) @@ -1636,9 +1607,9 @@ void ServerEnvironment::getSelectedActiveObjects( v3s16 current_normal; if (boxLineCollision(offsetted_box, shootline_on_map.start, line_vector, ¤t_intersection, ¤t_normal)) { - objects.push_back(PointedThing( - (s16) objectIds[i], current_intersection, current_normal, - (current_intersection - shootline_on_map.start).getLengthSQ())); + objects.emplace_back( + (s16) objectId, current_intersection, current_normal, + (current_intersection - shootline_on_map.start).getLengthSQ()); } } } @@ -1706,7 +1677,7 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, { // Add static object to active static list of the block v3f objectpos = object->getBasePosition(); - std::string staticdata = ""; + std::string staticdata; object->getStaticData(&staticdata); StaticObject s_obj(object->getType(), objectpos, staticdata); // Add to the block where the object is located in @@ -1732,71 +1703,62 @@ u16 ServerEnvironment::addActiveObjectRaw(ServerActiveObject *object, } /* - Remove objects that satisfy (m_removed && m_known_by_count==0) + Remove objects that satisfy (isGone() && m_known_by_count==0) */ void ServerEnvironment::removeRemovedObjects() { std::vector objects_to_remove; - for(ServerActiveObjectMap::iterator i = m_active_objects.begin(); - i != m_active_objects.end(); ++i) { - u16 id = i->first; - ServerActiveObject* obj = i->second; + for (auto &ao_it : m_active_objects) { + u16 id = ao_it.first; + ServerActiveObject* obj = ao_it.second; + // This shouldn't happen but check it - if(obj == NULL) - { - infostream<<"NULL object found in ServerEnvironment" - <<" while finding removed objects. id="<m_static_block) << std::endl; } } else { - infostream<<"Failed to emerge block from which an object to " - <<"be deactivated was loaded from. id="<getStaticData(&staticdata_new); StaticObject s_obj(obj->getType(), objectpos, staticdata_new); - block->m_static_objects.insert(id, s_obj); - obj->m_static_block = blockpos_o; - block->raiseModified(MOD_STATE_WRITE_NEEDED, - MOD_REASON_STATIC_DATA_ADDED); + // Save to block where object is located + saveStaticToBlock(blockpos_o, id, obj, s_obj, MOD_REASON_STATIC_DATA_ADDED); - // Delete from block where object was located - block = m_map->emergeBlock(old_static_block, false); - if(!block){ - errorstream<<"ServerEnvironment::deactivateFarObjects(): " - <<"Could not delete object id="<m_static_objects.remove(id); - block->raiseModified(MOD_STATE_WRITE_NEEDED, - MOD_REASON_STATIC_DATA_REMOVED); continue; } - // If block is active, don't remove + // If block is still active, don't remove if(!force_delete && m_active_blocks.contains(blockpos_o)) continue; - verbosestream<<"ServerEnvironment::deactivateFarObjects(): " - <<"deactivating object id="<m_known_by_count > 0 && !force_delete); @@ -2033,17 +1952,17 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete) /* Update the static data */ - if(obj->isStaticAllowed()) { // Create new static object - std::string staticdata_new = ""; + std::string staticdata_new; obj->getStaticData(&staticdata_new); StaticObject s_obj(obj->getType(), objectpos, staticdata_new); bool stays_in_same_block = false; bool data_changed = true; + // Check if static data has changed considerably if (obj->m_static_exists) { if (obj->m_static_block == blockpos_o) stays_in_same_block = true; @@ -2062,108 +1981,47 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete) (static_old.pos - objectpos).getLength() < save_movem) data_changed = false; } else { - errorstream<<"ServerEnvironment::deactivateFarObjects(): " - <<"id="<m_static_block)<m_static_block) << std::endl; } } } + /* + While changes are always saved, blocks are only marked as modified + if the object has moved or different staticdata. (see above) + */ bool shall_be_written = (!stays_in_same_block || data_changed); + u32 reason = shall_be_written ? MOD_REASON_STATIC_DATA_CHANGED : MOD_REASON_UNKNOWN; // Delete old static object - if(obj->m_static_exists) - { - MapBlock *block = m_map->emergeBlock(obj->m_static_block, false); - if(block) - { - block->m_static_objects.remove(id); - obj->m_static_exists = false; - // Only mark block as modified if data changed considerably - if(shall_be_written) - block->raiseModified(MOD_STATE_WRITE_NEEDED, - MOD_REASON_STATIC_DATA_CHANGED); - } - } + deleteStaticFromBlock(obj, id, reason, false); // Add to the block where the object is located in v3s16 blockpos = getNodeBlockPos(floatToInt(objectpos, BS)); - // Get or generate the block - MapBlock *block = NULL; - try{ - block = m_map->emergeBlock(blockpos); - } catch(InvalidPositionException &e){ - // Handled via NULL pointer - // NOTE: emergeBlock's failure is usually determined by it - // actually returning NULL - } - - if(block) - { - if (block->m_static_objects.m_stored.size() >= g_settings->getU16("max_objects_per_block")) { - warningstream << "ServerEnv: Trying to store id = " << obj->getId() - << " statically but block " << PP(blockpos) - << " already contains " - << block->m_static_objects.m_stored.size() - << " objects." - << " Forcing delete." << std::endl; - force_delete = true; - } else { - // If static counterpart already exists in target block, - // remove it first. - // This shouldn't happen because the object is removed from - // the previous block before this according to - // obj->m_static_block, but happens rarely for some unknown - // 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()){ - 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, - MOD_REASON_STATIC_DATA_CHANGED); - - obj->m_static_exists = true; - obj->m_static_block = block->getPos(); - } - } - else{ - if(!force_delete){ - v3s16 p = floatToInt(objectpos, BS); - errorstream<<"ServerEnv: Could not find or generate " - <<"a block for storing id="<getId() - <<" statically (pos="<m_pending_deactivation = true; continue; } - - verbosestream<<"ServerEnvironment::deactivateFarObjects(): " - <<"object id="<removingFromEnvironment(); @@ -2178,10 +2036,72 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete) } // Remove references from m_active_objects - for(std::vector::iterator i = objects_to_remove.begin(); - i != objects_to_remove.end(); ++i) { - m_active_objects.erase(*i); + for (u16 i : objects_to_remove) { + m_active_objects.erase(i); + } +} + +void ServerEnvironment::deleteStaticFromBlock( + ServerActiveObject *obj, u16 id, u32 mod_reason, bool no_emerge) +{ + if (!obj->m_static_exists) + return; + + MapBlock *block; + if (no_emerge) + block = m_map->getBlockNoCreateNoEx(obj->m_static_block); + else + block = m_map->emergeBlock(obj->m_static_block, false); + if (!block) { + if (!no_emerge) + errorstream << "ServerEnv: Failed to emerge block " << PP(obj->m_static_block) + << " when deleting static data of object from it. id=" << id << std::endl; + return; + } + + block->m_static_objects.remove(id); + if (mod_reason != MOD_REASON_UNKNOWN) // Do not mark as modified if requested + block->raiseModified(MOD_STATE_WRITE_NEEDED, mod_reason); + + obj->m_static_exists = false; +} + +bool ServerEnvironment::saveStaticToBlock( + v3s16 blockpos, u16 store_id, + ServerActiveObject *obj, const StaticObject &s_obj, + u32 mod_reason) +{ + MapBlock *block = nullptr; + try { + block = m_map->emergeBlock(blockpos); + } catch (InvalidPositionException &e) { + // Handled via NULL pointer + // NOTE: emergeBlock's failure is usually determined by it + // actually returning NULL + } + + if (!block) { + errorstream << "ServerEnv: Failed to emerge block " << PP(obj->m_static_block) + << " when saving static data of object to it. id=" << store_id << std::endl; + return false; + } + if (block->m_static_objects.m_stored.size() >= g_settings->getU16("max_objects_per_block")) { + warningstream << "ServerEnv: Trying to store id = " << store_id + << " statically but block " << PP(blockpos) + << " already contains " + << block->m_static_objects.m_stored.size() + << " objects." << std::endl; + return false; } + + block->m_static_objects.insert(store_id, s_obj); + if (mod_reason != MOD_REASON_UNKNOWN) // Do not mark as modified if requested + block->raiseModified(MOD_STATE_WRITE_NEEDED, mod_reason); + + obj->m_static_exists = true; + obj->m_static_block = blockpos; + + return true; } PlayerDatabase *ServerEnvironment::openPlayerDatabase(const std::string &name, @@ -2190,19 +2110,20 @@ PlayerDatabase *ServerEnvironment::openPlayerDatabase(const std::string &name, if (name == "sqlite3") return new PlayerDatabaseSQLite3(savedir); - else if (name == "dummy") + + if (name == "dummy") return new Database_Dummy(); #if USE_POSTGRESQL - else if (name == "postgresql") { - std::string connect_string = ""; + if (name == "postgresql") { + std::string connect_string; conf.getNoEx("pgsql_player_connection", connect_string); return new PlayerDatabasePostgreSQL(connect_string); } #endif - else if (name == "files") + if (name == "files") return new PlayerDatabaseFiles(savedir + DIR_DELIM + "players"); - else - throw BaseException(std::string("Database backend ") + name + " not supported."); + + throw BaseException(std::string("Database backend ") + name + " not supported."); } bool ServerEnvironment::migratePlayersDatabase(const GameParams &game_params,