Update Mapgen VoxelManipulator on buffer invalidation
authorkwolekr <kwolekr@minetest.net>
Mon, 1 Sep 2014 18:20:31 +0000 (14:20 -0400)
committerkwolekr <kwolekr@minetest.net>
Mon, 1 Sep 2014 19:12:22 +0000 (15:12 -0400)
doc/lua_api.txt
src/environment.cpp
src/map.cpp
src/map.h
src/script/lua_api/l_vmanip.cpp
src/script/lua_api/l_vmanip.h

index 86c64f9bec860c4555b8a032722ec8068a92fd84..46b789526f3e18131cb355a0d0e59a036cfb55ad 100644 (file)
@@ -2099,6 +2099,8 @@ methods:
   ^ To be used only by a VoxelManip object from minetest.get_mapgen_object
   ^ (p1, p2) is the area in which lighting is set; defaults to the whole area if left out
 - update_liquids():  Update liquid flow
+- was_modified(): Returns true or false if the data in the voxel manipulator had been modified since
+  the last read from map, due to a call to minetest.set_data() on the loaded area elsewhere
 
 VoxelArea: A helper class for voxel areas
 - Can be created via VoxelArea:new{MinEdge=pmin, MaxEdge=pmax}
index 24a498aa96b6c51414e16604458b4492ff9140a6..c8af72f6b96c23ff8fa5edaf8bdc876816bebd8a 100644 (file)
@@ -778,19 +778,26 @@ bool ServerEnvironment::setNode(v3s16 p, const MapNode &n)
 {
        INodeDefManager *ndef = m_gamedef->ndef();
        MapNode n_old = m_map->getNodeNoEx(p);
+
        // Call destructor
-       if(ndef->get(n_old).has_on_destruct)
+       if (ndef->get(n_old).has_on_destruct)
                m_script->node_on_destruct(p, n_old);
+
        // Replace node
-       bool succeeded = m_map->addNodeWithEvent(p, n);
-       if(!succeeded)
+       if (!m_map->addNodeWithEvent(p, n))
                return false;
+
+       // Update active VoxelManipulator if a mapgen thread
+       m_map->updateVManip(p);
+
        // Call post-destructor
-       if(ndef->get(n_old).has_after_destruct)
+       if (ndef->get(n_old).has_after_destruct)
                m_script->node_after_destruct(p, n_old);
+
        // Call constructor
-       if(ndef->get(n).has_on_construct)
+       if (ndef->get(n).has_on_construct)
                m_script->node_on_construct(p, n);
+
        return true;
 }
 
@@ -798,24 +805,36 @@ bool ServerEnvironment::removeNode(v3s16 p)
 {
        INodeDefManager *ndef = m_gamedef->ndef();
        MapNode n_old = m_map->getNodeNoEx(p);
+
        // Call destructor
-       if(ndef->get(n_old).has_on_destruct)
+       if (ndef->get(n_old).has_on_destruct)
                m_script->node_on_destruct(p, n_old);
+
        // Replace with air
        // This is slightly optimized compared to addNodeWithEvent(air)
-       bool succeeded = m_map->removeNodeWithEvent(p);
-       if(!succeeded)
+       if (!m_map->removeNodeWithEvent(p))
                return false;
+
+       // Update active VoxelManipulator if a mapgen thread
+       m_map->updateVManip(p);
+
        // Call post-destructor
-       if(ndef->get(n_old).has_after_destruct)
+       if (ndef->get(n_old).has_after_destruct)
                m_script->node_after_destruct(p, n_old);
+
        // Air doesn't require constructor
        return true;
 }
 
 bool ServerEnvironment::swapNode(v3s16 p, const MapNode &n)
 {
-       return m_map->addNodeWithEvent(p, n, false);
+       if (!m_map->addNodeWithEvent(p, n, false))
+               return false;
+
+       // Update active VoxelManipulator if a mapgen thread
+       m_map->updateVManip(p);
+
+       return true;
 }
 
 std::set<u16> ServerEnvironment::getObjectsInsideRadius(v3f pos, float radius)
