Skip to content

Commit 6eb03c1

Browse files
authoredJun 19, 2017
find_nodes_in_area: Extend maximal count to U32_MAX (#5277)
Extend documentation, limit area volume Remove u16 count limitation * Prevent integer overflow, replace minp/maxp with pos1/pos2
1 parent 071736b commit 6eb03c1

File tree

2 files changed

+49
-22
lines changed

2 files changed

+49
-22
lines changed
 

‎doc/lua_api.txt

+5-4
Original file line numberDiff line numberDiff line change
@@ -2465,12 +2465,13 @@ and `minetest.auth_reload` call the authetification handler.
24652465
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
24662466
* `search_center` is an optional boolean (default: `false`)
24672467
If true `pos` is also checked for the nodes
2468-
* `minetest.find_nodes_in_area(minp, maxp, nodenames)`: returns a list of positions
2469-
* returns as second value a table with the count of the individual nodes found
2468+
* `minetest.find_nodes_in_area(pos1, pos2, nodenames)`: returns a list of positions
24702469
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
2471-
* `minetest.find_nodes_in_area_under_air(minp, maxp, nodenames)`: returns a list of positions
2472-
* returned positions are nodes with a node air above
2470+
* First return value: Table with all node positions
2471+
* Second return value: Table with the count of each node with the node name as index
2472+
* `minetest.find_nodes_in_area_under_air(pos1, pos2, nodenames)`: returns a list of positions
24732473
* `nodenames`: e.g. `{"ignore", "group:tree"}` or `"default:dirt"`
2474+
* Return value: Table with all node positions with a node air above
24742475
* `minetest.get_perlin(noiseparams)`
24752476
* `minetest.get_perlin(seeddiff, octaves, persistence, scale)`
24762477
* Return world-specific perlin noise (`int(worldseed)+seeddiff`)

‎src/script/lua_api/l_env.cpp

+44-18
Original file line numberDiff line numberDiff line change
@@ -651,38 +651,51 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
651651
INodeDefManager *ndef = getServer(L)->ndef();
652652
v3s16 minp = read_v3s16(L, 1);
653653
v3s16 maxp = read_v3s16(L, 2);
654+
sortBoxVerticies(minp, maxp);
655+
656+
v3s16 cube = maxp - minp + 1;
657+
658+
/* Limit for too large areas, assume default values
659+
* and give tolerances of 1 node on each side
660+
* (chunksize * MAP_BLOCKSIZE + 2)^3 = 551368
661+
*/
662+
if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 551368) {
663+
luaL_error(L, "find_nodes_in_area(): area volume"
664+
" exceeds allowed value of 551368");
665+
return 0;
666+
}
667+
654668
std::set<content_t> filter;
655-
if(lua_istable(L, 3)) {
656-
int table = 3;
669+
if (lua_istable(L, 3)) {
657670
lua_pushnil(L);
658-
while(lua_next(L, table) != 0) {
671+
while (lua_next(L, 3) != 0) {
659672
// key at index -2 and value at index -1
660673
luaL_checktype(L, -1, LUA_TSTRING);
661674
ndef->getIds(lua_tostring(L, -1), filter);
662675
// removes value, keeps key for next iteration
663676
lua_pop(L, 1);
664677
}
665-
} else if(lua_isstring(L, 3)) {
678+
} else if (lua_isstring(L, 3)) {
666679
ndef->getIds(lua_tostring(L, 3), filter);
667680
}
668681

669-
std::map<content_t, u16> individual_count;
682+
std::unordered_map<content_t, u32> individual_count;
670683

671684
lua_newtable(L);
672685
u64 i = 0;
673686
for (s16 x = minp.X; x <= maxp.X; x++)
674-
for (s16 y = minp.Y; y <= maxp.Y; y++)
675-
for (s16 z = minp.Z; z <= maxp.Z; z++) {
676-
v3s16 p(x, y, z);
677-
content_t c = env->getMap().getNodeNoEx(p).getContent();
678-
if (filter.count(c) != 0) {
679-
push_v3s16(L, p);
680-
lua_rawseti(L, -2, ++i);
681-
individual_count[c]++;
682-
}
687+
for (s16 y = minp.Y; y <= maxp.Y; y++)
688+
for (s16 z = minp.Z; z <= maxp.Z; z++) {
689+
v3s16 p(x, y, z);
690+
content_t c = env->getMap().getNodeNoEx(p).getContent();
691+
if (filter.count(c) != 0) {
692+
push_v3s16(L, p);
693+
lua_rawseti(L, -2, ++i);
694+
individual_count[c]++;
695+
}
683696
}
684697
lua_newtable(L);
685-
for (std::set<content_t>::iterator it = filter.begin();
698+
for (std::set<content_t>::const_iterator it = filter.begin();
686699
it != filter.end(); ++it) {
687700
lua_pushnumber(L, individual_count[*it]);
688701
lua_setfield(L, -2, ndef->get(*it).name.c_str());
@@ -706,12 +719,25 @@ int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L)
706719
INodeDefManager *ndef = getServer(L)->ndef();
707720
v3s16 minp = read_v3s16(L, 1);
708721
v3s16 maxp = read_v3s16(L, 2);
722+
sortBoxVerticies(minp, maxp);
723+
724+
v3s16 cube = maxp - minp + 1;
725+
726+
/* Limit for too large areas, assume default values
727+
* and give tolerances of 1 node on each side
728+
* (chunksize * MAP_BLOCKSIZE + 2)^3 = 551368
729+
*/
730+
if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 551368) {
731+
luaL_error(L, "find_nodes_in_area_under_air(): area volume"
732+
" exceeds allowed value of 551368");
733+
return 0;
734+
}
735+
709736
std::set<content_t> filter;
710737

711738
if (lua_istable(L, 3)) {
712-
int table = 3;
713739
lua_pushnil(L);
714-
while(lua_next(L, table) != 0) {
740+
while (lua_next(L, 3) != 0) {
715741
// key at index -2 and value at index -1
716742
luaL_checktype(L, -1, LUA_TSTRING);
717743
ndef->getIds(lua_tostring(L, -1), filter);
@@ -732,7 +758,7 @@ int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L)
732758
for (; y <= maxp.Y; y++) {
733759
v3s16 psurf(x, y + 1, z);
734760
content_t csurf = env->getMap().getNodeNoEx(psurf).getContent();
735-
if(c != CONTENT_AIR && csurf == CONTENT_AIR &&
761+
if (c != CONTENT_AIR && csurf == CONTENT_AIR &&
736762
filter.count(c) != 0) {
737763
push_v3s16(L, v3s16(x, y, z));
738764
lua_rawseti(L, -2, ++i);

0 commit comments

Comments
 (0)
Please sign in to comment.