GenElementManager: Pass opaque handles to Lua and rename to ObjDefManager

Add core.clear_registered_schematics() and refactor schematics somewhat
This commit is contained in:
kwolekr 2015-03-30 23:40:35 -04:00
parent 6a48844eba
commit ed10005d38
16 changed files with 363 additions and 203 deletions

@ -419,6 +419,11 @@ the global `minetest.registered_*` tables.
* `minetest.register_craftitem(name, item definition)` * `minetest.register_craftitem(name, item definition)`
* added to `minetest.registered_items[name]` * 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)` * `minetest.register_ore(ore definition)`
* returns an integer uniquely identifying the registered ore * returns an integer uniquely identifying the registered ore
* added to `minetest.registered_ores` with the key of `ore.name` * 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` * added to `minetest.registered_decorations` with the key of `decoration.name`
* if `decoration.name` is nil, the key is the returned ID * 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()` * `minetest.clear_registered_ores()`
* clears all ores currently registered * clears all ores currently registered
* `minetest.clear_registered_decorations()` * `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 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 in these tables (e.g. when a mod has been removed). Always check for

@ -36,11 +36,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "treegen.h" #include "treegen.h"
#include "serialization.h" #include "serialization.h"
#include "util/serialize.h" #include "util/serialize.h"
#include "util/numeric.h"
#include "filesys.h" #include "filesys.h"
#include "log.h" #include "log.h"
const char *GenElementManager::ELEMENT_TITLE = "element";
FlagDesc flagdesc_mapgen[] = { FlagDesc flagdesc_mapgen[] = {
{"trees", MG_TREES}, {"trees", MG_TREES},
{"caves", MG_CAVES}, {"caves", MG_CAVES},
@ -64,6 +63,7 @@ FlagDesc flagdesc_gennotify[] = {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
Mapgen::Mapgen() Mapgen::Mapgen()
{ {
generating = false; 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(); m_ndef = gamedef->getNodeDefManager();
} }
GenElementManager::~GenElementManager() ObjDefManager::~ObjDefManager()
{ {
for (size_t i = 0; i != m_elements.size(); i++) for (size_t i = 0; i != m_objects.size(); i++)
delete m_elements[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 (obj->name.length() && getByName(obj->name))
if (m_elements[i] == NULL) { return OBJDEF_INVALID_HANDLE;
elem->id = i;
m_elements[i] = elem;
return i;
}
}
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; return -1;
elem->id = nelem; obj->index = nobjects;
m_elements.push_back(elem);
verbosestream << "GenElementManager: added " << this->ELEMENT_TITLE // Ensure UID is nonzero so that a valid handle == OBJDEF_INVALID_HANDLE
<< " element '" << elem->name << "'" << std::endl; // 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++) { ObjDef *old_obj = m_objects[index];
GenElement *elem = m_elements[i]; m_objects[index] = obj;
if (elem && name == elem->name) return old_obj;
return elem; }
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; return NULL;
} }
GenElement *GenElementManager::update(u32 id, GenElement *elem) void ObjDefManager::clear()
{ {
if (id >= m_elements.size()) for (size_t i = 0; i != m_objects.size(); i++)
return NULL; delete m_objects[i];
GenElement *old_elem = m_elements[id]; m_objects.clear();
m_elements[id] = elem;
return old_elem;
} }
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) void MapgenParams::load(const Settings &settings)
{ {
std::string seed_str; std::string seed_str;

@ -179,36 +179,68 @@ struct MapgenFactory {
virtual ~MapgenFactory() {} virtual ~MapgenFactory() {}
}; };
class GenElement { typedef std::map<std::string, std::string> 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: public:
virtual ~GenElement() {} virtual ~ObjDef() {}
u32 id;
u32 index;
u32 uid;
ObjDefHandle handle;
std::string name; std::string name;
}; };
class GenElementManager { class ObjDefManager {
public: public:
static const char *ELEMENT_TITLE; ObjDefManager(IGameDef *gamedef, ObjDefType type);
static const size_t ELEMENT_LIMIT = -1; virtual ~ObjDefManager();
GenElementManager(IGameDef *gamedef); virtual const char *getObjectTitle() const = 0;
virtual ~GenElementManager();
virtual GenElement *create(int type) = 0; virtual ObjDef *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 void clear(); 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: protected:
INodeDefManager *m_ndef; INodeDefManager *m_ndef;
std::vector<GenElement *> m_elements; std::vector<ObjDef *> m_objects;
ObjDefType m_objtype;
}; };
#endif #endif

@ -479,7 +479,7 @@ void MapgenV5::generateCaves(int max_stone_y)
for (s16 y=node_min.Y - 1; y<=node_max.Y + 1; 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); 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++) { 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(); content_t c = vm->m_data[i].getContent();
if (c == CONTENT_AIR if (c == CONTENT_AIR
|| (y <= water_level || (y <= water_level
@ -519,7 +519,7 @@ void MapgenV5::dustTopNodes()
for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 x = node_min.X; x <= node_max.X; x++, index++) { 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) if (biome->c_dust == CONTENT_IGNORE)
continue; continue;

@ -674,7 +674,7 @@ void MapgenV7::dustTopNodes()
for (s16 z = node_min.Z; z <= node_max.Z; z++) for (s16 z = node_min.Z; z <= node_max.Z; z++)
for (s16 x = node_min.X; x <= node_max.X; x++, index++) { 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) if (biome->c_dust == CONTENT_IGNORE)
continue; continue;
@ -821,7 +821,7 @@ void MapgenV7::generateCaves(int max_stone_y)
u32 i = vm->m_area.index(node_min.X, y, z); u32 i = vm->m_area.index(node_min.X, y, z);
for (s16 x = node_min.X; x <= node_max.X; for (s16 x = node_min.X; x <= node_max.X;
x++, i++, index++, index2d++) { 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(); content_t c = vm->m_data[i].getContent();
if (c == CONTENT_AIR || (y <= water_level && if (c == CONTENT_AIR || (y <= water_level &&
c != biome->c_stone && c != c_stone)) c != biome->c_stone && c != c_stone))

@ -27,18 +27,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "util/mathconstants.h" #include "util/mathconstants.h"
#include "porting.h" #include "porting.h"
const char *BiomeManager::ELEMENT_TITLE = "biome";
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
BiomeManager::BiomeManager(IGameDef *gamedef) : BiomeManager::BiomeManager(IGameDef *gamedef) :
GenElementManager(gamedef) ObjDefManager(gamedef, OBJDEF_BIOME)
{ {
// Create default biome to be used in case none exist // Create default biome to be used in case none exist
Biome *b = new Biome; Biome *b = new Biome;
b->id = 0;
b->name = "Default"; b->name = "Default";
b->flags = 0; b->flags = 0;
b->depth_top = 0; b->depth_top = 0;
@ -75,8 +73,10 @@ BiomeManager::~BiomeManager()
void BiomeManager::calcBiomes(s16 sx, s16 sy, float *heat_map, void BiomeManager::calcBiomes(s16 sx, s16 sy, float *heat_map,
float *humidity_map, s16 *height_map, u8 *biomeid_map) float *humidity_map, s16 *height_map, u8 *biomeid_map)
{ {
for (s32 i = 0; i != sx * sy; i++) for (s32 i = 0; i != sx * sy; i++) {
biomeid_map[i] = getBiome(heat_map[i], humidity_map[i], height_map[i])->id; 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; Biome *b, *biome_closest = NULL;
float dist_min = FLT_MAX; float dist_min = FLT_MAX;
for (size_t i = 1; i < m_elements.size(); i++) { for (size_t i = 1; i < m_objects.size(); i++) {
b = (Biome *)m_elements[i]; b = (Biome *)m_objects[i];
if (!b || y > b->y_max || y < b->y_min) if (!b || y > b->y_max || y < b->y_min)
continue; 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() void BiomeManager::clear()
{ {
for (size_t i = 1; i < m_elements.size(); i++) { for (size_t i = 1; i < m_objects.size(); i++) {
Biome *b = (Biome *)m_elements[i]; Biome *b = (Biome *)m_objects[i];
delete b; delete b;
} }
m_elements.resize(1); m_objects.resize(1);
} }

@ -33,7 +33,7 @@ enum BiomeType
BIOME_TYPE_FLAT BIOME_TYPE_FLAT
}; };
class Biome : public GenElement, public NodeResolver { class Biome : public ObjDef, public NodeResolver {
public: public:
u32 flags; u32 flags;
@ -56,14 +56,18 @@ public:
virtual void resolveNodeNames(NodeResolveInfo *nri); virtual void resolveNodeNames(NodeResolveInfo *nri);
}; };
class BiomeManager : public GenElementManager { class BiomeManager : public ObjDefManager {
public: public:
static const char *ELEMENT_TITLE; static const char *OBJECT_TITLE;
static const size_t ELEMENT_LIMIT = 0x100;
BiomeManager(IGameDef *gamedef); BiomeManager(IGameDef *gamedef);
~BiomeManager(); ~BiomeManager();
const char *getObjectTitle() const
{
return "biome";
}
Biome *create(int btt) Biome *create(int btt)
{ {
return new Biome; return new Biome;

@ -25,8 +25,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "log.h" #include "log.h"
#include "util/numeric.h" #include "util/numeric.h"
const char *DecorationManager::ELEMENT_TITLE = "decoration";
FlagDesc flagdesc_deco[] = { FlagDesc flagdesc_deco[] = {
{"place_center_x", DECO_PLACE_CENTER_X}, {"place_center_x", DECO_PLACE_CENTER_X},
{"place_center_y", DECO_PLACE_CENTER_Y}, {"place_center_y", DECO_PLACE_CENTER_Y},
@ -40,7 +38,7 @@ FlagDesc flagdesc_deco[] = {
DecorationManager::DecorationManager(IGameDef *gamedef) : 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; size_t nplaced = 0;
for (size_t i = 0; i != m_elements.size(); i++) { for (size_t i = 0; i != m_objects.size(); i++) {
Decoration *deco = (Decoration *)m_elements[i]; Decoration *deco = (Decoration *)m_objects[i];
if (!deco) if (!deco)
continue; continue;
@ -65,11 +63,11 @@ size_t DecorationManager::placeAllDecos(Mapgen *mg, u32 blockseed,
void DecorationManager::clear() void DecorationManager::clear()
{ {
for (size_t i = 0; i < m_elements.size(); i++) { for (size_t i = 0; i < m_objects.size(); i++) {
Decoration *deco = (Decoration *)m_elements[i]; Decoration *deco = (Decoration *)m_objects[i];
delete deco; 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); v3s16 pos(x, y, z);
if (generate(mg->vm, &ps, pos)) if (generate(mg->vm, &ps, pos))
mg->gennotify.addEvent(GENNOTIFY_DECORATION, pos, id); mg->gennotify.addEvent(GENNOTIFY_DECORATION, pos, index);
} }
} }

@ -59,7 +59,7 @@ struct CutoffData {
}; };
#endif #endif
class Decoration : public GenElement, public NodeResolver { class Decoration : public ObjDef, public NodeResolver {
public: public:
INodeDefManager *ndef; INodeDefManager *ndef;
@ -121,14 +121,16 @@ public:
}; };
*/ */
class DecorationManager : public GenElementManager { class DecorationManager : public ObjDefManager {
public: public:
static const char *ELEMENT_TITLE;
static const size_t ELEMENT_LIMIT = 0x10000;
DecorationManager(IGameDef *gamedef); DecorationManager(IGameDef *gamedef);
~DecorationManager() {} ~DecorationManager() {}
const char *getObjectTitle() const
{
return "decoration";
}
Decoration *create(int type) Decoration *create(int type)
{ {
switch (type) { switch (type) {

@ -24,8 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "map.h" #include "map.h"
#include "log.h" #include "log.h"
const char *OreManager::ELEMENT_TITLE = "ore";
FlagDesc flagdesc_ore[] = { FlagDesc flagdesc_ore[] = {
{"absheight", OREFLAG_ABSHEIGHT}, {"absheight", OREFLAG_ABSHEIGHT},
{NULL, 0} {NULL, 0}
@ -36,7 +34,7 @@ FlagDesc flagdesc_ore[] = {
OreManager::OreManager(IGameDef *gamedef) : 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; size_t nplaced = 0;
for (size_t i = 0; i != m_elements.size(); i++) { for (size_t i = 0; i != m_objects.size(); i++) {
Ore *ore = (Ore *)m_elements[i]; Ore *ore = (Ore *)m_objects[i];
if (!ore) if (!ore)
continue; continue;
@ -60,11 +58,11 @@ size_t OreManager::placeAllOres(Mapgen *mg, u32 blockseed, v3s16 nmin, v3s16 nma
void OreManager::clear() void OreManager::clear()
{ {
for (size_t i = 0; i < m_elements.size(); i++) { for (size_t i = 0; i < m_objects.size(); i++) {
Ore *ore = (Ore *)m_elements[i]; Ore *ore = (Ore *)m_objects[i];
delete ore; delete ore;
} }
m_elements.clear(); m_objects.clear();
} }

@ -47,7 +47,7 @@ enum OreType {
extern FlagDesc flagdesc_ore[]; extern FlagDesc flagdesc_ore[];
class Ore : public GenElement, public NodeResolver { class Ore : public ObjDef, public NodeResolver {
public: public:
static const bool NEEDS_NOISE = false; static const bool NEEDS_NOISE = false;
@ -112,14 +112,16 @@ public:
v3s16 nmin, v3s16 nmax); v3s16 nmin, v3s16 nmax);
}; };
class OreManager : public GenElementManager { class OreManager : public ObjDefManager {
public: public:
static const char *ELEMENT_TITLE;
static const size_t ELEMENT_LIMIT = 0x10000;
OreManager(IGameDef *gamedef); OreManager(IGameDef *gamedef);
~OreManager() {} ~OreManager() {}
const char *getObjectTitle() const
{
return "ore";
}
Ore *create(int type) Ore *create(int type)
{ {
switch (type) { switch (type) {

@ -28,13 +28,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "serialization.h" #include "serialization.h"
#include "filesys.h" #include "filesys.h"
const char *SchematicManager::ELEMENT_TITLE = "schematic";
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
SchematicManager::SchematicManager(IGameDef *gamedef) : 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, bool Schematic::loadSchematicFromFile(const char *filename, INodeDefManager *ndef,
std::map<std::string, std::string> &replace_names) StringMap *replace_names)
{ {
content_t cignore = CONTENT_IGNORE; content_t cignore = CONTENT_IGNORE;
bool have_cignore = false; bool have_cignore = false;
@ -246,8 +244,8 @@ bool Schematic::loadSchematicFromFile(const char *filename, INodeDefManager *nde
} }
std::map<std::string, std::string>::iterator it; std::map<std::string, std::string>::iterator it;
it = replace_names.find(name); it = replace_names->find(name);
if (it != replace_names.end()) if (it != replace_names->end())
name = it->second; name = it->second;
nri->nodenames.push_back(name); nri->nodenames.push_back(name);

@ -42,7 +42,7 @@ class NodeResolver;
#define MTSCHEM_PROB_ALWAYS 0xFF #define MTSCHEM_PROB_ALWAYS 0xFF
class Schematic : public GenElement, public NodeResolver { class Schematic : public ObjDef, public NodeResolver {
public: public:
std::vector<content_t> c_nodes; std::vector<content_t> c_nodes;
@ -62,7 +62,7 @@ public:
Rotation rot, bool force_placement, INodeDefManager *ndef); Rotation rot, bool force_placement, INodeDefManager *ndef);
bool loadSchematicFromFile(const char *filename, INodeDefManager *ndef, bool loadSchematicFromFile(const char *filename, INodeDefManager *ndef,
std::map<std::string, std::string> &replace_names); StringMap *replace_names);
void saveSchematicToFile(const char *filename, INodeDefManager *ndef); void saveSchematicToFile(const char *filename, INodeDefManager *ndef);
bool getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2); bool getSchematicFromMap(Map *map, v3s16 p1, v3s16 p2);
@ -73,14 +73,16 @@ public:
std::vector<std::pair<s16, u8> > *splist); std::vector<std::pair<s16, u8> > *splist);
}; };
class SchematicManager : public GenElementManager { class SchematicManager : public ObjDefManager {
public: public:
static const char *ELEMENT_TITLE;
static const size_t ELEMENT_LIMIT = 0x10000;
SchematicManager(IGameDef *gamedef); SchematicManager(IGameDef *gamedef);
~SchematicManager() {} ~SchematicManager() {}
const char *getObjectTitle() const
{
return "schematic";
}
Schematic *create(int type) Schematic *create(int type)
{ {
return new Schematic; return new Schematic;

@ -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, bool read_schematic_def(lua_State *L, int index, Schematic *schem,
INodeDefManager *ndef, std::map<std::string, std::string> &replace_names) INodeDefManager *ndef, StringMap *replace_names)
{ {
//// Get schematic size //// Get schematic size
lua_getfield(L, index, "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; param2 = !lua_isnil(L, -1) ? lua_tonumber(L, -1) : 0;
lua_pop(L, 1); lua_pop(L, 1);
std::map<std::string, std::string>::iterator it; StringMap::iterator it = replace_names->find(name);
it = replace_names.find(name); if (it != replace_names->end())
if (it != replace_names.end())
name = it->second; name = it->second;
schemdata[i] = MapNode(ndef, name, param1, param2); 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<std::string, std::string> &replace_names) void read_schematic_replacements(lua_State *L, int index, StringMap *replace_names)
{ {
if (index < 0) if (index < 0)
index = lua_gettop(L) + 1 + index; 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<std::string, std::string> &replace_names, int index)
{
lua_pushnil(L); lua_pushnil(L);
while (lua_next(L, index)) { while (lua_next(L, index)) {
std::string replace_from; std::string replace_from;
@ -238,7 +243,7 @@ void read_schematic_replacements(lua_State *L,
replace_to = lua_tostring(L, -1); 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); 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->humidity_point = getfloatfield_default(L, index, "humidity_point", 0.f);
b->flags = 0; //reserved b->flags = 0; //reserved
u32 id = bmgr->add(b); ObjDefHandle handle = bmgr->add(b);
if (id == (u32)-1) { if (handle == OBJDEF_INVALID_HANDLE) {
delete b; delete b;
return 0; return 0;
} }
NodeResolveInfo *nri = new NodeResolveInfo(b); NodeResolveInfo *nri = new NodeResolveInfo(b);
std::list<std::string> &nnames = nri->nodenames; std::list<std::string> &nnames = nri->nodenames;
nnames.push_back(getstringfield_default(L, index, "node_top", "")); 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_filler", ""));
nnames.push_back(getstringfield_default(L, index, "node_stone", "")); 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_top", ""));
nnames.push_back(getstringfield_default(L, index, "node_water", "")); 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_dust", ""));
ndef->pendNodeResolve(nri); ndef->pendNodeResolve(nri);
verbosestream << "register_biome: " << b->name << std::endl; lua_pushinteger(L, handle);
lua_pushinteger(L, id);
return 1; return 1;
} }
@ -556,20 +560,20 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
if (!b) if (!b)
continue; continue;
deco->biomes.insert(b->id); deco->biomes.insert(b->index);
} }
//// Handle decoration type-specific parameters //// Handle decoration type-specific parameters
bool success = false; bool success = false;
switch (decotype) { switch (decotype) {
case DECO_SIMPLE: case DECO_SIMPLE:
success = regDecoSimple(L, nri, (DecoSimple *)deco); success = regDecoSimple(L, nri, (DecoSimple *)deco);
break; break;
case DECO_SCHEMATIC: case DECO_SCHEMATIC:
success = regDecoSchematic(L, schemmgr, (DecoSchematic *)deco); success = regDecoSchematic(L, schemmgr, (DecoSchematic *)deco);
break; break;
case DECO_LSYSTEM: case DECO_LSYSTEM:
break; break;
} }
ndef->pendNodeResolve(nri); ndef->pendNodeResolve(nri);
@ -579,14 +583,13 @@ int ModApiMapgen::l_register_decoration(lua_State *L)
return 0; return 0;
} }
u32 id = decomgr->add(deco); ObjDefHandle handle = decomgr->add(deco);
if (id == (u32)-1) { if (handle == OBJDEF_INVALID_HANDLE) {
delete deco; delete deco;
return 0; return 0;
} }
verbosestream << "register_decoration: " << deco->name << std::endl; lua_pushinteger(L, handle);
lua_pushinteger(L, id);
return 1; return 1;
} }
@ -638,14 +641,14 @@ bool ModApiMapgen::regDecoSchematic(lua_State *L,
deco->rotation = (Rotation)getenumfield(L, index, "rotation", deco->rotation = (Rotation)getenumfield(L, index, "rotation",
es_Rotation, ROTATE_0); es_Rotation, ROTATE_0);
std::map<std::string, std::string> replace_names; StringMap replace_names;
lua_getfield(L, index, "replacements"); lua_getfield(L, index, "replacements");
if (lua_istable(L, -1)) 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_pop(L, 1);
lua_getfield(L, index, "schematic"); 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); lua_pop(L, 1);
deco->schematic = schem; deco->schematic = schem;
@ -719,8 +722,8 @@ int ModApiMapgen::l_register_ore(lua_State *L)
"random_factor", 1.f); "random_factor", 1.f);
} }
u32 id = oremgr->add(ore); ObjDefHandle handle = oremgr->add(ore);
if (id == (u32)-1) { if (handle == OBJDEF_INVALID_HANDLE) {
delete ore; delete ore;
return 0; return 0;
} }
@ -736,8 +739,7 @@ int ModApiMapgen::l_register_ore(lua_State *L)
ndef->pendNodeResolve(nri); ndef->pendNodeResolve(nri);
verbosestream << "register_ore: " << ore->name << std::endl; lua_pushinteger(L, handle);
lua_pushinteger(L, id);
return 1; return 1;
} }
@ -746,16 +748,21 @@ int ModApiMapgen::l_register_schematic(lua_State *L)
{ {
SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr; SchematicManager *schemmgr = getServer(L)->getEmergeManager()->schemmgr;
std::map<std::string, std::string> replace_names; StringMap replace_names;
if (lua_istable(L, 2)) 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) if (!schem)
return 0; return 0;
printf("register_schematic!\n");
verbosestream << "register_schematic: " << schem->name << std::endl; ObjDefHandle handle = schemmgr->add(schem);
lua_pushinteger(L, schem->id); if (handle == OBJDEF_INVALID_HANDLE) {
delete schem;
return 0;
}
lua_pushinteger(L, handle);
return 1; return 1;
} }
@ -837,7 +844,7 @@ int ModApiMapgen::l_generate_decorations(lua_State *L)
return 0; 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) int ModApiMapgen::l_create_schematic(lua_State *L)
{ {
Schematic schem; Schematic schem;
@ -894,6 +901,7 @@ int ModApiMapgen::l_create_schematic(lua_State *L)
actionstream << "create_schematic: saved schematic file '" actionstream << "create_schematic: saved schematic file '"
<< filename << "'." << std::endl; << filename << "'." << std::endl;
lua_pushboolean(L, true);
return 1; return 1;
} }
@ -917,12 +925,12 @@ int ModApiMapgen::l_place_schematic(lua_State *L)
force_placement = lua_toboolean(L, 5); force_placement = lua_toboolean(L, 5);
//// Read node replacements //// Read node replacements
std::map<std::string, std::string> replace_names; StringMap replace_names;
if (lua_istable(L, 4)) if (lua_istable(L, 4))
read_schematic_replacements(L, replace_names, 4); read_schematic_replacements(L, 4, &replace_names);
//// Read schematic //// Read schematic
Schematic *schem = get_schematic(L, 2, schemmgr, replace_names); Schematic *schem = get_schematic(L, 2, schemmgr, &replace_names);
if (!schem) { if (!schem) {
errorstream << "place_schematic: failed to get schematic" << std::endl; errorstream << "place_schematic: failed to get schematic" << std::endl;
return 0; return 0;
@ -931,6 +939,7 @@ int ModApiMapgen::l_place_schematic(lua_State *L)
schem->placeStructure(map, p, 0, (Rotation)rot, force_placement, schem->placeStructure(map, p, 0, (Rotation)rot, force_placement,
schemmgr->getNodeDef()); schemmgr->getNodeDef());
lua_pushboolean(L, true);
return 1; return 1;
} }

@ -183,7 +183,6 @@ u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed)
return h; return h;
} }
/* /*
blockpos: position of block in block coordinates blockpos: position of block in block coordinates
camera_pos: position of camera in nodes camera_pos: position of camera in nodes

@ -249,6 +249,28 @@ int myrand_range(int min, int max);
Miscellaneous functions 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); u64 murmur_hash_64_ua(const void *key, int len, unsigned int seed);
bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir, bool isBlockInSight(v3s16 blockpos_b, v3f camera_pos, v3f camera_dir,