diff options
Diffstat (limited to 'src/mapblock.h')
-rw-r--r-- | src/mapblock.h | 290 |
1 files changed, 201 insertions, 89 deletions
diff --git a/src/mapblock.h b/src/mapblock.h index dd5277668..e39db35bd 100644 --- a/src/mapblock.h +++ b/src/mapblock.h @@ -70,6 +70,74 @@ struct NodeMod u16 param; }; +class NodeModMap +{ +public: + /* + returns true if the mod was different last time + */ + bool set(v3s16 p, const NodeMod &mod) + { + // See if old is different, cancel if it is not different. + core::map<v3s16, NodeMod>::Node *n = m_mods.find(p); + if(n) + { + NodeMod old = n->getValue(); + if(old == mod) + return false; + + n->setValue(mod); + } + else + { + m_mods.insert(p, mod); + } + + return true; + } + // Returns true if there was one + bool get(v3s16 p, NodeMod *mod) + { + core::map<v3s16, NodeMod>::Node *n; + n = m_mods.find(p); + if(n == NULL) + return false; + if(mod) + *mod = n->getValue(); + return true; + } + bool clear(v3s16 p) + { + if(m_mods.find(p)) + { + m_mods.remove(p); + return true; + } + return false; + } + bool clear() + { + if(m_mods.size() == 0) + return false; + m_mods.clear(); + return true; + } + void copy(NodeModMap &dest) + { + dest.m_mods.clear(); + + for(core::map<v3s16, NodeMod>::Iterator + i = m_mods.getIterator(); + i.atEnd() == false; i++) + { + dest.m_mods.insert(i.getNode()->getKey(), i.getNode()->getValue()); + } + } + +private: + core::map<v3s16, NodeMod> m_mods; +}; + enum { NODECONTAINER_ID_MAPBLOCK, @@ -104,11 +172,26 @@ public: return m_parent; } + void reallocate() + { + if(data != NULL) + delete[] data; + u32 l = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE; + data = new MapNode[l]; + for(u32 i=0; i<l; i++){ + data[i] = MapNode(); + } + setChangedFlag(); + } + + /* + Flags + */ + bool isDummy() { return (data == NULL); } - void unDummify() { assert(isDummy()); @@ -119,16 +202,26 @@ public: { return changed; } - void resetChangedFlag() { changed = false; } - void setChangedFlag() { changed = true; } + + bool getIsUnderground() + { + return is_underground; + } + + void setIsUnderground(bool a_is_underground) + { + is_underground = a_is_underground; + setChangedFlag(); + } + #ifndef SERVER void setMeshExpired(bool expired) { @@ -140,6 +233,30 @@ public: return m_mesh_expired; } #endif + + void setLightingExpired(bool expired) + { + m_lighting_expired = expired; + setChangedFlag(); + } + bool getLightingExpired() + { + return m_lighting_expired; + } + + bool isValid() + { + if(m_lighting_expired) + return false; + if(data == NULL) + return false; + return true; + } + + /* + Position stuff + */ + v3s16 getPos() { return m_pos; @@ -150,17 +267,6 @@ public: return m_pos * MAP_BLOCKSIZE; } - bool getIsUnderground() - { - return is_underground; - } - - void setIsUnderground(bool a_is_underground) - { - is_underground = a_is_underground; - setChangedFlag(); - } - core::aabbox3d<s16> getBox() { return core::aabbox3d<s16>(getPosRelative(), @@ -168,19 +274,11 @@ public: + v3s16(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE) - v3s16(1,1,1)); } - - void reallocate() - { - if(data != NULL) - delete[] data; - u32 l = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE; - data = new MapNode[l]; - for(u32 i=0; i<l; i++){ - data[i] = MapNode(); - } - setChangedFlag(); - } + /* + Regular MapNode get-setters + */ + bool isValidPosition(v3s16 p) { if(data == NULL) @@ -190,10 +288,6 @@ public: && p.Z >= 0 && p.Z < MAP_BLOCKSIZE); } - /* - Regular MapNode get-setters - */ - MapNode getNode(s16 x, s16 y, s16 z) { if(data == NULL) @@ -271,9 +365,14 @@ public: setNode(x0+x, y0+y, z0+z, node); } + /* + Graphics-related methods + */ + + // A quick version with nodes passed as parameters u8 getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2, v3s16 face_dir); - + // A more convenient version u8 getFaceLight(u32 daynight_ratio, v3s16 p, v3s16 face_dir) { return getFaceLight(daynight_ratio, @@ -288,11 +387,16 @@ public: v3s16 dir, v3f scale, v3f posRelative_f, core::array<FastFace> &dest); - TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir); - u8 getNodeContent(v3s16 p, MapNode mn); + TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir, + NodeModMap &temp_mods); + u8 getNodeContent(v3s16 p, MapNode mn, + NodeModMap &temp_mods); /* - startpos: + Generates the FastFaces of a node row. This has a + ridiculous amount of parameters because that way they + can be precalculated by the caller. + translate_dir: unit vector with only one of x, y or z face_dir: unit vector with only one of x, y or z */ @@ -305,12 +409,14 @@ public: v3f translate_dir_f, v3s16 face_dir, v3f face_dir_f, - core::array<FastFace> &dest); - + core::array<FastFace> &dest, + NodeModMap &temp_mods); + + /* + Thread-safely updates the whole mesh of the mapblock. + */ void updateMesh(u32 daynight_ratio); - /*void updateMesh(s32 daynight_i); - // Updates all DAYNIGHT_CACHE_COUNT meshes - void updateMeshes(s32 first_i=0);*/ + #endif // !SERVER // See comments in mapblock.cpp @@ -322,7 +428,7 @@ public: void copyTo(VoxelManipulator &dst); /* - Object stuff + MapBlockObject stuff */ void serializeObjects(std::ostream &os, u8 version) @@ -384,9 +490,6 @@ public: m_objects.getObjects(origin, max_d, dest); } - /*void getPseudoObjects(v3f origin, f32 max_d, - core::array<DistanceSortedObject> &dest);*/ - s32 getObjectCount() { return m_objects.getCount(); @@ -399,7 +502,7 @@ public: returns true if the mod was different last time */ - bool setTempMod(v3s16 p, NodeMod mod) + bool setTempMod(v3s16 p, const NodeMod &mod) { /*dstream<<"setTempMod called on block" <<" ("<<p.X<<","<<p.Y<<","<<p.Z<<")" @@ -408,52 +511,33 @@ public: <<std::endl;*/ JMutexAutoLock lock(m_temp_mods_mutex); - // See if old is different, cancel if it is not different. - core::map<v3s16, NodeMod>::Node *n = m_temp_mods.find(p); - if(n) - { - NodeMod old = n->getValue(); - if(old == mod) - return false; - } - - m_temp_mods[p] = mod; - return true; + return m_temp_mods.set(p, mod); } // Returns true if there was one - bool getTempMod(v3s16 p, struct NodeMod *mod) + bool getTempMod(v3s16 p, NodeMod *mod) { JMutexAutoLock lock(m_temp_mods_mutex); - core::map<v3s16, NodeMod>::Node *n; - n = m_temp_mods.find(p); - if(n == NULL) - return false; - if(mod) - *mod = n->getValue(); - return true; + + return m_temp_mods.get(p, mod); } bool clearTempMod(v3s16 p) { JMutexAutoLock lock(m_temp_mods_mutex); - if(m_temp_mods.find(p)) - { - m_temp_mods.remove(p); - return true; - } - return false; + + return m_temp_mods.clear(p); } bool clearTempMods() { JMutexAutoLock lock(m_temp_mods_mutex); - if(m_temp_mods.size() == 0) - return false; - m_temp_mods.clear(); - return true; + + return m_temp_mods.clear(); } #endif /* - Day-night lighting difference + Update day-night lighting difference flag. + + Sets m_day_night_differs to appropriate value. These methods don't care about neighboring blocks. It means that to know if a block really doesn't need a mesh @@ -490,18 +574,11 @@ public: void deSerialize(std::istream &is, u8 version); +private: /* - Public member variables + Private methods */ -#ifndef SERVER - //scene::SMesh *mesh[DAYNIGHT_CACHE_COUNT]; - scene::SMesh *mesh; - JMutex mesh_mutex; -#endif - -private: - /* Used only internally, because changes can't be tracked */ @@ -520,28 +597,58 @@ private: return getNodeRef(p.X, p.Y, p.Z); } +public: + /* + Public member variables + */ + +#ifndef SERVER + scene::SMesh *mesh; + JMutex mesh_mutex; +#endif +private: + /* + Private member variables + */ + + // Parent container (practically the Map) + // Not a MapSector, it is just a structural element. NodeContainer *m_parent; // Position in blocks on parent v3s16 m_pos; + /* If NULL, block is a dummy block. Dummy blocks are used for caching not-found-on-disk blocks. */ MapNode * data; + /* - - On the client, this is used for checking whether to - recalculate the face cache. (Is it anymore?) - On the server, this is used for telling whether the block has been changed from the one on disk. + - On the client, this is used for nothing. */ bool changed; + /* - Used for some initial lighting stuff. - At least /has been/ used. 8) - It's probably useless now. + When propagating sunlight and the above block doesn't exist, + sunlight is assumed if this is false. + + In practice this is set to true if the block is completely + 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 m_lighting_expired; // Whether day and night lighting differs bool m_day_night_differs; @@ -552,11 +659,16 @@ private: float m_spawn_timer; #ifndef SERVER + /* + Set to true if the mesh has been ordered to be updated + sometime in the background. + In practice this is set when the day/night lighting switches. + */ bool m_mesh_expired; // Temporary modifications to nodes // These are only used when drawing - core::map<v3s16, NodeMod> m_temp_mods; + NodeModMap m_temp_mods; JMutex m_temp_mods_mutex; #endif }; |