index 147bd3584ea292106f0bda0fc1753795a7e93e8b..236972ae98a08751889f437e567e60709a2466f6 100644 (file)
@@ -2757,6 +2757,28 @@ MapBlock *ServerMap::getBlockOrEmerge(v3s16 p3d)
 void ServerMap::prepareBlock(MapBlock *block) {
 }
 
+// N.B.  This requires no synchronization, since data will not be modified unless
+// the VoxelManipulator being updated belongs to the same thread.
+void ServerMap::updateVManip(v3s16 pos)
+{
+       Mapgen *mg = m_emerge->getCurrentMapgen();
+       if (!mg)
+               return;
+
+       ManualMapVoxelManipulator *vm = mg->vm;
+       if (!vm)
+               return;
+
+       if (!vm->m_area.contains(pos))
+               return;
+
+       s32 idx = vm->m_area.index(pos);
+       vm->m_data[idx] = getNodeNoEx(pos);
+       vm->m_flags[idx] &= ~VOXELFLAG_NO_DATA;
+
+       vm->m_is_dirty = true;
+}
+
 s16 ServerMap::findGroundLevel(v2s16 p2d)
 {
 #if 0
@@ -3523,6 +3545,7 @@ void ServerMap::PrintInfo(std::ostream &out)
 
 ManualMapVoxelManipulator::ManualMapVoxelManipulator(Map *map):
                VoxelManipulator(),
+               m_is_dirty(false),
                m_create_area(false),
                m_map(map)
 {
@@ -3617,6 +3640,8 @@ void ManualMapVoxelManipulator::initialEmerge(v3s16 blockpos_min,
 
                m_loaded_blocks[p] = flags;
        }
+
+       m_is_dirty = false;
 }
 
 void ManualMapVoxelManipulator::blitBackAll(
index 9b505d8e66984807d19d305910f00126062dfc1f..1847c7ac7d331eaeffa68ce66b8ce3e1232d1f36 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -493,6 +493,8 @@ public:
        // Database version
        void loadBlock(std::string *blob, v3s16 p3d, MapSector *sector, bool save_after_load=false);
 
+       void updateVManip(v3s16 pos);
+
        // For debug printing
        virtual void PrintInfo(std::ostream &out);
 
@@ -550,6 +552,8 @@ public:
        void blitBackAll(std::map<v3s16, MapBlock*> * modified_blocks,
                        bool overwrite_generated = true);
 
+       bool m_is_dirty;
+
 protected:
        bool m_create_area;
        Map *m_map;
index f3c1fa67ae0869b55cffcb1860ea4980440fe834..2a3cfcafa3393349e1cc559c8a71e65dde7760b7 100644 (file)
@@ -304,6 +304,18 @@ int LuaVoxelManip::l_update_map(lua_State *L)
        return 0;
 }
 
+int LuaVoxelManip::l_was_modified(lua_State *L)
+{
+       NO_MAP_LOCK_REQUIRED;
+
+       LuaVoxelManip *o = checkobject(L, 1);
+       ManualMapVoxelManipulator *vm = o->vm;
+
+       lua_pushboolean(L, vm->m_is_dirty);
+
+       return 1;
+}
+
 LuaVoxelManip::LuaVoxelManip(ManualMapVoxelManipulator *mmvm, bool is_mg_vm)
 {
        this->vm           = mmvm;
@@ -396,5 +408,6 @@ const luaL_reg LuaVoxelManip::methods[] = {
        luamethod(LuaVoxelManip, set_light_data),
        luamethod(LuaVoxelManip, get_param2_data),
        luamethod(LuaVoxelManip, set_param2_data),
+       luamethod(LuaVoxelManip, was_modified),
        {0,0}
 };
index fc7ef30e6c929130b85248feeb713db40cca5b46..70468b3448498a7a39042333275bd4a689dfff02 100644 (file)
@@ -58,6 +58,8 @@ private:
        static int l_get_param2_data(lua_State *L);
        static int l_set_param2_data(lua_State *L);
 
+       static int l_was_modified(lua_State *L);
+
 public:
        LuaVoxelManip(ManualMapVoxelManipulator *mmvm, bool is_mapgen_vm);
        LuaVoxelManip(Map *map);