Add Lua on_mapgen_init callback, and minetest.set_mapgen_params API
authorkwolekr <kwolekr@minetest.net>
Thu, 27 Jun 2013 21:06:52 +0000 (17:06 -0400)
committerkwolekr <kwolekr@minetest.net>
Fri, 28 Jun 2013 02:35:35 +0000 (22:35 -0400)
18 files changed:
builtin/misc_register.lua
doc/lua_api.txt
minetest.conf.example
src/emerge.cpp
src/emerge.h
src/mapgen.cpp
src/mapgen.h
src/mapgen_math.cpp
src/mapgen_singlenode.cpp
src/mapgen_singlenode.h
src/mapgen_v6.cpp
src/mapgen_v7.cpp
src/mapgen_v7.h
src/script/cpp_api/s_env.cpp
src/script/cpp_api/s_env.h
src/script/lua_api/l_env.cpp
src/script/lua_api/l_env.h
src/server.cpp

index 4041fb9e21fe92a1fc43839f5e54a8d6a228737f..2d25568b61cca60e14128afe724324766a0386a9 100644 (file)
@@ -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()
index 62abb2e3ed8d2616c6e8d06c02c059379319f7a1..a4e1372da2981872ec101c896665ac9a9e33815e 100644 (file)
@@ -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
index 07063b9138dc150d88936559f8a72e25973f2fe4..3f1977268967daf3dcbe1bcb7e2f96b7ef795de8 100644 (file)
 #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
index e1e6c6574ad7a3153caf68a211f3e89495c6c5a4..09a58149d38f3e2a9fb7709db2807393f6c11664 100644 (file)
@@ -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);
index d51177110366d077b9fcc4b99de50db4b98bc00d..ee95c348f9e1a595c2fa69c88853e49dc116d85e 100644 (file)
@@ -24,6 +24,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <queue>
 #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<v3s16, BlockEmergeData *> blocks_enqueued;
index d1a38bb20726bfee98c491d9177301b5bbf7d8af..d80d2107fa3bbdf03ca6b49f662136c4767de7d7 100644 (file)
@@ -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}
 };
 
index 96a27ade77588feadbfb90ef90ee6a18cdf59329..9a8b99c4a1bec34d5e33e6be3a88d67a173823de 100644 (file)
@@ -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() {}
 };
 
index a8a093a4a3462837649a9a429e651831e807df6a..6d0bf12923436c4d7a89ec3ead70b7f121a637b6 100644 (file)
@@ -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();
index f05ddd2f4e32a137e3b3188354f1a6fc014c79b7..30787c6bb660bfbae38231e3e20f8e783f7b78ce 100644 (file)
@@ -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;
 }
index 8b816aa25af0b25414e059b6cbeeeeea222742cd..e2eb1bb9006f8f4f4178218c69618ec6ef04419f 100644 (file)
@@ -33,6 +33,8 @@ struct MapgenSinglenodeParams : public MapgenParams {
 
 class MapgenSinglenode : public Mapgen {
 public:
+       u32 flags;
+
        MapgenSinglenode(int mapgenid, MapgenSinglenodeParams *params);
        ~MapgenSinglenode();
        
index d3db00dc20b0d93807a2376704cc69e118edf1f6..7643f3a48920ce4d187294ac7c52fcd62eba9b95 100644 (file)
@@ -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;
 }
index 870e7343e4f894781388b4cae3b2b70015a408dc..861cdde626089acad778bd078ef59d05365c39ee 100644 (file)
@@ -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);
 
index 6267350d633dc368ccc2847eb98cab0eabf59ef7..e39bf715857b0f5cabf42f62f608f47c455c1de4 100644 (file)
@@ -59,7 +59,6 @@ public:
 
        int ystride;
        u32 flags;
-       bool lighting;
        bool ridges;
 
        u32 blockseed;
index 334d196bc68c2c49875cc22960179781dca9d69d..632b28f458c5e455e4ab49b6bb6fc65550bf9954 100644 (file)
@@ -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
index c5b739eb4ec9b869be66bc4c943486c6e890ad97..51cf15036e450b44e3676eacbccd89743fb3941a 100644 (file)
@@ -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);
 };
index b5c40977ef2960de65900b98dcb7f91d16a2dacc..b6bafbcd99bda5afe309ce7ef69ef3061438cf6e 100644 (file)
@@ -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);
index 8f769e35001b3484f8ab1a90a3066ddb69ddfbfe..713cfa69f1095446fa6b69112aca126d30080795 100644 (file)
@@ -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
index 01692210354d2b0be254b9099852d1c9e7dc1034..1618a091522f885f29df63c49009135026a78558 100644 (file)
@@ -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);