Add initial Lua biomedef support, fixed biome selection
authorkwolekr <mirrorisim@gmail.com>
Tue, 18 Dec 2012 18:23:16 +0000 (13:23 -0500)
committerPerttu Ahola <celeron55@gmail.com>
Mon, 21 Jan 2013 19:41:37 +0000 (21:41 +0200)
games/minimal/mods/default/init.lua
src/biome.cpp
src/biome.h
src/mapgen.cpp
src/noise.cpp
src/noise.h
src/scriptapi.cpp
src/server.h

index 9900b98a5076683cbd3d2a246483b4d4a6dd6e90..15cc5a0bdf6b1393acde64d329e84a05a3fb464d 100644 (file)
@@ -1586,6 +1586,82 @@ minetest.register_alias("mapgen_stone_with_coal", "default:stone_with_coal")
 minetest.register_alias("mapgen_stone_with_iron", "default:stone_with_iron")
 minetest.register_alias("mapgen_mese", "default:mese")
 
+minetest.register_biome_groups({
+0.35, 0.30, 0.20
+})
+
+--
+-- Register the biomes for the map generator
+--
+minetest.register_biome({
+       group_id = 0,
+       name = "Ocean",
+       terrain_type = "liquid",
+       node_top = "default:gravel",
+       node_filler = "default:stone",
+       num_top_nodes = 4,
+       height_min = -3000,
+       height_max = 3000,
+       heat_min = -20.0,
+       heat_max = 100.0,
+       humidity_min = 0.0,
+       humidity_max = 100.0,
+       scale = 10.0,
+       offset = -10.0,
+})
+
+minetest.register_biome({
+       group_id = 1,
+       name = "Beach",
+       terrain_type = "normal",
+       node_top = "default:sand",
+       node_filler = "default:stone",
+       num_top_nodes = 5,
+       height_min = -3000,
+       height_max = 3000,
+       heat_min = 60.0,
+       heat_max = 100.0,
+       humidity_min = 0.0,
+       humidity_max = 100.0,
+       scale = 5.0,
+       offset = 5.0,
+})
+
+minetest.register_biome({
+       group_id = 2,
+       name = "Land",
+       terrain_type = "normal",
+       node_top = "default:dirt_with_grass",
+       node_filler = "default:stone",
+       num_top_nodes = 5,
+       height_min = -3000,
+       height_max = 3000,
+       heat_min = -50.0,
+       heat_max = 100.0,
+       humidity_min = 0.0,
+       humidity_max = 100.0,
+       scale = 12.0,
+       offset = 10.0,
+})
+
+minetest.register_biome({
+       group_id = 3,
+       name = "Hills",
+       terrain_type = "normal",
+       node_top = "default:dirt",
+       node_filler = "default:stone",
+       num_top_nodes = 3,
+       height_min = -3000,
+       height_max = 3000,
+       heat_min = -50.0,
+       heat_max = 100.0,
+       humidity_min = 0.0,
+       humidity_max = 100.0,
+       scale = 70.0,
+       offset = 30.0,
+})
+
+
 -- Support old code
 function default.spawn_falling_node(p, nodename)
        spawn_falling_node(p, nodename)
