Cleanup in content_mapblock (#5746)
[oweals/minetest.git] / src / mapblock.h
index 9e36fe113c0139ef1d1d39452ae57f412ba0710c..8816dc817f7ef7f7f18b3ca44c4972dc50028a3f 100644 (file)
@@ -31,6 +31,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "nodetimer.h"
 #include "modifiedstate.h"
 #include "util/numeric.h" // getContainerPos
+#include "settings.h"
+#include "mapgen.h"
 
 class Map;
 class NodeMetadataList;
@@ -104,7 +106,7 @@ public:
 #define MOD_REASON_INITIAL                   (1 << 0)
 #define MOD_REASON_REALLOCATE                (1 << 1)
 #define MOD_REASON_SET_IS_UNDERGROUND        (1 << 2)
-#define MOD_REASON_SET_LIGHTING_EXPIRED      (1 << 3)
+#define MOD_REASON_SET_LIGHTING_COMPLETE     (1 << 3)
 #define MOD_REASON_SET_GENERATED             (1 << 4)
 #define MOD_REASON_SET_NODE                  (1 << 5)
 #define MOD_REASON_SET_NODE_NO_CHECK         (1 << 6)
@@ -145,14 +147,18 @@ public:
        void reallocate()
        {
                delete[] data;
-               u32 datasize = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
-               data = new MapNode[datasize];
-               for (u32 i = 0; i < datasize; i++)
+               data = new MapNode[nodecount];
+               for (u32 i = 0; i < nodecount; i++)
                        data[i] = MapNode(CONTENT_IGNORE);
 
                raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_REALLOCATE);
        }
 
+       MapNode* getData()
+       {
+               return data;
+       }
+
        ////
        //// Modification tracking methods
        ////
@@ -213,17 +219,42 @@ public:
                raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_IS_UNDERGROUND);
        }
 
-       inline void setLightingExpired(bool expired)
+       inline void setLightingComplete(u16 newflags)
        {
-               if (expired != m_lighting_expired){
-                       m_lighting_expired = expired;
-                       raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_LIGHTING_EXPIRED);
+               if (newflags != m_lighting_complete) {
+                       m_lighting_complete = newflags;
+                       raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_LIGHTING_COMPLETE);
                }
        }
 
-       inline bool getLightingExpired()
+       inline u16 getLightingComplete()
+       {
+               return m_lighting_complete;
+       }
+
+       inline void setLightingComplete(LightBank bank, u8 direction,
+               bool is_complete)
        {
-               return m_lighting_expired;
+               assert(direction >= 0 && direction <= 5);
+               if (bank == LIGHTBANK_NIGHT) {
+                       direction += 6;
+               }
+               u16 newflags = m_lighting_complete;
+               if (is_complete) {
+                       newflags |= 1 << direction;
+               } else {
+                       newflags &= ~(1 << direction);
+               }
+               setLightingComplete(newflags);
+       }
+
+       inline bool isLightingComplete(LightBank bank, u8 direction)
+       {
+               assert(direction >= 0 && direction <= 5);
+               if (bank == LIGHTBANK_NIGHT) {
+                       direction += 6;
+               }
+               return (m_lighting_complete & (1 << direction)) != 0;
        }
 
        inline bool isGenerated()
@@ -239,15 +270,6 @@ public:
                }
        }
 
-       inline bool isValid()
-       {
-               if (m_lighting_expired)
-                       return false;
-               if (data == NULL)
-                       return false;
-               return true;
-       }
-
        ////
        //// Position stuff
        ////
@@ -259,7 +281,7 @@ public:
 
        inline v3s16 getPosRelative()
        {
-               return m_pos * MAP_BLOCKSIZE;
+               return m_pos_relative;
        }
 
        inline core::aabbox3d<s16> getBox()
@@ -294,7 +316,7 @@ public:
                if (!*valid_position)
                        return MapNode(CONTENT_IGNORE);
 
-               return data[z * MAP_BLOCKSIZE * MAP_BLOCKSIZE + y * MAP_BLOCKSIZE + x];
+               return data[z * zstride + y * ystride + x];
        }
 
        inline MapNode getNode(v3s16 p, bool *valid_position)
@@ -305,8 +327,7 @@ public:
        inline MapNode getNodeNoEx(v3s16 p)
        {
                bool is_valid;
-               MapNode node = getNode(p.X, p.Y, p.Z, &is_valid);
-               return is_valid ? node : MapNode(CONTENT_IGNORE);
+               return getNode(p.X, p.Y, p.Z, &is_valid);
        }
 
        inline void setNode(s16 x, s16 y, s16 z, MapNode & n)
@@ -341,6 +362,22 @@ public:
                return getNodeNoCheck(p.X, p.Y, p.Z, valid_position);
        }
 
