Skip to content

Commit aa1bab2

Browse files
committed
Implement API to create empty VoxelManip
1 parent 6274a8d commit aa1bab2

3 files changed

Lines changed: 62 additions & 17 deletions

File tree

‎doc/lua_api.md‎

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5005,7 +5005,8 @@ A VoxelManip object can be created any time using either:
50055005
If the optional position parameters are present for either of these routines,
50065006
the specified region will be pre-loaded into the VoxelManip object on creation.
50075007
Otherwise, the area of map you wish to manipulate must first be loaded into the
5008-
VoxelManip object using `VoxelManip:read_from_map()`.
5008+
VoxelManip object using `VoxelManip:read_from_map()`, or an empty one created
5009+
with `VoxelManip:initialize()`.
50095010

50105011
Note that `VoxelManip:read_from_map()` returns two position vectors. The region
50115012
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()`.
50165017
Now that the VoxelManip object is populated with map data, your mod can fetch a
50175018
copy of this data using either of two methods. `VoxelManip:get_node_at()`,
50185019
which retrieves an individual node in a MapNode formatted table at the position
5019-
requested is the simplest method to use, but also the slowest.
5020+
requested. This is the simplest method to use, but also the slowest.
50205021

50215022
Nodes in a VoxelManip object may also be read in bulk to a flat array table
50225023
using:
50235024

50245025
* `VoxelManip:get_data()` for node content (in Content ID form, see section
50255026
[Content IDs]),
5026-
* `VoxelManip:get_light_data()` for node light levels, and
5027+
* `VoxelManip:get_light_data()` for node param (usually light levels), and
50275028
* `VoxelManip:get_param2_data()` for the node type-dependent "param2" values.
50285029

50295030
See section [Flat array format] for more details.
@@ -5038,17 +5039,16 @@ internal state unless otherwise explicitly stated.
50385039
Once the bulk data has been edited to your liking, the internal VoxelManip
50395040
state can be set using:
50405041

5041-
* `VoxelManip:set_data()` for node content (in Content ID form, see section
5042-
[Content IDs]),
5043-
* `VoxelManip:set_light_data()` for node light levels, and
5044-
* `VoxelManip:set_param2_data()` for the node type-dependent `param2` values.
5042+
* `VoxelManip:set_data()` or
5043+
* `VoxelManip:set_light_data()` or
5044+
* `VoxelManip:set_param2_data()`
50455045

50465046
The parameter to each of the above three functions can use any table at all in
50475047
the same flat array format as produced by `get_data()` etc. and is not required
50485048
to be a table retrieved from `get_data()`.
50495049

50505050
Once the internal VoxelManip state has been modified to your liking, the
5051-
changes can be committed back to the map by calling `VoxelManip:write_to_map()`
5051+
changes can be committed back to the map by calling `VoxelManip:write_to_map()`.
50525052

50535053
### Flat array format
50545054

@@ -5180,15 +5180,22 @@ inside the VoxelManip.
51805180
Methods
51815181
-------
51825182

5183-
* `read_from_map(p1, p2)`: Loads a chunk of map into the VoxelManip object
5183+
* `read_from_map(p1, p2)`: Loads a part of the map into the VoxelManip object
51845184
containing the region formed by `p1` and `p2`.
5185-
* returns actual emerged `pmin`, actual emerged `pmax`
5185+
* returns actual emerged `pmin`, actual emerged `pmax` (MapBlock-aligned)
51865186
* Note that calling this multiple times will *add* to the area loaded in the
51875187
VoxelManip, and not reset it.
5188+
* `initialize(p1, p2, [node])`: Clears and resizes the VoxelManip object to
5189+
comprise the region formed by `p1` and `p2`.
5190+
* **No data** is read from the map, so you can use this to treat `VoxelManip`
5191+
objects as general containers of node data.
5192+
* `node`: if present the data will be filled with this node; if not it will
5193+
be uninitialized
5194+
* returns actual emerged `pmin`, actual emerged `pmax` (MapBlock-aligned)
5195+
* (introduced in 5.13.0)
51885196
* `write_to_map([light])`: Writes the data loaded from the `VoxelManip` back to
51895197
the map.
5190-
* **important**: data must be set using `VoxelManip:set_data()` before
5191-
calling this.
5198+
* **important**: you should call `set_data()` before this, or nothing will change.
51925199
* if `light` is true, then lighting is automatically recalculated.
51935200
The default value is true.
51945201
If `light` is false, no light calculations happen, and you should correct
@@ -5249,6 +5256,8 @@ Methods
52495256
where the engine will keep the map and the VM in sync automatically.
52505257
* Note: this doesn't do what you think it does and is subject to removal. Don't use it!
52515258
* `get_emerged_area()`: Returns actual emerged minimum and maximum positions.
5259+
* "Emerged" does not imply that this region was actually loaded from the map,
5260+
if `initialize()` has been used.
52525261
* `close()`: Frees the data buffers associated with the VoxelManip object.
52535262
It will become empty.
52545263
* Since Lua's garbage collector is not aware of the potentially significant

‎src/script/lua_api/l_vmanip.cpp‎

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,40 @@ int LuaVoxelManip::l_read_from_map(lua_State *L)
4444

4545
push_v3s16(L, vm->m_area.MinEdge);
4646
push_v3s16(L, vm->m_area.MaxEdge);
47+
return 2;
48+
}
49+
50+
int LuaVoxelManip::l_initialize(lua_State *L)
51+
{
52+
MAP_LOCK_REQUIRED;
53+
54+
LuaVoxelManip *o = checkObject<LuaVoxelManip>(L, 1);
55+
MMVManip *vm = o->vm;
4756

57+
if (o->is_mapgen_vm)
58+
throw LuaError("Cannot modify mapgen VoxelManip object");
59+
60+
VoxelArea area;
61+
{
62+
v3s16 bp1 = getNodeBlockPos(check_v3s16(L, 2));
63+
v3s16 bp2 = getNodeBlockPos(check_v3s16(L, 3));
64+
sortBoxVerticies(bp1, bp2);
65+
area = VoxelArea(bp1 * MAP_BLOCKSIZE, (bp2+1) * MAP_BLOCKSIZE - v3s16(1));
66+
}
67+
assert(!area.hasEmptyExtent());
68+
69+
vm->clear();
70+
vm->addArea(area);
71+
if (lua_istable(L, 4)) {
72+
MapNode n = readnode(L, 4);
73+
const u32 volume = vm->m_area.getVolume();
74+
for (u32 i = 0; i != volume; i++)
75+
vm->m_data[i] = n;
76+
vm->clearFlags(vm->m_area, VOXELFLAG_NO_DATA);
77+
}
78+
79+
push_v3s16(L, vm->m_area.MinEdge);
80+
push_v3s16(L, vm->m_area.MaxEdge);
4881
return 2;
4982
}
5083

@@ -93,11 +126,12 @@ int LuaVoxelManip::l_set_data(lua_State *L)
93126
lua_pop(L, 1);
94127
}
95128

96-
// FIXME: in theory we should clear VOXELFLAG_NO_DATA here
97-
// However there is no way to tell which values Lua code has intended to set
98-
// (if they were VOXELFLAG_NO_DATA before), and which were just not touched.
99-
// In practice this doesn't cause problems because read_from_map() will cause
100-
// all covered blocks to be loaded anyway.
129+
// Mark all data as present, since we just got it from Lua
130+
// Note that we can't tell if the caller intended to put CONTENT_IGNORE or
131+
// is just repeating the dummy values we push in l_get_data() in case
132+
// VOXELFLAG_NO_DATA is set. In practice this doesn't matter since ignore
133+
// isn't written back to the map anyway.
134+
vm->clearFlags(vm->m_area, VOXELFLAG_NO_DATA);
101135

102136
return 0;
103137
}
@@ -449,6 +483,7 @@ void LuaVoxelManip::Register(lua_State *L)
449483
const char LuaVoxelManip::className[] = "VoxelManip";
450484
const luaL_Reg LuaVoxelManip::methods[] = {
451485
luamethod(LuaVoxelManip, read_from_map),
486+
luamethod(LuaVoxelManip, initialize),
452487
luamethod(LuaVoxelManip, get_data),
453488
luamethod(LuaVoxelManip, set_data),
454489
luamethod(LuaVoxelManip, get_node_at),

‎src/script/lua_api/l_vmanip.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class LuaVoxelManip : public ModApiBase
2424
static int gc_object(lua_State *L);
2525

2626
static int l_read_from_map(lua_State *L);
27+
static int l_initialize(lua_State *L);
2728
static int l_get_data(lua_State *L);
2829
static int l_set_data(lua_State *L);
2930
static int l_write_to_map(lua_State *L);

0 commit comments

Comments
 (0)