51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifndef MAPBLOCK_HEADER
-#define MAPBLOCK_HEADER
+#pragma once
#include <set>
-#include "debug.h"
#include "irr_v3d.h"
#include "mapnode.h"
#include "exceptions.h"
#include "modifiedstate.h"
#include "util/numeric.h" // getContainerPos
#include "settings.h"
+#include "mapgen/mapgen.h"
class Map;
class NodeMetadataList;
#define BLOCK_TIMESTAMP_UNDEFINED 0xffffffff
-/*// Named by looking towards z+
-enum{
- FACE_BACK=0,
- FACE_TOP,
- FACE_RIGHT,
- FACE_FRONT,
- FACE_BOTTOM,
- FACE_LEFT
-};*/
-
-// NOTE: If this is enabled, set MapBlock to be initialized with
-// CONTENT_IGNORE.
-/*enum BlockGenerationStatus
-{
- // Completely non-generated (filled with CONTENT_IGNORE).
- BLOCKGEN_UNTOUCHED=0,
- // Trees or similar might have been blitted from other blocks to here.
- // Otherwise, the block contains CONTENT_IGNORE
- BLOCKGEN_FROM_NEIGHBORS=2,
- // Has been generated, but some neighbors might put some stuff in here
- // when they are generated.
- // Does not contain any CONTENT_IGNORE
- BLOCKGEN_SELF_GENERATED=4,
- // The block and all its neighbors have been generated
- BLOCKGEN_FULLY_GENERATED=6
-};*/
-
-#if 0
-enum
-{
- NODECONTAINER_ID_MAPBLOCK,
- NODECONTAINER_ID_MAPSECTOR,
- NODECONTAINER_ID_MAP,
- NODECONTAINER_ID_MAPBLOCKCACHE,
- NODECONTAINER_ID_VOXELMANIPULATOR,
-};
-
-class NodeContainer
-{
-public:
- virtual bool isValidPosition(v3s16 p) = 0;
- virtual MapNode getNode(v3s16 p) = 0;
- virtual void setNode(v3s16 p, MapNode & n) = 0;
- virtual u16 nodeContainerId() const = 0;
-
- MapNode getNodeNoEx(v3s16 p)
- {
- try{
- return getNode(p);
- }
- catch(InvalidPositionException &e){
- return MapNode(CONTENT_IGNORE);
- }
- }
-};
-#endif
-
////
//// MapBlock modified reason flags
////
#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)
#define MOD_REASON_STATIC_DATA_REMOVED (1 << 16)
#define MOD_REASON_STATIC_DATA_CHANGED (1 << 17)
#define MOD_REASON_EXPIRE_DAYNIGHTDIFF (1 << 18)
-#define MOD_REASON_UNKNOWN (1 << 19)
+#define MOD_REASON_VMANIP (1 << 19)
+#define MOD_REASON_UNKNOWN (1 << 20)
////
//// MapBlock itself
////
-class MapBlock /*: public NodeContainer*/
+class MapBlock
{
public:
MapBlock(Map *parent, v3s16 pos, IGameDef *gamedef, bool dummy=false);
raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_REALLOCATE);
}
+ MapNode* getData()
+ {
+ return data;
+ }
+
////
//// Modification tracking methods
////
} else if (mod == m_modified) {
m_modified_reason |= reason;
}
+ if (mod == MOD_STATE_WRITE_NEEDED)
+ contents_cached = false;
}
inline u32 getModified()
inline bool isDummy()
{
- return (data == NULL);
+ return !data;
}
inline void unDummify()
raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_IS_UNDERGROUND);
}
- inline void setLightingExpired(bool expired)
+ inline void setLightingComplete(u16 newflags)
+ {
+ if (newflags != m_lighting_complete) {
+ m_lighting_complete = newflags;
+ raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_LIGHTING_COMPLETE);
+ }
+ }
+
+ inline u16 getLightingComplete()
+ {
+ return m_lighting_complete;
+ }
+
+ inline void setLightingComplete(LightBank bank, u8 direction,
+ bool is_complete)
{
- if (expired != m_lighting_expired){
- m_lighting_expired = expired;
- raiseModified(MOD_STATE_WRITE_NEEDED, MOD_REASON_SET_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 getLightingExpired()
+ inline bool isLightingComplete(LightBank bank, u8 direction)
{
- return m_lighting_expired;
+ assert(direction >= 0 && direction <= 5);
+ if (bank == LIGHTBANK_NIGHT) {
+ direction += 6;
+ }
+ return (m_lighting_complete & (1 << direction)) != 0;
}
inline bool isGenerated()
}
}
- inline bool isValid()
- {
- if (m_lighting_expired)
- return false;
- if (data == NULL)
- return false;
- return true;
- }
-
////
//// Position stuff
////
inline bool isValidPosition(s16 x, s16 y, s16 z)
{
- return data != NULL
+ return data
&& x >= 0 && x < MAP_BLOCKSIZE
&& y >= 0 && y < MAP_BLOCKSIZE
&& z >= 0 && z < MAP_BLOCKSIZE;
*valid_position = isValidPosition(x, y, z);
if (!*valid_position)
- return MapNode(CONTENT_IGNORE);
+ return {CONTENT_IGNORE};
return data[z * zstride + y * ystride + x];
}
inline MapNode getNodeNoCheck(s16 x, s16 y, s16 z, bool *valid_position)
{
- *valid_position = data != NULL;
- if (!valid_position)
- return MapNode(CONTENT_IGNORE);
+ *valid_position = data != nullptr;
+ if (!*valid_position)
+ return {CONTENT_IGNORE};
return data[z * zstride + y * ystride + x];
}
inline void setNodeNoCheck(s16 x, s16 y, s16 z, MapNode & n)
{
- if (data == NULL)
+ if (!data)
throw InvalidPositionException();
data[z * zstride + y * ystride + x] = n;
setNode(x0 + x, y0 + y, z0 + z, node);
}
- // See comments in mapblock.cpp
- bool propagateSunlight(std::set<v3s16> &light_sources,
- bool remove_light=false, bool *black_air_left=NULL);
-
// Copies data to VoxelManipulator to getPosRelative()
void copyTo(VoxelManipulator &dst);
//// Node Timers
////
- inline NodeTimer getNodeTimer(v3s16 p)
+ inline NodeTimer getNodeTimer(const v3s16 &p)
{
return m_node_timers.get(p);
}
- inline void removeNodeTimer(v3s16 p)
+ inline void removeNodeTimer(const v3s16 &p)
{
m_node_timers.remove(p);
}
// 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:
/*
*/
#ifndef SERVER // Only on client
- MapBlockMesh *mesh;
+ MapBlockMesh *mesh = nullptr;
#endif
NodeMetadataList m_node_metadata;
static const u32 nodecount = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
+ //// ABM optimizations ////
+ // Cache of content types
+ std::unordered_set<content_t> contents;
+ // True if content types are cached
+ bool contents_cached = false;
+ // True if we never want to cache content types for this block
+ bool do_not_cache_contents = false;
+
private:
/*
Private member variables
If NULL, block is a dummy block.
Dummy blocks are used for caching not-found-on-disk blocks.
*/
- MapNode *data;
+ MapNode *data = nullptr;
/*
- On the server, this is used for telling whether the
block has been modified from the one on disk.
- On the client, this is used for nothing.
*/
- u32 m_modified;
- u32 m_modified_reason;
+ u32 m_modified = MOD_STATE_WRITE_NEEDED;
+ u32 m_modified_reason = MOD_REASON_INITIAL;
/*
When propagating sunlight and the above block doesn't exist,
undeground with nothing visible above the ground except
caves.
*/
- 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.
+ bool is_underground = false;
+
+ /*!
+ * 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 = 0xFFFF;
// Whether day and night lighting differs
- bool m_day_night_differs;
- bool m_day_night_differs_expired;
+ bool m_day_night_differs = false;
+ bool m_day_night_differs_expired = true;
- bool m_generated;
+ bool m_generated = false;
/*
When block is removed from active blocks, this is set to gametime.
Value BLOCK_TIMESTAMP_UNDEFINED=0xffffffff means there is no timestamp.
*/
- u32 m_timestamp;
+ u32 m_timestamp = BLOCK_TIMESTAMP_UNDEFINED;
// The on-disk (or to-be on-disk) timestamp value
- u32 m_disk_timestamp;
+ u32 m_disk_timestamp = BLOCK_TIMESTAMP_UNDEFINED;
/*
When the block is accessed, this is set to 0.
Map will unload the block when this reaches a timeout.
*/
- float m_usage_timer;
+ float m_usage_timer = 0;
/*
Reference count; currently used for determining if this block is in
the list of blocks to be drawn.
*/
- int m_refcount;
+ int m_refcount = 0;
};
typedef std::vector<MapBlock*> MapBlockVect;
inline bool objectpos_over_limit(v3f p)
{
- const static float map_gen_limit_bs = MYMIN(MAX_MAP_GENERATION_LIMIT,
- g_settings->getU16("map_generation_limit")) * BS;
- return (p.X < -map_gen_limit_bs
- || p.X > map_gen_limit_bs
- || p.Y < -map_gen_limit_bs
- || p.Y > map_gen_limit_bs
- || p.Z < -map_gen_limit_bs
- || p.Z > map_gen_limit_bs);
+ 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_limit(v3s16 p)
+inline bool blockpos_over_max_limit(v3s16 p)
{
- const static u16 map_gen_limit = MYMIN(MAX_MAP_GENERATION_LIMIT,
- g_settings->getU16("map_generation_limit"));
- return (p.X < -map_gen_limit / MAP_BLOCKSIZE
- || p.X > map_gen_limit / MAP_BLOCKSIZE
- || p.Y < -map_gen_limit / MAP_BLOCKSIZE
- || p.Y > map_gen_limit / MAP_BLOCKSIZE
- || p.Z < -map_gen_limit / MAP_BLOCKSIZE
- || p.Z > map_gen_limit / MAP_BLOCKSIZE);
+ 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;
}
/*
Returns the position of the block where the node is located
*/
-inline v3s16 getNodeBlockPos(v3s16 p)
-{
- return getContainerPos(p, MAP_BLOCKSIZE);
-}
-
-inline v2s16 getNodeSectorPos(v2s16 p)
+inline v3s16 getNodeBlockPos(const v3s16 &p)
{
return getContainerPos(p, MAP_BLOCKSIZE);
}
-inline s16 getNodeBlockY(s16 y)
-{
- return getContainerPos(y, MAP_BLOCKSIZE);
-}
-
inline void getNodeBlockPosWithOffset(const v3s16 &p, v3s16 &block, v3s16 &offset)
{
getContainerPosWithOffset(p, MAP_BLOCKSIZE, block, offset);
}
-inline void getNodeSectorPosWithOffset(const v2s16 &p, v2s16 &block, v2s16 &offset)
-{
- getContainerPosWithOffset(p, MAP_BLOCKSIZE, block, offset);
-}
-
/*
Get a quick string to describe what a block actually contains
*/
std::string analyze_block(MapBlock *block);
-
-#endif