X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Fscript%2Flua_api%2Fl_env.cpp;h=a489d245c431e18b0a4f079b3f5a85283f3ff0c3;hb=21df26984da91143c15587f5a03c98d68c3adc4e;hp=8a72acee1fa0e11cb802c302af6fc1d72ff3cdae;hpb=d8b8c1d313c29e92b4ef15ad0a1fddd5ec8bc651;p=dragonfireclient.git diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index 8a72acee1..a489d245c 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -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 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 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(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 individual_count; individual_count.resize(filter.size()); - + lua_newtable(L); u32 i = 0; - + for (int d = start_radius; d <= radius; d++) { const std::vector &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 individual_count; individual_count.resize(filter.size()); - + lua_newtable(L); u32 i = 0; - + for (int d = start_radius; d <= radius; d++) { const std::vector &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 individual_count; individual_count.resize(filter.size()); - + lua_newtable(L); u32 i = 0; - + for (int d = start_radius; d <= radius; d++) { const std::vector &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 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 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 path = get_path(&env->getServerMap(), env->getGameDef()->ndef(), pos1, pos2, + std::vector 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,6 +1626,7 @@ 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); @@ -1553,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); } @@ -1569,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); }