diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 1431181f1..19d4f1672 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -419,6 +419,11 @@ the global `minetest.registered_*` tables. * `minetest.register_craftitem(name, item definition)` * added to `minetest.registered_items[name]` +* `minetest.register_biome(biome definition)` + * returns an integer uniquely identifying the registered biome + * added to `minetest.registered_biome` with the key of `biome.name` + * if `biome.name` is nil, the key is the returned ID + * `minetest.register_ore(ore definition)` * returns an integer uniquely identifying the registered ore * added to `minetest.registered_ores` with the key of `ore.name` @@ -429,11 +434,23 @@ the global `minetest.registered_*` tables. * added to `minetest.registered_decorations` with the key of `decoration.name` * if `decoration.name` is nil, the key is the returned ID +* `minetest.register_schematic(schematic definition)` + * returns an integer uniquely identifying the registered schematic + * added to `minetest.registered_schematic` with the key of `schematic.name` + * if `schematic.name` is nil, the key is the returned ID + * if the schematic is loaded from a file, schematic.name is set to the filename + +* `minetest.clear_registered_biomes()` + * clears all biomes currently registered + * `minetest.clear_registered_ores()` - * clears all ores currently registered + * clears all ores currently registered * `minetest.clear_registered_decorations()` - * clears all decorations currently registered + * clears all decorations currently registered + +* `minetest.clear_registered_schematics()` + * clears all schematics currently registered Note that in some cases you will stumble upon things that are not contained in these tables (e.g. when a mod has been removed). Always check for diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 851f018ee..fcde5bdb8 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -36,11 +36,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "treegen.h" #include "serialization.h" #include "util/serialize.h" +#include "util/numeric.h" #include "filesys.h" #include "log.h" -const char *GenElementManager::ELEMENT_TITLE = "element"; - FlagDesc flagdesc_mapgen[] = { {"trees", MG_TREES}, {"caves", MG_CAVES}, @@ -64,6 +63,7 @@ FlagDesc flagdesc_gennotify[] = { /////////////////////////////////////////////////////////////////////////////// + Mapgen::Mapgen() { generating = false; @@ -431,85 +431,162 @@ void GenerateNotifier::getEvents( /////////////////////////////////////////////////////////////////////////////// -GenElementManager::GenElementManager(IGameDef *gamedef) +ObjDefManager::ObjDefManager(IGameDef *gamedef, ObjDefType type) { + m_objtype = type; m_ndef = gamedef->getNodeDefManager(); } -GenElementManager::~GenElementManager() +ObjDefManager::~ObjDefManager() { - for (size_t i = 0; i != m_elements.size(); i++) - delete m_elements[i]; + for (size_t i = 0; i != m_objects.size(); i++) + delete m_objects[i]; } -u32 GenElementManager::add(GenElement *elem) +ObjDefHandle ObjDefManager::add(ObjDef *obj) { - size_t nelem = m_elements.size(); + assert(obj); - for (size_t i = 0; i != nelem; i++) { - if (m_elements[i] == NULL) { - elem->id = i; - m_elements[i] = elem; - return i; - } - } + if (obj->name.length() && getByName(obj->name)) + return OBJDEF_INVALID_HANDLE; - if (nelem >= this->ELEMENT_LIMIT) + u32 index = addRaw(obj); + if (index == OBJDEF_INVALID_INDEX) + return OBJDEF_INVALID_HANDLE; + + obj->handle = createHandle(index, m_objtype, obj->uid); + return obj->handle; +} + + +ObjDef *ObjDefManager::get(ObjDefHandle handle) const +{ + u32 index = validateHandle(handle); + return (index != OBJDEF_INVALID_INDEX) ? getRaw(index) : NULL; +} + + +ObjDef *ObjDefManager::set(ObjDefHandle handle, ObjDef *obj) +{ + u32 index = validateHandle(handle); + return (index != OBJDEF_INVALID_INDEX) ? setRaw(index, obj) : NULL; +} + + +u32 ObjDefManager::addRaw(ObjDef *obj) +{ + size_t nobjects = m_objects.size(); + if (nobjects >= OBJDEF_MAX_ITEMS) return -1; - elem->id = nelem; - m_elements.push_back(elem); + obj->index = nobjects; - verbosestream << "GenElementManager: added " << this->ELEMENT_TITLE - << " element '" << elem->name << "'" << std::endl; + // Ensure UID is nonzero so that a valid handle == OBJDEF_INVALID_HANDLE + // is not possible. The slight randomness bias isn't very significant. + obj->uid = myrand() & OBJDEF_UID_MASK; + if (obj->uid == 0) + obj->uid = 1; - return nelem; + m_objects.push_back(obj); + + infostream << "ObjDefManager: added " << getObjectTitle() + << ": name=\"" << obj->name + << "\" index=" << obj->index + << " uid=" << obj->uid + << std::endl; + + return nobjects; } -GenElement *GenElementManager::get(u32 id) +ObjDef *ObjDefManager::getRaw(u32 index) const { - return (id < m_elements.size()) ? m_elements[id] : NULL; + return m_objects[index]; } -GenElement *GenElementManager::getByName(const std::string &name) +ObjDef *ObjDefManager::setRaw(u32 index, ObjDef *obj) { - for (size_t i = 0; i != m_elements.size(); i++) { - GenElement *elem = m_elements[i]; - if (elem && name == elem->name) - return elem; + ObjDef *old_obj = m_objects[index]; + m_objects[index] = obj; + return old_obj; +} + + +ObjDef *ObjDefManager::getByName(const std::string &name) const +{ + for (size_t i = 0; i != m_objects.size(); i++) { + ObjDef *obj = m_objects[i]; + if (obj && !strcasecmp(name.c_str(), obj->name.c_str())) + return obj; } return NULL; } -GenElement *GenElementManager::update(u32 id, GenElement *elem) +void ObjDefManager::clear() { - if (id >= m_elements.size()) - return NULL; + for (size_t i = 0; i != m_objects.size(); i++) + delete m_objects[i]; - GenElement *old_elem = m_elements[id]; - m_elements[id] = elem; - return old_elem; + m_objects.clear(); } -GenElement *GenElementManager::remove(u32 id) +u32 ObjDefManager::validateHandle(ObjDefHandle handle) const { - return update(id, NULL); + ObjDefType type; + u32 index; + u32 uid; + + bool is_valid = + (handle != OBJDEF_INVALID_HANDLE) && + decodeHandle(handle, &index, &type, &uid) && + (type == m_objtype) && + (index < m_objects.size()) && + (m_objects[index]->uid == uid); + + return is_valid ? index : -1; } -void GenElementManager::clear() +ObjDefHandle ObjDefManager::createHandle(u32 index, ObjDefType type, u32 uid) { - m_elements.clear(); + ObjDefHandle handle = 0; + set_bits(&handle, 0, 18, index); + set_bits(&handle, 18, 6, type); + set_bits(&handle, 24, 7, uid); + + u32 parity = calc_parity(handle); + set_bits(&handle, 31, 1, parity); + + return handle ^ OBJDEF_HANDLE_SALT; } +bool ObjDefManager::decodeHandle(ObjDefHandle handle, u32 *index, + ObjDefType *type, u32 *uid) +{ + handle ^= OBJDEF_HANDLE_SALT; + + u32 parity = get_bits(handle, 31, 1); + set_bits(&handle, 31, 1, 0); + if (parity != calc_parity(handle)) + return false; + + *index = get_bits(handle, 0, 18); + *type = (ObjDefType)get_bits(handle, 18, 6); + *uid = get_bits(handle, 24, 7); + return true; +} + + +/////////////////////////////////////////////////////////////////////////////// + + void MapgenParams::load(const Settings &settings) { std::string seed_str; diff --git a/src/mapgen.h b/src/mapgen.h index 5b5ed19a2..59fe2fca7 100644 --- a/src/mapgen.h +++ b/src/mapgen.h @@ -179,36 +179,68 @@ struct MapgenFactory { virtual ~MapgenFactory() {} }; -class GenElement { +typedef std::map StringMap; +typedef u32 ObjDefHandle; + +#define OBJDEF_INVALID_INDEX ((u32)(-1)) +#define OBJDEF_INVALID_HANDLE 0 +#define OBJDEF_HANDLE_SALT 0x00585e6fu +#define OBJDEF_MAX_ITEMS (1 << 18) +#define OBJDEF_UID_MASK ((1 << 7) - 1) + +enum ObjDefType { + OBJDEF_GENERIC, + OBJDEF_BIOME, + OBJDEF_ORE, + OBJDEF_DECORATION, + OBJDEF_SCHEMATIC, +}; + +class ObjDef { public: - virtual ~GenElement() {} - u32 id; + virtual ~ObjDef() {} + + u32 index; + u32 uid; + ObjDefHandle handle; std::string name; }; -class GenElementManager { +class ObjDefManager { public: - static const char *ELEMENT_TITLE; - static const size_t ELEMENT_LIMIT = -1; + ObjDefManager(IGameDef *gamedef, ObjDefType type); + virtual ~ObjDefManager(); - GenElementManager(IGameDef *gamedef); - virtual ~GenElementManager(); + virtual const char *getObjectTitle() const = 0; - virtual GenElement *create(int type) = 0; - - virtual u32 add(GenElement *elem); - virtual GenElement *get(u32 id); - virtual GenElement *update(u32 id, GenElement *elem); - virtual GenElement *remove(u32 id); + virtual ObjDef *create(int type) = 0; virtual void clear(); + virtual ObjDef *getByName(const std::string &name) const; - virtual GenElement *getByName(const std::string &name); + //// Add new/get/set object definitions by handle + virtual ObjDefHandle add(ObjDef *obj); + virtual ObjDef *get(ObjDefHandle handle) const; + virtual ObjDef *set(ObjDefHandle handle, ObjDef *obj); - INodeDefManager *getNodeDef() { return m_ndef; } + //// Raw variants that work on indexes + virtual u32 addRaw(ObjDef *obj); + + // It is generally assumed that getRaw() will always return a valid object + // This won't be true if people do odd things such as call setRaw() with NULL + virtual ObjDef *getRaw(u32 index) const; + virtual ObjDef *setRaw(u32 index, ObjDef *obj); + + INodeDefManager *getNodeDef() const { return m_ndef; } + + u32 validateHandle(ObjDefHandle handle) const; + static ObjDefHandle createHandle(u32 index, ObjDefType type, u32 uid); + static bool decodeHandle(ObjDefHandle handle, u32 *index, + ObjDefType *type, u32 *uid); protected: INodeDefManager *m_ndef; - std::vector m_elements; + std::vector m_objects; + ObjDefType m_objtype; }; #endif diff --git a/src/mapgen_v5.cpp b/src/mapgen_v5.cpp index 240ae500a..7d74c80bd 100644 --- a/src/mapgen_v5.cpp +++ b/src/mapgen_v5.cpp @@ -479,7 +479,7 @@ void MapgenV5::generateCaves(int max_stone_y) for (s16 y=node_min.Y - 1; y<=node_max.Y + 1; y++) { u32 i = vm->m_area.index(node_min.X, y, z); for (s16 x=node_min.X; x<=node_max.X; x++, i++, index++, index2d++) { - Biome *biome = (Biome *)bmgr->get(biomemap[index2d]); + Biome *biome = (Biome *)bmgr->getRaw(biomemap[index2d]); content_t c = vm->m_data[i].getContent(); if (c == CONTENT_AIR || (y <= water_level @@ -519,7 +519,7 @@ void MapgenV5::dustTopNodes() for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index++) { - Biome *biome = (Biome *)bmgr->get(biomemap[index]); + Biome *biome = (Biome *)bmgr->getRaw(biomemap[index]); if (biome->c_dust == CONTENT_IGNORE) continue; diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp index 44cb37f11..3e7188a2c 100644 --- a/src/mapgen_v7.cpp +++ b/src/mapgen_v7.cpp @@ -674,7 +674,7 @@ void MapgenV7::dustTopNodes() for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 x = node_min.X; x <= node_max.X; x++, index++) { - Biome *biome = (Biome *)bmgr->get(biomemap[index]); + Biome *biome = (Biome *)bmgr->getRaw(biomemap[index]); if (biome->c_dust == CONTENT_IGNORE) continue; @@ -821,7 +821,7 @@ void MapgenV7::generateCaves(int max_stone_y) u32 i = vm->m_area.index(node_min.X, y, z); for (s16 x = node_min.X; x <= node_max.X; x++, i++, index++, index2d++) { - Biome *biome = (Biome *)bmgr->get(biomemap[index2d]); + Biome *biome = (Biome *)bmgr->getRaw(biomemap[index2d]); content_t c = vm->m_data[i].getContent(); if (c == CONTENT_AIR || (y <= water_level && c != biome->c_stone && c != c_stone)) diff --git a/src/mg_biome.cpp b/src/mg_biome.cpp index e076d3092..a8b150e53 100644 --- a/src/mg_biome.cpp +++ b/src/mg_biome.cpp @@ -27,18 +27,16 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/mathconstants.h" #include "porting.h" -const char *BiomeManager::ELEMENT_TITLE = "biome"; - /////////////////////////////////////////////////////////////////////////////// + BiomeManager::BiomeManager(IGameDef *gamedef) : - GenElementManager(gamedef) + ObjDefManager(gamedef, OBJDEF_BIOME) { // Create default biome to be used in case none exist Biome *b = new Biome; - b->id = 0; b->name = "Default"; b->flags = 0; b->depth_top = 0; @@ -75,8 +73,10 @@ BiomeManager::~BiomeManager() void BiomeManager::calcBiomes(s16 sx, s16 sy, float *heat_map, float *humidity_map, s16 *height_map, u8 *biomeid_map) { - for (s32 i = 0; i != sx * sy; i++) - biomeid_map[i] = getBiome(heat_map[i], humidity_map[i], height_map[i])->id; + for (s32 i = 0; i != sx * sy; i++) { + Biome *biome = getBiome(heat_map[i], humidity_map[i], height_map[i]); + biomeid_map[i] = biome->index; + } } @@ -85,8 +85,8 @@ Biome *BiomeManager::getBiome(float heat, float humidity, s16 y) Biome *b, *biome_closest = NULL; float dist_min = FLT_MAX; - for (size_t i = 1; i < m_elements.size(); i++) { - b = (Biome *)m_elements[i]; + for (size_t i = 1; i < m_objects.size(); i++) { + b = (Biome *)m_objects[i]; if (!b || y > b->y_max || y < b->y_min) continue; @@ -100,18 +100,18 @@ Biome *BiomeManager::getBiome(float heat, float humidity, s16 y) } } - return biome_closest ? biome_closest : (Biome *)m_elements[0]; + return biome_closest ? biome_closest : (Biome *)m_objects[0]; } void BiomeManager::clear() { - for (size_t i = 1; i < m_elements.size(); i++) { - Biome *b = (Biome *)m_elements[i]; + for (size_t i = 1; i < m_objects.size(); i++) { + Biome *b = (Biome *)m_objects[i]; delete b; } - m_elements.resize(1); + m_objects.resize(1); } diff --git a/src/mg_biome.h b/src/mg_biome.h index 3648c085d..4e7e3fd7e 100644 --- a/src/mg_biome.h +++ b/src/mg_biome.h @@ -33,7 +33,7 @@ enum BiomeType BIOME_TYPE_FLAT }; -class Biome : public GenElement, public NodeResolver { +class Biome : public ObjDef, public NodeResolver { public: u32 flags; @@ -56,14 +56,18 @@ public: virtual void resolveNodeNames(NodeResolveInfo *nri); }; -class BiomeManager : public GenElementManager { +class BiomeManager : public ObjDefManager { public: - static const char *ELEMENT_TITLE; - static const size_t ELEMENT_LIMIT = 0x100; + static const char *OBJECT_TITLE; BiomeManager(IGameDef *gamedef); ~BiomeManager(); + const char *getObjectTitle() const + { + return "biome"; + } + Biome *create(int btt) { return new Biome; diff --git a/src/mg_decoration.cpp b/src/mg_decoration.cpp index 23bbfa730..1858e346a 100644 --- a/src/mg_decoration.cpp +++ b/src/mg_decoration.cpp @@ -25,8 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "util/numeric.h" -const char *DecorationManager::ELEMENT_TITLE = "decoration"; - FlagDesc flagdesc_deco[] = { {"place_center_x", DECO_PLACE_CENTER_X}, {"place_center_y", DECO_PLACE_CENTER_Y}, @@ -40,7 +38,7 @@ FlagDesc flagdesc_deco[] = { DecorationManager::DecorationManager(IGameDef *gamedef) : - GenElementManager(gamedef) + ObjDefManager(gamedef, OBJDEF_DECORATION) { } @@ -50,8 +48,8 @@ size_t DecorationManager::placeAllDecos(Mapgen *mg, u32 blockseed, { size_t nplaced = 0; - for (size_t i = 0; i != m_elements.size(); i++) { - Decoration *deco = (Decoration *)m_elements[i]; + for (size_t i = 0; i != m_objects.size(); i++) { + Decoration *deco = (Decoration *)m_objects[i]; if (!deco) continue; @@ -65,11 +63,11 @@ size_t DecorationManager::placeAllDecos(Mapgen *mg, u32 blockseed, void DecorationManager::clear() { - for (size_t i = 0; i < m_elements.size(); i++) { - Decoration *deco = (Decoration *)m_elements[i]; + for (size_t i = 0; i < m_objects.size(); i++) { + Decoration *deco = (Decoration *)m_objects[i]; delete deco; } - m_elements.clear(); + m_objects.clear(); } @@ -169,7 +167,7 @@ size_t Decoration::placeDeco(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nmax) v3s16 pos(x, y, z); if (generate(mg->vm, &ps, pos)) - mg->gennotify.addEvent(GENNOTIFY_DECORATION, pos, id); + mg->gennotify.addEvent(GENNOTIFY_DECORATION, pos, index); } } diff --git a/src/mg_decoration.h b/src/mg_decoration.h index 20a22d449..3b809b8d4 100644 --- a/src/mg_decoration.h +++ b/src/mg_decoration.h @@ -59,7 +59,7 @@ struct CutoffData { }; #endif -class Decoration : public GenElement, public NodeResolver { +class Decoration : public ObjDef, public NodeResolver { public: INodeDefManager *ndef; @@ -121,14 +121,16 @@ public: }; */ -class DecorationManager : public GenElementManager { +class DecorationManager : public ObjDefManager { public: - static const char *ELEMENT_TITLE; - static const size_t ELEMENT_LIMIT = 0x10000; - DecorationManager(IGameDef *gamedef); ~DecorationManager() {} + const char *getObjectTitle() const + { + return "decoration"; + } + Decoration *create(int type) { switch (type) { diff --git a/src/mg_ore.cpp b/src/mg_ore.cpp index 850f25516..e7e062c69 100644 --- a/src/mg_ore.cpp +++ b/src/mg_ore.cpp @@ -24,8 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "map.h" #include "log.h" -const char *OreManager::ELEMENT_TITLE = "ore"; - FlagDesc flagdesc_ore[] = { {"absheight", OREFLAG_ABSHEIGHT}, {NULL, 0} @@ -36,7 +34,7 @@ FlagDesc flagdesc_ore[] = { OreManager::OreManager(IGameDef *gamedef) : - GenElementManager(gamedef) + ObjDefManager(gamedef, OBJDEF_ORE) { } @@ -45,8 +43,8 @@ size_t OreManager::placeAllOres(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nma { size_t nplaced = 0; - for (size_t i = 0; i != m_elements.size(); i++) { - Ore *ore = (Ore *)m_elements[i]; + for (size_t i = 0; i != m_objects.size(); i++) { + Ore *ore = (Ore *)m_objects[i]; if (!ore) continue; @@ -60,11 +58,11 @@ size_t OreManager::placeAllOres(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nma void OreManager::clear() { - for (size_t i = 0; i < m_elements.size(); i++) { - Ore *ore = (Ore *)m_elements[i]; + for (size_t i = 0; i < m_objects.size(); i++) { + Ore *ore = (Ore *)m_objects[i]; delete ore; } - m_elements.clear(); + m_objects.clear(); } diff --git a/src/mg_ore.h b/src/mg_ore.h index 67ca9a849..978b8ae3d 100644 --- a/src/mg_ore.h +++ b/src/mg_ore.h @@ -47,7 +47,7 @@ enum OreType { extern FlagDesc flagdesc_ore[]; -class Ore : public GenElement, public NodeResolver { +class Ore : public ObjDef, public NodeResolver { public: static const bool NEEDS_NOISE = false; @@ -112,14 +112,16 @@ public: v3s16 nmin, v3s16 nmax); }; -class OreManager : public GenElementManager { +class OreManager : public ObjDefManager { public: - static const char *ELEMENT_TITLE; - static const size_t ELEMENT_LIMIT = 0x10000; - OreManager(IGameDef *gamedef); ~OreManager() {} + const char *getObjectTitle() const + { + return "ore"; + } + Ore *create(int type) { switch (type) { diff --git a/src/mg_schematic.cpp b/src/mg_schematic.cpp index 23b62115f..f154f4fda 100644 --- a/src/mg_schematic.cpp +++ b/src/mg_schematic.cpp @@ -28,13 +28,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serialization.h" #include "filesys.h" -const char *SchematicManager::ELEMENT_TITLE = "schematic"; - /////////////////////////////////////////////////////////////////////////////// SchematicManager::SchematicManager(IGameDef *gamedef) : - GenElementManager(gamedef) + ObjDefManager(gamedef, OBJDEF_SCHEMATIC) { } @@ -201,7 +199,7 @@ void Schematic::placeStructure(Map *map, v3s16 p, u32 flags, Rotation rot, bool Schematic::loadSchematicFromFile(const char *filename, INodeDefManager *ndef, - std::map &replace_names) + StringMap *replace_names) { content_t cignore = CONTENT_IGNORE; bool have_cignore = false; @@ -246,8 +244,8 @@ bool Schematic::loadSchematicFromFile(const char *filename, INodeDefManager *nde } std::map::iterator it; - it = replace_names.find(name); - if (it != replace_names.end()) + it = replace_names->find(name); + if (it != replace_names->end()) name = it->second; nri->nodenames.push_back(name); diff --git a/src/mg_schematic.h b/src/mg_schematic.h index ad5afb15f..4a85f69a6 100644 --- a/src/mg_schematic.h +++ b/src/mg_schematic.h @@ -42,7 +42,7 @@ class NodeResolver; #define MTSCHEM_PROB_ALWAYS 0xFF -class Schematic : public GenElement, public NodeResolver { +class Schematic : public ObjDef, public NodeResolver { public: std::vector c_nodes; @@ -62,7 +62,7 @@ public: Rotation rot, bool force_placement, INodeDefManager *ndef); bool loadSchematicFromFile(const char *filename, INodeDefManager *ndef, - std::map &replace_names); + StringMap *replace_names); void saveSchematicToFile(const char *filename, INodeDefManager *ndef); bool getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2); @@ -73,14 +73,16 @@ public: std::vector > *splist); }; -class SchematicManager : public GenElementManager { +class SchematicManager : public ObjDefManager { public: - static const char *ELEMENT_TITLE; - static const size_t ELEMENT_LIMIT = 0x10000; - SchematicManager(IGameDef *gamedef); ~SchematicManager() {} + const char *getObjectTitle() const + { + return "schematic"; + } + Schematic *create(int type) { return new Schematic; diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index 172f2b5cc..5af6cf457 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -86,11 +86,56 @@ struct EnumString ModApiMapgen::es_Rotation[] = }; +bool read_schematic_def(lua_State *L, int index, Schematic *schem, + INodeDefManager *ndef, StringMap *replace_names); + /////////////////////////////////////////////////////////////////////////////// +Schematic *get_schematic(lua_State *L, int index, + SchematicManager *schemmgr, StringMap *replace_names) +{ + if (index < 0) + index = lua_gettop(L) + 1 + index; + + Schematic *schem; + + if (lua_isnumber(L, index)) { + return (Schematic *)schemmgr->get(lua_tointeger(L, index)); + } else if (lua_istable(L, index)) { + schem = new Schematic; + if (!read_schematic_def(L, index, schem, + schemmgr->getNodeDef(), replace_names)) { + delete schem; + return NULL; + } + } else if (lua_isstring(L, index)) { + const char *filename = lua_tostring(L, index); + schem = (Schematic *)schemmgr->getByName(filename); + if (schem) + return schem; + + schem = new Schematic; + if (!schem->loadSchematicFromFile(filename, + schemmgr->getNodeDef(), replace_names)) { + delete schem; + return NULL; + } + } else { + return NULL; + } + + if (schemmgr->add(schem) == OBJDEF_INVALID_HANDLE) { + delete schem; + return NULL; + } + + return schem; +} + + bool read_schematic_def(lua_State *L, int index, Schematic *schem, - INodeDefManager *ndef, std::map &replace_names) + INodeDefManager *ndef, StringMap *replace_names) { //// Get schematic size lua_getfield(L, index, "size"); @@ -128,9 +173,8 @@ bool read_schematic_def(lua_State *L, int index, Schematic *schem, param2 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : 0; lua_pop(L, 1); - std::map::iterator it; - it = replace_names.find(name); - if (it != replace_names.end()) + StringMap::iterator it = replace_names->find(name); + if (it != replace_names->end()) name = it->second; schemdata[i] = MapNode(ndef, name, param1, param2); @@ -175,51 +219,12 @@ bool read_schematic_def(lua_State *L, int index, Schematic *schem, } -Schematic *get_schematic(lua_State *L, int index, SchematicManager *schemmgr, - std::map &replace_names) + +void read_schematic_replacements(lua_State *L, int index, StringMap *replace_names) { if (index < 0) index = lua_gettop(L) + 1 + index; - Schematic *schem; - - if (lua_isnumber(L, index)) { - return (Schematic *)schemmgr->get(lua_tointeger(L, index)); - } else if (lua_istable(L, index)) { - schem = new Schematic; - if (!read_schematic_def(L, index, schem, - schemmgr->getNodeDef(), replace_names)) { - delete schem; - return NULL; - } - } else if (lua_isstring(L, index)) { - const char *filename = lua_tostring(L, index); - schem = (Schematic *)schemmgr->getByName(filename); - if (schem) - return schem; - - schem = new Schematic; - if (!schem->loadSchematicFromFile(filename, - schemmgr->getNodeDef(), replace_names)) { - delete schem; - return NULL; - } - } else { - return NULL; - } - - if (schemmgr->add(schem) == (u32)-1) { - delete schem; - return 0; - } - - return schem; -} - - -void read_schematic_replacements(lua_State *L, - std::map &replace_names, int index) -{ lua_pushnil(L); while (lua_next(L, index)) { std::string replace_from; @@ -238,7 +243,7 @@ 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); } } @@ -477,24 +482,23 @@ int ModApiMapgen::l_register_biome(lua_State *L) b->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.f); b->flags = 0; //reserved - u32 id = bmgr->add(b); - if (id == (u32)-1) { + ObjDefHandle handle = bmgr->add(b); + if (handle == OBJDEF_INVALID_HANDLE) { delete b; return 0; } NodeResolveInfo *nri = new NodeResolveInfo(b); std::list &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_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", "")); + 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_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; } @@ -556,20 +560,20 @@ int ModApiMapgen::l_register_decoration(lua_State *L) if (!b) continue; - deco->biomes.insert(b->id); + deco->biomes.insert(b->index); } //// 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, schemmgr, (DecoSchematic *)deco); - break; - case DECO_LSYSTEM: - break; + case DECO_SIMPLE: + success = regDecoSimple(L, nri, (DecoSimple *)deco); + break; + case DECO_SCHEMATIC: + success = regDecoSchematic(L, schemmgr, (DecoSchematic *)deco); + break; + case DECO_LSYSTEM: + break; } ndef->pendNodeResolve(nri); @@ -579,14 +583,13 @@ int ModApiMapgen::l_register_decoration(lua_State *L) return 0; } - u32 id = decomgr->add(deco); - if (id == (u32)-1) { + 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; } @@ -638,14 +641,14 @@ bool ModApiMapgen::regDecoSchematic(lua_State *L, deco->rotation = (Rotation)getenumfield(L, index, "rotation", es_Rotation, ROTATE_0); - std::map 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); lua_getfield(L, index, "schematic"); - Schematic *schem = get_schematic(L, -1, schemmgr, replace_names); + Schematic *schem = get_schematic(L, -1, schemmgr, &replace_names); lua_pop(L, 1); deco->schematic = schem; @@ -719,8 +722,8 @@ int ModApiMapgen::l_register_ore(lua_State *L) "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; } @@ -736,8 +739,7 @@ int ModApiMapgen::l_register_ore(lua_State *L) ndef->pendNodeResolve(nri); - verbosestream << "register_ore: " << ore->name << std::endl; - lua_pushinteger(L, id); + lua_pushinteger(L, handle); return 1; } @@ -746,16 +748,21 @@ int ModApiMapgen::l_register_schematic(lua_State *L) { SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr; - std::map replace_names; + StringMap replace_names; if (lua_istable(L, 2)) - read_schematic_replacements(L, replace_names, 2); + read_schematic_replacements(L, 2, &replace_names); - Schematic *schem = get_schematic(L, 1, schemmgr, replace_names); + Schematic *schem = get_schematic(L, 1, schemmgr, &replace_names); if (!schem) return 0; - printf("register_schematic!\n"); - verbosestream << "register_schematic: " << schem->name << std::endl; - lua_pushinteger(L, schem->id); + + ObjDefHandle handle = schemmgr->add(schem); + if (handle == OBJDEF_INVALID_HANDLE) { + delete schem; + return 0; + } + + lua_pushinteger(L, handle); return 1; } @@ -837,7 +844,7 @@ int ModApiMapgen::l_generate_decorations(lua_State *L) return 0; } -// create_schematic(p1, p2, probability_list, filename) +// create_schematic(p1, p2, probability_list, filename, y_slice_prob_list) int ModApiMapgen::l_create_schematic(lua_State *L) { Schematic schem; @@ -894,6 +901,7 @@ int ModApiMapgen::l_create_schematic(lua_State *L) actionstream << "create_schematic: saved schematic file '" << filename << "'." << std::endl; + lua_pushboolean(L, true); return 1; } @@ -917,12 +925,12 @@ int ModApiMapgen::l_place_schematic(lua_State *L) force_placement = lua_toboolean(L, 5); //// Read node replacements - std::map 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 - Schematic *schem = get_schematic(L, 2, schemmgr, replace_names); + Schematic *schem = get_schematic(L, 2, schemmgr, &replace_names); if (!schem) { errorstream << "place_schematic: failed to get schematic" << std::endl; return 0; @@ -931,6 +939,7 @@ int ModApiMapgen::l_place_schematic(lua_State *L) schem->placeStructure(map, p, 0, (Rotation)rot, force_placement, schemmgr->getNodeDef()); + lua_pushboolean(L, true); return 1; } diff --git a/src/util/numeric.cpp b/src/util/numeric.cpp index a1f1fd0ab..2306976ec 100644 --- a/src/util/numeric.cpp +++ b/src/util/numeric.cpp @@ -183,7 +183,6 @@ u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed) return h; } - /* blockpos: position of block in block coordinates camera_pos: position of camera in nodes diff --git a/src/util/numeric.h b/src/util/numeric.h index ccc9fbee4..74c1dfea6 100644 --- a/src/util/numeric.h +++ b/src/util/numeric.h @@ -249,6 +249,28 @@ int myrand_range(int min, int max); Miscellaneous functions */ +inline u32 get_bits(u32 x, u32 pos, u32 len) +{ + u32 mask = (1 << len) - 1; + return (x >> pos) & mask; +} + +inline void set_bits(u32 *x, u32 pos, u32 len, u32 val) +{ + u32 mask = (1 << len) - 1; + *x &= ~(mask << len); + *x |= (val & mask) << pos; +} + +inline u32 calc_parity(u32 v) +{ + v ^= v >> 16; + v ^= v >> 8; + v ^= v >> 4; + v &= 0xf; + return (0x6996 >> v) & 1; +} + u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed); bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,