index 4b240d5a546f46a21a870ac99e5eacaf23737fb4..c66c2494c405fd6a844e3b47ef3249772c7c2ab3 100644 (file)
@@ -64,11 +64,14 @@ int bg4_biomes[]  = {BT_HILLS, BT_EXTREMEHILLS, BT_MOUNTAINS, BT_DESERT, BT_DESE
 float bg5_temps[] = {5.0, 40.0};
 int bg5_biomes[]  = {BT_LAKE, BT_PLAINS, BT_DESERT};*/
 
+NoiseParams np_default = {0.0, 20.0, v3f(250., 250., 250.), 82341, 5, 0.6};
+
 
 BiomeDefManager::BiomeDefManager(IGameDef *gamedef) {
        this->m_gamedef = gamedef;
        this->ndef      = gamedef->ndef();
 
+       bgroups.push_back(new std::vector<Biome *>); //the initial biome group
        //addDefaultBiomes(); //can't do this in the ctor, too early
 }
 
@@ -79,19 +82,51 @@ BiomeDefManager::~BiomeDefManager() {
 }
 
 
-void BiomeDefManager::addBiome() {
+Biome *BiomeDefManager::createBiome(BiomeTerrainType btt) {
+       switch (btt) {
+               case BIOME_TERRAIN_NORMAL:
+                       return new Biome;
+               case BIOME_TERRAIN_LIQUID:
+                       return new BiomeLiquid;
+               case BIOME_TERRAIN_NETHER:
+                       return new BiomeHell;
+               case BIOME_TERRAIN_AETHER:
+                       return new BiomeAether;
+               case BIOME_TERRAIN_FLAT:
+                       return new BiomeSuperflat;
+       }
+}
+
+
+void BiomeDefManager::addBiomeGroup(float freq) {
+       int size = bgroup_freqs.size();
+       float newfreq = freq;
 
+       if (size)
+               newfreq += bgroup_freqs[size - 1];
+       bgroup_freqs.push_back(newfreq);
+       bgroups.push_back(new std::vector<Biome *>);
+       printf("added biome with freq %f\n", newfreq);
 }
 
 
-NoiseParams npmtdef = {0.0, 20.0, v3f(250., 250., 250.), 82341, 5, 0.6};
+void BiomeDefManager::addBiome(int groupid, Biome *b) {
+       std::vector<Biome *> *bgroup;
+
+       if (groupid >= bgroups.size()) {
+               printf("blahblahblah");
+               return;
+       }
+
+       bgroup = bgroups[groupid];
+       bgroup->push_back(b);
+}
+
 
 void BiomeDefManager::addDefaultBiomes() {
        std::vector<Biome *> *bgroup;
        Biome *b;
 
-       //bgroup = new std::vector<Biome *>;
-
        b = new Biome;
        b->name         = "Default";
        b->n_top        = MapNode(ndef->getId("mapgen_stone"));
@@ -103,30 +138,25 @@ void BiomeDefManager::addDefaultBiomes() {
        b->heat_max     = FLT_MAX;
        b->humidity_min = FLT_MIN;
        b->humidity_max = FLT_MAX;
-       b->np = &npmtdef;
+       b->np = &np_default;
        biome_default = b;
-
-       //bgroup->push_back(b);
-       //bgroups.push_back(bgroup);
 }
 
 
 Biome *BiomeDefManager::getBiome(float bgfreq, float heat, float humidity) {
-       std::vector<Biome *> bgroup;
+       std::vector<Biome *> *bgroup;
        Biome *b;
        int i;
 
        int ngroups = bgroup_freqs.size();
        if (!ngroups)
                return biome_default;
-       for (i = 0; (i != ngroups - 1) && (bgfreq > bgroup_freqs[i]); i++);
-       bgroup = *(bgroups[i]);
+       for (i = 0; (i != ngroups) && (bgfreq > bgroup_freqs[i]); i++);
+       bgroup = bgroups[i];
 
-       int nbiomes = bgroup.size();
-       if (!nbiomes)
-               return biome_default;
-       for (i = 0; i != nbiomes - 1; i++) {
-               b = bgroup[i];
+       int nbiomes = bgroup->size();
+       for (i = 0; i != nbiomes; i++) {
+               b = bgroup->operator[](i);///////////////////////////
                if (heat >= b->heat_min && heat <= b->heat_max &&
                        humidity >= b->humidity_min && humidity <= b->humidity_max)
                        return b;
@@ -145,13 +175,11 @@ int Biome::getSurfaceHeight(float noise_terrain) {
 
 
 void Biome::genColumn(Mapgen *mg, int x, int z, int y1, int y2) {
-       //printf("(%d, %d): %f\n", x, z, mg->map_terrain[z * mg->ystride + x]);
-
-       //int surfaceh = 4;
-       int surfaceh = np->offset + np->scale * mg->map_terrain[(z - mg->node_min.Z) * 80 /*THIS IS TEMPORARY mg->ystride*/ + (x - mg->node_min.X)];
-       //printf("gen column %f\n", );
+       int i = (z - mg->node_min.Z) * mg->csize.Z + (x - mg->node_min.X);
+       int surfaceh = np->offset + np->scale * mg->map_terrain[i];
        int y = y1;
-       int i = mg->vmanip->m_area.index(x, y, z);  //z * mg->zstride + x + (y - mg->vmanip->m_area.MinEdge.Y) * mg->ystride;
+
+       i = mg->vmanip->m_area.index(x, y, z);
        for (; y <= surfaceh - ntopnodes && y <= y2; y++, i += mg->ystride)
                mg->vmanip->m_data[i] = n_filler;
        for (; y <= surfaceh && y <= y2; y++, i += mg->ystride)
@@ -166,16 +194,18 @@ void Biome::genColumn(Mapgen *mg, int x, int z, int y1, int y2) {
 
 
 
-void BiomeOcean::genColumn(Mapgen *mg, int x, int z, int y1, int y2) {
-       int y, i = 0;
-
-       int surfaceh = np->offset + np->scale * mg->map_terrain[z * mg->ystride + x];
+void BiomeLiquid::genColumn(Mapgen *mg, int x, int z, int y1, int y2) {
+       int i = (z - mg->node_min.Z) * mg->csize.Z + (x - mg->node_min.X);
+       int surfaceh = np->offset + np->scale * mg->map_terrain[i];
+       int y = y1;
 
-       i = z * mg->zstride + x;
-       for (y = y1; y <= surfaceh - ntopnodes && y <= y2; y++, i += mg->ystride)
+       i = mg->vmanip->m_area.index(x, y, z);
+       for (; y <= surfaceh - ntopnodes && y <= y2; y++, i += mg->ystride)
                mg->vmanip->m_data[i] = n_filler;
        for (; y <= surfaceh && y <= y2; y++, i += mg->ystride)
                mg->vmanip->m_data[i] = n_top;
+       for (; y <= mg->water_level && y <= y2; y++, i += mg->ystride)
+               mg->vmanip->m_data[i] = mg->n_water;
        for (; y <= y2; y++, i += mg->ystride)
                mg->vmanip->m_data[i] = mg->n_air;
 }
@@ -190,22 +220,23 @@ int BiomeHell::getSurfaceHeight(float noise_terrain) {
 
 
 void BiomeHell::genColumn(Mapgen *mg, int x, int z, int y1, int y2) {
-       int y, i = 0;
-
-       int surfaceh = np->offset + np->scale * mg->map_terrain[z * mg->ystride + x];
 
-       i = z * mg->zstride + x;
-       for (y = y1; y <= surfaceh - ntopnodes && y <= y2; y++, i += mg->ystride)
-               mg->vmanip->m_data[i] = n_filler;
-       for (; y <= surfaceh && y <= y2; y++, i += mg->ystride)
-               mg->vmanip->m_data[i] = n_top;
-       for (; y <= y2; y++, i += mg->ystride)
-               mg->vmanip->m_data[i] = mg->n_air;
 }
 
 
 ///////////////////////////// [ Aether biome ] ////////////////////////////////
 
+
+int BiomeAether::getSurfaceHeight(float noise_terrain) {
+       return np->offset + np->scale * noise_terrain;
+}
+
+
+void BiomeAether::genColumn(Mapgen *mg, int x, int z, int y1, int y2) {
+
+}
+
+
 /////////////////////////// [ Superflat biome ] ///////////////////////////////
 
 
@@ -215,15 +246,5 @@ int BiomeSuperflat::getSurfaceHeight(float noise_terrain) {
 
 
 void BiomeSuperflat::genColumn(Mapgen *mg, int x, int z, int y1, int y2) {
-       int y, i = 0;
-
-       int surfaceh = ntopnodes;
 
-       i = z * mg->zstride + x;
-       for (y = y1; y <= surfaceh - ntopnodes && y <= y2; y++, i += mg->ystride)
-               mg->vmanip->m_data[i] = n_filler;
-       for (; y <= surfaceh && y <= y2; y++, i += mg->ystride)
-               mg->vmanip->m_data[i] = n_top;
-       for (; y <= y2; y++, i += mg->ystride)
-               mg->vmanip->m_data[i] = mg->n_air;
 }
index 5e43ab6d758f61f70a70925654c423042abd3477..bb35dd1c405c5ac2f85fbe423e0e9bc10b9af245 100644 (file)
@@ -20,12 +20,23 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #ifndef BIOME_HEADER
 #define BIOME_HEADER
 
+#include <string>
 #include "nodedef.h"
 #include "gamedef.h"
 #include "mapnode.h"
 #include "noise.h"
 #include "mapgen.h"
 
+
+enum BiomeTerrainType
+{
+       BIOME_TERRAIN_NORMAL,
+       BIOME_TERRAIN_LIQUID,
+       BIOME_TERRAIN_NETHER,
+       BIOME_TERRAIN_AETHER,
+       BIOME_TERRAIN_FLAT
+};
+
 class Biome {
 public:
        MapNode n_top;
@@ -38,14 +49,14 @@ public:
        float heat_max;
        float humidity_min;
        float humidity_max;
-       const char *name;
+       std::string name;
        NoiseParams *np;
 
        virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2);
        virtual int getSurfaceHeight(float noise_terrain);
 };
 
-class BiomeOcean : public Biome {
+class BiomeLiquid : public Biome {
        virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2);
 };
 
@@ -54,6 +65,11 @@ class BiomeHell : public Biome {
        virtual int getSurfaceHeight(float noise_terrain);
 };
 
+class BiomeAether : public Biome {
+       virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2);
+       virtual int getSurfaceHeight(float noise_terrain);
+};
+
 class BiomeSuperflat : public Biome {
        virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2);
        virtual int getSurfaceHeight(float noise_terrain);
@@ -70,9 +86,11 @@ public:
        BiomeDefManager(IGameDef *gamedef);
        ~BiomeDefManager();
 
+       Biome *createBiome(BiomeTerrainType btt);
        Biome *getBiome(float bgfreq, float heat, float humidity);
 
-       void addBiome();
+       void addBiomeGroup(float freq);
+       void addBiome(int groupid, Biome *b);
        void addDefaultBiomes();
 };
 
index 7271b7652c5f9d46116fc0018bb11c0274d542cb..f9c27ac1eb27664ab28e28130cbe346cadb108c7 100644 (file)
@@ -35,9 +35,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "treegen.h"
 
 NoiseParams nparams_mtdefault =
-       {0.0, 20.0, v3f(250., 250., 250.), 82341, 5, 0.6}; //terrain
+       {10.0, 12.0, v3f(350., 350., 350.), 82341, 5, 0.6}; //terrain
 NoiseParams nparams_def_bgroup =
-       {0.5, 1/(2*1.6), v3f(250., 250., 250.), 5923, 2, 0.60}; //0 to 1
+       {0.5, 1/(2*1.6), v3f(350., 350., 350.), 5923, 2, 0.60}; //0 to 1
 NoiseParams nparams_def_heat =
        {25.0, 50.0, v3f(500., 500., 500.), 35293, 1, 0.00}; //-25 to 75
 NoiseParams nparams_def_humidity =
@@ -139,9 +139,13 @@ void Mapgen::makeChunk(BlockMakeData *data) {
        map_heat     = noise_heat->perlinMap2D(x, z);
        map_humidity = noise_humidity->perlinMap2D(x, z);
 
+       noise_bgroup->transformNoiseMap();
+       noise_heat->transformNoiseMap();
+       noise_humidity->transformNoiseMap();
+
        int i = 0;
-       for (x = node_min.X; x <= node_max.X; x++) {
-               for (z = node_min.Z; z <= node_max.Z; z++) {
+       for (z = node_min.Z; z <= node_max.Z; z++) {
+               for (x = node_min.X; x <= node_max.X; x++) {
                        Biome *biome = biomedef->getBiome(map_bgroup[i], map_heat[i], map_humidity[i]);
                        biome->genColumn(this, x, z, y1, y2);
                        i++;
@@ -153,7 +157,7 @@ void Mapgen::makeChunk(BlockMakeData *data) {
        //genDungeon();
        //add blobs of dirt and gravel underground
        //decorateChunk();
-       //updateLiquid(full_node_min, full_node_max);
+       updateLiquid(full_node_min, full_node_max);
        updateLighting(node_min, node_max);
 
        this->generating = false;
@@ -164,7 +168,6 @@ void Mapgen::makeChunk(BlockMakeData *data) {
 void Mapgen::updateLiquid(v3s16 node_min, v3s16 node_max) {
        bool isliquid, wasliquid;
        u32 i;
-       content_t c;
 
        for (s16 z = node_min.Z; z <= node_max.Z; z++) {
                for (s16 x = node_min.X; x <= node_max.X; x++) {
index 5cb4be29a1d7ce862f800b33a9bed7366696d01c..3874848ad3836672138caa24cc36d6268fd6f3eb 100644 (file)
@@ -287,7 +287,7 @@ Noise::Noise(NoiseParams *np, int seed, int sx, int sy) {
        this->seed = seed;
        this->sx   = sx;
        this->sy   = sy;
-       this->sz   = 0;
+       this->sz   = 1;
        this->noisebuf = new float[nlx * nly];
        this->buf      = new float[sx * sy];
        this->result   = new float[sx * sy];
@@ -538,3 +538,16 @@ float *Noise::perlinMap3D(float x, float y, float z) {
 
        return result;
 }
+
+
+void Noise::transformNoiseMap() {
+       int i = 0;
+       for (int z = 0; z != sz; z++) {
+               for (int y = 0; y != sy; y++) {
+                       for (int x = 0; x != sx; x++) {
+                               result[i] = result[i] * np->scale + np->offset;
+                               i++;
+                       }
+               }
+       }
+}
index 6e5120003f21e94c4d9fa2aa6e63d12f328b4b36..0ab162b73a9f504e135cf107c382dbd976aaab05 100644 (file)
@@ -95,6 +95,7 @@ public:
                int seed);
        float *perlinMap2D(float x, float y);
        float *perlinMap3D(float x, float y, float z);
+       void transformNoiseMap();
 };
 
 // Return value: -1 ... 1
index 69ee48a7630a93f01b1445f1e9ea7a6c28286696..27f48be27af150f802569a8bf659bf5cb8909392 100644 (file)
@@ -37,6 +37,7 @@ extern "C" {
 #include "content_sao.h" // For LuaEntitySAO and PlayerSAO
 #include "itemdef.h"
 #include "nodedef.h"
+#include "biome.h"
 #include "craftdef.h"
 #include "main.h" // For g_settings
 #include "settings.h" // For accessing g_settings
@@ -436,6 +437,16 @@ struct EnumString es_TileAnimationType[] =
        {0, NULL},
 };
 
+struct EnumString es_BiomeTerrainType[] =
+{
+       {BIOME_TERRAIN_NORMAL, "normal"},
+       {BIOME_TERRAIN_LIQUID, "liquid"},
+       {BIOME_TERRAIN_NETHER, "nether"},
+       {BIOME_TERRAIN_AETHER, "aether"},
+       {BIOME_TERRAIN_FLAT,   "flat"},
+       {0, NULL},
+};
+
 /*
        C struct <-> Lua table converter functions
 */
@@ -988,7 +999,7 @@ static void read_object_properties(lua_State *L, int index,
        if(lua_istable(L, -1))
                prop->initial_sprite_basepos = read_v2s16(L, -1);
        lua_pop(L, 1);
-       
+
        getboolfield(L, -1, "is_visible", prop->is_visible);
        getboolfield(L, -1, "makes_footstep_sound", prop->makes_footstep_sound);
        getfloatfield(L, -1, "automatic_rotate", prop->automatic_rotate);
@@ -1032,7 +1043,7 @@ static ItemDefinition read_item_definition(lua_State *L, int index,
 
        warn_if_field_exists(L, index, "tool_digging_properties",
                        "deprecated: use tool_capabilities");
-       
+
        lua_getfield(L, index, "tool_capabilities");
        if(lua_istable(L, -1)){
                def.tool_capabilities = new ToolCapabilities(
@@ -1067,7 +1078,7 @@ static TileDef read_tiledef(lua_State *L, int index)
 {
        if(index < 0)
                index = lua_gettop(L) + 1 + index;
-       
+
        TileDef tiledef;
 
        // key at index -2 and value at index
@@ -1113,7 +1124,7 @@ static ContentFeatures read_content_features(lua_State *L, int index)
                index = lua_gettop(L) + 1 + index;
 
        ContentFeatures f;
-       
+
        /* Cache existence of some callbacks */
        lua_getfield(L, index, "on_construct");
        if(!lua_isnil(L, -1)) f.has_on_construct = true;
@@ -1138,7 +1149,7 @@ static ContentFeatures read_content_features(lua_State *L, int index)
        f.drawtype = (NodeDrawType)getenumfield(L, index, "drawtype", es_DrawType,
                        NDT_NORMAL);
        getfloatfield(L, index, "visual_scale", f.visual_scale);
-       
+
        // tiles = {}
        lua_getfield(L, index, "tiles");
        // If nil, try the deprecated name "tile_images" instead
@@ -1173,7 +1184,7 @@ static ContentFeatures read_content_features(lua_State *L, int index)
                }
        }
        lua_pop(L, 1);
-       
+
        // special_tiles = {}
        lua_getfield(L, index, "special_tiles");
        // If nil, try the deprecated name "special_materials" instead
@@ -1204,7 +1215,7 @@ static ContentFeatures read_content_features(lua_State *L, int index)
        f.alpha = getintfield_default(L, index, "alpha", 255);
 
        /* Other stuff */
-       
+
        lua_getfield(L, index, "post_effect_color");
        if(!lua_isnil(L, -1))
                f.post_effect_color = readARGB8(L, -1);
@@ -1228,7 +1239,7 @@ static ContentFeatures read_content_features(lua_State *L, int index)
                        "deprecated: use 'drop' field");
        warn_if_field_exists(L, index, "metadata_name",
                        "deprecated: use on_add and metadata callbacks");
-       
+
        // True for all ground-like things like stone and mud, false for eg. trees
        getboolfield(L, index, "is_ground_content", f.is_ground_content);
        f.light_propagates = (f.param_type == CPT_LIGHT);
@@ -1264,7 +1275,7 @@ static ContentFeatures read_content_features(lua_State *L, int index)
                        "light_source", f.light_source);
        f.damage_per_second = getintfield_default(L, index,
                        "damage_per_second", f.damage_per_second);
-       
+
        lua_getfield(L, index, "node_box");
        if(lua_istable(L, -1))
                f.node_box = read_nodebox(L, -1);
@@ -1279,7 +1290,7 @@ static ContentFeatures read_content_features(lua_State *L, int index)
        getboolfield(L, index, "legacy_facedir_simple", f.legacy_facedir_simple);
        // Set to true if wall_mounted used to be set to true
        getboolfield(L, index, "legacy_wallmounted", f.legacy_wallmounted);
-       
+
        // Sound table
        lua_getfield(L, index, "sounds");
        if(lua_istable(L, -1)){
@@ -1368,7 +1379,7 @@ private:
        static const luaL_reg methods[];
 
        // Exported functions
-       
+
        // garbage collector
        static int gc_object(lua_State *L)
        {
@@ -1621,7 +1632,7 @@ public:
        {
                return m_stack;
        }
-       
+
        // LuaItemStack(itemstack or itemstring or table or nil)
        // Creates an LuaItemStack and leaves it on top of stack
        static int create_object(lua_State *L)
@@ -1810,7 +1821,7 @@ private:
                if(!ud) luaL_typerror(L, narg, className);
                return *(InvRef**)ud;  // unbox pointer
        }
-       
+
        static Inventory* getinv(lua_State *L, InvRef *ref)
        {
                return get_server(L)->getInventory(ref->m_loc);
@@ -1830,9 +1841,9 @@ private:
                // Inform other things that the inventory has changed
                get_server(L)->setInventoryModified(ref->m_loc);
        }
-       
+
        // Exported functions
-       
+
        // garbage collector
        static int gc_object(lua_State *L) {
                InvRef *o = *(InvRef **)(lua_touserdata(L, 1));
@@ -2185,7 +2196,7 @@ private:
                if(!ud) luaL_typerror(L, narg, className);
                return *(NodeMetaRef**)ud;  // unbox pointer
        }
-       
+
        static NodeMetadata* getmeta(NodeMetaRef *ref, bool auto_create)
        {
                NodeMetadata *meta = ref->m_env->getMap().getNodeMetadata(ref->m_p);
@@ -2212,9 +2223,9 @@ private:
                        block->raiseModified(MOD_STATE_WRITE_NEEDED,
                                        "NodeMetaRef::reportMetadataChange");
        }
-       
+
        // Exported functions
-       
+
        // garbage collector
        static int gc_object(lua_State *L) {
                NodeMetaRef *o = *(NodeMetaRef **)(lua_touserdata(L, 1));
@@ -2327,7 +2338,7 @@ private:
                InvRef::createNodeMeta(L, ref->m_p);
                return 1;
        }
-       
+
        // to_table(self)
        static int l_to_table(lua_State *L)
        {
@@ -2373,7 +2384,7 @@ private:
        {
                NodeMetaRef *ref = checkobject(L, 1);
                int base = 2;
-               
+
                if(lua_isnil(L, base)){
                        // No metadata
                        ref->m_env->getMap().removeNodeMetadata(ref->m_p);
@@ -2497,7 +2508,7 @@ public:
                if(!ud) luaL_typerror(L, narg, className);
                return *(ObjectRef**)ud;  // unbox pointer
        }
-       
+
        static ServerActiveObject* getobject(ObjectRef *ref)
        {
                ServerActiveObject *co = ref->m_object;
@@ -2513,7 +2524,7 @@ private:
                        return NULL;
                return (LuaEntitySAO*)obj;
        }
-       
+
        static PlayerSAO* getplayersao(ObjectRef *ref)
        {
                ServerActiveObject *obj = getobject(ref);
@@ -2523,7 +2534,7 @@ private:
                        return NULL;
                return (PlayerSAO*)obj;
        }
-       
+
        static Player* getplayer(ObjectRef *ref)
        {
                PlayerSAO *playersao = getplayersao(ref);
@@ -2531,9 +2542,9 @@ private:
                        return NULL;
                return playersao->getPlayer();
        }
-       
+
        // Exported functions
-       
+
        // garbage collector
        static int gc_object(lua_State *L) {
                ObjectRef *o = *(ObjectRef **)(lua_touserdata(L, 1));
@@ -2552,7 +2563,7 @@ private:
                co->m_removed = true;
                return 0;
        }
-       
+
        // getpos(self)
        // returns: {x=num, y=num, z=num}
        static int l_getpos(lua_State *L)
@@ -2570,7 +2581,7 @@ private:
                lua_setfield(L, -2, "z");
                return 1;
        }
-       
+
        // setpos(self, pos)
        static int l_setpos(lua_State *L)
        {
@@ -2584,7 +2595,7 @@ private:
                co->setPos(pos);
                return 0;
        }
-       
+
        // moveto(self, pos, continuous=false)
        static int l_moveto(lua_State *L)
        {
@@ -2856,7 +2867,7 @@ private:
                co->setVelocity(pos);
                return 0;
        }
-       
+
        // getvelocity(self)
        static int l_getvelocity(lua_State *L)
        {
@@ -2868,7 +2879,7 @@ private:
                pushFloatPos(L, v);
                return 1;
        }
-       
+
        // setacceleration(self, {x=num, y=num, z=num})
        static int l_setacceleration(lua_State *L)
        {
@@ -2881,7 +2892,7 @@ private:
                co->setAcceleration(pos);
                return 0;
        }
-       
+
        // getacceleration(self)
        static int l_getacceleration(lua_State *L)
        {
@@ -2893,7 +2904,7 @@ private:
                pushFloatPos(L, v);
                return 1;
        }
-       
+
        // setyaw(self, radians)
        static int l_setyaw(lua_State *L)
        {
@@ -2905,7 +2916,7 @@ private:
                co->setYaw(yaw);
                return 0;
        }
-       
+
        // getyaw(self)
        static int l_getyaw(lua_State *L)
        {
@@ -2917,7 +2928,7 @@ private:
                lua_pushnumber(L, yaw);
                return 1;
        }
-       
+
        // settexturemod(self, mod)
        static int l_settexturemod(lua_State *L)
        {
@@ -2929,7 +2940,7 @@ private:
                co->setTextureMod(mod);
                return 0;
        }
-       
+
        // setsprite(self, p={x=0,y=0}, num_frames=1, framelength=0.2,
        //           select_horiz_by_yawpitch=false)
        static int l_setsprite(lua_State *L)
@@ -2966,7 +2977,7 @@ private:
                lua_pushstring(L, name.c_str());
                return 1;
        }
-       
+
        // get_luaentity(self)
        static int l_get_luaentity(lua_State *L)
        {
@@ -2977,7 +2988,7 @@ private:
                luaentity_get(L, co->getId());
                return 1;
        }
-       
+
        /* Player-only */
 
        // is_player(self)
@@ -2988,7 +2999,7 @@ private:
                lua_pushboolean(L, (player != NULL));
                return 1;
        }
-       
+
        // get_player_name(self)
        static int l_get_player_name(lua_State *L)
        {
@@ -3002,7 +3013,7 @@ private:
                lua_pushstring(L, player->getName());
                return 1;
        }
-       
+
        // get_look_dir(self)
        static int l_get_look_dir(lua_State *L)
        {
@@ -3144,7 +3155,7 @@ public:
                ObjectRef *o = checkobject(L, -1);
                o->m_object = NULL;
        }
-       
+
        static void Register(lua_State *L)
        {
                lua_newtable(L);
@@ -3370,7 +3381,7 @@ private:
                if(!ud) luaL_typerror(L, narg, className);
                return *(NodeTimerRef**)ud;  // unbox pointer
        }
-       
+
        static int l_set(lua_State *L)
        {
                NodeTimerRef *o = checkobject(L, 1);
@@ -3381,7 +3392,7 @@ private:
                env->getMap().setNodeTimer(o->m_p,NodeTimer(t,e));
                return 0;
        }
-       
+
        static int l_start(lua_State *L)
        {
                NodeTimerRef *o = checkobject(L, 1);
@@ -3391,7 +3402,7 @@ private:
                env->getMap().setNodeTimer(o->m_p,NodeTimer(t,0));
                return 0;
        }
-       
+
        static int l_stop(lua_State *L)
        {
                NodeTimerRef *o = checkobject(L, 1);
@@ -3400,7 +3411,7 @@ private:
                env->getMap().removeNodeTimer(o->m_p);
                return 0;
        }
-       
+
        static int l_is_started(lua_State *L)
        {
                NodeTimerRef *o = checkobject(L, 1);
@@ -3411,7 +3422,7 @@ private:
                lua_pushboolean(L,(t.timeout != 0));
                return 1;
        }
-       
+
        static int l_get_timeout(lua_State *L)
        {
                NodeTimerRef *o = checkobject(L, 1);
@@ -3422,7 +3433,7 @@ private:
                lua_pushnumber(L,t.timeout);
                return 1;
        }
-       
+
        static int l_get_elapsed(lua_State *L)
        {
                NodeTimerRef *o = checkobject(L, 1);
@@ -3460,7 +3471,7 @@ public:
                NodeTimerRef *o = checkobject(L, -1);
                o->m_env = NULL;
        }
-       
+
        static void Register(lua_State *L)
        {
                lua_newtable(L);
@@ -3525,7 +3536,7 @@ private:
                if(!ud) luaL_typerror(L, narg, className);
                return *(EnvRef**)ud;  // unbox pointer
        }
-       
+
        // Exported functions
 
        // EnvRef:set_node(pos, node)
@@ -3969,7 +3980,7 @@ private:
                lua_getglobal(L, "table");
                lua_getfield(L, -1, "insert");
                int table_insert = lua_gettop(L);
-               
+
                lua_newtable(L);
                int table = lua_gettop(L);
                for(s16 x=minp.X; x<=maxp.X; x++)
@@ -4094,7 +4105,7 @@ public:
                EnvRef *o = checkobject(L, -1);
                o->m_env = NULL;
        }
-       
+
        static void Register(lua_State *L)
        {
                lua_newtable(L);
@@ -4147,6 +4158,8 @@ const luaL_reg EnvRef::methods[] = {
        method(EnvRef, find_node_near),
        method(EnvRef, find_nodes_in_area),
        method(EnvRef, get_perlin),
+       //method{EnvRef, get_perlin_map_2d},
+       //method{EnvRef, get_perlin_map_3d},
        method(EnvRef, clear_objects),
        method(EnvRef, spawn_tree),
        {0,0}
@@ -4166,7 +4179,7 @@ private:
        static const luaL_reg methods[];
 
        // Exported functions
-       
+
        // garbage collector
        static int gc_object(lua_State *L)
        {
@@ -4217,7 +4230,7 @@ public:
        {
                return m_pseudo;
        }
-       
+
        // LuaPseudoRandom(seed)
        // Creates an LuaPseudoRandom and leaves it on top of stack
        static int create_object(lua_State *L)
@@ -4321,7 +4334,7 @@ public:
                        u32 active_object_count, u32 active_object_count_wider)
        {
                lua_State *L = m_lua;
-       
+
                realitycheck(L);
                assert(lua_checkstack(L, 20));
                StackUnroller stack_unroller(L);
@@ -4337,7 +4350,7 @@ public:
                lua_gettable(L, registered_abms);
                if(lua_isnil(L, -1))
                        assert(0);
-               
+
                // Call action
                luaL_checktype(L, -1, LUA_TTABLE);
                lua_getfield(L, -1, "action");
@@ -4442,6 +4455,77 @@ static int l_get_server_status(lua_State *L)
        return 1;
 }
 
+// register_biome_groups({frequencies})
+static int l_register_biome_groups(lua_State *L)
+{
+       luaL_checktype(L, 1, LUA_TTABLE);
+       int index = 1;
+       if (!lua_istable(L, index)) {
+
+               return 0;
+       }
+
+       BiomeDefManager *bmgr = get_server(L)->getEmergeManager()->biomedef;
+
+       lua_pushnil(L);
+       for (int i = 1; lua_next(L, index) != 0; i++) {
+               bmgr->addBiomeGroup(lua_tonumber(L, -1));
+               lua_pop(L, 1);
+       }
+       lua_pop(L, 1);
+
+       return 0;
+}
+
+// register_biome({lots of stuff})
+static int l_register_biome(lua_State *L)
+{
+       luaL_checktype(L, 1, LUA_TTABLE);
+       int index = 1, groupid;
+       std::string nodename;
+
+       IWritableNodeDefManager *ndef = get_server(L)->getWritableNodeDefManager();
+       BiomeDefManager *bmgr = get_server(L)->getEmergeManager()->biomedef;
+
+       groupid = getintfield_default(L, index, "group_id", 0);
+
+       enum BiomeTerrainType terrain = (BiomeTerrainType)getenumfield(L, index,
+                                       "terrain_type", es_BiomeTerrainType, BIOME_TERRAIN_NORMAL);
+       Biome *b = bmgr->createBiome(terrain);
+
+       b->name = getstringfield_default(L, index, "name", "");
+
+       if (getstringfield(L, index, "node_top", nodename))
+               b->n_top = MapNode(ndef->getId(nodename));
+       else
+               b->n_top = MapNode(CONTENT_IGNORE);
+
+       if (getstringfield(L, index, "node_filler", nodename))
+               b->n_filler = MapNode(ndef->getId(nodename));
+       else
+               b->n_filler = b->n_top;
+
+       b->ntopnodes = getintfield_default(L, index, "num_top_nodes", 0);
+
+       b->height_min   = getintfield_default(L, index, "height_min", 0);
+       b->height_max   = getintfield_default(L, index, "height_max", 0);
+       b->heat_min     = getfloatfield_default(L, index, "heat_min", 0.);
+       b->heat_max     = getfloatfield_default(L, index, "heat_max", 0.);
+       b->humidity_min = getfloatfield_default(L, index, "humidity_min", 0.);
+       b->humidity_max = getfloatfield_default(L, index, "humidity_max", 0.);
+
+//////hrm, what to do about the noiseparams...
+       b->np = new NoiseParams; /////just a hacky solution
+       getfloatfield(L, index, "scale", b->np->scale);
+       getfloatfield(L, index, "offset", b->np->offset);
+       //TODO: add configurable spread factor and octaves!?
+       //I'd have to create a Noise for every Biome...
+       bmgr->addBiome(groupid, b);
+       printf(" - added biome '%s'  -  %d %d\n", b->name.c_str(), b->n_top.param0, b->n_filler.param0);
+
+       return 0;
+}
+
 // register_item_raw({lots of stuff})
 static int l_register_item_raw(lua_State *L)
 {
@@ -4481,7 +4565,7 @@ static int l_register_item_raw(lua_State *L)
                else
                        def.node_placement_prediction = "";
        }
-       
+
        // Register item definition
        idef->registerItem(def);
 
@@ -4504,9 +4588,9 @@ static int l_register_alias_raw(lua_State *L)
        // Get the writable item definition manager from the server
        IWritableItemDefManager *idef =
                        get_server(L)->getWritableItemDefManager();
-       
+
        idef->registerAlias(name, convert_to);
-       
+
        return 0; /* number of results */
 }
 
@@ -4615,7 +4699,7 @@ static int l_register_craft(lua_State *L)
        // Get the writable craft definition manager from the server
        IWritableCraftDefManager *craftdef =
                        get_server(L)->getWritableCraftDefManager();
-       
+
        std::string type = getstringfield_default(L, table, "type", "shaped");
 
        /*
@@ -4899,7 +4983,7 @@ static int l_get_inventory(lua_State *L)
                std::string name = checkstringfield(L, 1, "name");
                loc.setDetached(name);
        }
-       
+
        if(get_server(L)->getInventory(loc) != NULL)
                InvRef::create(L, loc);
        else
@@ -5116,7 +5200,7 @@ static int l_get_craft_result(lua_State *L)
        lua_getfield(L, input_i, "items");
        std::vector<ItemStack> items = read_items(L, -1);
        lua_pop(L, 1); // items
-       
+
        IGameDef *gdef = get_server(L);
        ICraftDefManager *cdef = gdef->cdef();
        CraftInput input(method, width, items);
@@ -5151,7 +5235,7 @@ static int l_get_craft_recipe(lua_State *L)
        char tmp[20];
        int input_i = 1;
        std::string o_item = luaL_checkstring(L,input_i);
-       
+
        IGameDef *gdef = get_server(L);
        ICraftDefManager *cdef = gdef->cdef();
        CraftInput input;
@@ -5254,6 +5338,8 @@ static const struct luaL_Reg minetest_f [] = {
        {"register_item_raw", l_register_item_raw},
        {"register_alias_raw", l_register_alias_raw},
        {"register_craft", l_register_craft},
+       {"register_biome", l_register_biome},
+       {"register_biome_groups", l_register_biome_groups},
        {"setting_set", l_setting_set},
        {"setting_get", l_setting_get},
        {"setting_getbool", l_setting_getbool},
@@ -5304,7 +5390,7 @@ void scriptapi_export(lua_State *L, Server *server)
        lua_newtable(L);
        luaL_register(L, NULL, minetest_f);
        lua_setglobal(L, "minetest");
-       
+
        // Get the main minetest table
        lua_getglobal(L, "minetest");
 
@@ -5337,7 +5423,7 @@ bool scriptapi_loadmod(lua_State *L, const std::string &scriptpath,
                                <<"Only chararacters [a-z0-9_] are allowed."<<std::endl;
                return false;
        }
-       
+
        bool success = false;
 
        try{
@@ -5381,7 +5467,7 @@ void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
        lua_getfield(L, -1, "registered_abms");
        luaL_checktype(L, -1, LUA_TTABLE);
        int registered_abms = lua_gettop(L);
-       
+
        if(lua_istable(L, registered_abms)){
                int table = lua_gettop(L);
                lua_pushnil(L);
@@ -5432,7 +5518,7 @@ void scriptapi_add_environment(lua_State *L, ServerEnvironment *env)
 
                        LuaABM *abm = new LuaABM(L, id, trigger_contents,
                                        required_neighbors, trigger_interval, trigger_chance);
-                       
+
                        env->addActiveBlockModifier(abm);
 
                        // removes value, keeps key for next iteration
@@ -5476,7 +5562,7 @@ void scriptapi_add_object_reference(lua_State *L, ServerActiveObject *cobj)
        lua_getfield(L, -1, "object_refs");
        luaL_checktype(L, -1, LUA_TTABLE);
        int objectstable = lua_gettop(L);
-       
+
        // object_refs[id] = object
        lua_pushnumber(L, cobj->getId()); // Push id
        lua_pushvalue(L, object); // Copy object to top of stack
@@ -5495,7 +5581,7 @@ void scriptapi_rm_object_reference(lua_State *L, ServerActiveObject *cobj)
        lua_getfield(L, -1, "object_refs");
        luaL_checktype(L, -1, LUA_TTABLE);
        int objectstable = lua_gettop(L);
-       
+
        // Get object_refs[id]
        lua_pushnumber(L, cobj->getId()); // Push id
        lua_gettable(L, objectstable);
@@ -5759,7 +5845,7 @@ bool scriptapi_get_auth(lua_State *L, const std::string &playername,
        realitycheck(L);
        assert(lua_checkstack(L, 20));
        StackUnroller stack_unroller(L);
-       
+
        get_auth_handler(L);
        lua_getfield(L, -1, "get_auth");
        if(lua_type(L, -1) != LUA_TFUNCTION)
@@ -5767,12 +5853,12 @@ bool scriptapi_get_auth(lua_State *L, const std::string &playername,
        lua_pushstring(L, playername.c_str());
        if(lua_pcall(L, 1, 1, 0))
                script_error(L, "error: %s", lua_tostring(L, -1));
-       
+
        // nil = login not allowed
        if(lua_isnil(L, -1))
                return false;
        luaL_checktype(L, -1, LUA_TTABLE);
-       
+
        std::string password;
        bool found = getstringfield(L, -1, "password", password);
        if(!found)
@@ -5787,7 +5873,7 @@ bool scriptapi_get_auth(lua_State *L, const std::string &playername,
        if(dst_privs)
                read_privileges(L, -1, *dst_privs);
        lua_pop(L, 1);
-       
+
        return true;
 }
 
@@ -5797,7 +5883,7 @@ void scriptapi_create_auth(lua_State *L, const std::string &playername,
        realitycheck(L);
        assert(lua_checkstack(L, 20));
        StackUnroller stack_unroller(L);
-       
+
        get_auth_handler(L);
        lua_getfield(L, -1, "create_auth");
        if(lua_type(L, -1) != LUA_TFUNCTION)
@@ -5814,7 +5900,7 @@ bool scriptapi_set_password(lua_State *L, const std::string &playername,
        realitycheck(L);
        assert(lua_checkstack(L, 20));
        StackUnroller stack_unroller(L);
-       
+
        get_auth_handler(L);
        lua_getfield(L, -1, "set_password");
        if(lua_type(L, -1) != LUA_TFUNCTION)
@@ -5830,7 +5916,7 @@ bool scriptapi_set_password(lua_State *L, const std::string &playername,
        player
 */
 
-void scriptapi_on_player_receive_fields(lua_State *L, 
+void scriptapi_on_player_receive_fields(lua_State *L,
                ServerActiveObject *player,
                const std::string &formname,
                const std::map<std::string, std::string> &fields)
@@ -6097,7 +6183,7 @@ bool scriptapi_node_on_timer(lua_State *L, v3s16 p, MapNode node, f32 dtime)
                script_error(L, "error: %s", lua_tostring(L, -1));
        if((bool)lua_isboolean(L,-1) && (bool)lua_toboolean(L,-1) == true)
                return true;
-       
+
        return false;
 }
 
@@ -6111,7 +6197,7 @@ void scriptapi_node_on_receive_fields(lua_State *L, v3s16 p,
        StackUnroller stack_unroller(L);
 
        INodeDefManager *ndef = get_server(L)->ndef();
-       
+
        // If node doesn't exist, we don't know what callback to call
        MapNode node = get_env(L)->getMap().getNodeNoEx(p);
        if(node.getContent() == CONTENT_IGNORE)
@@ -6679,7 +6765,7 @@ bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name)
        verbosestream<<"scriptapi_luaentity_add: id="<<id<<" name=\""
                        <<name<<"\""<<std::endl;
        StackUnroller stack_unroller(L);
-       
+
        // Get minetest.registered_entities[name]
        lua_getglobal(L, "minetest");
        lua_getfield(L, -1, "registered_entities");
@@ -6694,7 +6780,7 @@ bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name)
        }
        int prototype_table = lua_gettop(L);
        //dump2(L, "prototype_table");
-       
+
        // Create entity object
        lua_newtable(L);
        int object = lua_gettop(L);
@@ -6702,7 +6788,7 @@ bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name)
        // Set object metatable
        lua_pushvalue(L, prototype_table);
        lua_setmetatable(L, -2);
-       
+
        // Add object reference
        // This should be userdata with metatable ObjectRef
        objectref_get(L, id);
@@ -6718,7 +6804,7 @@ bool scriptapi_luaentity_add(lua_State *L, u16 id, const char *name)
        lua_pushnumber(L, id); // Push id
        lua_pushvalue(L, object); // Copy object to top of stack
        lua_settable(L, -3);
-       
+
        return true;
 }
 
@@ -6729,11 +6815,11 @@ void scriptapi_luaentity_activate(lua_State *L, u16 id,
        assert(lua_checkstack(L, 20));
        verbosestream<<"scriptapi_luaentity_activate: id="<<id<<std::endl;
        StackUnroller stack_unroller(L);
-       
+
        // Get minetest.luaentities[id]
        luaentity_get(L, id);
        int object = lua_gettop(L);
-       
+
        // Get on_activate function
        lua_pushvalue(L, object);
        lua_getfield(L, -1, "on_activate");
@@ -6760,12 +6846,12 @@ void scriptapi_luaentity_rm(lua_State *L, u16 id)
        lua_getfield(L, -1, "luaentities");
        luaL_checktype(L, -1, LUA_TTABLE);
        int objectstable = lua_gettop(L);
-       
+
        // Set luaentities[id] = nil
        lua_pushnumber(L, id); // Push id
        lua_pushnil(L);
        lua_settable(L, objectstable);
-       
+
        lua_pop(L, 2); // pop luaentities, minetest
 }
 
@@ -6779,20 +6865,20 @@ std::string scriptapi_luaentity_get_staticdata(lua_State *L, u16 id)
        // Get minetest.luaentities[id]
        luaentity_get(L, id);
        int object = lua_gettop(L);
-       
+
        // Get get_staticdata function
        lua_pushvalue(L, object);
        lua_getfield(L, -1, "get_staticdata");
        if(lua_isnil(L, -1))
                return "";
-       
+
        luaL_checktype(L, -1, LUA_TFUNCTION);
        lua_pushvalue(L, object); // self
        // Call with 1 arguments, 1 results
        if(lua_pcall(L, 1, 1, 0))
                script_error(L, "error running function get_staticdata: %s\n",
                                lua_tostring(L, -1));
-       
+
        size_t len=0;
        const char *s = lua_tolstring(L, -1, &len);
        return std::string(s, len);
@@ -6812,9 +6898,9 @@ void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
 
        // Set default values that differ from ObjectProperties defaults
        prop->hp_max = 10;
-       
+
        /* Read stuff */
-       
+
        prop->hp_max = getintfield_default(L, -1, "hp_max", 10);
 
        getboolfield(L, -1, "physical", prop->physical);
@@ -6829,10 +6915,10 @@ void scriptapi_luaentity_get_properties(lua_State *L, u16 id,
        getstringfield(L, -1, "visual", prop->visual);
 
        getstringfield(L, -1, "mesh", prop->mesh);
-       
+
        // Deprecated: read object properties directly
        read_object_properties(L, -1, prop);
-       
+
        // Read initial_properties
        lua_getfield(L, -1, "initial_properties");
        read_object_properties(L, -1, prop);
index a60be2c0b52483ec3d9d925a5660829cc99428e8..34515faf7acc788a46047daeccbf5c5f0a4aaf51 100644 (file)
@@ -103,14 +103,14 @@ public:
                        delete q;
                }
        }
-       
+
        /*
                peer_id=0 adds with nobody to send to
        */
        void addBlock(u16 peer_id, v3s16 pos, u8 flags)
        {
                DSTACK(__FUNCTION_NAME);
-       
+
                JMutexAutoLock lock(m_mutex);
 
                if(peer_id != 0)
@@ -130,7 +130,7 @@ public:
                                }
                        }
                }
-               
+
                /*
                        Add the block
                */
@@ -160,7 +160,7 @@ public:
                JMutexAutoLock lock(m_mutex);
                return m_queue.size();
        }
-       
+
        u32 peerItemCount(u16 peer_id)
        {
                JMutexAutoLock lock(m_mutex);
@@ -238,7 +238,7 @@ struct PlayerInfo
 
 /*
        Used for queueing and sorting block transfers in containers
-       
+
        Lower priority number means higher priority.
 */
 struct PrioritySortedBlockTransfer
@@ -303,7 +303,7 @@ struct ServerSoundParams
                max_hear_distance(32*BS),
                loop(false)
        {}
-       
+
        v3f getPos(ServerEnvironment *env, bool *pos_exists) const;
 };
 
@@ -347,7 +347,7 @@ public:
        ~RemoteClient()
        {
        }
-       
+
        /*
                Finds block that should be sent next to the client.
                Environment should be locked when this is called.
@@ -367,7 +367,7 @@ public:
        {
                return m_blocks_sending.size();
        }
-       
+
        // Increments timeouts and removes timed-out blocks from list
        // NOTE: This doesn't fix the server-not-sending-block bug
        //       because it is related to emerging, not sending.
@@ -386,13 +386,13 @@ public:
 
        // Time from last placing or removing blocks
        float m_time_from_building;
-       
+
        /*JMutex m_dig_mutex;
        float m_dig_time_remaining;
        // -1 = not digging
        s16 m_dig_tool_item;
        v3s16 m_dig_position;*/
-       
+
        /*
                List of active objects that the client knows of.
                Value is dummy.
@@ -405,7 +405,7 @@ private:
                - These don't have to be sent again.
                - A block is cleared from here when client says it has
                  deleted it from it's memory
-               
+
                Key is position, value is dummy.
                No MapBlock* is stored here because the blocks can get deleted.
        */
@@ -413,7 +413,7 @@ private:
        s16 m_nearest_unsent_d;
        v3s16 m_last_center;
        float m_nearest_unsent_reset_timer;
-       
+
        /*
                Blocks that are currently on the line.
                This is used for throttling the sending of blocks.
@@ -432,7 +432,7 @@ private:
                This is resetted by PrintInfo()
        */
        u32 m_excess_gotblocks;
-       
+
        // CPU usage optimization
        u32 m_nothing_to_send_counter;
        float m_nothing_to_send_pause_timer;
@@ -446,7 +446,7 @@ public:
        /*
                NOTE: Every public method should be thread-safe
        */
-       
+
        Server(
                const std::string &path_world,
                const std::string &path_config,
@@ -477,7 +477,7 @@ public:
        {
                return m_shutdown_requested;
        }
-       
+
        /*
                Shall be called with the environment locked.
                This is accessed by the map, which is inside the environment,
@@ -503,7 +503,7 @@ public:
        // Envlock + conlock
        s32 playSound(const SimpleSoundSpec &spec, const ServerSoundParams &params);
        void stopSound(s32 handle);
-       
+
        // Envlock + conlock
        std::set<std::string> getPlayerEffectivePrivs(const std::string &name);
        bool checkPriv(const std::string &name, const std::string &priv);
@@ -534,26 +534,30 @@ public:
        {
                return m_con.GetPeerAddress(peer_id);
        }
-       
+
        // Envlock and conlock should be locked when calling this
        void notifyPlayer(const char *name, const std::wstring msg);
        void notifyPlayers(const std::wstring msg);
 
        void queueBlockEmerge(v3s16 blockpos, bool allow_generate);
-       
+
        // Creates or resets inventory
        Inventory* createDetachedInventory(const std::string &name);
-       
+
        // Envlock and conlock should be locked when using Lua
        lua_State *getLua(){ return m_lua; }
 
        // Envlock should be locked when using the rollback manager
        IRollbackManager *getRollbackManager(){ return m_rollback; }
+
+       //TODO:  determine what should be locked when accessing the emerge manager
+       EmergeManager *getEmergeManager(){ return m_emerge; }
+
        // actions: time-reversed list
        // Return value: success/failure
        bool rollbackRevertActions(const std::list<RollbackAction> &actions,
                        std::list<std::string> *log);
-       
+
        // IGameDef interface
        // Under envlock
        virtual IItemDefManager* getItemDefManager();
@@ -565,7 +569,7 @@ public:
        virtual ISoundManager* getSoundManager();
        virtual MtEventManager* getEventManager();
        virtual IRollbackReportSink* getRollbackReportSink();
-       
+
        IWritableItemDefManager* getWritableItemDefManager();
        IWritableNodeDefManager* getWritableNodeDefManager();
        IWritableCraftDefManager* getWritableCraftDefManager();
@@ -573,7 +577,7 @@ public:
        const ModSpec* getModSpec(const std::string &modname);
        void getModNames(core::list<std::string> &modlist);
        std::string getBuiltinLuaPath();
-       
+
        std::string getWorldPath(){ return m_path_world; }
 
        bool isSingleplayer(){ return m_simple_singleplayer_mode; }
@@ -591,11 +595,11 @@ private:
        // As of now, these create and remove clients and players.
        void peerAdded(con::Peer *peer);
        void deletingPeer(con::Peer *peer, bool timeout);
-       
+
        /*
                Static send methods
        */
-       
+
        static void SendHP(con::Connection &con, u16 peer_id, u8 hp);
        static void SendAccessDenied(con::Connection &con, u16 peer_id,
                        const std::wstring &reason);
@@ -605,7 +609,7 @@ private:
                        IItemDefManager *itemdef);
        static void SendNodeDef(con::Connection &con, u16 peer_id,
                        INodeDefManager *nodedef, u16 protocol_version);
-       
+
        /*
                Non-static send methods.
                Conlock should be always used.
@@ -633,18 +637,18 @@ private:
        void sendAddNode(v3s16 p, MapNode n, u16 ignore_id=0,
                        core::list<u16> *far_players=NULL, float far_d_nodes=100);
        void setBlockNotSent(v3s16 p);
-       
+
        // Environment and Connection must be locked when called
        void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
-       
+
        // Sends blocks to clients (locks env and con on its own)
        void SendBlocks(float dtime);
-       
+
        void fillMediaCache();
        void sendMediaAnnouncement(u16 peer_id);
        void sendRequestedMedia(u16 peer_id,
                        const core::list<MediaRequest> &tosend);
-       
+
        void sendDetachedInventory(const std::string &name, u16 peer_id);
        void sendDetachedInventoryToAll(const std::string &name);
        void sendDetachedInventories(u16 peer_id);
@@ -652,15 +656,15 @@ private:
        /*
                Something random
        */
-       
+
        void DiePlayer(u16 peer_id);
        void RespawnPlayer(u16 peer_id);
-       
+
        void UpdateCrafting(u16 peer_id);
-       
+
        // When called, connection mutex should be locked
        RemoteClient* getClient(u16 peer_id);
-       
+
        // When called, environment mutex should be locked
        std::string getPlayerName(u16 peer_id)
        {
@@ -687,7 +691,7 @@ private:
                Call with env and con locked.
        */
        PlayerSAO *emergePlayer(const char *name, u16 peer_id);
-       
+
        // Locks environment and connection by its own
        struct PeerChange;
        void handlePeerChange(PeerChange &c);
@@ -696,7 +700,7 @@ private:
        /*
                Variables
        */
-       
+
        // World directory
        std::string m_path_world;
        // Path to user's configuration file ("" = no configuration file)
@@ -709,7 +713,7 @@ private:
 
        // Thread can set; step() will throw as ServerError
        MutexedVariable<std::string> m_async_fatal_error;
-       
+
        // Some timers
        float m_liquid_transform_timer;
        float m_print_info_timer;
@@ -717,14 +721,14 @@ private:
        float m_emergethread_trigger_timer;
        float m_savemap_timer;
        IntervalLimiter m_map_timer_and_unload_interval;
-       
+
        // NOTE: If connection and environment are both to be locked,
        // environment shall be locked first.
 
        // Environment
        ServerEnvironment *m_env;
        JMutex m_env_mutex;
-       
+
        // Connection
        con::Connection m_con;
        JMutex m_con_mutex;
@@ -748,23 +752,23 @@ private:
 
        // Item definition manager
        IWritableItemDefManager *m_itemdef;
-       
+
        // Node definition manager
        IWritableNodeDefManager *m_nodedef;
-       
+
        // Craft definition manager
        IWritableCraftDefManager *m_craftdef;
-       
+
        // Event manager
        EventManager *m_event;
-       
+
        // Mods
        std::vector<ModSpec> m_mods;
-       
+
        /*
                Threads
        */
-       
+
        // A buffer for time steps
        // step() increments and AsyncRunStep() run by m_thread reads it.
        float m_step_dtime;
@@ -776,7 +780,7 @@ private:
        EmergeThread m_emergethread;
        // Queue of block coordinates to be processed by the emerge thread
        BlockEmergeQueue m_emerge_queue;
-       
+
        /*
                Time related stuff
        */
@@ -785,7 +789,7 @@ private:
        float m_time_of_day_send_timer;
        // Uptime of server in seconds
        MutexedVariable<double> m_uptime;
-       
+
        /*
                Peer change queue.
                Queues stuff from peerAdded() and deletingPeer() to
@@ -807,7 +811,7 @@ private:
        /*
                Random stuff
        */
-       
+
        // Mod parent directory paths
        core::list<std::string> m_modspaths;