+       ////
+       //// Non-checking, unsafe variants of the above
+       //// MapBlock must be loaded by another function in the same scope/function
+       //// Caller must ensure that this is not a dummy block (by calling isDummy())
+       ////
+
+       inline const MapNode &getNodeUnsafe(s16 x, s16 y, s16 z)
+       {
+               return data[z * zstride + y * ystride + x];
+       }
+
+       inline const MapNode &getNodeUnsafe(v3s16 &p)
+       {
+               return getNodeUnsafe(p.X, p.Y, p.Z);
+       }
+
        inline void setNodeNoCheck(s16 x, s16 y, s16 z, MapNode & n)
        {
                if (data == NULL)
@@ -488,9 +525,9 @@ public:
                m_node_timers.remove(p);
        }
 
-       inline void setNodeTimer(v3s16 p, NodeTimer t)
+       inline void setNodeTimer(const NodeTimer &t)
        {
-               m_node_timers.set(p,t);
+               m_node_timers.set(t);
        }
 
        inline void clearNodeTimers()
@@ -504,15 +541,14 @@ public:
 
        // These don't write or read version by itself
        // Set disk to true for on-disk format, false for over-the-network format
-       // Precondition: version >= SER_FMT_CLIENT_VER_LOWEST
+       // Precondition: version >= SER_FMT_VER_LOWEST_WRITE
        void serialize(std::ostream &os, u8 version, bool disk);
        // If disk == true: In addition to doing other things, will add
        // unknown blocks from id-name mapping to wndef
        void deSerialize(std::istream &is, u8 version, bool disk);
 
-       void serializeNetworkSpecific(std::ostream &os, u16 net_proto_version);
+       void serializeNetworkSpecific(std::ostream &os);
        void deSerializeNetworkSpecific(std::istream &is);
-
 private:
        /*
                Private methods
@@ -553,6 +589,8 @@ public:
        static const u32 ystride = MAP_BLOCKSIZE;
        static const u32 zstride = MAP_BLOCKSIZE * MAP_BLOCKSIZE;
 
+       static const u32 nodecount = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
+
 private:
        /*
                Private member variables
@@ -563,6 +601,14 @@ private:
        // Position in blocks on parent
        v3s16 m_pos;
 
+       /* This is the precalculated m_pos_relative value
+       * This caches the value, improving performance by removing 3 s16 multiplications
+       * at runtime on each getPosRelative call
+       * For a 5 minutes runtime with valgrind this removes 3 * 19M s16 multiplications
+       * The gain can be estimated in Release Build to 3 * 100M multiply operations for 5 mins
+       */
+       v3s16 m_pos_relative;
+
        IGameDef *m_gamedef;
 
        /*
@@ -589,14 +635,15 @@ private:
        */
        bool is_underground;
 
-       /*
-               Set to true if changes has been made that make the old lighting
-               values wrong but the lighting hasn't been actually updated.
-
-               If this is false, lighting is exactly right.
-               If this is true, lighting might be wrong or right.
+       /*!
+        * Each bit indicates if light spreading was finished
+        * in a direction. (Because the neighbor could also be unloaded.)
+        * Bits (most significant first):
+        * nothing,  nothing,  nothing,  nothing,
+        * night X-, night Y-, night Z-, night Z+, night Y+, night X+,
+        * day X-,   day Y-,   day Z-,   day Z+,   day Y+,   day X+.
        */
-       bool m_lighting_expired;
+       u16 m_lighting_complete;
 
        // Whether day and night lighting differs
        bool m_day_night_differs;
@@ -627,15 +674,26 @@ private:
 
 typedef std::vector<MapBlock*> MapBlockVect;
 
-inline bool blockpos_over_limit(v3s16 p)
+inline bool objectpos_over_limit(v3f p)
 {
-       return
-         (p.X < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
-       || p.X >  MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
-       || p.Y < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
-       || p.Y >  MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
-       || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
-       || p.Z >  MAP_GENERATION_LIMIT / MAP_BLOCKSIZE);
+       const float max_limit_bs = MAX_MAP_GENERATION_LIMIT * BS;
+       return p.X < -max_limit_bs ||
+               p.X >  max_limit_bs ||
+               p.Y < -max_limit_bs ||
+               p.Y >  max_limit_bs ||
+               p.Z < -max_limit_bs ||
+               p.Z >  max_limit_bs;
+}
+
+inline bool blockpos_over_max_limit(v3s16 p)
+{
+       const s16 max_limit_bp = MAX_MAP_GENERATION_LIMIT / MAP_BLOCKSIZE;
+       return p.X < -max_limit_bp ||
+               p.X >  max_limit_bp ||
+               p.Y < -max_limit_bp ||
+               p.Y >  max_limit_bp ||
+               p.Z < -max_limit_bp ||
+               p.Z >  max_limit_bp;
 }
 
 /*
@@ -672,4 +730,3 @@ inline void getNodeSectorPosWithOffset(const v2s16 &p, v2s16 &block, v2s16 &offs
 std::string analyze_block(MapBlock *block);
 
 #endif
-