Skip to content

Commit

Permalink
Update Mapgen VoxelManipulator on buffer invalidation
Browse files Browse the repository at this point in the history
  • Loading branch information
kwolekr committed Sep 1, 2014
1 parent 3fa4f78 commit 9e4e707
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 10 deletions.
2 changes: 2 additions & 0 deletions doc/lua_api.txt
Expand Up @@ -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}
Expand Down
39 changes: 29 additions & 10 deletions src/environment.cpp
Expand Up @@ -778,44 +778,63 @@ 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;
}

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)
Expand Down
25 changes: 25 additions & 0 deletions src/map.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -3617,6 +3640,8 @@ void ManualMapVoxelManipulator::initialEmerge(v3s16 blockpos_min,

m_loaded_blocks[p] = flags;
}

m_is_dirty = false;
}

void ManualMapVoxelManipulator::blitBackAll(
Expand Down
4 changes: 4 additions & 0 deletions src/map.h
Expand Up @@ -493,6 +493,8 @@ class ServerMap : public Map
// 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);

Expand Down Expand Up @@ -550,6 +552,8 @@ class ManualMapVoxelManipulator : public VoxelManipulator
void blitBackAll(std::map<v3s16, MapBlock*> * modified_blocks,
bool overwrite_generated = true);

bool m_is_dirty;

protected:
bool m_create_area;
Map *m_map;
Expand Down
13 changes: 13 additions & 0 deletions src/script/lua_api/l_vmanip.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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}
};
2 changes: 2 additions & 0 deletions src/script/lua_api/l_vmanip.h
Expand Up @@ -58,6 +58,8 @@ class LuaVoxelManip : public ModApiBase {
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);
Expand Down

0 comments on commit 9e4e707

Please sign in to comment.