diff options
Diffstat (limited to 'src/script/lua_api/l_mapgen.cpp')
-rw-r--r-- | src/script/lua_api/l_mapgen.cpp | 986 |
1 files changed, 664 insertions, 322 deletions
diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index d470cef88..d30b68054 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_vmanip.h" #include "common/c_converter.h" #include "common/c_content.h" +#include "cpp_api/s_security.h" #include "util/serialize.h" #include "server.h" #include "environment.h" @@ -32,18 +33,17 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mg_schematic.h" #include "mapgen_v5.h" #include "mapgen_v7.h" +#include "filesys.h" #include "settings.h" -#include "main.h" #include "log.h" - struct EnumString ModApiMapgen::es_BiomeTerrainType[] = { - {BIOME_TYPE_NORMAL, "normal"}, - {BIOME_TYPE_LIQUID, "liquid"}, - {BIOME_TYPE_NETHER, "nether"}, - {BIOME_TYPE_AETHER, "aether"}, - {BIOME_TYPE_FLAT, "flat"}, + {BIOME_NORMAL, "normal"}, + {BIOME_LIQUID, "liquid"}, + {BIOME_NETHER, "nether"}, + {BIOME_AETHER, "aether"}, + {BIOME_FLAT, "flat"}, {0, NULL}, }; @@ -68,10 +68,10 @@ struct EnumString ModApiMapgen::es_MapgenObject[] = struct EnumString ModApiMapgen::es_OreType[] = { - {ORE_TYPE_SCATTER, "scatter"}, - {ORE_TYPE_SHEET, "sheet"}, - {ORE_TYPE_BLOB, "blob"}, - {ORE_TYPE_VEIN, "vein"}, + {ORE_SCATTER, "scatter"}, + {ORE_SHEET, "sheet"}, + {ORE_BLOB, "blob"}, + {ORE_VEIN, "vein"}, {0, NULL}, }; @@ -85,116 +85,238 @@ struct EnumString ModApiMapgen::es_Rotation[] = {0, NULL}, }; +struct EnumString ModApiMapgen::es_SchematicFormatType[] = +{ + {SCHEM_FMT_HANDLE, "handle"}, + {SCHEM_FMT_MTS, "mts"}, + {SCHEM_FMT_LUA, "lua"}, + {0, NULL}, +}; + +ObjDef *get_objdef(lua_State *L, int index, ObjDefManager *objmgr); + +Biome *get_or_load_biome(lua_State *L, int index, + BiomeManager *biomemgr); +Biome *read_biome_def(lua_State *L, int index, INodeDefManager *ndef); +size_t get_biome_list(lua_State *L, int index, + BiomeManager *biomemgr, std::set<u8> *biome_id_list); + +Schematic *get_or_load_schematic(lua_State *L, int index, + SchematicManager *schemmgr, StringMap *replace_names); +Schematic *load_schematic(lua_State *L, int index, INodeDefManager *ndef, + StringMap *replace_names); +Schematic *load_schematic_from_def(lua_State *L, int index, + INodeDefManager *ndef, StringMap *replace_names); +bool read_schematic_def(lua_State *L, int index, + Schematic *schem, std::vector<std::string> *names); + +bool read_deco_simple(lua_State *L, DecoSimple *deco); +bool read_deco_schematic(lua_State *L, SchematicManager *schemmgr, DecoSchematic *deco); + /////////////////////////////////////////////////////////////////////////////// +ObjDef *get_objdef(lua_State *L, int index, ObjDefManager *objmgr) +{ + if (index < 0) + index = lua_gettop(L) + 1 + index; -bool read_schematic(lua_State *L, int index, Schematic *schem, - INodeDefManager *ndef, std::map<std::string, std::string> &replace_names) + // If a number, assume this is a handle to an object def + if (lua_isnumber(L, index)) + return objmgr->get(lua_tointeger(L, index)); + + // If a string, assume a name is given instead + if (lua_isstring(L, index)) + return objmgr->getByName(lua_tostring(L, index)); + + return NULL; +} + +/////////////////////////////////////////////////////////////////////////////// + +Schematic *get_or_load_schematic(lua_State *L, int index, + SchematicManager *schemmgr, StringMap *replace_names) { + if (index < 0) + index = lua_gettop(L) + 1 + index; + + Schematic *schem = (Schematic *)get_objdef(L, index, schemmgr); + if (schem) + return schem; + + schem = load_schematic(L, index, schemmgr->getNodeDef(), + replace_names); + if (!schem) + return NULL; + + if (schemmgr->add(schem) == OBJDEF_INVALID_HANDLE) { + delete schem; + return NULL; + } + + return schem; +} + + +Schematic *load_schematic(lua_State *L, int index, INodeDefManager *ndef, + StringMap *replace_names) +{ + if (index < 0) + index = lua_gettop(L) + 1 + index; + + Schematic *schem = NULL; + + if (lua_istable(L, index)) { + schem = load_schematic_from_def(L, index, ndef, + replace_names); + if (!schem) { + delete schem; + return NULL; + } + } else if (lua_isnumber(L, index)) { + return NULL; + } else if (lua_isstring(L, index)) { + schem = SchematicManager::create(SCHEMATIC_NORMAL); + + std::string filepath = lua_tostring(L, index); + if (!fs::IsPathAbsolute(filepath)) + filepath = ModApiBase::getCurrentModPath(L) + DIR_DELIM + filepath; + + if (!schem->loadSchematicFromFile(filepath, ndef, + replace_names)) { + delete schem; + return NULL; + } + } + + return schem; +} + + +Schematic *load_schematic_from_def(lua_State *L, int index, + INodeDefManager *ndef, StringMap *replace_names) +{ + Schematic *schem = SchematicManager::create(SCHEMATIC_NORMAL); + + if (!read_schematic_def(L, index, schem, &schem->m_nodenames)) { + delete schem; + return NULL; + } + + size_t num_nodes = schem->m_nodenames.size(); + + schem->m_nnlistsizes.push_back(num_nodes); + + if (replace_names) { + for (size_t i = 0; i != num_nodes; i++) { + StringMap::iterator it = replace_names->find(schem->m_nodenames[i]); + if (it != replace_names->end()) + schem->m_nodenames[i] = it->second; + } + } + + if (ndef) + ndef->pendNodeResolve(schem); + + return schem; +} + + +bool read_schematic_def(lua_State *L, int index, + Schematic *schem, std::vector<std::string> *names) +{ + if (!lua_istable(L, index)) + return false; + //// Get schematic size lua_getfield(L, index, "size"); - v3s16 size = read_v3s16(L, -1); + v3s16 size = check_v3s16(L, -1); lua_pop(L, 1); + schem->size = size; + //// Get schematic data lua_getfield(L, index, "data"); luaL_checktype(L, -1, LUA_TTABLE); - int numnodes = size.X * size.Y * size.Z; - MapNode *schemdata = new MapNode[numnodes]; - int i = 0; + u32 numnodes = size.X * size.Y * size.Z; + schem->schemdata = new MapNode[numnodes]; - lua_pushnil(L); - while (lua_next(L, -2)) { - if (i >= numnodes) { - i++; - lua_pop(L, 1); + size_t names_base = names->size(); + std::map<std::string, content_t> name_id_map; + + u32 i = 0; + for (lua_pushnil(L); lua_next(L, -2); i++, lua_pop(L, 1)) { + if (i >= numnodes) continue; - } - // same as readnode, except param1 default is MTSCHEM_PROB_CONST - lua_getfield(L, -1, "name"); - std::string name = luaL_checkstring(L, -1); - lua_pop(L, 1); + //// Read name + std::string name; + if (!getstringfield(L, -1, "name", name)) + throw LuaError("Schematic data definition with missing name field"); + //// Read param1/prob u8 param1; - lua_getfield(L, -1, "param1"); - param1 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : MTSCHEM_PROB_ALWAYS; - lua_pop(L, 1); - - u8 param2; - lua_getfield(L, -1, "param2"); - param2 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : 0; - lua_pop(L, 1); - - std::map<std::string, std::string>::iterator it; - it = replace_names.find(name); - if (it != replace_names.end()) - name = it->second; + if (!getintfield(L, -1, "param1", param1) && + !getintfield(L, -1, "prob", param1)) + param1 = MTSCHEM_PROB_ALWAYS_OLD; + + //// Read param2 + u8 param2 = getintfield_default(L, -1, "param2", 0); + + //// Find or add new nodename-to-ID mapping + std::map<std::string, content_t>::iterator it = name_id_map.find(name); + content_t name_index; + if (it != name_id_map.end()) { + name_index = it->second; + } else { + name_index = names->size() - names_base; + name_id_map[name] = name_index; + names->push_back(name); + } - schemdata[i] = MapNode(ndef, name, param1, param2); + //// Perform probability/force_place fixup on param1 + param1 >>= 1; + if (getboolfield_default(L, -1, "force_place", false)) + param1 |= MTSCHEM_FORCE_PLACE; - i++; - lua_pop(L, 1); + //// Actually set the node in the schematic + schem->schemdata[i] = MapNode(name_index, param1, param2); } if (i != numnodes) { - errorstream << "read_schematic: incorrect number of " + errorstream << "read_schematic_def: incorrect number of " "nodes provided in raw schematic data (got " << i << ", expected " << numnodes << ")." << std::endl; - delete schemdata; return false; } //// Get Y-slice probability values (if present) - u8 *slice_probs = new u8[size.Y]; - for (i = 0; i != size.Y; i++) - slice_probs[i] = MTSCHEM_PROB_ALWAYS; + schem->slice_probs = new u8[size.Y]; + for (i = 0; i != (u32) size.Y; i++) + schem->slice_probs[i] = MTSCHEM_PROB_ALWAYS; lua_getfield(L, index, "yslice_prob"); if (lua_istable(L, -1)) { - lua_pushnil(L); - while (lua_next(L, -2)) { - if (getintfield(L, -1, "ypos", i) && i >= 0 && i < size.Y) { - slice_probs[i] = getintfield_default(L, -1, - "prob", MTSCHEM_PROB_ALWAYS); - } - lua_pop(L, 1); + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + u16 ypos; + if (!getintfield(L, -1, "ypos", ypos) || (ypos >= size.Y) || + !getintfield(L, -1, "prob", schem->slice_probs[ypos])) + continue; + + schem->slice_probs[ypos] >>= 1; } } - // Here, we read the nodes directly from the INodeDefManager - there is no - // need for pending node resolutions so we'll mark this schematic as updated - schem->flags = SCHEM_CIDS_UPDATED; - - schem->size = size; - schem->schemdata = schemdata; - schem->slice_probs = slice_probs; return true; } -bool get_schematic(lua_State *L, int index, Schematic *schem, - INodeDefManager *ndef, std::map<std::string, std::string> &replace_names) +void read_schematic_replacements(lua_State *L, int index, StringMap *replace_names) { if (index < 0) index = lua_gettop(L) + 1 + index; - if (lua_istable(L, index)) { - return read_schematic(L, index, schem, ndef, replace_names); - } else if (lua_isstring(L, index)) { - const char *filename = lua_tostring(L, index); - return schem->loadSchematicFromFile(filename, ndef, replace_names); - } else { - return false; - } -} - - -void read_schematic_replacements(lua_State *L, - std::map<std::string, std::string> &replace_names, int index) -{ lua_pushnil(L); while (lua_next(L, index)) { std::string replace_from; @@ -213,11 +335,119 @@ void read_schematic_replacements(lua_State *L, replace_to = lua_tostring(L, -1); } - replace_names[replace_from] = replace_to; + replace_names->insert(std::make_pair(replace_from, replace_to)); lua_pop(L, 1); } } +/////////////////////////////////////////////////////////////////////////////// + +Biome *get_or_load_biome(lua_State *L, int index, BiomeManager *biomemgr) +{ + if (index < 0) + index = lua_gettop(L) + 1 + index; + + Biome *biome = (Biome *)get_objdef(L, index, biomemgr); + if (biome) + return biome; + + biome = read_biome_def(L, index, biomemgr->getNodeDef()); + if (!biome) + return NULL; + + if (biomemgr->add(biome) == OBJDEF_INVALID_HANDLE) { + delete biome; + return NULL; + } + + return biome; +} + + +Biome *read_biome_def(lua_State *L, int index, INodeDefManager *ndef) +{ + if (!lua_istable(L, index)) + return NULL; + + BiomeType biometype = (BiomeType)getenumfield(L, index, "type", + ModApiMapgen::es_BiomeTerrainType, BIOME_NORMAL); + Biome *b = BiomeManager::create(biometype); + + b->name = getstringfield_default(L, index, "name", ""); + b->depth_top = getintfield_default(L, index, "depth_top", 0); + b->depth_filler = getintfield_default(L, index, "depth_filler", -31000); + b->depth_water_top = getintfield_default(L, index, "depth_water_top", 0); + b->y_min = getintfield_default(L, index, "y_min", -31000); + b->y_max = getintfield_default(L, index, "y_max", 31000); + b->heat_point = getfloatfield_default(L, index, "heat_point", 0.f); + b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.f); + b->flags = 0; //reserved + + std::vector<std::string> &nn = b->m_nodenames; + nn.push_back(getstringfield_default(L, index, "node_top", "")); + nn.push_back(getstringfield_default(L, index, "node_filler", "")); + nn.push_back(getstringfield_default(L, index, "node_stone", "")); + nn.push_back(getstringfield_default(L, index, "node_water_top", "")); + nn.push_back(getstringfield_default(L, index, "node_water", "")); + nn.push_back(getstringfield_default(L, index, "node_river_water", "")); + nn.push_back(getstringfield_default(L, index, "node_dust", "")); + ndef->pendNodeResolve(b); + + return b; +} + + +size_t get_biome_list(lua_State *L, int index, + BiomeManager *biomemgr, std::set<u8> *biome_id_list) +{ + if (index < 0) + index = lua_gettop(L) + 1 + index; + + if (lua_isnil(L, index)) + return 0; + + bool is_single = true; + if (lua_istable(L, index)) { + lua_getfield(L, index, "name"); + is_single = !lua_isnil(L, -1); + lua_pop(L, 1); + } + + if (is_single) { + Biome *biome = get_or_load_biome(L, index, biomemgr); + if (!biome) { + errorstream << "get_biome_list: failed to get biome '" + << (lua_isstring(L, index) ? lua_tostring(L, index) : "") + << "'." << std::endl; + return 1; + } + + biome_id_list->insert(biome->index); + return 0; + } + + // returns number of failed resolutions + size_t fail_count = 0; + size_t count = 0; + + for (lua_pushnil(L); lua_next(L, index); lua_pop(L, 1)) { + count++; + Biome *biome = get_or_load_biome(L, -1, biomemgr); + if (!biome) { + fail_count++; + errorstream << "get_biome_list: failed to get biome '" + << (lua_isstring(L, -1) ? lua_tostring(L, -1) : "") + << "'" << std::endl; + continue; + } + + biome_id_list->insert(biome->index); + } + + return fail_count; +} + +/////////////////////////////////////////////////////////////////////////////// // get_mapgen_object(objectname) // returns the requested object used during map generation @@ -239,92 +469,98 @@ int ModApiMapgen::l_get_mapgen_object(lua_State *L) size_t maplen = mg->csize.X * mg->csize.Z; switch (mgobj) { - case MGOBJ_VMANIP: { - MMVManip *vm = mg->vm; + case MGOBJ_VMANIP: { + MMVManip *vm = mg->vm; - // VoxelManip object - LuaVoxelManip *o = new LuaVoxelManip(vm, true); - *(void **)(lua_newuserdata(L, sizeof(void *))) = o; - luaL_getmetatable(L, "VoxelManip"); - lua_setmetatable(L, -2); + // VoxelManip object + LuaVoxelManip *o = new LuaVoxelManip(vm, true); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, "VoxelManip"); + lua_setmetatable(L, -2); - // emerged min pos - push_v3s16(L, vm->m_area.MinEdge); + // emerged min pos + push_v3s16(L, vm->m_area.MinEdge); - // emerged max pos - push_v3s16(L, vm->m_area.MaxEdge); + // emerged max pos + push_v3s16(L, vm->m_area.MaxEdge); - return 3; + return 3; + } + case MGOBJ_HEIGHTMAP: { + if (!mg->heightmap) + return 0; + + lua_newtable(L); + for (size_t i = 0; i != maplen; i++) { + lua_pushinteger(L, mg->heightmap[i]); + lua_rawseti(L, -2, i + 1); } - case MGOBJ_HEIGHTMAP: { - if (!mg->heightmap) - return 0; - - lua_newtable(L); - for (size_t i = 0; i != maplen; i++) { - lua_pushinteger(L, mg->heightmap[i]); - lua_rawseti(L, -2, i + 1); - } - return 1; + return 1; + } + case MGOBJ_BIOMEMAP: { + if (!mg->biomemap) + return 0; + + lua_newtable(L); + for (size_t i = 0; i != maplen; i++) { + lua_pushinteger(L, mg->biomemap[i]); + lua_rawseti(L, -2, i + 1); } - case MGOBJ_BIOMEMAP: { - if (!mg->biomemap) - return 0; - lua_newtable(L); - for (size_t i = 0; i != maplen; i++) { - lua_pushinteger(L, mg->biomemap[i]); - lua_rawseti(L, -2, i + 1); - } - - return 1; + return 1; + } + case MGOBJ_HEATMAP: { + if (!mg->heatmap) + return 0; + + lua_newtable(L); + for (size_t i = 0; i != maplen; i++) { + lua_pushnumber(L, mg->heatmap[i]); + lua_rawseti(L, -2, i + 1); } - case MGOBJ_HEATMAP: { // Mapgen V7 specific objects - case MGOBJ_HUMIDMAP: - if (strcmp(emerge->params.mg_name.c_str(), "v7")) - return 0; - - MapgenV7 *mgv7 = (MapgenV7 *)mg; - float *arr = (mgobj == MGOBJ_HEATMAP) ? - mgv7->noise_heat->result : mgv7->noise_humidity->result; - if (!arr) - return 0; + return 1; + } - lua_newtable(L); - for (size_t i = 0; i != maplen; i++) { - lua_pushnumber(L, arr[i]); - lua_rawseti(L, -2, i + 1); - } + case MGOBJ_HUMIDMAP: { + if (!mg->humidmap) + return 0; - return 1; + lua_newtable(L); + for (size_t i = 0; i != maplen; i++) { + lua_pushnumber(L, mg->humidmap[i]); + lua_rawseti(L, -2, i + 1); } - case MGOBJ_GENNOTIFY: { - std::map<std::string, std::vector<v3s16> >event_map; - std::map<std::string, std::vector<v3s16> >::iterator it; - mg->gennotify.getEvents(event_map); + return 1; + } + case MGOBJ_GENNOTIFY: { + std::map<std::string, std::vector<v3s16> >event_map; + std::map<std::string, std::vector<v3s16> >::iterator it; - lua_newtable(L); - for (it = event_map.begin(); it != event_map.end(); ++it) { - lua_newtable(L); + mg->gennotify.getEvents(event_map); - for (size_t j = 0; j != it->second.size(); j++) { - push_v3s16(L, it->second[j]); - lua_rawseti(L, -2, j + 1); - } + lua_newtable(L); + for (it = event_map.begin(); it != event_map.end(); ++it) { + lua_newtable(L); - lua_setfield(L, -2, it->first.c_str()); + for (size_t j = 0; j != it->second.size(); j++) { + push_v3s16(L, it->second[j]); + lua_rawseti(L, -2, j + 1); } - return 1; + lua_setfield(L, -2, it->first.c_str()); } + + return 1; + } } return 0; } + int ModApiMapgen::l_get_mapgen_params(lua_State *L) { MapgenParams *params = &getServer(L)->getEmergeManager()->params; @@ -350,6 +586,7 @@ int ModApiMapgen::l_get_mapgen_params(lua_State *L) return 1; } + // set_mapgen_params(params) // set mapgen parameters int ModApiMapgen::l_set_mapgen_params(lua_State *L) @@ -389,6 +626,7 @@ int ModApiMapgen::l_set_mapgen_params(lua_State *L) return 0; } + // set_noiseparams(name, noiseparams, set_default) // set global config values for noise parameters int ModApiMapgen::l_set_noiseparams(lua_State *L) @@ -406,6 +644,21 @@ int ModApiMapgen::l_set_noiseparams(lua_State *L) return 0; } + +// get_noiseparams(name) +int ModApiMapgen::l_get_noiseparams(lua_State *L) +{ + std::string name = luaL_checkstring(L, 1); + + NoiseParams np; + if (!g_settings->getNoiseParams(name, np)) + return 0; + + push_noiseparams(L, &np); + return 1; +} + + // set_gen_notify(flags, {deco_id_table}) int ModApiMapgen::l_set_gen_notify(lua_State *L) { @@ -421,7 +674,7 @@ int ModApiMapgen::l_set_gen_notify(lua_State *L) lua_pushnil(L); while (lua_next(L, 2)) { if (lua_isnumber(L, -1)) - emerge->gen_notify_on_deco_ids.insert(lua_tonumber(L, -1)); + emerge->gen_notify_on_deco_ids.insert((u32)lua_tonumber(L, -1)); lua_pop(L, 1); } } @@ -429,6 +682,26 @@ int ModApiMapgen::l_set_gen_notify(lua_State *L) return 0; } + +// get_gen_notify() +int ModApiMapgen::l_get_gen_notify(lua_State *L) +{ + EmergeManager *emerge = getServer(L)->getEmergeManager(); + push_flags_string(L, flagdesc_gennotify, emerge->gen_notify_on, + emerge->gen_notify_on); + + lua_newtable(L); + int i = 1; + for (std::set<u32>::iterator it = emerge->gen_notify_on_deco_ids.begin(); + it != emerge->gen_notify_on_deco_ids.end(); ++it) { + lua_pushnumber(L, *it); + lua_rawseti(L, -2, i); + i++; + } + return 2; +} + + // register_biome({lots of stuff}) int ModApiMapgen::l_register_biome(lua_State *L) { @@ -438,66 +711,20 @@ int ModApiMapgen::l_register_biome(lua_State *L) INodeDefManager *ndef = getServer(L)->getNodeDefManager(); BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr; - enum BiomeType biometype = (BiomeType)getenumfield(L, index, "type", - es_BiomeTerrainType, BIOME_TYPE_NORMAL); - Biome *b = bmgr->create(biometype); - - b->name = getstringfield_default(L, index, "name", ""); - b->depth_top = getintfield_default(L, index, "depth_top", 1); - b->depth_filler = getintfield_default(L, index, "depth_filler", 3); - b->height_shore = getintfield_default(L, index, "height_shore", 3); - b->depth_water_top = getintfield_default(L, index, "depth_water_top", 0); - b->y_min = getintfield_default(L, index, "y_min", -31000); - b->y_max = getintfield_default(L, index, "y_max", 31000); - b->heat_point = getfloatfield_default(L, index, "heat_point", 0.f); - b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.f); - b->flags = 0; //reserved + Biome *biome = read_biome_def(L, index, ndef); + if (!biome) + return 0; - u32 id = bmgr->add(b); - if (id == (u32)-1) { - delete b; + ObjDefHandle handle = bmgr->add(biome); + if (handle == OBJDEF_INVALID_HANDLE) { + delete biome; return 0; } - NodeResolveInfo *nri = new NodeResolveInfo(b); - std::list<std::string> &nnames = nri->nodenames; - nnames.push_back(getstringfield_default(L, index, "node_top", "")); - nnames.push_back(getstringfield_default(L, index, "node_filler", "")); - nnames.push_back(getstringfield_default(L, index, "node_shore_top", "")); - nnames.push_back(getstringfield_default(L, index, "node_shore_filler", "")); - nnames.push_back(getstringfield_default(L, index, "node_underwater", "")); - nnames.push_back(getstringfield_default(L, index, "node_stone", "")); - nnames.push_back(getstringfield_default(L, index, "node_water_top", "")); - nnames.push_back(getstringfield_default(L, index, "node_water", "")); - nnames.push_back(getstringfield_default(L, index, "node_dust", "")); - ndef->pendNodeResolve(nri); - - verbosestream << "register_biome: " << b->name << std::endl; - - lua_pushinteger(L, id); + lua_pushinteger(L, handle); return 1; } -int ModApiMapgen::l_clear_registered_biomes(lua_State *L) -{ - BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr; - bmgr->clear(); - return 0; -} - -int ModApiMapgen::l_clear_registered_decorations(lua_State *L) -{ - DecorationManager *dmgr = getServer(L)->getEmergeManager()->decomgr; - dmgr->clear(); - return 0; -} - -int ModApiMapgen::l_clear_registered_ores(lua_State *L) -{ - OreManager *omgr = getServer(L)->getEmergeManager()->oremgr; - omgr->clear(); - return 0; -} // register_decoration({lots of stuff}) int ModApiMapgen::l_register_decoration(lua_State *L) @@ -508,6 +735,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L) INodeDefManager *ndef = getServer(L)->getNodeDefManager(); DecorationManager *decomgr = getServer(L)->getEmergeManager()->decomgr; BiomeManager *biomemgr = getServer(L)->getEmergeManager()->biomemgr; + SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr; enum DecorationType decotype = (DecorationType)getenumfield(L, index, "deco_type", es_DecorationType, -1); @@ -515,7 +743,7 @@ int ModApiMapgen::l_register_decoration(lua_State *L) Decoration *deco = decomgr->create(decotype); if (!deco) { errorstream << "register_decoration: decoration placement type " - << decotype << " not implemented"; + << decotype << " not implemented" << std::endl; return 0; } @@ -531,15 +759,11 @@ int ModApiMapgen::l_register_decoration(lua_State *L) return 0; } - NodeResolveInfo *nri = new NodeResolveInfo(deco); - //// Get node name(s) to place decoration on - std::vector<const char *> place_on_names; - getstringlistfield(L, index, "place_on", place_on_names); - nri->nodelistinfo.push_back(NodeListInfo(place_on_names.size())); - for (size_t i = 0; i != place_on_names.size(); i++) - nri->nodenames.push_back(place_on_names[i]); + size_t nread = getstringlistfield(L, index, "place_on", &deco->m_nodenames); + deco->m_nnlistsizes.push_back(nread); + //// Get decoration flags getflagsfield(L, index, "flags", flagdesc_deco, &deco->flags, NULL); //// Get NoiseParams to define how decoration is placed @@ -549,51 +773,45 @@ int ModApiMapgen::l_register_decoration(lua_State *L) lua_pop(L, 1); //// Get biomes associated with this decoration (if any) - std::vector<const char *> biome_list; - getstringlistfield(L, index, "biomes", biome_list); - for (size_t i = 0; i != biome_list.size(); i++) { - Biome *b = (Biome *)biomemgr->getByName(biome_list[i]); - if (!b) - continue; - - deco->biomes.insert(b->id); - } + lua_getfield(L, index, "biomes"); + if (get_biome_list(L, -1, biomemgr, &deco->biomes)) + errorstream << "register_decoration: couldn't get all biomes " << std::endl; + lua_pop(L, 1); //// Handle decoration type-specific parameters bool success = false; switch (decotype) { - case DECO_SIMPLE: - success = regDecoSimple(L, nri, (DecoSimple *)deco); - break; - case DECO_SCHEMATIC: - success = regDecoSchematic(L, ndef, (DecoSchematic *)deco); - break; - case DECO_LSYSTEM: - break; + case DECO_SIMPLE: + success = read_deco_simple(L, (DecoSimple *)deco); + break; + case DECO_SCHEMATIC: + success = read_deco_schematic(L, schemmgr, (DecoSchematic *)deco); + break; + case DECO_LSYSTEM: + break; } - ndef->pendNodeResolve(nri); - if (!success) { delete deco; return 0; } - u32 id = decomgr->add(deco); - if (id == (u32)-1) { + ndef->pendNodeResolve(deco); + + ObjDefHandle handle = decomgr->add(deco); + if (handle == OBJDEF_INVALID_HANDLE) { delete deco; return 0; } - verbosestream << "register_decoration: " << deco->name << std::endl; - - lua_pushinteger(L, id); + lua_pushinteger(L, handle); return 1; } -bool ModApiMapgen::regDecoSimple(lua_State *L, - NodeResolveInfo *nri, DecoSimple *deco) + +bool read_deco_simple(lua_State *L, DecoSimple *deco) { + size_t nnames; int index = 1; deco->deco_height = getintfield_default(L, index, "height", 1); @@ -606,60 +824,48 @@ bool ModApiMapgen::regDecoSimple(lua_State *L, return false; } - std::vector<const char *> deco_names; - getstringlistfield(L, index, "decoration", deco_names); - if (deco_names.size() == 0) { + nnames = getstringlistfield(L, index, "decoration", &deco->m_nodenames); + deco->m_nnlistsizes.push_back(nnames); + if (nnames == 0) { errorstream << "register_decoration: no decoration nodes " "defined" << std::endl; return false; } - nri->nodelistinfo.push_back(NodeListInfo(deco_names.size())); - for (size_t i = 0; i != deco_names.size(); i++) - nri->nodenames.push_back(deco_names[i]); - std::vector<const char *> spawnby_names; - getstringlistfield(L, index, "spawn_by", spawnby_names); - if (deco->nspawnby != -1 && spawnby_names.size() == 0) { + nnames = getstringlistfield(L, index, "spawn_by", &deco->m_nodenames); + deco->m_nnlistsizes.push_back(nnames); + if (nnames == 0 && deco->nspawnby != -1) { errorstream << "register_decoration: no spawn_by nodes defined," " but num_spawn_by specified" << std::endl; return false; } - nri->nodelistinfo.push_back(NodeListInfo(spawnby_names.size())); - for (size_t i = 0; i != spawnby_names.size(); i++) - nri->nodenames.push_back(spawnby_names[i]); return true; } -bool ModApiMapgen::regDecoSchematic(lua_State *L, INodeDefManager *ndef, - DecoSchematic *deco) + +bool read_deco_schematic(lua_State *L, SchematicManager *schemmgr, DecoSchematic *deco) { int index = 1; deco->rotation = (Rotation)getenumfield(L, index, "rotation", - es_Rotation, ROTATE_0); + ModApiMapgen::es_Rotation, ROTATE_0); - std::map<std::string, std::string> replace_names; + StringMap replace_names; lua_getfield(L, index, "replacements"); if (lua_istable(L, -1)) - read_schematic_replacements(L, replace_names, lua_gettop(L)); + read_schematic_replacements(L, -1, &replace_names); lua_pop(L, 1); - // TODO(hmmmm): get a ref from registered schematics - Schematic *schem = new Schematic; lua_getfield(L, index, "schematic"); - if (!get_schematic(L, -1, schem, ndef, replace_names)) { - lua_pop(L, 1); - delete schem; - return false; - } + Schematic *schem = get_or_load_schematic(L, -1, schemmgr, &replace_names); lua_pop(L, 1); deco->schematic = schem; - - return true; + return schem != NULL; } + // register_ore({lots of stuff}) int ModApiMapgen::l_register_ore(lua_State *L) { @@ -667,10 +873,11 @@ int ModApiMapgen::l_register_ore(lua_State *L) luaL_checktype(L, index, LUA_TTABLE); INodeDefManager *ndef = getServer(L)->getNodeDefManager(); + BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr; OreManager *oremgr = getServer(L)->getEmergeManager()->oremgr; enum OreType oretype = (OreType)getenumfield(L, index, - "ore_type", es_OreType, ORE_TYPE_SCATTER); + "ore_type", es_OreType, ORE_SCATTER); Ore *ore = oremgr->create(oretype); if (!ore) { errorstream << "register_ore: ore_type " << oretype << " not implemented"; @@ -686,6 +893,7 @@ int ModApiMapgen::l_register_ore(lua_State *L) ore->noise = NULL; ore->flags = 0; + //// Get y_min/y_max warn_if_field_exists(L, index, "height_min", "Deprecated: new name is \"y_min\"."); warn_if_field_exists(L, index, "height_max", @@ -708,8 +916,16 @@ int ModApiMapgen::l_register_ore(lua_State *L) return 0; } + //// Get flags getflagsfield(L, index, "flags", flagdesc_ore, &ore->flags, NULL); + //// Get biomes associated with this decoration (if any) + lua_getfield(L, index, "biomes"); + if (get_biome_list(L, -1, bmgr, &ore->biomes)) + errorstream << "register_ore: couldn't get all biomes " << std::endl; + lua_pop(L, 1); + + //// Get noise parameters if needed lua_getfield(L, index, "noise_params"); if (read_noiseparams(L, -1, &ore->np)) { ore->flags |= OREFLAG_USE_NOISE; @@ -721,45 +937,152 @@ int ModApiMapgen::l_register_ore(lua_State *L) } lua_pop(L, 1); - if (oretype == ORE_TYPE_VEIN) { + if (oretype == ORE_VEIN) { OreVein *orevein = (OreVein *)ore; orevein->random_factor = getfloatfield_default(L, index, "random_factor", 1.f); } - u32 id = oremgr->add(ore); - if (id == (u32)-1) { + ObjDefHandle handle = oremgr->add(ore); + if (handle == OBJDEF_INVALID_HANDLE) { delete ore; return 0; } - NodeResolveInfo *nri = new NodeResolveInfo(ore); - nri->nodenames.push_back(getstringfield_default(L, index, "ore", "")); + ore->m_nodenames.push_back(getstringfield_default(L, index, "ore", "")); + + size_t nnames = getstringlistfield(L, index, "wherein", &ore->m_nodenames); + ore->m_nnlistsizes.push_back(nnames); + + ndef->pendNodeResolve(ore); + + lua_pushinteger(L, handle); + return 1; +} + - std::vector<const char *> wherein_names; - getstringlistfield(L, index, "wherein", wherein_names); - nri->nodelistinfo.push_back(NodeListInfo(wherein_names.size())); - for (size_t i = 0; i != wherein_names.size(); i++) - nri->nodenames.push_back(wherein_names[i]); +// register_schematic({schematic}, replacements={}) +int ModApiMapgen::l_register_schematic(lua_State *L) +{ + SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr; + + StringMap replace_names; + if (lua_istable(L, 2)) + read_schematic_replacements(L, 2, &replace_names); - ndef->pendNodeResolve(nri); + Schematic *schem = load_schematic(L, 1, schemmgr->getNodeDef(), + &replace_names); + if (!schem) + return 0; - verbosestream << "register_ore: " << ore->name << std::endl; + ObjDefHandle handle = schemmgr->add(schem); + if (handle == OBJDEF_INVALID_HANDLE) { + delete schem; + return 0; + } - lua_pushinteger(L, id); + lua_pushinteger(L, handle); return 1; } -// create_schematic(p1, p2, probability_list, filename) + +// clear_registered_biomes() +int ModApiMapgen::l_clear_registered_biomes(lua_State *L) +{ + BiomeManager *bmgr = getServer(L)->getEmergeManager()->biomemgr; + bmgr->clear(); + return 0; +} + + +// clear_registered_decorations() +int ModApiMapgen::l_clear_registered_decorations(lua_State *L) +{ + DecorationManager *dmgr = getServer(L)->getEmergeManager()->decomgr; + dmgr->clear(); + return 0; +} + + +// clear_registered_ores() +int ModApiMapgen::l_clear_registered_ores(lua_State *L) +{ + OreManager *omgr = getServer(L)->getEmergeManager()->oremgr; + omgr->clear(); + return 0; +} + + +// clear_registered_schematics() +int ModApiMapgen::l_clear_registered_schematics(lua_State *L) +{ + SchematicManager *smgr = getServer(L)->getEmergeManager()->schemmgr; + smgr->clear(); + return 0; +} + + +// generate_ores(vm, p1, p2, [ore_id]) +int ModApiMapgen::l_generate_ores(lua_State *L) +{ + EmergeManager *emerge = getServer(L)->getEmergeManager(); + + Mapgen mg; + mg.seed = emerge->params.seed; + mg.vm = LuaVoxelManip::checkobject(L, 1)->vm; + mg.ndef = getServer(L)->getNodeDefManager(); + + v3s16 pmin = lua_istable(L, 2) ? check_v3s16(L, 2) : + mg.vm->m_area.MinEdge + v3s16(1,1,1) * MAP_BLOCKSIZE; + v3s16 pmax = lua_istable(L, 3) ? check_v3s16(L, 3) : + mg.vm->m_area.MaxEdge - v3s16(1,1,1) * MAP_BLOCKSIZE; + sortBoxVerticies(pmin, pmax); + + u32 blockseed = Mapgen::getBlockSeed(pmin, mg.seed); + + emerge->oremgr->placeAllOres(&mg, blockseed, pmin, pmax); + + return 0; +} + + +// generate_decorations(vm, p1, p2, [deco_id]) +int ModApiMapgen::l_generate_decorations(lua_State *L) +{ + EmergeManager *emerge = getServer(L)->getEmergeManager(); + + Mapgen mg; + mg.seed = emerge->params.seed; + mg.vm = LuaVoxelManip::checkobject(L, 1)->vm; + mg.ndef = getServer(L)->getNodeDefManager(); + + v3s16 pmin = lua_istable(L, 2) ? check_v3s16(L, 2) : + mg.vm->m_area.MinEdge + v3s16(1,1,1) * MAP_BLOCKSIZE; + v3s16 pmax = lua_istable(L, 3) ? check_v3s16(L, 3) : + mg.vm->m_area.MaxEdge - v3s16(1,1,1) * MAP_BLOCKSIZE; + sortBoxVerticies(pmin, pmax); + + u32 blockseed = Mapgen::getBlockSeed(pmin, mg.seed); + + emerge->decomgr->placeAllDecos(&mg, blockseed, pmin, pmax); + + return 0; +} + + +// create_schematic(p1, p2, probability_list, filename, y_slice_prob_list) int ModApiMapgen::l_create_schematic(lua_State *L) { - Schematic schem; + INodeDefManager *ndef = getServer(L)->getNodeDefManager(); + + const char *filename = luaL_checkstring(L, 4); + CHECK_SECURE_PATH_OPTIONAL(L, filename); Map *map = &(getEnv(L)->getMap()); - INodeDefManager *ndef = getServer(L)->getNodeDefManager(); + Schematic schem; - v3s16 p1 = read_v3s16(L, 1); - v3s16 p2 = read_v3s16(L, 2); + v3s16 p1 = check_v3s16(L, 1); + v3s16 p2 = check_v3s16(L, 2); sortBoxVerticies(p1, p2); std::vector<std::pair<v3s16, u8> > prob_list; @@ -768,7 +1091,7 @@ int ModApiMapgen::l_create_schematic(lua_State *L) while (lua_next(L, 3)) { if (lua_istable(L, -1)) { lua_getfield(L, -1, "pos"); - v3s16 pos = read_v3s16(L, -1); + v3s16 pos = check_v3s16(L, -1); lua_pop(L, 1); u8 prob = getintfield_default(L, -1, "prob", MTSCHEM_PROB_ALWAYS); @@ -793,8 +1116,6 @@ int ModApiMapgen::l_create_schematic(lua_State *L) } } - const char *filename = luaL_checkstring(L, 4); - if (!schem.getSchematicFromMap(map, p1, p2)) { errorstream << "create_schematic: failed to get schematic " "from map" << std::endl; @@ -807,60 +1128,25 @@ int ModApiMapgen::l_create_schematic(lua_State *L) actionstream << "create_schematic: saved schematic file '" << filename << "'." << std::endl; + lua_pushboolean(L, true); return 1; } -// generate_ores(vm, [ore_id]) -int ModApiMapgen::l_generate_ores(lua_State *L) -{ - EmergeManager *emerge = getServer(L)->getEmergeManager(); - - Mapgen mg; - mg.seed = emerge->params.seed; - mg.vm = LuaVoxelManip::checkobject(L, 1)->vm; - mg.ndef = getServer(L)->getNodeDefManager(); - - u32 blockseed = Mapgen::getBlockSeed(mg.vm->m_area.MinEdge, mg.seed); - - emerge->oremgr->placeAllOres(&mg, blockseed, - mg.vm->m_area.MinEdge, mg.vm->m_area.MaxEdge); - - return 0; -} - -// generate_decorations(vm, [deco_id]) -int ModApiMapgen::l_generate_decorations(lua_State *L) -{ - EmergeManager *emerge = getServer(L)->getEmergeManager(); - - Mapgen mg; - mg.seed = emerge->params.seed; - mg.vm = LuaVoxelManip::checkobject(L, 1)->vm; - mg.ndef = getServer(L)->getNodeDefManager(); - - u32 blockseed = Mapgen::getBlockSeed(mg.vm->m_area.MinEdge, mg.seed); - - emerge->decomgr->placeAllDecos(&mg, blockseed, - mg.vm->m_area.MinEdge, mg.vm->m_area.MaxEdge); - - return 0; -} // place_schematic(p, schematic, rotation, replacement) int ModApiMapgen::l_place_schematic(lua_State *L) { - Schematic schem; - Map *map = &(getEnv(L)->getMap()); - INodeDefManager *ndef = getServer(L)->getNodeDefManager(); + SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr; //// Read position - v3s16 p = read_v3s16(L, 1); + v3s16 p = check_v3s16(L, 1); //// Read rotation int rot = ROTATE_0; - if (lua_isstring(L, 3)) - string_to_enum(es_Rotation, rot, std::string(lua_tostring(L, 3))); + const char *enumstr = lua_tostring(L, 3); + if (enumstr) + string_to_enum(es_Rotation, rot, std::string(enumstr)); //// Read force placement bool force_placement = true; @@ -868,21 +1154,73 @@ int ModApiMapgen::l_place_schematic(lua_State *L) force_placement = lua_toboolean(L, 5); //// Read node replacements - std::map<std::string, std::string> replace_names; + StringMap replace_names; if (lua_istable(L, 4)) - read_schematic_replacements(L, replace_names, 4); + read_schematic_replacements(L, 4, &replace_names); //// Read schematic - if (!get_schematic(L, 2, &schem, ndef, replace_names)) { + Schematic *schem = get_or_load_schematic(L, 2, schemmgr, &replace_names); + if (!schem) { errorstream << "place_schematic: failed to get schematic" << std::endl; return 0; } - schem.placeStructure(map, p, 0, (Rotation)rot, force_placement, ndef); + schem->placeStructure(map, p, 0, (Rotation)rot, force_placement); + + lua_pushboolean(L, true); + return 1; +} + +// serialize_schematic(schematic, format, options={...}) +int ModApiMapgen::l_serialize_schematic(lua_State *L) +{ + SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr; + + //// Read options + bool use_comments = getboolfield_default(L, 3, "lua_use_comments", false); + u32 indent_spaces = getintfield_default(L, 3, "lua_num_indent_spaces", 0); + + //// 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 << "serialize_schematic: failed to get schematic" << std::endl; + return 0; + } + + //// Read format of definition to save as + int schem_format = SCHEM_FMT_MTS; + const char *enumstr = lua_tostring(L, 2); + if (enumstr) + string_to_enum(es_SchematicFormatType, schem_format, std::string(enumstr)); + + //// Serialize to binary string + std::ostringstream os(std::ios_base::binary); + switch (schem_format) { + case SCHEM_FMT_MTS: + schem->serializeToMts(&os, schem->m_nodenames); + break; + case SCHEM_FMT_LUA: + schem->serializeToLua(&os, schem->m_nodenames, + use_comments, indent_spaces); + break; + default: + return 0; + } + + if (was_loaded) + delete schem; + std::string ser = os.str(); + lua_pushlstring(L, ser.c_str(), ser.length()); return 1; } + void ModApiMapgen::Initialize(lua_State *L, int top) { API_FCT(get_mapgen_object); @@ -890,19 +1228,23 @@ void ModApiMapgen::Initialize(lua_State *L, int top) API_FCT(get_mapgen_params); API_FCT(set_mapgen_params); API_FCT(set_noiseparams); + API_FCT(get_noiseparams); API_FCT(set_gen_notify); + API_FCT(get_gen_notify); API_FCT(register_biome); API_FCT(register_decoration); API_FCT(register_ore); + API_FCT(register_schematic); API_FCT(clear_registered_biomes); API_FCT(clear_registered_decorations); API_FCT(clear_registered_ores); + API_FCT(clear_registered_schematics); API_FCT(generate_ores); API_FCT(generate_decorations); - API_FCT(create_schematic); API_FCT(place_schematic); + API_FCT(serialize_schematic); } |