diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 62fe94b45..84769f8d8 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1116,6 +1116,8 @@ minetest.get_perlin(seeddiff, octaves, persistence, scale) ^ Return world-specific perlin noise (int(worldseed)+seeddiff) minetest.get_voxel_manip() ^ Return voxel manipulator object +minetest.get_mapgen_object(objectname) +^ Return requested mapgen object if available (see Mapgen objects) minetest.clear_objects() ^ clear all objects in the environments minetest.line_of_sight(pos1,pos2,stepsize) ->true/false @@ -1544,6 +1546,35 @@ methods: ^ To be used only by VoxelManip objects passed to a callback; otherwise, calculated lighting will be ignored - update_liquids(): Update liquid flow +Mapgen objects +--------------- +A mapgen object is a construct used in map generation. Mapgen objects can be used by an on_generate +callback to speed up operations by avoiding unnecessary recalculations; these can be retrieved using the +minetest.get_mapgen_object() function. If the requested Mapgen object is unavailable, or +get_mapgen_object() was called outside of an on_generate() callback, nil is returned. + +The following Mapgen objects are currently available: + +- voxelmanip + This returns four values; the VoxelManip object to be used, the voxel data, minimum emerge position, +and maximum emerged position. All mapgens support this object. + +- heightmap + Returns an array containing the y coordinates of the ground levels of nodes in the most recently +generated chunk by the current mapgen. + +- biomemap + Returns an array containing the biome IDs of nodes in the most recently generated chunk by the +current mapgen. + +- heatmap + Returns an array containing the temperature values of nodes in the most recently generated chunk by +the current mapgen. + +- humiditymap + Returns an array containing the humidity values of nodes in the most recently generated chunk by the +current mapgen. + Registered entities -------------------- - Functions receive a "luaentity" as self: diff --git a/src/emerge.cpp b/src/emerge.cpp index aed9af7b5..e1e6c6574 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -144,6 +144,16 @@ void EmergeManager::initMapgens(MapgenParams *mgparams) { } +Mapgen *EmergeManager::getCurrentMapgen() { + for (unsigned int i = 0; i != emergethread.size(); i++) { + if (emergethread[i]->IsSameThread()) + return emergethread[i]->mapgen; + } + + return NULL; +} + + bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate) { std::map::const_iterator iter; BlockEmergeData *bedata; diff --git a/src/emerge.h b/src/emerge.h index 084956932..d51177110 100644 --- a/src/emerge.h +++ b/src/emerge.h @@ -93,6 +93,7 @@ public: ~EmergeManager(); void initMapgens(MapgenParams *mgparams); + Mapgen *getCurrentMapgen(); Mapgen *createMapgen(std::string mgname, int mgid, MapgenParams *mgparams); MapgenParams *createMapgenParams(std::string mgname); @@ -111,6 +112,7 @@ public: class EmergeThread : public SimpleThread { +public: Server *m_server; ServerMap *map; EmergeManager *emerge; @@ -118,7 +120,6 @@ class EmergeThread : public SimpleThread bool enable_mapgen_debug_info; int id; -public: Event qevent; std::queue blockqueue; diff --git a/src/jthread/jthread.h b/src/jthread/jthread.h index 9440a158d..cd78231e9 100644 --- a/src/jthread/jthread.h +++ b/src/jthread/jthread.h @@ -47,6 +47,7 @@ public: virtual void *Thread() = 0; bool IsRunning(); void *GetReturnValue(); + bool IsSameThread(); protected: void ThreadStarted(); private: diff --git a/src/jthread/pthread/jthread.cpp b/src/jthread/pthread/jthread.cpp index 978cac20a..4a5c736eb 100644 --- a/src/jthread/pthread/jthread.cpp +++ b/src/jthread/pthread/jthread.cpp @@ -148,6 +148,11 @@ void *JThread::GetReturnValue() return val; } +bool JThread::IsSameThread() +{ + return pthread_equal(pthread_self(), threadid); +} + void *JThread::TheThread(void *param) { JThread *jthread; diff --git a/src/jthread/win32/jthread.cpp b/src/jthread/win32/jthread.cpp index 54b110bfd..c07425dca 100644 --- a/src/jthread/win32/jthread.cpp +++ b/src/jthread/win32/jthread.cpp @@ -141,6 +141,11 @@ void *JThread::GetReturnValue() return val; } +bool JThread::IsSameThread() +{ + return GetCurrentThreadId() == threadid; +} + #ifndef _WIN32_WCE UINT __stdcall JThread::TheThread(void *param) #else diff --git a/src/mapgen.h b/src/mapgen.h index 0ed64f85c..96a27ade7 100644 --- a/src/mapgen.h +++ b/src/mapgen.h @@ -93,8 +93,10 @@ public: int id; ManualMapVoxelManipulator *vm; INodeDefManager *ndef; + s16 *heightmap; u8 *biomemap; + v3s16 csize; Mapgen(); virtual ~Mapgen() {} @@ -124,6 +126,14 @@ struct MapgenFactory { virtual ~MapgenFactory() {} }; +enum MapgenObject { + MGOBJ_VMANIP, + MGOBJ_HEIGHTMAP, + MGOBJ_BIOMEMAP, + MGOBJ_HEATMAP, + MGOBJ_HUMIDMAP +}; + enum OreType { ORE_SCATTER, ORE_SHEET, diff --git a/src/mapgen_v6.h b/src/mapgen_v6.h index f4ffd25f3..14736e3d0 100644 --- a/src/mapgen_v6.h +++ b/src/mapgen_v6.h @@ -84,7 +84,6 @@ public: EmergeManager *emerge; int ystride; - v3s16 csize; u32 flags; u32 blockseed; diff --git a/src/mapgen_v7.h b/src/mapgen_v7.h index 3bba9938c..6267350d6 100644 --- a/src/mapgen_v7.h +++ b/src/mapgen_v7.h @@ -58,7 +58,6 @@ public: BiomeDefManager *bmgr; int ystride; - v3s16 csize; u32 flags; bool lighting; bool ridges; diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index 6f663646c..b5c40977e 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -35,11 +35,27 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_noise.h" #include "treegen.h" #include "pathfinder.h" +#include "emerge.h" +#include "mapgen_v7.h" #define GET_ENV_PTR ServerEnvironment* env = \ dynamic_cast(getEnv(L)); \ if( env == NULL) return 0 + +struct EnumString ModApiEnvMod::es_MapgenObject[] = +{ + {MGOBJ_VMANIP, "voxelmanip"}, + {MGOBJ_HEIGHTMAP, "heightmap"}, + {MGOBJ_BIOMEMAP, "biomemap"}, + {MGOBJ_HEATMAP, "heatmap"}, + {MGOBJ_HUMIDMAP, "humiditymap"}, + {0, NULL}, +}; + + +/////////////////////////////////////////////////////////////////////////////// + void LuaABM::trigger(ServerEnvironment *env, v3s16 p, MapNode n, u32 active_object_count, u32 active_object_count_wider) @@ -541,14 +557,101 @@ int ModApiEnvMod::l_get_voxel_manip(lua_State *L) GET_ENV_PTR; Map *map = &(env->getMap()); - LuaVoxelManip *vm = new LuaVoxelManip(map); + LuaVoxelManip *o = new LuaVoxelManip(map); - *(void **)(lua_newuserdata(L, sizeof(void *))) = vm; + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; luaL_getmetatable(L, "VoxelManip"); lua_setmetatable(L, -2); return 1; } +// minetest.get_mapgen_object(objectname) +// returns the requested object used during map generation +int ModApiEnvMod::l_get_mapgen_object(lua_State *L) +{ + const char *mgobjstr = lua_tostring(L, 1); + + int mgobjint; + if (!string_to_enum(es_MapgenObject, mgobjint, mgobjstr ? mgobjstr : "")) + return 0; + + enum MapgenObject mgobj = (MapgenObject)mgobjint; + + EmergeManager *emerge = getServer(L)->getEmergeManager(); + Mapgen *mg = emerge->getCurrentMapgen(); + + size_t maplen = mg->csize.X * mg->csize.Z; + + int nargs = 1; + + switch (mgobj) { + case MGOBJ_VMANIP: { + ManualMapVoxelManipulator *vm = mg->vm; + + // VoxelManip object + LuaVoxelManip *o = new LuaVoxelManip(vm, false); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, "VoxelManip"); + lua_setmetatable(L, -2); + + // VoxelManip data + int volume = vm->m_area.getVolume(); + lua_newtable(L); + for (int i = 0; i != volume; i++) { + lua_Number cid = vm->m_data[i].getContent(); + lua_pushnumber(L, cid); + lua_rawseti(L, -2, i + 1); + } + + // emerged min pos + push_v3s16(L, vm->m_area.MinEdge); + + // emerged max pos + push_v3s16(L, vm->m_area.MaxEdge); + + nargs = 4; + + break; } + 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); + } + break; } + case MGOBJ_BIOMEMAP: { + if (!mg->heightmap) + 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); + } + break; } + case MGOBJ_HEATMAP: { // Mapgen V7 specific objects + case MGOBJ_HUMIDMAP: + MapgenV7 *mgv7 = (MapgenV7 *)mg; + + float *arr = (mgobj == MGOBJ_HEATMAP) ? + mgv7->noise_heat->result : mgv7->noise_humidity->result; + if (!arr) + return 0; + + lua_newtable(L); + for (size_t i = 0; i != maplen; i++) { + lua_pushnumber(L, arr[i]); + lua_rawseti(L, -2, i + 1); + } + break; } + } + + return nargs; +} + // minetest.clear_objects() // clear all objects in the environment int ModApiEnvMod::l_clear_objects(lua_State *L) @@ -695,6 +798,7 @@ bool ModApiEnvMod::Initialize(lua_State *L,int top) retval &= API_FCT(get_perlin); retval &= API_FCT(get_perlin_map); retval &= API_FCT(get_voxel_manip); + retval &= API_FCT(get_mapgen_object); retval &= API_FCT(clear_objects); retval &= API_FCT(spawn_tree); retval &= API_FCT(find_path); diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h index 24700d27c..8f769e350 100644 --- a/src/script/lua_api/l_env.h +++ b/src/script/lua_api/l_env.h @@ -113,6 +113,10 @@ private: // minetest.get_voxel_manip() // returns world-specific voxel manipulator static int l_get_voxel_manip(lua_State *L); + + // minetest.get_mapgen_object(objectname) + // returns the requested object used during map generation + static int l_get_mapgen_object(lua_State *L); // minetest.clear_objects() // clear all objects in the environment @@ -127,7 +131,9 @@ private: // minetest.find_path(pos1, pos2, searchdistance, // max_jump, max_drop, algorithm) -> table containing path static int l_find_path(lua_State *L); - + + static struct EnumString es_MapgenObject[]; + public: bool Initialize(lua_State *L, int top); }; diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp index c69562dda..4069c61ce 100644 --- a/src/script/lua_api/l_item.cpp +++ b/src/script/lua_api/l_item.cpp @@ -466,7 +466,7 @@ int ModApiItemMod::l_get_content_id(lua_State *L) INodeDefManager *ndef = STACK_TO_SERVER(L)->getNodeDefManager(); content_t c = ndef->getId(name); - lua_pushnumber(L, c); + lua_pushinteger(L, c); return 1; /* number of results */ } diff --git a/src/script/lua_api/l_vmanip.cpp b/src/script/lua_api/l_vmanip.cpp index e0397dfce..6743f40f9 100644 --- a/src/script/lua_api/l_vmanip.cpp +++ b/src/script/lua_api/l_vmanip.cpp @@ -33,7 +33,8 @@ with this program; if not, write to the Free Software Foundation, Inc., int LuaVoxelManip::gc_object(lua_State *L) { LuaVoxelManip *o = *(LuaVoxelManip **)(lua_touserdata(L, 1)); - delete o; + if (o->do_gc) + delete o; return 0; } @@ -82,7 +83,6 @@ int LuaVoxelManip::l_write_chunk(lua_State *L) vm->m_data[i].setContent(c); lua_pop(L, 1); - } vm->blitBackAll(&o->modified_blocks); @@ -184,6 +184,12 @@ int LuaVoxelManip::l_update_map(lua_State *L) return 0; } +LuaVoxelManip::LuaVoxelManip(ManualMapVoxelManipulator *mmvm, bool dogc) +{ + this->vm = mmvm; + this->do_gc = dogc; +} + LuaVoxelManip::LuaVoxelManip(Map *map) { vm = new ManualMapVoxelManipulator(map); diff --git a/src/script/lua_api/l_vmanip.h b/src/script/lua_api/l_vmanip.h index 568f7104e..5a57d6bfa 100644 --- a/src/script/lua_api/l_vmanip.h +++ b/src/script/lua_api/l_vmanip.h @@ -36,6 +36,7 @@ class LuaVoxelManip private: ManualMapVoxelManipulator *vm; std::map modified_blocks; + bool do_gc; static const char className[]; static const luaL_reg methods[]; @@ -50,6 +51,7 @@ private: static int l_set_lighting(lua_State *L); public: + LuaVoxelManip(ManualMapVoxelManipulator *mmvm, bool dogc); LuaVoxelManip(Map *map); ~LuaVoxelManip();