Skip to content

Commit

Permalink
GenElementManager: Pass opaque handles to Lua and rename to ObjDefMan…
Browse files Browse the repository at this point in the history
…ager

Add core.clear_registered_schematics() and refactor schematics somewhat
  • Loading branch information
kwolekr committed Mar 31, 2015
1 parent 6a48844 commit ed10005
Show file tree
Hide file tree
Showing 16 changed files with 363 additions and 203 deletions.
21 changes: 19 additions & 2 deletions doc/lua_api.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand All @@ -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
Expand Down
153 changes: 115 additions & 38 deletions src/mapgen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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},
Expand All @@ -64,6 +63,7 @@ FlagDesc flagdesc_gennotify[] = {

///////////////////////////////////////////////////////////////////////////////


Mapgen::Mapgen()
{
generating = false;
Expand Down Expand Up @@ -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;

u32 index = addRaw(obj);
if (index == OBJDEF_INVALID_INDEX)
return OBJDEF_INVALID_HANDLE;

if (nelem >= this->ELEMENT_LIMIT)
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;

// 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;

m_objects.push_back(obj);

verbosestream << "GenElementManager: added " << this->ELEMENT_TITLE
<< " element '" << elem->name << "'" << std::endl;
infostream << "ObjDefManager: added " << getObjectTitle()
<< ": name=\"" << obj->name
<< "\" index=" << obj->index
<< " uid=" << obj->uid
<< std::endl;

return nelem;
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()))

This comment has been minimized.

Copy link
@racam
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;
Expand Down
66 changes: 49 additions & 17 deletions src/mapgen.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,36 +179,68 @@ struct 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:
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;

//// 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);

//// 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);

virtual GenElement *getByName(const std::string &name);
INodeDefManager *getNodeDef() const { return m_ndef; }

INodeDefManager *getNodeDef() { 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<GenElement *> m_elements;
std::vector<ObjDef *> m_objects;
ObjDefType m_objtype;
};

#endif
4 changes: 2 additions & 2 deletions src/mapgen_v5.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions src/mapgen_v7.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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))
Expand Down
Loading

0 comments on commit ed10005

Please sign in to comment.