]> 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 bd5865bf670edc23e3066a5ffab40d090792e7cb..a489d245c431e18b0a4f079b3f5a85283f3ff0c3 100644 (file)
@@ -46,13 +46,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "client/client.h"
 #endif
 
-struct EnumString ModApiEnvMod::es_ClearObjectsMode[] =
+const EnumString ModApiEnvMod::es_ClearObjectsMode[] =
 {
        {CLEAR_OBJECTS_MODE_FULL,  "full"},
        {CLEAR_OBJECTS_MODE_QUICK, "quick"},
        {0, NULL},
 };
 
+const EnumString ModApiEnvMod::es_BlockStatusType[] =
+{
+       {ServerEnvironment::BS_UNKNOWN, "unknown"},
+       {ServerEnvironment::BS_EMERGING, "emerging"},
+       {ServerEnvironment::BS_LOADED,  "loaded"},
+       {ServerEnvironment::BS_ACTIVE,  "active"},
+       {0, NULL},
+};
+
 ///////////////////////////////////////////////////////////////////////////////
 
 
@@ -228,7 +237,7 @@ void LuaRaycast::Register(lua_State *L)
 
        lua_pop(L, 1);
 
-       luaL_openlib(L, 0, methods, 0);
+       luaL_register(L, nullptr, methods);
        lua_pop(L, 1);
 
        lua_register(L, className, create_object);
@@ -407,6 +416,46 @@ int ModApiEnvMod::l_get_node_light(lua_State *L)
        return 1;
 }
 
+
+// get_natural_light(pos, timeofday)
+// pos = {x=num, y=num, z=num}
+// timeofday: nil = current time, 0 = night, 0.5 = day
+int ModApiEnvMod::l_get_natural_light(lua_State *L)
+{
+       GET_ENV_PTR;
+
+       v3s16 pos = read_v3s16(L, 1);
+
+       bool is_position_ok;
+       MapNode n = env->getMap().getNode(pos, &is_position_ok);
+       if (!is_position_ok)
+               return 0;
+
+       // If the daylight is 0, nothing needs to be calculated
+       u8 daylight = n.param1 & 0x0f;
+       if (daylight == 0) {
+               lua_pushinteger(L, 0);
+               return 1;
+       }
+
+       u32 time_of_day;
+       if (lua_isnumber(L, 2)) {
+               time_of_day = 24000.0 * lua_tonumber(L, 2);
+               time_of_day %= 24000;
+       } else {
+               time_of_day = env->getTimeOfDay();
+       }
+       u32 dnr = time_to_daynight_ratio(time_of_day, true);
+
+       // If it's the same as the artificial light, the sunlight needs to be
+       // searched for because the value may not emanate from the sun
+       if (daylight == n.param1 >> 4)
+               daylight = env->findSunlight(pos);
+
+       lua_pushinteger(L, dnr * daylight / 1000);
+       return 1;
+}
+
 // place_node(pos, node)
 // pos = {x=num, y=num, z=num}
 int ModApiEnvMod::l_place_node(lua_State *L)
@@ -428,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;
@@ -703,6 +752,31 @@ int ModApiEnvMod::l_get_objects_inside_radius(lua_State *L)
        return 1;
 }
 
+// get_objects_in_area(pos, minp, maxp)
+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);
+       box.repair();
+       std::vector<ServerActiveObject *> objs;
+
+       auto include_obj_cb = [](ServerActiveObject *obj){ return !obj->isGone(); };
+       env->getObjectsInArea(objs, box, include_obj_cb);
+
+       int i = 0;
+       lua_createtable(L, objs.size(), 0);
+       for (const auto obj : objs) {
+               // Insert object reference into table
+               script->objectrefGetOrCreate(L, obj);
+               lua_rawseti(L, -2, ++i);
+       }
+       return 1;
+}
+
 // set_timeofday(val)
 // val = 0...1
 int ModApiEnvMod::l_set_timeofday(lua_State *L)
@@ -711,8 +785,9 @@ int ModApiEnvMod::l_set_timeofday(lua_State *L)
 
        // Do it
        float timeofday_f = readParam<float>(L, 1);
