]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/script/lua_api/l_env.cpp
Merge branch 'master' of https://github.com/minetest/minetest
[dragonfireclient.git] / src / script / lua_api / l_env.cpp
index 98f8861faef9560e138184c5a0f3f02efefb1881..a489d245c431e18b0a4f079b3f5a85283f3ff0c3 100644 (file)
@@ -477,7 +477,7 @@ int ModApiEnvMod::l_place_node(lua_State *L)
                return 1;
        }
        // Create item to place
-       ItemStack item(ndef->get(n).name, 1, 0, idef);
+       Optional<ItemStack> item = ItemStack(ndef->get(n).name, 1, 0, idef);
        // Make pointed position
        PointedThing pointed;
        pointed.type = POINTEDTHING_NODE;
@@ -757,7 +757,7 @@ int ModApiEnvMod::l_get_objects_in_area(lua_State *L)
 {
        GET_ENV_PTR;
        ScriptApiBase *script = getScriptApiBase(L);
-       
+
        v3f minp = read_v3f(L, 1) * BS;
        v3f maxp = read_v3f(L, 2) * BS;
        aabb3f box(minp, maxp);
@@ -857,7 +857,6 @@ int ModApiEnvMod::l_find_node_near(lua_State *L)
        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
@@ -880,6 +879,180 @@ 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_near_under_air_except(pos, radius, nodenames, [search_center])
+// nodenames: eg. {"ignore", "group:tree"} or "default:dirt"
+int ModApiEnvMod::l_find_nodes_near_under_air_except(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;
+}
+
+static void checkArea(v3s16 &minp, v3s16 &maxp)
+{
+       auto volume = VoxelArea(minp, maxp).getVolume();
+       // Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
+       if (volume > 4096000) {
+               throw LuaError("Area volume exceeds allowed value of 4096000");
+       }
+
+       // Clamp to map range to avoid problems
+#define CLAMP(arg) core::clamp(arg, (s16)-MAX_MAP_GENERATION_LIMIT, (s16)MAX_MAP_GENERATION_LIMIT)
+       minp = v3s16(CLAMP(minp.X), CLAMP(minp.Y), CLAMP(minp.Z));
+       maxp = v3s16(CLAMP(maxp.X), CLAMP(maxp.Y), CLAMP(maxp.Z));
+#undef CLAMP
+}
+
 // find_nodes_in_area(minp, maxp, nodenames, [grouped])
 int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
 {
@@ -899,13 +1072,7 @@ int ModApiEnvMod::l_find_nodes_in_area(lua_State *L)
        }
 #endif
 
-       v3s16 cube = maxp - minp + 1;
-       // Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
-       if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 4096000) {
-               luaL_error(L, "find_nodes_in_area(): area volume"
-                               " exceeds allowed value of 4096000");
-               return 0;
-       }
+       checkArea(minp, maxp);
 
        std::vector<content_t> filter;
        collectNodeIds(L, 3, ndef, filter);
@@ -1010,13 +1177,7 @@ int ModApiEnvMod::l_find_nodes_in_area_under_air(lua_State *L)
        }
 #endif
 
-       v3s16 cube = maxp - minp + 1;
-       // Volume limit equal to 8 default mapchunks, (80 * 2) ^ 3 = 4,096,000
-       if ((u64)cube.X * (u64)cube.Y * (u64)cube.Z > 4096000) {
-               luaL_error(L, "find_nodes_in_area_under_air(): area volume"
-                               " exceeds allowed value of 4096000");
-               return 0;
-       }
+       checkArea(minp, maxp);
 
        std::vector<content_t> filter;
        collectNodeIds(L, 3, ndef, filter);
@@ -1282,7 +1443,7 @@ int ModApiEnvMod::l_delete_area(lua_State *L)
 //     max_jump, max_drop, algorithm) -> table containing path
 int ModApiEnvMod::l_find_path(lua_State *L)
 {
-       GET_ENV_PTR;
+       Environment *env = getEnv(L);
 
        v3s16 pos1                  = read_v3s16(L, 1);
        v3s16 pos2                  = read_v3s16(L, 2);
@@ -1300,7 +1461,7 @@ int ModApiEnvMod::l_find_path(lua_State *L)
                        algo = PA_DIJKSTRA;
        }
 
-       std::vector<v3s16> path = get_path(&env->getServerMap(), env->getGameDef()->ndef(), pos1, pos2,
+       std::vector<v3s16> path = get_path(&env->getMap(), env->getGameDef()->ndef(), pos1, pos2,
                searchdistance, max_jump, max_drop, algo);
 
        if (!path.empty()) {
@@ -1383,7 +1544,7 @@ int ModApiEnvMod::l_transforming_liquid_add(lua_State *L)
        GET_ENV_PTR;
 
        v3s16 p0 = read_v3s16(L, 1);
-       env->getMap().transforming_liquid_add(p0);
+       env->getServerMap().transforming_liquid_add(p0);
        return 1;
 }
 
@@ -1406,7 +1567,7 @@ int ModApiEnvMod::l_compare_block_status(lua_State *L)
        v3s16 nodepos = check_v3s16(L, 1);
        std::string condition_s = luaL_checkstring(L, 2);
        auto status = env->getBlockStatus(getNodeBlockPos(nodepos));
-       
+
        int condition_i = -1;
        if (!string_to_enum(es_BlockStatusType, condition_i, condition_s))
                return 0; // Unsupported
@@ -1501,8 +1662,13 @@ 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_near_under_air_except);
        API_FCT(find_nodes_in_area);
        API_FCT(find_nodes_in_area_under_air);
+       API_FCT(get_voxel_manip);
+       API_FCT(find_path);
        API_FCT(line_of_sight);
        API_FCT(raycast);
 }