diff --git a/builtin/misc_register.lua b/builtin/misc_register.lua index 4041fb9e2..2d25568b6 100644 --- a/builtin/misc_register.lua +++ b/builtin/misc_register.lua @@ -307,6 +307,7 @@ end minetest.registered_on_chat_messages, minetest.register_on_chat_message = make_registration() minetest.registered_globalsteps, minetest.register_globalstep = make_registration() +minetest.registered_on_mapgen_inits, minetest.register_on_mapgen_init = make_registration() minetest.registered_on_shutdown, minetest.register_on_shutdown = make_registration() minetest.registered_on_punchnodes, minetest.register_on_punchnode = make_registration() minetest.registered_on_placenodes, minetest.register_on_placenode = make_registration() diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 62abb2e3e..a4e1372da 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -1034,6 +1034,9 @@ minetest.register_on_player_receive_fields(func(player, formname, fields)) ^ Called when a button is pressed in player's inventory form ^ Newest functions are called first ^ If function returns true, remaining functions are not called +minetest.register_on_mapgen_init(func(MapgenParams)) +^ Called just before the map generator is initialized but before the environment is initialized +^ MapgenParams consists of a table with the fields mgname, seed, water_level, and flags Other registration functions: minetest.register_chatcommand(cmd, chatcommand definition) @@ -1118,6 +1121,14 @@ minetest.get_voxel_manip() ^ Return voxel manipulator object minetest.get_mapgen_object(objectname) ^ Return requested mapgen object if available (see Mapgen objects) +minetest.set_mapgen_params(MapgenParams) +^ Set map generation parameters +^ Function can *only* be called within a minetest.on_mapgen_init() callback +^ Takes a table as an argument with the fields mgname, seed, water_level, flags, and flagmask. +^ Leave field unset to leave that parameter unchanged +^ flagmask field must be set to all mapgen flags that are being modified +^ flags contains only the flags that are being set +^ flags and flagmask are in the same format and have the same options as 'mgflags' in minetest.conf minetest.clear_objects() ^ clear all objects in the environments minetest.line_of_sight(pos1,pos2,stepsize) ->true/false diff --git a/minetest.conf.example b/minetest.conf.example index 07063b913..3f1977268 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -331,7 +331,7 @@ #water_level = 1 # Size of chunks to be generated. #chunksize = 5 -# Map generation attributes. Currently supported: trees, caves, flat, v6_biome_blend, v6_jungles, dungeons +# Map generation attributes. Currently supported: trees, caves, flat, v6_biome_blend, v6_jungles, dungeons, nolight #mg_flags = trees, caves, v6_biome_blend # How large deserts and beaches are #mgv6_freq_desert = 0.45 diff --git a/src/emerge.cpp b/src/emerge.cpp index e1e6c6574..09a58149d 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -59,6 +59,10 @@ EmergeManager::EmergeManager(IGameDef *gamedef) { this->biomedef = new BiomeDefManager(); this->params = NULL; + this->luaoverride_params = NULL; + this->luaoverride_params_modified = 0; + this->luaoverride_flagmask = 0; + mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info"); queuemutex.Init(); @@ -124,12 +128,37 @@ void EmergeManager::initMapgens(MapgenParams *mgparams) { if (mapgen.size()) return; + // Resolve names of nodes for things that were registered + // (at this point, the registration period is over) biomedef->resolveNodeNames(ndef); + for (size_t i = 0; i != ores.size(); i++) ores[i]->resolveNodeNames(ndef); + for (size_t i = 0; i != decorations.size(); i++) decorations[i]->resolveNodeNames(ndef); + // Apply mapgen parameter overrides from Lua + if (luaoverride_params) { + if (luaoverride_params_modified & MGPARAMS_SET_MGNAME) + mgparams->mg_name = luaoverride_params->mg_name; + + if (luaoverride_params_modified & MGPARAMS_SET_SEED) + mgparams->seed = luaoverride_params->seed; + + if (luaoverride_params_modified & MGPARAMS_SET_WATER_LEVEL) + mgparams->water_level = luaoverride_params->water_level; + + if (luaoverride_params_modified & MGPARAMS_SET_FLAGS) { + mgparams->flags &= ~luaoverride_flagmask; + mgparams->flags |= luaoverride_params->flags; + } + + delete luaoverride_params; + luaoverride_params = NULL; + } + + // Create the mapgens this->params = mgparams; for (size_t i = 0; i != emergethread.size(); i++) { mg = createMapgen(params->mg_name, 0, params); diff --git a/src/emerge.h b/src/emerge.h index d51177110..ee95c348f 100644 --- a/src/emerge.h +++ b/src/emerge.h @@ -24,6 +24,11 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "util/thread.h" +#define MGPARAMS_SET_MGNAME 1 +#define MGPARAMS_SET_SEED 2 +#define MGPARAMS_SET_WATER_LEVEL 4 +#define MGPARAMS_SET_FLAGS 8 + #define BLOCK_EMERGE_ALLOWGEN (1<<0) #define EMERGE_DBG_OUT(x) \ @@ -79,6 +84,10 @@ public: u16 qlimit_diskonly; u16 qlimit_generate; + MapgenParams *luaoverride_params; + u32 luaoverride_params_modified; + u32 luaoverride_flagmask; + //block emerge queue data structures JMutex queuemutex; std::map blocks_enqueued; diff --git a/src/mapgen.cpp b/src/mapgen.cpp index d1a38bb20..d80d2107f 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -44,6 +44,7 @@ FlagDesc flagdesc_mapgen[] = { {"v6_jungles", MGV6_JUNGLES}, {"v6_biome_blend", MGV6_BIOME_BLEND}, {"flat", MG_FLAT}, + {"nolight", MG_NOLIGHT}, {NULL, 0} }; diff --git a/src/mapgen.h b/src/mapgen.h index 96a27ade7..9a8b99c4a 100644 --- a/src/mapgen.h +++ b/src/mapgen.h @@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #define MGV6_JUNGLES 0x08 #define MGV6_BIOME_BLEND 0x10 #define MG_FLAT 0x20 +#define MG_NOLIGHT 0x40 /////////////////// Ore generation flags // Use absolute value of height to determine ore placement @@ -80,8 +81,8 @@ struct MapgenParams { flags = MG_TREES | MG_CAVES | MGV6_BIOME_BLEND; } - virtual bool readParams(Settings *settings) = 0; - virtual void writeParams(Settings *settings) = 0; + virtual bool readParams(Settings *settings) { return true; } + virtual void writeParams(Settings *settings) {} virtual ~MapgenParams() {} }; diff --git a/src/mapgen_math.cpp b/src/mapgen_math.cpp index a8a093a4a..6d0bf1292 100644 --- a/src/mapgen_math.cpp +++ b/src/mapgen_math.cpp @@ -171,8 +171,8 @@ void MapgenMathParams::writeParams(Settings *settings) { MapgenMath::MapgenMath(int mapgenid, MapgenMathParams *params_, EmergeManager *emerge) : MapgenV7(mapgenid, params_, emerge) { mg_params = params_; - this->lighting = 0; - this->ridges = 0; + this->flags |= MG_NOLIGHT; + this->ridges = 0; Json::Value & params = mg_params->params; invert = params["invert"].empty() ? 1 : params["invert"].asBool(); //params["invert"].empty()?1:params["invert"].asBool(); diff --git a/src/mapgen_singlenode.cpp b/src/mapgen_singlenode.cpp index f05ddd2f4..30787c6bb 100644 --- a/src/mapgen_singlenode.cpp +++ b/src/mapgen_singlenode.cpp @@ -42,6 +42,7 @@ void MapgenSinglenodeParams::writeParams(Settings *settings) { /////////////////////////////////////////////////////////////////////////////// MapgenSinglenode::MapgenSinglenode(int mapgenid, MapgenSinglenodeParams *params) { + flags = params->flags; } @@ -91,8 +92,9 @@ void MapgenSinglenode::makeChunk(BlockMakeData *data) { updateLiquid(&data->transforming_liquid, node_min, node_max); // Calculate lighting - calcLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, - node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE); + if (!(flags & MG_NOLIGHT)) + calcLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, + node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE); this->generating = false; } diff --git a/src/mapgen_singlenode.h b/src/mapgen_singlenode.h index 8b816aa25..e2eb1bb90 100644 --- a/src/mapgen_singlenode.h +++ b/src/mapgen_singlenode.h @@ -33,6 +33,8 @@ struct MapgenSinglenodeParams : public MapgenParams { class MapgenSinglenode : public Mapgen { public: + u32 flags; + MapgenSinglenode(int mapgenid, MapgenSinglenodeParams *params); ~MapgenSinglenode(); diff --git a/src/mapgen_v6.cpp b/src/mapgen_v6.cpp index d3db00dc2..7643f3a48 100644 --- a/src/mapgen_v6.cpp +++ b/src/mapgen_v6.cpp @@ -459,8 +459,9 @@ void MapgenV6::makeChunk(BlockMakeData *data) { } // Calculate lighting - calcLighting(node_min - v3s16(1, 1, 1) * MAP_BLOCKSIZE, - node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE); + if (!(flags & MG_NOLIGHT)) + calcLighting(node_min - v3s16(1, 1, 1) * MAP_BLOCKSIZE, + node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE); this->generating = false; } diff --git a/src/mapgen_v7.cpp b/src/mapgen_v7.cpp index 870e7343e..861cdde62 100644 --- a/src/mapgen_v7.cpp +++ b/src/mapgen_v7.cpp @@ -77,7 +77,6 @@ MapgenV7::MapgenV7(int mapgenid, MapgenV7Params *params, EmergeManager *emerge) this->seed = (int)params->seed; this->water_level = params->water_level; this->flags = params->flags; - this->lighting = 1; this->ridges = 1; this->csize = v3s16(1, 1, 1) * params->chunksize * MAP_BLOCKSIZE; @@ -215,9 +214,9 @@ void MapgenV7::makeChunk(BlockMakeData *data) { updateLiquid(&data->transforming_liquid, full_node_min, full_node_max); - if (this->lighting) + if (!(flags & MG_NOLIGHT)) calcLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, - node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE); + node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE); //setLighting(node_min - v3s16(1, 0, 1) * MAP_BLOCKSIZE, // node_max + v3s16(1, 0, 1) * MAP_BLOCKSIZE, 0xFF); diff --git a/src/mapgen_v7.h b/src/mapgen_v7.h index 6267350d6..e39bf7158 100644 --- a/src/mapgen_v7.h +++ b/src/mapgen_v7.h @@ -59,7 +59,6 @@ public: int ystride; u32 flags; - bool lighting; bool ridges; u32 blockseed; diff --git a/src/script/cpp_api/s_env.cpp b/src/script/cpp_api/s_env.cpp index 334d196bc..632b28f45 100644 --- a/src/script/cpp_api/s_env.cpp +++ b/src/script/cpp_api/s_env.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common/c_converter.h" #include "log.h" #include "environment.h" +#include "mapgen.h" #include "lua_api/l_env.h" extern "C" { @@ -55,6 +56,33 @@ void ScriptApiEnv::environment_Step(float dtime) runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); } +void ScriptApiEnv::environment_OnMapgenInit(MapgenParams *mgparams) +{ + SCRIPTAPI_PRECHECKHEADER + + // Get minetest.registered_on_mapgen_inits + lua_getglobal(L, "minetest"); + lua_getfield(L, -1, "registered_on_mapgen_inits"); + + // Call callbacks + lua_newtable(L); + + lua_pushstring(L, mgparams->mg_name.c_str()); + lua_setfield(L, -2, "mgname"); + + lua_pushinteger(L, mgparams->seed); + lua_setfield(L, -2, "seed"); + + lua_pushinteger(L, mgparams->water_level); + lua_setfield(L, -2, "water_level"); + + std::string flagstr = writeFlagString(mgparams->flags, flagdesc_mapgen); + lua_pushstring(L, flagstr.c_str()); + lua_setfield(L, -2, "flags"); + + runCallbacks(1, RUN_CALLBACKS_MODE_FIRST); +} + void ScriptApiEnv::initializeEnvironment(ServerEnvironment *env) { SCRIPTAPI_PRECHECKHEADER diff --git a/src/script/cpp_api/s_env.h b/src/script/cpp_api/s_env.h index c5b739eb4..51cf15036 100644 --- a/src/script/cpp_api/s_env.h +++ b/src/script/cpp_api/s_env.h @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irr_v3d.h" class ServerEnvironment; +struct MapgenParams; class ScriptApiEnv : virtual public ScriptApiBase @@ -33,6 +34,8 @@ public: void environment_Step(float dtime); // After generating a piece of map void environment_OnGenerated(v3s16 minp, v3s16 maxp,u32 blockseed); + // After initializing mapgens + void environment_OnMapgenInit(MapgenParams *mgparams); void initializeEnvironment(ServerEnvironment *env); }; diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index b5c40977e..b6bafbcd9 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -652,6 +652,59 @@ int ModApiEnvMod::l_get_mapgen_object(lua_State *L) return nargs; } +// minetest.set_mapgen_params(params) +// set mapgen parameters +int ModApiEnvMod::l_set_mapgen_params(lua_State *L) +{ + if (!lua_istable(L, 1)) + return 0; + + EmergeManager *emerge = getServer(L)->getEmergeManager(); + if (emerge->mapgen.size()) + return 0; + + MapgenParams *oparams = new MapgenParams; + u32 paramsmodified = 0; + u32 flagmask = 0; + + lua_getfield(L, 1, "mgname"); + if (lua_isstring(L, -1)) { + oparams->mg_name = std::string(lua_tostring(L, -1)); + paramsmodified |= MGPARAMS_SET_MGNAME; + } + + lua_getfield(L, 1, "seed"); + if (lua_isnumber(L, -1)) { + oparams->seed = lua_tointeger(L, -1); + paramsmodified |= MGPARAMS_SET_SEED; + } + + lua_getfield(L, 1, "water_level"); + if (lua_isnumber(L, -1)) { + oparams->water_level = lua_tointeger(L, -1); + paramsmodified |= MGPARAMS_SET_WATER_LEVEL; + } + + lua_getfield(L, 1, "flags"); + if (lua_isstring(L, -1)) { + std::string flagstr = std::string(lua_tostring(L, -1)); + oparams->flags = readFlagString(flagstr, flagdesc_mapgen); + paramsmodified |= MGPARAMS_SET_FLAGS; + + lua_getfield(L, 1, "flagmask"); + if (lua_isstring(L, -1)) { + flagstr = std::string(lua_tostring(L, -1)); + flagmask = readFlagString(flagstr, flagdesc_mapgen); + } + } + + emerge->luaoverride_params = oparams; + emerge->luaoverride_params_modified = paramsmodified; + emerge->luaoverride_flagmask = flagmask; + + return 0; +} + // minetest.clear_objects() // clear all objects in the environment int ModApiEnvMod::l_clear_objects(lua_State *L) @@ -799,6 +852,7 @@ bool ModApiEnvMod::Initialize(lua_State *L,int top) retval &= API_FCT(get_perlin_map); retval &= API_FCT(get_voxel_manip); retval &= API_FCT(get_mapgen_object); + retval &= API_FCT(set_mapgen_params); 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 8f769e350..713cfa69f 100644 --- a/src/script/lua_api/l_env.h +++ b/src/script/lua_api/l_env.h @@ -117,6 +117,10 @@ private: // minetest.get_mapgen_object(objectname) // returns the requested object used during map generation static int l_get_mapgen_object(lua_State *L); + + // minetest.set_mapgen_params(params) + // set mapgen parameters + static int l_set_mapgen_params(lua_State *L); // minetest.clear_objects() // clear all objects in the environment diff --git a/src/server.cpp b/src/server.cpp index 016922103..1618a0915 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -807,7 +807,12 @@ Server::Server( ServerMap *servermap = new ServerMap(path_world, this, m_emerge); m_env = new ServerEnvironment(servermap, m_script, this, this); - m_emerge->initMapgens(servermap->getMapgenParams()); + // Run some callbacks after the MG params have been set up but before activation + MapgenParams *mgparams = servermap->getMapgenParams(); + m_script->environment_OnMapgenInit(mgparams); + + // Initialize mapgens + m_emerge->initMapgens(mgparams); // Give environment reference to scripting api m_script->initializeEnvironment(m_env);