]> git.lizzy.rs Git - minetest.git/blobdiff - src/serverenvironment.cpp
CollisionMoveSimple: Collide with 'ignore' nodes
[minetest.git] / src / serverenvironment.cpp
index a5f30755426d435bbde54e691cea815626ad911c..ae0f397eeedfc2cc12f250f2fcc11e360cb911b4 100644 (file)
@@ -37,11 +37,11 @@ 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 <algorithm>
 
@@ -80,7 +80,7 @@ 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);
 
@@ -292,8 +292,27 @@ void fillRadiusBlock(v3s16 p0, s16 r, std::set<v3s16> &list)
                        }
 }
 
-void ActiveBlockList::update(std::vector<v3s16> &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<v3s16> &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<PlayerSAO*> &active_players,
+       s16 active_block_range,
+       s16 active_object_range,
        std::set<v3s16> &blocks_removed,
        std::set<v3s16> &blocks_added)
 {
@@ -301,8 +320,25 @@ void ActiveBlockList::update(std::vector<v3s16> &active_positions,
                Create the new list
        */
        std::set<v3s16> newlist = m_forceloaded_list;
-       for (const v3s16 &active_position : active_positions) {
-               fillRadiusBlock(active_position, 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);
+               }
        }
 
        /*
@@ -405,10 +441,10 @@ ServerMap & ServerEnvironment::getServerMap()
        return *m_map;
 }
 
-RemotePlayer *ServerEnvironment::getPlayer(const u16 peer_id)
+RemotePlayer *ServerEnvironment::getPlayer(const session_t peer_id)
 {
        for (RemotePlayer *player : m_players) {
-               if (player->peer_id == peer_id)
+               if (player->getPeerId() == peer_id)
                        return player;
        }
        return NULL;
@@ -431,8 +467,8 @@ void ServerEnvironment::addPlayer(RemotePlayer *player)
                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.
@@ -456,30 +492,21 @@ 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;
 }
 
@@ -487,7 +514,7 @@ void ServerEnvironment::kickAllPlayers(AccessDeniedCode reason,
        const std::string &str_reason, bool reconnect)
 {
        for (RemotePlayer *player : m_players) {
-               m_server->DenyAccessVerCompliant(player->peer_id,
+               m_server->DenyAccessVerCompliant(player->getPeerId(),
                        player->protocol_version, reason, str_reason, reconnect);
        }
 }
@@ -523,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
@@ -540,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());
@@ -664,7 +690,7 @@ class ABMHandler
        {
                if(dtime_s < 0.001)
                        return;
-               INodeDefManager *ndef = env->getGameDef()->ndef();
+               const NodeDefManager *ndef = env->getGameDef()->ndef();
                for (ABMWithState &abmws : abms) {
                        ActiveBlockModifier *abm = abmws.abm;
                        float trigger_interval = abm->getTriggerInterval();
@@ -873,10 +899,6 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
                                        elapsed_timer.position));
                }
        }
-
-       /* Handle ActiveBlockModifiers */
-       ABMHandler abmhandler(m_abms, dtime_s, this, false);
-       abmhandler.apply(block);
 }
 
 void ServerEnvironment::addActiveBlockModifier(ActiveBlockModifier *abm)
@@ -891,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
@@ -906,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;
@@ -918,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
@@ -1024,7 +1052,7 @@ 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;
 
@@ -1070,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;
@@ -1090,7 +1118,7 @@ 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;
 }
@@ -1124,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
@@ -1140,27 +1168,30 @@ void ServerEnvironment::step(float dtime)
                /*
                        Get player block positions
                */
-               std::vector<v3s16> players_blockpos;
+               std::vector<PlayerSAO*> 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<v3s16> blocks_removed;
                std::set<v3s16> 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);
 
                /*
@@ -1187,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;
                        }
 
@@ -1248,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;