#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},
+};
+
///////////////////////////////////////////////////////////////////////////////
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);
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)
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;
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)
// 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.
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;
}
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) {
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) {
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) {
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)
{
}
#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);
}
#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);
// 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);
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()) {
GET_ENV_PTR;
v3s16 p0 = read_v3s16(L, 1);
- env->getMap().transforming_liquid_add(p0);
+ env->getServerMap().transforming_liquid_add(p0);
return 1;
}
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)
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;
}
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);
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);
API_FCT(transforming_liquid_add);
API_FCT(forceload_block);
API_FCT(forceload_free_block);
+ API_FCT(compare_block_status);
API_FCT(get_translated_string);
}
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);
}