mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-11-04 01:05:48 +01:00 
			
		
		
		
	Implement API to create empty VoxelManip
This commit is contained in:
		@@ -5005,7 +5005,8 @@ A VoxelManip object can be created any time using either:
 | 
			
		||||
If the optional position parameters are present for either of these routines,
 | 
			
		||||
the specified region will be pre-loaded into the VoxelManip object on creation.
 | 
			
		||||
Otherwise, the area of map you wish to manipulate must first be loaded into the
 | 
			
		||||
VoxelManip object using `VoxelManip:read_from_map()`.
 | 
			
		||||
VoxelManip object using `VoxelManip:read_from_map()`, or an empty one created
 | 
			
		||||
with `VoxelManip:initialize()`.
 | 
			
		||||
 | 
			
		||||
Note that `VoxelManip:read_from_map()` returns two position vectors. The region
 | 
			
		||||
formed by these positions indicate the minimum and maximum (respectively)
 | 
			
		||||
@@ -5016,14 +5017,14 @@ be queried any time after loading map data with `VoxelManip:get_emerged_area()`.
 | 
			
		||||
Now that the VoxelManip object is populated with map data, your mod can fetch a
 | 
			
		||||
copy of this data using either of two methods. `VoxelManip:get_node_at()`,
 | 
			
		||||
which retrieves an individual node in a MapNode formatted table at the position
 | 
			
		||||
requested is the simplest method to use, but also the slowest.
 | 
			
		||||
requested. This is the simplest method to use, but also the slowest.
 | 
			
		||||
 | 
			
		||||
Nodes in a VoxelManip object may also be read in bulk to a flat array table
 | 
			
		||||
using:
 | 
			
		||||
 | 
			
		||||
* `VoxelManip:get_data()` for node content (in Content ID form, see section
 | 
			
		||||
  [Content IDs]),
 | 
			
		||||
* `VoxelManip:get_light_data()` for node light levels, and
 | 
			
		||||
* `VoxelManip:get_light_data()` for node param (usually light levels), and
 | 
			
		||||
* `VoxelManip:get_param2_data()` for the node type-dependent "param2" values.
 | 
			
		||||
 | 
			
		||||
See section [Flat array format] for more details.
 | 
			
		||||
@@ -5038,17 +5039,16 @@ internal state unless otherwise explicitly stated.
 | 
			
		||||
Once the bulk data has been edited to your liking, the internal VoxelManip
 | 
			
		||||
state can be set using:
 | 
			
		||||
 | 
			
		||||
* `VoxelManip:set_data()` for node content (in Content ID form, see section
 | 
			
		||||
  [Content IDs]),
 | 
			
		||||
* `VoxelManip:set_light_data()` for node light levels, and
 | 
			
		||||
* `VoxelManip:set_param2_data()` for the node type-dependent `param2` values.
 | 
			
		||||
* `VoxelManip:set_data()` or
 | 
			
		||||
* `VoxelManip:set_light_data()` or
 | 
			
		||||
* `VoxelManip:set_param2_data()`
 | 
			
		||||
 | 
			
		||||
The parameter to each of the above three functions can use any table at all in
 | 
			
		||||
the same flat array format as produced by `get_data()` etc. and is not required
 | 
			
		||||
to be a table retrieved from `get_data()`.
 | 
			
		||||
 | 
			
		||||
Once the internal VoxelManip state has been modified to your liking, the
 | 
			
		||||
changes can be committed back to the map by calling `VoxelManip:write_to_map()`
 | 
			
		||||
changes can be committed back to the map by calling `VoxelManip:write_to_map()`.
 | 
			
		||||
 | 
			
		||||
### Flat array format
 | 
			
		||||
 | 
			
		||||
@@ -5180,15 +5180,22 @@ inside the VoxelManip.
 | 
			
		||||
Methods
 | 
			
		||||
-------
 | 
			
		||||
 | 
			
		||||
* `read_from_map(p1, p2)`: Loads a chunk of map into the VoxelManip object
 | 
			
		||||
* `read_from_map(p1, p2)`: Loads a part of the map into the VoxelManip object
 | 
			
		||||
  containing the region formed by `p1` and `p2`.
 | 
			
		||||
    * returns actual emerged `pmin`, actual emerged `pmax`
 | 
			
		||||
    * returns actual emerged `pmin`, actual emerged `pmax` (MapBlock-aligned)
 | 
			
		||||
    * Note that calling this multiple times will *add* to the area loaded in the
 | 
			
		||||
      VoxelManip, and not reset it.
 | 
			
		||||
* `initialize(p1, p2, [node])`: Clears and resizes the VoxelManip object to
 | 
			
		||||
  comprise the region formed by `p1` and `p2`.
 | 
			
		||||
   * **No data** is read from the map, so you can use this to treat `VoxelManip`
 | 
			
		||||
     objects as general containers of node data.
 | 
			
		||||
   * `node`: if present the data will be filled with this node; if not it will
 | 
			
		||||
     be uninitialized
 | 
			
		||||
   * returns actual emerged `pmin`, actual emerged `pmax` (MapBlock-aligned)
 | 
			
		||||
   * (introduced in 5.13.0)
 | 
			
		||||
* `write_to_map([light])`: Writes the data loaded from the `VoxelManip` back to
 | 
			
		||||
  the map.
 | 
			
		||||
    * **important**: data must be set using `VoxelManip:set_data()` before
 | 
			
		||||
      calling this.
 | 
			
		||||
    * **important**: you should call `set_data()` before this, or nothing will change.
 | 
			
		||||
    * if `light` is true, then lighting is automatically recalculated.
 | 
			
		||||
      The default value is true.
 | 
			
		||||
      If `light` is false, no light calculations happen, and you should correct
 | 
			
		||||