-       sanity_check(timeofday_f >= 0.0 && timeofday_f <= 1.0);
-       int timeofday_mh = (int)(timeofday_f * 24000.0);
+       luaL_argcheck(L, timeofday_f >= 0.0f && timeofday_f <= 1.0f, 1,
+               "value must be between 0 and 1");
+       int timeofday_mh = (int)(timeofday_f * 24000.0f);
        // This should be set directly in the environment but currently
        // such changes aren't immediately sent to the clients, so call
        // the server instead.
@@ -796,7 +871,6 @@ int ModApiEnvMod::l_find_node_near(lua_State *L)
                        v3s16 p = pos + i;
                        content_t c = map.getNode(p).getContent();
                        if (CONTAINS(filter, c)) {
-                               std::cout << p.X << " " << p.Y << " " << p.Z << std::endl;
                                push_v3s16(L, p);
                                return 1;
                        }
@@ -826,13 +900,13 @@ int ModApiEnvMod::l_find_nodes_near(lua_State *L)
        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) {
@@ -876,13 +950,13 @@ int ModApiEnvMod::l_find_nodes_near_under_air(lua_State *L)
        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) {
@@ -930,13 +1004,13 @@ int ModApiEnvMod::l_find_nodes_near_under_air_except(lua_State *L)
        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) {
@@ -964,6 +1038,21 @@ int ModApiEnvMod::l_find_nodes_near_under_air_except(lua_State *L)
        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)
 {
@@ -983,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);
@@ -1094,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);
@@ -1366,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);
@@ -1384,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()) {
@@ -1467,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;
 }
 
@@ -1482,6 +1559,24 @@ int ModApiEnvMod::l_forceload_block(lua_State *L)
        return 0;
 }
 
+// compare_block_status(nodepos)
+int ModApiEnvMod::l_compare_block_status(lua_State *L)
+{
+       GET_ENV_PTR;
+
+       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
+
+       lua_pushboolean(L, status >= condition_i);
+       return 1;
+}
+
+
 // forceload_free_block(blockpos)
 // blockpos = {x=num, y=num, z=num}
 int ModApiEnvMod::l_forceload_free_block(lua_State *L)
@@ -1499,9 +1594,9 @@ int ModApiEnvMod::l_get_translated_string(lua_State * L)
        GET_ENV_PTR;
        std::string lang_code = luaL_checkstring(L, 1);
        std::string string = luaL_checkstring(L, 2);
-       getServer(L)->loadTranslationLanguage(lang_code);
-       string = wide_to_utf8(translate_string(utf8_to_wide(string),
-                       &(*g_server_translations)[lang_code]));
+
+       auto *translations = getServer(L)->getTranslationLanguage(lang_code);
+       string = wide_to_utf8(translate_string(utf8_to_wide(string), translations));
        lua_pushstring(L, string.c_str());
        return 1;
 }
@@ -1517,6 +1612,7 @@ void ModApiEnvMod::Initialize(lua_State *L, int top)
        API_FCT(get_node);
        API_FCT(get_node_or_nil);
        API_FCT(get_node_light);
+       API_FCT(get_natural_light);
        API_FCT(place_node);
        API_FCT(dig_node);
        API_FCT(punch_node);
@@ -1530,14 +1626,13 @@ void ModApiEnvMod::Initialize(lua_State *L, int top)
        API_FCT(get_node_timer);
        API_FCT(get_connected_players);
        API_FCT(get_player_by_name);
+       API_FCT(get_objects_in_area);
        API_FCT(get_objects_inside_radius);
        API_FCT(set_timeofday);
        API_FCT(get_timeofday);
        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);
@@ -1555,6 +1650,7 @@ void ModApiEnvMod::Initialize(lua_State *L, int top)
        API_FCT(transforming_liquid_add);
        API_FCT(forceload_block);
        API_FCT(forceload_free_block);
+       API_FCT(compare_block_status);
        API_FCT(get_translated_string);
 }
 
@@ -1571,6 +1667,8 @@ void ModApiEnvMod::InitializeClient(lua_State *L, int top)
        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);
 }