diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 6506dc2b2..3d7d3ed3d 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4844,6 +4844,18 @@ Schematics the Lua code generated will use that number of spaces as indentation instead of a tab character. +* `minetest.read_schematic(schematic, options)` + * Returns a Lua table representing the schematic (see: [Schematic specifier]) + * `schematic` is the schematic to read (see: [Schematic specifier]) + * `options` is a table containing the following optional parameters: + * `write_yslice_prob`: string value: + * `none`: no `write_yslice_prob` table is inserted, + * `low`: only probabilities that are not 254 or 255 are written in + the `write_ylisce_prob` table, + * `all`: write all probabilities to the `write_yslice_prob` table. + * The default for this option is `all`. + * Any invalid value will be interpreted as `all`. + HTTP Requests ------------- diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index e7e002c16..2e0cba8dd 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -1754,6 +1754,83 @@ int ModApiMapgen::l_serialize_schematic(lua_State *L) return 1; } +// read_schematic(schematic, options={...}) +int ModApiMapgen::l_read_schematic(lua_State *L) +{ + NO_MAP_LOCK_REQUIRED; + + SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr; + + //// Read options + std::string write_yslice = getstringfield_default(L, 2, "write_yslice_prob", "all"); + + //// Get schematic + bool was_loaded = false; + Schematic *schem = (Schematic *)get_objdef(L, 1, schemmgr); + if (!schem) { + schem = load_schematic(L, 1, NULL, NULL); + was_loaded = true; + } + if (!schem) { + errorstream << "read_schematic: failed to get schematic" << std::endl; + return 0; + } + lua_pop(L, 2); + + //// Create the Lua table + u32 numnodes = schem->size.X * schem->size.Y * schem->size.Z; + const std::vector &names = schem->m_nodenames; + + lua_createtable(L, 0, (write_yslice == "none") ? 2 : 3); + + // Create the size field + push_v3s16(L, schem->size); + lua_setfield(L, 1, "size"); + + // Create the yslice_prob field + if (write_yslice != "none") { + lua_createtable(L, schem->size.Y, 0); + for (u16 y = 0; y != schem->size.Y; ++y) { + u8 probability = schem->slice_probs[y] & MTSCHEM_PROB_MASK; + if (probability < MTSCHEM_PROB_ALWAYS || write_yslice != "low") { + lua_createtable(L, 0, 2); + lua_pushinteger(L, y); + lua_setfield(L, 3, "ypos"); + lua_pushinteger(L, probability * 2); + lua_setfield(L, 3, "prob"); + lua_rawseti(L, 2, y + 1); + } + } + lua_setfield(L, 1, "yslice_prob"); + } + + // Create the data field + lua_createtable(L, numnodes, 0); // data table + for (u32 i = 0; i < numnodes; ++i) { + MapNode node = schem->schemdata[i]; + u8 probability = node.param1 & MTSCHEM_PROB_MASK; + bool force_place = node.param1 & MTSCHEM_FORCE_PLACE; + lua_createtable(L, 0, force_place ? 4 : 3); + lua_pushstring(L, names[schem->schemdata[i].getContent()].c_str()); + lua_setfield(L, 3, "name"); + lua_pushinteger(L, probability * 2); + lua_setfield(L, 3, "prob"); + lua_pushinteger(L, node.param2); + lua_setfield(L, 3, "param2"); + if (force_place) { + lua_pushboolean(L, 1); + lua_setfield(L, 3, "force_place"); + } + lua_rawseti(L, 2, i + 1); + } + lua_setfield(L, 1, "data"); + + if (was_loaded) + delete schem; + + return 1; +} + void ModApiMapgen::Initialize(lua_State *L, int top) { @@ -1793,4 +1870,5 @@ void ModApiMapgen::Initialize(lua_State *L, int top) API_FCT(place_schematic); API_FCT(place_schematic_on_vmanip); API_FCT(serialize_schematic); + API_FCT(read_schematic); } diff --git a/src/script/lua_api/l_mapgen.h b/src/script/lua_api/l_mapgen.h index 1339791f3..4a6a9ccf4 100644 --- a/src/script/lua_api/l_mapgen.h +++ b/src/script/lua_api/l_mapgen.h @@ -131,6 +131,9 @@ private: // serialize_schematic(schematic, format, options={...}) static int l_serialize_schematic(lua_State *L); + // read_schematic(schematic, options={...}) + static int l_read_schematic(lua_State *L); + public: static void Initialize(lua_State *L, int top);