@@ -5249,6 +5256,8 @@ Methods
 | 
			
		||||
   where the engine will keep the map and the VM in sync automatically.
 | 
			
		||||
   * Note: this doesn't do what you think it does and is subject to removal. Don't use it!
 | 
			
		||||
* `get_emerged_area()`: Returns actual emerged minimum and maximum positions.
 | 
			
		||||
   * "Emerged" does not imply that this region was actually loaded from the map,
 | 
			
		||||
      if `initialize()` has been used.
 | 
			
		||||
* `close()`: Frees the data buffers associated with the VoxelManip object.
 | 
			
		||||
   It will become empty.
 | 
			
		||||
   * Since Lua's garbage collector is not aware of the potentially significant
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,40 @@ int LuaVoxelManip::l_read_from_map(lua_State *L)
 | 
			
		||||
 | 
			
		||||
	push_v3s16(L, vm->m_area.MinEdge);
 | 
			
		||||
	push_v3s16(L, vm->m_area.MaxEdge);
 | 
			
		||||
	return 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int LuaVoxelManip::l_initialize(lua_State *L)
 | 
			
		||||
{
 | 
			
		||||
	MAP_LOCK_REQUIRED;
 | 
			
		||||
 | 
			
		||||
	LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
 | 
			
		||||
	MMVManip *vm = o->vm;
 | 
			
		||||
 | 
			
		||||
	if (o->is_mapgen_vm)
 | 
			
		||||
		throw LuaError("Cannot modify mapgen VoxelManip object");
 | 
			
		||||
 | 
			
		||||
	VoxelArea area;
 | 
			
		||||
	{
 | 
			
		||||
		v3s16 bp1 = getNodeBlockPos(check_v3s16(L, 2));
 | 
			
		||||
		v3s16 bp2 = getNodeBlockPos(check_v3s16(L, 3));
 | 
			
		||||
		sortBoxVerticies(bp1, bp2);
 | 
			
		||||
		area = VoxelArea(bp1 * MAP_BLOCKSIZE, (bp2+1) * MAP_BLOCKSIZE - v3s16(1));
 | 
			
		||||
	}
 | 
			
		||||
	assert(!area.hasEmptyExtent());
 | 
			
		||||
 | 
			
		||||
	vm->clear();
 | 
			
		||||
	vm->addArea(area);
 | 
			
		||||
	if (lua_istable(L, 4)) {
 | 
			
		||||
		MapNode n = readnode(L, 4);
 | 
			
		||||
		const u32 volume = vm->m_area.getVolume();
 | 
			
		||||
		for (u32 i = 0; i != volume; i++)
 | 
			
		||||
			vm->m_data[i] = n;
 | 
			
		||||
		vm->clearFlags(vm->m_area, VOXELFLAG_NO_DATA);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	push_v3s16(L, vm->m_area.MinEdge);
 | 
			
		||||
	push_v3s16(L, vm->m_area.MaxEdge);
 | 
			
		||||
	return 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -93,11 +126,12 @@ int LuaVoxelManip::l_set_data(lua_State *L)
 | 
			
		||||
		lua_pop(L, 1);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// FIXME: in theory we should clear VOXELFLAG_NO_DATA here
 | 
			
		||||
	// However there is no way to tell which values Lua code has intended to set
 | 
			
		||||
	// (if they were VOXELFLAG_NO_DATA before), and which were just not touched.
 | 
			
		||||
	// In practice this doesn't cause problems because read_from_map() will cause
 | 
			
		||||
	// all covered blocks to be loaded anyway.
 | 
			
		||||
	// Mark all data as present, since we just got it from Lua
 | 
			
		||||
	// Note that we can't tell if the caller intended to put CONTENT_IGNORE or
 | 
			
		||||
	// is just repeating the dummy values we push in l_get_data() in case
 | 
			
		||||
	// VOXELFLAG_NO_DATA is set. In practice this doesn't matter since ignore
 | 
			
		||||
	// isn't written back to the map anyway.
 | 
			
		||||
	vm->clearFlags(vm->m_area, VOXELFLAG_NO_DATA);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -449,6 +483,7 @@ void LuaVoxelManip::Register(lua_State *L)
 | 
			
		||||
const char LuaVoxelManip::className[] = "VoxelManip";
 | 
			
		||||
const luaL_Reg LuaVoxelManip::methods[] = {
 | 
			
		||||
	luamethod(LuaVoxelManip, read_from_map),
 | 
			
		||||
	luamethod(LuaVoxelManip, initialize),
 | 
			
		||||
	luamethod(LuaVoxelManip, get_data),
 | 
			
		||||
	luamethod(LuaVoxelManip, set_data),
 | 
			
		||||
	luamethod(LuaVoxelManip, get_node_at),
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@ private:
 | 
			
		||||
	static int gc_object(lua_State *L);
 | 
			
		||||
 | 
			
		||||
	static int l_read_from_map(lua_State *L);
 | 
			
		||||
	static int l_initialize(lua_State *L);
 | 
			
		||||
	static int l_get_data(lua_State *L);
 | 
			
		||||
	static int l_set_data(lua_State *L);
 | 
			
		||||
	static int l_write_to_map(lua_State *L);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user