diff options
-rw-r--r-- | clientmods/world/init.lua | 15 | ||||
-rw-r--r-- | src/script/lua_api/l_env.cpp | 110 | ||||
-rw-r--r-- | src/script/lua_api/l_env.h | 8 |
3 files changed, 125 insertions, 8 deletions
diff --git a/clientmods/world/init.lua b/clientmods/world/init.lua index 198bc597f..b8a058c32 100644 --- a/clientmods/world/init.lua +++ b/clientmods/world/init.lua @@ -59,19 +59,18 @@ minetest.register_globalstep(function() {x = 2, y = 0, z = z} } for i, p in pairs(positions) do - if i > count then break end minetest.place_node(p) end elseif minetest.settings:get_bool("destroy_liquids") then - local p = minetest.find_node_near(pos, 5, "mcl_core:water_source", true) or minetest.find_node_near(pos, 5, "mcl_core:water_floating", true) - if p then + local positions = minetest.find_nodes_near(pos, 5, {"mcl_core:water_source", "mcl_core:water_floating"}, true) + for _, p in pairs(positions) do minetest.place_node(p) end - elseif minetest.settings:get_bool("fill") then - local positions = minetest.find_nodes_in_area(vector.add(pos, {x = 5, y = -0.6, z = 5}), vector.add(pos, {x = -5, y = -5.6, z = -5}), "air") + elseif minetest.settings:get_bool("placeoncobble") then + local positions = minetest.find_nodes_near_under_air(pos, 5, "mcl_core:cobble", true) for i, p in pairs(positions) do - if i > count then break end - minetest.place_node(p) + if i > 8 then break end + minetest.place_node(vector.add(p, {x = 0, y = 1, z = 0})) end end end @@ -87,4 +86,4 @@ minetest.register_cheat("Scaffold", "World", "scaffold") minetest.register_cheat("HighwayZ", "World", "highway_z") minetest.register_cheat("Fucker", "World", "fucker") minetest.register_cheat("BlockWater", "World", "destroy_liquids") -minetest.register_cheat("Fill", "World", "fill") +minetest.register_cheat("PlaceOnCobble", "World", "placeoncobble") diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index b2bc8c5f6..d80f1e025 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -805,6 +805,112 @@ int ModApiEnvMod::l_find_node_near(lua_State *L) return 0; } +// find_nodes_near(pos, radius, nodenames, [search_center]) +// nodenames: eg. {"ignore", "group:tree"} or "default:dirt" +int ModApiEnvMod::l_find_nodes_near(lua_State *L) +{ + GET_PLAIN_ENV_PTR; + + const NodeDefManager *ndef = env->getGameDef()->ndef(); + Map &map = env->getMap(); + + v3s16 pos = read_v3s16(L, 1); + int radius = luaL_checkinteger(L, 2); + std::vector<content_t> filter; + collectNodeIds(L, 3, ndef, filter); + + int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1; + +#ifndef SERVER + // Client API limitations + if (Client *client = getClient(L)) + radius = client->CSMClampRadius(pos, radius); +#endif + + std::vector<u32> individual_count; + individual_count.resize(filter.size()); + + lua_newtable(L); + u32 i = 0; + + for (int d = start_radius; d <= radius; d++) { + const std::vector<v3s16> &list = FacePositionCache::getFacePositions(d); + for (const v3s16 &posi : list) { + v3s16 p = pos + posi; + content_t c = map.getNode(p).getContent(); + auto it = std::find(filter.begin(), filter.end(), c); + if (it != filter.end()) { + push_v3s16(L, p); + lua_rawseti(L, -2, ++i); + + u32 filt_index = it - filter.begin(); + individual_count[filt_index]++; + } + } + } + lua_createtable(L, 0, filter.size()); + for (u32 i = 0; i < filter.size(); i++) { + lua_pushinteger(L, individual_count[i]); + lua_setfield(L, -2, ndef->get(filter[i]).name.c_str()); + } + return 2; +} + +// find_nodes_near_under_air(pos, radius, nodenames, [search_center]) +// nodenames: eg. {"ignore", "group:tree"} or "default:dirt" +int ModApiEnvMod::l_find_nodes_near_under_air(lua_State *L) +{ + GET_PLAIN_ENV_PTR; + + const NodeDefManager *ndef = env->getGameDef()->ndef(); + Map &map = env->getMap(); + + v3s16 pos = read_v3s16(L, 1); + int radius = luaL_checkinteger(L, 2); + std::vector<content_t> filter; + collectNodeIds(L, 3, ndef, filter); + + int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1; + +#ifndef SERVER + // Client API limitations + if (Client *client = getClient(L)) + radius = client->CSMClampRadius(pos, radius); +#endif + + std::vector<u32> individual_count; + individual_count.resize(filter.size()); + + lua_newtable(L); + u32 i = 0; + + for (int d = start_radius; d <= radius; d++) { + const std::vector<v3s16> &list = FacePositionCache::getFacePositions(d); + for (const v3s16 &posi : list) { + v3s16 p = pos + posi; + content_t c = map.getNode(p).getContent(); + v3s16 psurf(p.X, p.Y + 1, p.Z); + content_t csurf = map.getNode(psurf).getContent(); + if (c == CONTENT_AIR || csurf != CONTENT_AIR) + continue; + auto it = std::find(filter.begin(), filter.end(), c); + if (it != filter.end()) { + push_v3s16(L, p); + lua_rawseti(L, -2, ++i); + + u32 filt_index = it - filter.begin(); + individual_count[filt_index]++; + } + } + } + lua_createtable(L, 0, filter.size()); + for (u32 i = 0; i < filter.size(); i++) { + lua_pushinteger(L, individual_count[i]); + lua_setfield(L, -2, ndef->get(filter[i]).name.c_str()); + } + return 2; +} + // find_nodes_in_area(minp, maxp, nodenames, [grouped]) int ModApiEnvMod::l_find_nodes_in_area(lua_State *L) { @@ -1377,6 +1483,8 @@ void ModApiEnvMod::Initialize(lua_State *L, int top) API_FCT(get_gametime); API_FCT(get_day_count); API_FCT(find_node_near); + API_FCT(find_nodes_near); + API_FCT(find_nodes_near_under_air); API_FCT(find_nodes_in_area); API_FCT(find_nodes_in_area_under_air); API_FCT(fix_light); @@ -1405,6 +1513,8 @@ void ModApiEnvMod::InitializeClient(lua_State *L, int top) API_FCT(get_node_level); API_FCT(find_nodes_with_meta); API_FCT(find_node_near); + API_FCT(find_nodes_near); + API_FCT(find_nodes_near_under_air); API_FCT(find_nodes_in_area); API_FCT(find_nodes_in_area_under_air); API_FCT(line_of_sight); diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h index 07d4d2438..e31fba8be 100644 --- a/src/script/lua_api/l_env.h +++ b/src/script/lua_api/l_env.h @@ -126,6 +126,14 @@ private: // find_node_near(pos, radius, nodenames, search_center) -> pos or nil // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" static int l_find_node_near(lua_State *L); + + // find_nodes_near(pos, radius, nodenames, search_center) -> list of positions + // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" + static int l_find_nodes_near(lua_State *L); + + // find_nodes_near_under_air(pos, radius, nodenames, search_center) -> list of positions + // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" + static int l_find_nodes_near_under_air(lua_State *L); // find_nodes_in_area(minp, maxp, nodenames) -> list of positions // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" |