The new mapgen, noise functions, et al.
authorkwolekr <mirrorisim@gmail.com>
Mon, 26 Nov 2012 02:16:48 +0000 (21:16 -0500)
committerPerttu Ahola <celeron55@gmail.com>
Mon, 21 Jan 2013 19:41:33 +0000 (21:41 +0200)
23 files changed:
src/CMakeLists.txt
src/biome.cpp [new file with mode: 0644]
src/biome.h [new file with mode: 0644]
src/defaultsettings.cpp
src/environment.cpp
src/environment.h
src/farmesh.cpp
src/guiPauseMenu.cpp
src/guiPauseMenu.h
src/map.cpp
src/map.h
src/mapgen.cpp
src/mapgen.h
src/nodedef.cpp
src/noise.cpp
src/noise.h
src/scriptapi.cpp
src/server.cpp
src/server.h
src/settings.h
src/util/numeric.h
src/voxel.h
src/voxelalgorithms.cpp

index ac39e43e3d91465a02835bfdddeb6987e05b9488..995d031e37eb68720a8a85b0819454bb83a2c77e 100644 (file)
@@ -218,6 +218,7 @@ set(common_SRCS
        sha1.cpp
        base64.cpp
        ban.cpp
+       biome.cpp
        clientserver.cpp
        staticobject.cpp
        util/serialize.cpp
diff --git a/src/biome.cpp b/src/biome.cpp
new file mode 100644 (file)
index 0000000..4b240d5
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+Minetest-c55
+Copyright (C) 2010-2011 kwolekr, Ryan Kwolek <kwolekr2@cs.scranton.edu>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "biome.h"
+#include "nodedef.h"
+#include "map.h" //for ManualMapVoxelManipulator
+#include "main.h"
+
+#define BT_NONE                        0
+#define BT_OCEAN               1
+#define BT_LAKE                        2
+#define BT_SBEACH              3
+#define BT_GBEACH              4
+#define BT_PLAINS              5
+#define BT_HILLS               6
+#define BT_EXTREMEHILLS 7
+#define BT_MOUNTAINS   8
+#define BT_DESERT              9
+#define BT_DESERTHILLS 10
+#define BT_HELL                        11
+#define BT_AETHER              12
+
+#define BT_BTMASK              0x3F
+
+#define BTF_SNOW               0x40
+#define BTF_FOREST             0x80
+
+#define BGFREQ_1 (           0.40)
+#define BGFREQ_2 (BGFREQ_1 + 0.05)
+#define BGFREQ_3 (BGFREQ_2 + 0.08)
+#define BGFREQ_4 (BGFREQ_3 + 0.35)
+#define BGFREQ_5 (BGFREQ_4 + 0.18)
+//BGFREQ_5 is not checked as an upper bound; it ought to sum up to 1.00, but it's okay if it doesn't.
+
+
+/*float bg1_temps[] = {0.0};
+int bg1_biomes[]  = {BT_OCEAN};
+
+float bg2_temps[] = {10.0};
+int bg2_biomes[]  = {BT_GBEACH, BT_SBEACH};
+
+float bg3_temps[] = {30.0, 40.0};
+int bg3_biomes[]  = {BT_HILLS, BT_EXTREMEHILLS, BT_MOUNTAINS};
+
+float bg4_temps[] = {25.0, 30.0, 35.0, 40.0};
+int bg4_biomes[]  = {BT_HILLS, BT_EXTREMEHILLS, BT_MOUNTAINS, BT_DESERT, BT_DESERTHILLS};
+
+float bg5_temps[] = {5.0, 40.0};
+int bg5_biomes[]  = {BT_LAKE, BT_PLAINS, BT_DESERT};*/
+
+
+BiomeDefManager::BiomeDefManager(IGameDef *gamedef) {
+       this->m_gamedef = gamedef;
+       this->ndef      = gamedef->ndef();
+
+       //addDefaultBiomes(); //can't do this in the ctor, too early
+}
+
+
+BiomeDefManager::~BiomeDefManager() {
+       for (int i = 0; i != bgroups.size(); i++)
+               delete bgroups[i];
+}
+
+
+void BiomeDefManager::addBiome() {
+
+}
+
+
+NoiseParams npmtdef = {0.0, 20.0, v3f(250., 250., 250.), 82341, 5, 0.6};
+
+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"));
+       b->n_filler     = b->n_top;
+       b->ntopnodes    = 0;
+       b->height_min   = -MAP_GENERATION_LIMIT;
+       b->height_max   = MAP_GENERATION_LIMIT;
+       b->heat_min     = FLT_MIN;
+       b->heat_max     = FLT_MAX;
+       b->humidity_min = FLT_MIN;
+       b->humidity_max = FLT_MAX;
+       b->np = &npmtdef;
+       biome_default = b;
+
+       //bgroup->push_back(b);
+       //bgroups.push_back(bgroup);
+}
+
+
+Biome *BiomeDefManager::getBiome(float bgfreq, float heat, float humidity) {
+       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]);
+
+       int nbiomes = bgroup.size();
+       if (!nbiomes)
+               return biome_default;
+       for (i = 0; i != nbiomes - 1; i++) {
+               b = bgroup[i];
+               if (heat >= b->heat_min && heat <= b->heat_max &&
+                       humidity >= b->humidity_min && humidity <= b->humidity_max)
+                       return b;
+       }
+
+       return biome_default;
+}
+
+
+//////////////////////////// [ Generic biome ] ////////////////////////////////
+
+
+int Biome::getSurfaceHeight(float noise_terrain) {
+       return np->offset + np->scale * 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 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;
+       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 <= y2; y++, i += mg->ystride)
+               mg->vmanip->m_data[i] = mg->n_air;
+}
+
+
+
+///////////////////////////// [ Ocean biome ] /////////////////////////////////
+
+
+
+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];
+
+       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;
+}
+
+
+///////////////////////////// [ Nether biome ] /////////////////////////////////
+
+
+int BiomeHell::getSurfaceHeight(float noise_terrain) {
+       return np->offset + np->scale * 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 ] ////////////////////////////////
+
+/////////////////////////// [ Superflat biome ] ///////////////////////////////
+
+
+int BiomeSuperflat::getSurfaceHeight(float noise_terrain) {
+       return ntopnodes;
+}
+
+
+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;
+}
diff --git a/src/biome.h b/src/biome.h
new file mode 100644 (file)
index 0000000..5e43ab6
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+Minetest-c55
+Copyright (C) 2010-2011 kwolekr, Ryan Kwolek <kwolekr2@cs.scranton.edu>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef BIOME_HEADER
+#define BIOME_HEADER
+
+#include "nodedef.h"
+#include "gamedef.h"
+#include "mapnode.h"
+#include "noise.h"
+#include "mapgen.h"
+
+class Biome {
+public:
+       MapNode n_top;
+       MapNode n_filler;
+       s16 ntopnodes;
+       s16 flags;
+       s16 height_min;
+       s16 height_max;
+       float heat_min;
+       float heat_max;
+       float humidity_min;
+       float humidity_max;
+       const char *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 {
+       virtual void genColumn(Mapgen *mg, int x, int z, int y1, int y2);
+};
+
+class BiomeHell : 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);
+};
+
+class BiomeDefManager {
+public:
+       std::vector<float> bgroup_freqs;
+       std::vector<std::vector<Biome *> *> bgroups;
+       Biome *biome_default;
+       IGameDef *m_gamedef;
+       INodeDefManager *ndef;
+
+       BiomeDefManager(IGameDef *gamedef);
+       ~BiomeDefManager();
+
+       Biome *getBiome(float bgfreq, float heat, float humidity);
+
+       void addBiome();
+       void addDefaultBiomes();
+};
+
+#endif
index 5a1b76b4aa19de879d82af31cbcc0259d020b7a8..38b9accd15213a1a1f959fd210b0e009aa2c18a3 100644 (file)
@@ -163,7 +163,7 @@ void set_default_settings(Settings *settings)
        settings->setDefault("max_block_generate_distance", "7");
        settings->setDefault("time_send_interval", "5");
        settings->setDefault("time_speed", "72");
-       settings->setDefault("water_level", "1");
+       settings->setDefault("default_water_level", "1");
        settings->setDefault("server_unload_unused_data_timeout", "29");
        settings->setDefault("server_map_save_interval", "5.3");
        settings->setDefault("full_block_send_enable_min_time_from_building", "2.0");
index 3f94484fe41610c69c6652e8ca1e7b16074d5540..51255b91847113885e552db5febe0a9a07a167f5 100644 (file)
@@ -1301,6 +1301,7 @@ u16 ServerEnvironment::addActiveObject(ServerActiveObject *object)
        return id;
 }
 
+#if 0
 bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
 {
        assert(obj);
@@ -1343,6 +1344,7 @@ bool ServerEnvironment::addActiveObjectAsStatic(ServerActiveObject *obj)
 
        return succeeded;
 }
+#endif
 
 /*
        Finds out what new objects have been added to
@@ -1563,13 +1565,15 @@ void ServerEnvironment::removeRemovedObjects()
                */
                if(obj->m_static_exists && obj->m_removed)
                {
-                       MapBlock *block = m_map->emergeBlock(obj->m_static_block);
-                       if(block)
-                       {
+                       MapBlock *block = m_map->emergeBlock(obj->m_static_block, false);
+                       if (block) {
                                block->m_static_objects.remove(id);
                                block->raiseModified(MOD_STATE_WRITE_NEEDED,
                                                "removeRemovedObjects");
                                obj->m_static_exists = false;
+                       } else {
+                               infostream << "failed to emerge block from which "
+                                       "an object to be removed was loaded from. id="<<id<<std::endl;
                        }
                }
 
@@ -1717,6 +1721,8 @@ void ServerEnvironment::activateObjects(MapBlock *block, u32 dtime_s)
 
        If force_delete is set, active object is deleted nevertheless. It
        shall only be set so in the destructor of the environment.
+
+       If block wasn't generated (not in memory or on disk), 
 */
 void ServerEnvironment::deactivateFarObjects(bool force_delete)
 {
index d17edeacd96e7267f69b2af4543c043fe493a9d8..d1e61967fd2b10e813868289e2dfc986d5447805 100644 (file)
@@ -241,8 +241,9 @@ public:
                MapBlock.
                Caller allocates memory, ServerEnvironment frees memory.
                Return value: true if succeeded, false if failed.
+               (note:  not used, pending removal from engine)
        */
-       bool addActiveObjectAsStatic(ServerActiveObject *object);
+       //bool addActiveObjectAsStatic(ServerActiveObject *object);
        
        /*
                Find out what new objects have been added to
index bd08acadc3fd28133262d4ff80672d2976a9ff37..23f3db5f6597d4a263490c12027d90e05f35d691 100644 (file)
@@ -120,14 +120,14 @@ HeightPoint ground_height(u64 seed, v2s16 p2d)
        if(n)
                return n->getValue();
        HeightPoint hp;
-       s16 level = mapgen::find_ground_level_from_noise(seed, p2d, 3);
+       s16 level = Mapgen::find_ground_level_from_noise(seed, p2d, 3);
        hp.gh = (level-4)*BS;
        hp.ma = (4)*BS;
        /*hp.gh = BS*base_rock_level_2d(seed, p2d);
        hp.ma = BS*get_mud_add_amount(seed, p2d);*/
-       hp.have_sand = mapgen::get_have_beach(seed, p2d);
+       hp.have_sand = Mapgen::get_have_beach(seed, p2d);
        if(hp.gh > BS*WATER_LEVEL)
-               hp.tree_amount = mapgen::tree_amount_2d(seed, p2d);
+               hp.tree_amount = Mapgen::tree_amount_2d(seed, p2d);
        else
                hp.tree_amount = 0;
        // No mud has been added if mud amount is less than 1
index c800cf9529e76eb65657fe687bf8200dbe2b8dd8..f6cbf248fc2240bb121f9a545dee51c857826fa1 100644 (file)
-/*\r
-Minetest-c55\r
-Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>\r
-\r
-This program is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU Lesser General Public License as published by\r
-the Free Software Foundation; either version 2.1 of the License, or\r
-(at your option) any later version.\r
-\r
-This program is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-GNU Lesser General Public License for more details.\r
-\r
-You should have received a copy of the GNU Lesser General Public License along\r
-with this program; if not, write to the Free Software Foundation, Inc.,\r
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-*/\r
-\r
-#include "guiPauseMenu.h"\r
-#include "debug.h"\r
-#include "serialization.h"\r
-#include "porting.h"\r
-#include "config.h"\r
-#include "main.h"\r
-#include <IGUICheckBox.h>\r
-#include <IGUIEditBox.h>\r
-#include <IGUIButton.h>\r
-#include <IGUIStaticText.h>\r
-#include <IGUIFont.h>\r
-#include "gettext.h"\r
-#include "util/string.h"\r
-\r
-GUIPauseMenu::GUIPauseMenu(gui::IGUIEnvironment* env,\r
-               gui::IGUIElement* parent, s32 id,\r
-               IGameCallback *gamecallback,\r
-               IMenuManager *menumgr,\r
-               bool simple_singleplayer_mode):\r
-       GUIModalMenu(env, parent, id, menumgr),\r
-       m_gamecallback(gamecallback),\r
-       m_simple_singleplayer_mode(simple_singleplayer_mode)\r
-{\r
-}\r
-\r
-GUIPauseMenu::~GUIPauseMenu()\r
-{\r
-       removeChildren();\r
-}\r
-\r
-void GUIPauseMenu::removeChildren()\r
-{\r
-       {\r
-               gui::IGUIElement *e = getElementFromId(256);\r
-               if(e != NULL)\r
-                       e->remove();\r
-       }\r
-       {\r
-               gui::IGUIElement *e = getElementFromId(257);\r
-               if(e != NULL)\r
-                       e->remove();\r
-       }\r
-       {\r
-               gui::IGUIElement *e = getElementFromId(258);\r
-               if(e != NULL)\r
-                       e->remove();\r
-       }\r
-       {\r
-               gui::IGUIElement *e = getElementFromId(259);\r
-               if(e != NULL)\r
-                       e->remove();\r
-       }\r
-       {\r
-               gui::IGUIElement *e = getElementFromId(260);\r
-               if(e != NULL)\r
-                       e->remove();\r
-       }\r
-       {\r
-               gui::IGUIElement *e = getElementFromId(261);\r
-               if(e != NULL)\r
-                       e->remove();\r
-       }\r
-}\r
-\r
-void GUIPauseMenu::regenerateGui(v2u32 screensize)\r
-{\r
-       /*\r
-               Remove stuff\r
-       */\r
-       removeChildren();\r
-       \r
-       /*\r
-               Calculate new sizes and positions\r
-       */\r
-       core::rect<s32> rect(\r
-                       screensize.X/2 - 580/2,\r
-                       screensize.Y/2 - 300/2,\r
-                       screensize.X/2 + 580/2,\r
-                       screensize.Y/2 + 300/2\r
-       );\r
-       \r
-       DesiredRect = rect;\r
-       recalculateAbsolutePosition(false);\r
-\r
-       v2s32 size = rect.getSize();\r
-\r
-       /*\r
-               Add stuff\r
-       */\r
-       const s32 btn_height = 30;\r
-       const s32 btn_gap = 20;\r
-       const s32 btn_num = m_simple_singleplayer_mode ? 3 : 4;\r
-       s32 btn_y = size.Y/2-((btn_num*btn_height+(btn_num-1)*btn_gap))/2;\r
-       changeCtype("");\r
-       {\r
-               core::rect<s32> rect(0, 0, 140, btn_height);\r
-               rect = rect + v2s32(size.X/2-140/2, btn_y);\r
-               Environment->addButton(rect, this, 256,\r
-                       wgettext("Continue"));\r
-       }\r
-       btn_y += btn_height + btn_gap;\r
-       if(!m_simple_singleplayer_mode)\r
-       {\r
-               {\r
-                       core::rect<s32> rect(0, 0, 140, btn_height);\r
-                       rect = rect + v2s32(size.X/2-140/2, btn_y);\r
-                       Environment->addButton(rect, this, 261,\r
-                               wgettext("Change Password"));\r
-               }\r
-               btn_y += btn_height + btn_gap;\r
-       }\r
-       {\r
-               core::rect<s32> rect(0, 0, 140, btn_height);\r
-               rect = rect + v2s32(size.X/2-140/2, btn_y);\r
-               Environment->addButton(rect, this, 260,\r
-                       wgettext("Exit to Menu"));\r
-       }\r
-       btn_y += btn_height + btn_gap;\r
-       {\r
-               core::rect<s32> rect(0, 0, 140, btn_height);\r
-               rect = rect + v2s32(size.X/2-140/2, btn_y);\r
-               Environment->addButton(rect, this, 257,\r
-                       wgettext("Exit to OS"));\r
-       }\r
-\r
-       {\r
-               core::rect<s32> rect(0, 0, 180, 240);\r
-               rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2);\r
-               Environment->addStaticText(chartowchar_t(gettext(\r
-               "Default Controls:\n"\r
-               "- WASD: Walk\n"\r
-               "- Mouse left: dig/hit\n"\r
-               "- Mouse right: place/use\n"\r
-               "- Mouse wheel: select item\n"\r
-               "- 0...9: select item\n"\r
-               "- Shift: sneak\n"\r
-               "- R: Toggle viewing all loaded chunks\n"\r
-               "- I: Inventory menu\n"\r
-               "- ESC: This menu\n"\r
-               "- T: Chat\n"\r
-               )), rect, false, true, this, 258);\r
-       }\r
-       {\r
-               core::rect<s32> rect(0, 0, 180, 220);\r
-               rect = rect + v2s32(size.X/2 - 90 - rect.getWidth(), size.Y/2-rect.getHeight()/2);\r
-       \r
-               v2u32 max_texture_size;\r
-               {\r
-                       video::IVideoDriver* driver = Environment->getVideoDriver();\r
-                       max_texture_size = driver->getMaxTextureSize();\r
-               }\r
-\r
-               std::ostringstream os;\r
-               os<<"Minetest\n";\r
-               os<<BUILD_INFO<<"\n";\r
-               os<<"path_user = "<<wrap_rows(porting::path_user, 20)<<"\n";\r
-       \r
-               Environment->addStaticText(narrow_to_wide(os.str()).c_str(), rect, false, true, this, 259);\r
-       }\r
-       changeCtype("C");\r
-}\r
-\r
-void GUIPauseMenu::drawMenu()\r
-{\r
-       gui::IGUISkin* skin = Environment->getSkin();\r
-       if (!skin)\r
-               return;\r
-       video::IVideoDriver* driver = Environment->getVideoDriver();\r
-       \r
-       video::SColor bgcolor(140,0,0,0);\r
-       driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);\r
-\r
-       gui::IGUIElement::draw();\r
-}\r
-\r
-bool GUIPauseMenu::OnEvent(const SEvent& event)\r
-{\r
-\r
-       if(event.EventType==EET_KEY_INPUT_EVENT)\r
-       {\r
-               if(event.KeyInput.PressedDown)\r
-               {\r
-                       if(event.KeyInput.Key==KEY_ESCAPE)\r
-                       {\r
-                               quitMenu();\r
-                               return true;\r
-                       }\r
-                       else if(event.KeyInput.Key==KEY_RETURN)\r
-                       {\r
-                               quitMenu();\r
-                               return true;\r
-                       }\r
-               }\r
-       }\r
-       if(event.EventType==EET_GUI_EVENT)\r
-       {\r
-               if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST\r
-                               && isVisible())\r
-               {\r
-                       if(!canTakeFocus(event.GUIEvent.Element))\r
-                       {\r
-                               dstream<<"GUIPauseMenu: Not allowing focus change."\r
-                                               <<std::endl;\r
-                               // Returning true disables focus change\r
-                               return true;\r
-                       }\r
-               }\r
-               if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)\r
-               {\r
-                       switch(event.GUIEvent.Caller->getID())\r
-                       {\r
-                       case 256: // continue\r
-                               quitMenu();\r
-                               // ALWAYS return immediately after quitMenu()\r
-                               return true;\r
-                       case 261:\r
-                               quitMenu();\r
-                               m_gamecallback->changePassword();\r
-                               return true;\r
-                       case 260: // disconnect\r
-                               m_gamecallback->disconnect();\r
-                               quitMenu();\r
-                               return true;\r
-                       case 257: // exit\r
-                               m_gamecallback->exitToOS();\r
-                               quitMenu();\r
-                               return true;\r
-                       }\r
-               }\r
-       }\r
-       \r
-       return Parent ? Parent->OnEvent(event) : false;\r
-}\r
-\r
+/*
+Minetest-c55
+Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "guiPauseMenu.h"
+#include "debug.h"
+#include "serialization.h"
+#include "porting.h"
+#include "config.h"
+#include "main.h"
+#include <IGUICheckBox.h>
+#include <IGUIEditBox.h>
+#include <IGUIButton.h>
+#include <IGUIStaticText.h>
+#include <IGUIFont.h>
+#include "gettext.h"
+#include "util/string.h"
+
+GUIPauseMenu::GUIPauseMenu(gui::IGUIEnvironment* env,
+               gui::IGUIElement* parent, s32 id,
+               IGameCallback *gamecallback,
+               IMenuManager *menumgr,
+               bool simple_singleplayer_mode):
+       GUIModalMenu(env, parent, id, menumgr),
+       m_gamecallback(gamecallback),
+       m_simple_singleplayer_mode(simple_singleplayer_mode)
+{
+}
+
+GUIPauseMenu::~GUIPauseMenu()
+{
+       removeChildren();
+}
+
+void GUIPauseMenu::removeChildren()
+{
+       {
+               gui::IGUIElement *e = getElementFromId(256);
+               if(e != NULL)
+                       e->remove();
+       }
+       {
+               gui::IGUIElement *e = getElementFromId(257);
+               if(e != NULL)
+                       e->remove();
+       }
+       {
+               gui::IGUIElement *e = getElementFromId(258);
+               if(e != NULL)
+                       e->remove();
+       }
+       {
+               gui::IGUIElement *e = getElementFromId(259);
+               if(e != NULL)
+                       e->remove();
+       }
+       {
+               gui::IGUIElement *e = getElementFromId(260);
+               if(e != NULL)
+                       e->remove();
+       }
+       {
+               gui::IGUIElement *e = getElementFromId(261);
+               if(e != NULL)
+                       e->remove();
+       }
+}
+
+void GUIPauseMenu::regenerateGui(v2u32 screensize)
+{
+       /*
+               Remove stuff
+       */
+       removeChildren();
+       
+       /*
+               Calculate new sizes and positions
+       */
+       core::rect<s32> rect(
+                       screensize.X/2 - 580/2,
+                       screensize.Y/2 - 300/2,
+                       screensize.X/2 + 580/2,
+                       screensize.Y/2 + 300/2
+       );
+       
+       DesiredRect = rect;
+       recalculateAbsolutePosition(false);
+
+       v2s32 size = rect.getSize();
+
+       /*
+               Add stuff
+       */
+       const s32 btn_height = 30;
+       const s32 btn_gap = 20;
+       const s32 btn_num = m_simple_singleplayer_mode ? 3 : 4;
+       s32 btn_y = size.Y/2-((btn_num*btn_height+(btn_num-1)*btn_gap))/2;
+       changeCtype("");
+       {
+               core::rect<s32> rect(0, 0, 140, btn_height);
+               rect = rect + v2s32(size.X/2-140/2, btn_y);
+               Environment->addButton(rect, this, 256,
+                       wgettext("Continue"));
+       }
+       btn_y += btn_height + btn_gap;
+       if(!m_simple_singleplayer_mode)
+       {
+               {
+                       core::rect<s32> rect(0, 0, 140, btn_height);
+                       rect = rect + v2s32(size.X/2-140/2, btn_y);
+                       Environment->addButton(rect, this, 261,
+                               wgettext("Change Password"));
+               }
+               btn_y += btn_height + btn_gap;
+       }
+       {
+               core::rect<s32> rect(0, 0, 140, btn_height);
+               rect = rect + v2s32(size.X/2-140/2, btn_y);
+               Environment->addButton(rect, this, 260,
+                       wgettext("Exit to Menu"));
+       }
+       btn_y += btn_height + btn_gap;
+       {
+               core::rect<s32> rect(0, 0, 140, btn_height);
+               rect = rect + v2s32(size.X/2-140/2, btn_y);
+               Environment->addButton(rect, this, 257,
+                       wgettext("Exit to OS"));
+       }
+
+       {
+               core::rect<s32> rect(0, 0, 180, 240);
+               rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2);
+               Environment->addStaticText(chartowchar_t(gettext(
+               "Default Controls:\n"
+               "- WASD: Walk\n"
+               "- Mouse left: dig/hit\n"
+               "- Mouse right: place/use\n"
+               "- Mouse wheel: select item\n"
+               "- 0...9: select item\n"
+               "- Shift: sneak\n"
+               "- R: Toggle viewing all loaded chunks\n"
+               "- I: Inventory menu\n"
+               "- ESC: This menu\n"
+               "- T: Chat\n"
+               )), rect, false, true, this, 258);
+       }
+       {
+               core::rect<s32> rect(0, 0, 180, 220);
+               rect = rect + v2s32(size.X/2 - 90 - rect.getWidth(), size.Y/2-rect.getHeight()/2);
+       
+               v2u32 max_texture_size;
+               {
+                       video::IVideoDriver* driver = Environment->getVideoDriver();
+                       max_texture_size = driver->getMaxTextureSize();
+               }
+
+               std::ostringstream os;
+               os<<"Minetest\n";
+               os<<BUILD_INFO<<"\n";
+               os<<"path_user = "<<wrap_rows(porting::path_user, 20)<<"\n";
+       
+               Environment->addStaticText(narrow_to_wide(os.str()).c_str(), rect, false, true, this, 259);
+       }
+       changeCtype("C");
+}
+
+void GUIPauseMenu::drawMenu()
+{
+       gui::IGUISkin* skin = Environment->getSkin();
+       if (!skin)
+               return;
+       video::IVideoDriver* driver = Environment->getVideoDriver();
+       
+       video::SColor bgcolor(140,0,0,0);
+       driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
+
+       gui::IGUIElement::draw();
+}
+
+bool GUIPauseMenu::OnEvent(const SEvent& event)
+{
+
+       if(event.EventType==EET_KEY_INPUT_EVENT)
+       {
+               if(event.KeyInput.PressedDown)
+               {
+                       if(event.KeyInput.Key==KEY_ESCAPE)
+                       {
+                               quitMenu();
+                               return true;
+                       }
+                       else if(event.KeyInput.Key==KEY_RETURN)
+                       {
+                               quitMenu();
+                               return true;
+                       }
+               }
+       }
+       if(event.EventType==EET_GUI_EVENT)
+       {
+               if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
+                               && isVisible())
+               {
+                       if(!canTakeFocus(event.GUIEvent.Element))
+                       {
+                               dstream<<"GUIPauseMenu: Not allowing focus change."
+                                               <<std::endl;
+                               // Returning true disables focus change
+                               return true;
+                       }
+               }
+               if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
+               {
+                       switch(event.GUIEvent.Caller->getID())
+                       {
+                       case 256: // continue
+                               quitMenu();
+                               // ALWAYS return immediately after quitMenu()
+                               return true;
+                       case 261:
+                               quitMenu();
+                               m_gamecallback->changePassword();
+                               return true;
+                       case 260: // disconnect
+                               m_gamecallback->disconnect();
+                               quitMenu();
+                               return true;
+                       case 257: // exit
+                               m_gamecallback->exitToOS();
+                               quitMenu();
+                               return true;
+                       }
+               }
+       }
+       
+       return Parent ? Parent->OnEvent(event) : false;
+}
+
index e28159a93c864fe5977f70b26e14fd198717aa93..4b15fc74fc1f6c28577b27c268db516952db14b7 100644 (file)
@@ -1,60 +1,60 @@
-/*\r
-Minetest-c55\r
-Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>\r
-\r
-This program is free software; you can redistribute it and/or modify\r
-it under the terms of the GNU Lesser General Public License as published by\r
-the Free Software Foundation; either version 2.1 of the License, or\r
-(at your option) any later version.\r
-\r
-This program is distributed in the hope that it will be useful,\r
-but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-GNU Lesser General Public License for more details.\r
-\r
-You should have received a copy of the GNU Lesser General Public License along\r
-with this program; if not, write to the Free Software Foundation, Inc.,\r
-51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-*/\r
-\r
-#ifndef GUIPAUSEMENU_HEADER\r
-#define GUIPAUSEMENU_HEADER\r
-\r
-#include "irrlichttypes_extrabloated.h"\r
-#include "modalMenu.h"\r
-\r
-class IGameCallback\r
-{\r
-public:\r
-       virtual void exitToOS() = 0;\r
-       virtual void disconnect() = 0;\r
-       virtual void changePassword() = 0;\r
-};\r
-\r
-class GUIPauseMenu : public GUIModalMenu\r
-{\r
-public:\r
-       GUIPauseMenu(gui::IGUIEnvironment* env,\r
-                       gui::IGUIElement* parent, s32 id,\r
-                       IGameCallback *gamecallback,\r
-                       IMenuManager *menumgr,\r
-                       bool simple_singleplayer_mode);\r
-       ~GUIPauseMenu();\r
-       \r
-       void removeChildren();\r
-       /*\r
-               Remove and re-add (or reposition) stuff\r
-       */\r
-       void regenerateGui(v2u32 screensize);\r
-\r
-       void drawMenu();\r
-\r
-       bool OnEvent(const SEvent& event);\r
-       \r
-private:\r
-       IGameCallback *m_gamecallback;\r
-       bool m_simple_singleplayer_mode;\r
-};\r
-\r
-#endif\r
-\r
+/*
+Minetest-c55
+Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU Lesser General Public License as published by
+the Free Software Foundation; either version 2.1 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public License along
+with this program; if not, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#ifndef GUIPAUSEMENU_HEADER
+#define GUIPAUSEMENU_HEADER
+
+#include "irrlichttypes_extrabloated.h"
+#include "modalMenu.h"
+
+class IGameCallback
+{
+public:
+       virtual void exitToOS() = 0;
+       virtual void disconnect() = 0;
+       virtual void changePassword() = 0;
+};
+
+class GUIPauseMenu : public GUIModalMenu
+{
+public:
+       GUIPauseMenu(gui::IGUIEnvironment* env,
+                       gui::IGUIElement* parent, s32 id,
+                       IGameCallback *gamecallback,
+                       IMenuManager *menumgr,
+                       bool simple_singleplayer_mode);
+       ~GUIPauseMenu();
+       
+       void removeChildren();
+       /*
+               Remove and re-add (or reposition) stuff
+       */
+       void regenerateGui(v2u32 screensize);
+
+       void drawMenu();
+
+       bool OnEvent(const SEvent& event);
+       
+private:
+       IGameCallback *m_gamecallback;
+       bool m_simple_singleplayer_mode;
+};
+
+#endif
+
index 6147bb635f9dfa604c295603734f57171f01d7e0..0896c9b4f2feae02bcff1d8f4735ff1d64c18c0b 100644 (file)
@@ -1994,7 +1994,7 @@ void Map::removeNodeTimer(v3s16 p)
        ServerMap
 */
 
-ServerMap::ServerMap(std::string savedir, IGameDef *gamedef):
+ServerMap::ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emerge):
        Map(dout_server, gamedef),
        m_seed(0),
        m_map_metadata_changed(true),
@@ -2004,6 +2004,8 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef):
 {
        verbosestream<<__FUNCTION_NAME<<std::endl;
 
+       m_emerge = emerge;
+
        //m_chunksize = 8; // Takes a few seconds
 
        if (g_settings->get("fixed_map_seed").empty())
@@ -2011,12 +2013,15 @@ ServerMap::ServerMap(std::string savedir, IGameDef *gamedef):
                m_seed = (((u64)(myrand()%0xffff)<<0)
                                + ((u64)(myrand()%0xffff)<<16)
                                + ((u64)(myrand()%0xffff)<<32)
-                               + ((u64)(myrand()%0xffff)<<48));
+                               + ((u64)(myrand()&0xffff)<<48));
        }
        else
        {
                m_seed = g_settings->getU64("fixed_map_seed");
        }
+       emerge->seed = m_seed;
+       emerge->water_level = g_settings->getS16("default_water_level");
+       //<set noiseparams here>
 
        /*
                Experimental and debug stuff
@@ -2136,7 +2141,7 @@ ServerMap::~ServerMap()
 #endif
 }
 
-void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
+void ServerMap::initBlockMake(BlockMakeData *data, v3s16 blockpos)
 {
        bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info");
        if(enable_mapgen_debug_info)
@@ -2208,7 +2213,7 @@ void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
 
                                                Refer to the map generator heuristics.
                                        */
-                                       bool ug = mapgen::block_is_underground(data->seed, p);
+                                       bool ug = m_emerge->isBlockUnderground(p);
                                        block->setIsUnderground(ug);
                                }
 
@@ -2243,7 +2248,7 @@ void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
        // Data is ready now.
 }
 
-MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
+MapBlock* ServerMap::finishBlockMake(BlockMakeData *data,
                core::map<v3s16, MapBlock*> &changed_blocks)
 {
        v3s16 blockpos_min = data->blockpos_min;
@@ -2483,6 +2488,7 @@ ServerMapSector * ServerMap::createSector(v2s16 p2d)
        return sector;
 }
 
+#if 0
 /*
        This is a quick-hand function for calling makeBlock().
 */
@@ -2518,7 +2524,7 @@ MapBlock * ServerMap::generateBlock(
        /*
                Create block make data
        */
-       mapgen::BlockMakeData data;
+       BlockMakeData data;
        initBlockMake(&data, p);
 
        /*
@@ -2526,7 +2532,8 @@ MapBlock * ServerMap::generateBlock(
        */
        {
                TimeTaker t("mapgen::make_block()");
-               mapgen::make_block(&data);
+               mapgen->makeChunk(&data);
+               //mapgen::make_block(&data);
 
                if(enable_mapgen_debug_info == false)
                        t.stop(true); // Hide output
@@ -2595,6 +2602,7 @@ MapBlock * ServerMap::generateBlock(
 
        return block;
 }
+#endif
 
 MapBlock * ServerMap::createBlock(v3s16 p)
 {
@@ -2656,14 +2664,15 @@ MapBlock * ServerMap::createBlock(v3s16 p)
        }
        // Create blank
        block = sector->createBlankBlock(block_y);
+
        return block;
 }
 
-MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
+MapBlock * ServerMap::emergeBlock(v3s16 p, bool create_blank)
 {
-       DSTACKF("%s: p=(%d,%d,%d), allow_generate=%d",
+       DSTACKF("%s: p=(%d,%d,%d), create_blank=%d",
                        __FUNCTION_NAME,
-                       p.X, p.Y, p.Z, allow_generate);
+                       p.X, p.Y, p.Z, create_blank);
        
        {
                MapBlock *block = getBlockNoCreateNoEx(p);
@@ -2677,7 +2686,13 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
                        return block;
        }
 
-       if(allow_generate)
+       if (create_blank) {
+               ServerMapSector *sector = createSector(v2s16(p.X, p.Z));
+               MapBlock *block = sector->createBlankBlock(p.Y);
+
+               return block;
+       }
+       /*if(allow_generate)
        {
                core::map<v3s16, MapBlock*> modified_blocks;
                MapBlock *block = generateBlock(p, modified_blocks);
@@ -2700,7 +2715,7 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
                                                                
                        return block;
                }
-       }
+       }*/
 
        return NULL;
 }
@@ -2742,7 +2757,7 @@ plan_b:
                Determine from map generator noise functions
        */
        
-       s16 level = mapgen::find_ground_level_from_noise(m_seed, p2d, 1);
+       s16 level = m_emerge->getGroundLevelAtPoint(p2d);
        return level;
 
        //double level = base_rock_level_2d(m_seed, p2d) + AVERAGE_MUD_AMOUNT;
@@ -3062,6 +3077,7 @@ void ServerMap::saveMapMeta()
        
        Settings params;
        params.setU64("seed", m_seed);
+       params.setS16("water_level", m_emerge->water_level);
 
        params.writeLines(os);
 
@@ -3100,8 +3116,11 @@ void ServerMap::loadMapMeta()
                        break;
                params.parseConfigLine(line);
        }
-
+       
        m_seed = params.getU64("seed");
+       m_emerge->seed        = m_seed;
+       m_emerge->water_level = params.getS16("water_level");
+       //m_emerge->np = ;
 
        verbosestream<<"ServerMap::loadMapMeta(): "<<"seed="<<m_seed<<std::endl;
 }
index 30cf626bb7d7aa15b06ea5684483dc6d724d35e3..3097d15b9fcc52549919ac1008d97118f55f4c21 100644 (file)
--- a/src/map.h
+++ b/src/map.h
@@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "mapnode.h"
 #include "constants.h"
 #include "voxel.h"
+#include "mapgen.h" //for BlockMakeData and EmergeManager
 #include "modifiedstate.h"
 #include "util/container.h"
 #include "nodetimer.h"
@@ -46,9 +47,6 @@ class NodeMetadata;
 class IGameDef;
 class IRollbackReportSink;
 
-namespace mapgen{
-       struct BlockMakeData;
-};
 
 /*
        MapEditEvent
@@ -360,7 +358,7 @@ public:
        /*
                savedir: directory to which map data should be saved
        */
-       ServerMap(std::string savedir, IGameDef *gamedef);
+       ServerMap(std::string savedir, IGameDef *gamedef, EmergeManager *emerge);
        ~ServerMap();
 
        s32 mapType() const
@@ -379,15 +377,15 @@ public:
        /*
                Blocks are generated by using these and makeBlock().
        */
-       void initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos);
-       MapBlock* finishBlockMake(mapgen::BlockMakeData *data,
+       void initBlockMake(BlockMakeData *data, v3s16 blockpos);
+       MapBlock* finishBlockMake(BlockMakeData *data,
                        core::map<v3s16, MapBlock*> &changed_blocks);
        
-       // A non-threaded wrapper to the above
-       MapBlock * generateBlock(
+       // A non-threaded wrapper to the above  - DEFUNCT
+/*     MapBlock * generateBlock(
                        v3s16 p,
                        core::map<v3s16, MapBlock*> &modified_blocks
-       );
+       );*/
        
        /*
                Get a block from somewhere.
@@ -400,9 +398,10 @@ public:
                Forcefully get a block from somewhere.
                - Memory
                - Load from disk
-               - Generate
+               - Create blank filled with CONTENT_IGNORE
+               
        */
-       MapBlock * emergeBlock(v3s16 p, bool allow_generate=true);
+       MapBlock * emergeBlock(v3s16 p, bool create_blank=true);
        
        // Helper for placing objects on ground level
        s16 findGroundLevel(v2s16 p2d);
@@ -479,6 +478,7 @@ public:
 
        u64 getSeed(){ return m_seed; }
 
+       EmergeManager *m_emerge;
 private:
        // Seed used for all kinds of randomness in generation
        u64 m_seed;
index ae0c551cb5d6d84cdb311034e229fdf209cd69f5..7271b7652c5f9d46116fc0018bb11c0274d542cb 100644 (file)
@@ -20,7 +20,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "mapgen.h"
 #include "voxel.h"
 #include "noise.h"
+#include "biome.h"
 #include "mapblock.h"
+#include "mapnode.h"
 #include "map.h"
 //#include "serverobject.h"
 #include "content_sao.h"
@@ -28,9 +30,296 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "content_mapnode.h" // For content_mapnode_get_new_name
 #include "voxelalgorithms.h"
 #include "profiler.h"
+#include "settings.h" // For g_settings
 #include "main.h" // For g_profiler
 #include "treegen.h"
 
+NoiseParams nparams_mtdefault =
+       {0.0, 20.0, v3f(250., 250., 250.), 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
+NoiseParams nparams_def_heat =
+       {25.0, 50.0, v3f(500., 500., 500.), 35293, 1, 0.00}; //-25 to 75
+NoiseParams nparams_def_humidity =
+       {50, 100/(2*1.6), v3f(750., 750., 750.), 12094, 2, 0.60}; //0 to 100
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+/*
+Mapgen::Mapgen(BiomeDefManager *biomedef) {
+       Mapgen(0, 0, biomedef);
+}*/
+
+
+Mapgen::Mapgen(BiomeDefManager *biomedef, int mapgenid, u64 seed) {
+       initMapgen(biomedef, mapgenid, seed,
+               &nparams_mtdefault, &nparams_def_bgroup,
+               &nparams_def_heat,  &nparams_def_humidity);
+}
+
+
+Mapgen::Mapgen(BiomeDefManager *biomedef, int mapgenid, u64 seed,
+                          NoiseParams *np_terrain, NoiseParams *np_bgroup,
+                          NoiseParams *np_heat,    NoiseParams *np_humidity) {
+       initMapgen(biomedef, mapgenid, seed,
+               np_terrain, np_bgroup, np_heat, np_humidity);
+}
+
+void Mapgen::initMapgen(BiomeDefManager *biomedef, int mapgenid, u64 seed,
+                          NoiseParams *np_terrain, NoiseParams *np_bgroup,
+                          NoiseParams *np_heat,    NoiseParams *np_humidity) {
+       this->generating  = false;
+       this->id       = mapgenid;
+       this->seed     = (int)seed;
+       this->biomedef = biomedef;
+       this->csize       = v3s16(5, 5, 5) * MAP_BLOCKSIZE; /////////////////get this from config!
+       this->water_level = g_settings->getS16("default_water_level"); ////fix this!
+
+       this->np_terrain  = np_terrain;
+       this->np_bgroup   = np_bgroup;
+       this->np_heat     = np_heat;
+       this->np_humidity = np_humidity;
+       noise_terrain  = new Noise(np_terrain,  seed, csize.X, csize.Y);
+       noise_bgroup   = new Noise(np_bgroup,   seed, csize.X, csize.Y);
+       noise_heat     = new Noise(np_heat,     seed, csize.X, csize.Y);
+       noise_humidity = new Noise(np_humidity, seed, csize.X, csize.Y);
+
+       this->ndef = biomedef->ndef;
+       n_air   = MapNode(ndef->getId("mapgen_air"));
+       n_water = MapNode(ndef->getId("mapgen_water_source"));
+       n_lava  = MapNode(ndef->getId("mapgen_lava_source"));
+}
+
+
+Mapgen::~Mapgen() {
+       delete noise_terrain;
+       delete noise_bgroup;
+       delete noise_heat;
+       delete noise_humidity;
+}
+
+
+void Mapgen::makeChunk(BlockMakeData *data) {
+       if (data->no_op)
+               return;
+
+       //printf("generating...\n");//////////////
+
+       assert(data->vmanip);
+       assert(data->nodedef);
+       assert(data->blockpos_requested.X >= data->blockpos_min.X &&
+                  data->blockpos_requested.Y >= data->blockpos_min.Y &&
+                  data->blockpos_requested.Z >= data->blockpos_min.Z);
+       assert(data->blockpos_requested.X <= data->blockpos_max.X &&
+                  data->blockpos_requested.Y <= data->blockpos_max.Y &&
+                  data->blockpos_requested.Z <= data->blockpos_max.Z);
+
+       this->generating = true;
+
+       this->data    = data;
+       this->vmanip  = data->vmanip;
+       v3s16 em = vmanip->m_area.getExtent();
+       this->ystride = em.X;
+       this->zstride = em.Y * em.X;
+
+       node_min = (data->blockpos_min) * MAP_BLOCKSIZE;
+       node_max = (data->blockpos_max + v3s16(1, 1, 1)) * MAP_BLOCKSIZE - v3s16(1, 1, 1);
+       v3s16 full_node_min = (data->blockpos_min - 1) * MAP_BLOCKSIZE;
+       v3s16 full_node_max = (data->blockpos_max + 2) * MAP_BLOCKSIZE - v3s16(1,1,1);
+
+       int y1 = node_min.Y;
+       int y2 = node_max.Y;
+       int x  = node_min.X;
+       int z  = node_min.Z;
+       //printf("full_node_min.X: %d  |  full_node_min.Z:  %d   |  MinEdge:  %d   |  MaxEdge:  %d\n", node_min.X, node_min.Z, vmanip->m_area.MinEdge.X, vmanip->m_area.MinEdge.Z);
+       TimeTaker timer("Generating terrain");
+       map_terrain  = noise_terrain->perlinMap2D(x, z);
+       map_bgroup   = noise_bgroup->perlinMap2D(x, z);
+       map_heat     = noise_heat->perlinMap2D(x, z);
+       map_humidity = noise_humidity->perlinMap2D(x, z);
+
+       int i = 0;
+       for (x = node_min.X; x <= node_max.X; x++) {
+               for (z = node_min.Z; z <= node_max.Z; z++) {
+                       Biome *biome = biomedef->getBiome(map_bgroup[i], map_heat[i], map_humidity[i]);
+                       biome->genColumn(this, x, z, y1, y2);
+                       i++;
+               }
+       }
+       timer.stop();
+
+       //genCave();
+       //genDungeon();
+       //add blobs of dirt and gravel underground
+       //decorateChunk();
+       //updateLiquid(full_node_min, full_node_max);
+       updateLighting(node_min, node_max);
+
+       this->generating = false;
+       //printf("generated block (%d, %d) to (%d, %d)\n", node_min.X, node_min.Y, node_max.X, node_max.Y);//////////
+}
+
+
+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++) {
+                       v2s16 p2d(x, z);
+                       wasliquid = true;
+                       v3s16 em  = vmanip->m_area.getExtent();
+                       i = vmanip->m_area.index(v3s16(p2d.X, node_max.Y, p2d.Y));
+
+                       for (s16 y = node_max.Y; y >= node_min.Y; y--) {
+                               isliquid = ndef->get(vmanip->m_data[i]).isLiquid();
+                               //there was a change between liquid and nonliquid, add to queue
+                               if (isliquid != wasliquid)
+                                       data->transforming_liquid.push_back(v3s16(p2d.X, y, p2d.Y));
+
+                               wasliquid = isliquid;
+                               vmanip->m_area.add_y(em, i, -1);
+                       }
+               }
+       }
+}
+
+
+void Mapgen::updateLighting(v3s16 node_min, v3s16 node_max) {
+       enum LightBank banks[2] = {LIGHTBANK_DAY, LIGHTBANK_NIGHT};
+
+       VoxelArea a(node_min - v3s16(1,0,1) * MAP_BLOCKSIZE,
+                               node_max + v3s16(1,0,1) * MAP_BLOCKSIZE);
+       bool block_is_underground = (water_level > node_max.Y);
+       bool sunlight = !block_is_underground;
+
+       ScopeProfiler sp(g_profiler, "EmergeThread: mapgen lighting update", SPT_AVG);
+       for (int i = 0; i < 2; i++) {
+               enum LightBank bank = banks[i];
+        core::map<v3s16, bool> light_sources;
+        core::map<v3s16, u8> unlight_from;
+
+               voxalgo::clearLightAndCollectSources(*vmanip, a, bank, ndef,
+                                        light_sources, unlight_from);
+               voxalgo::propagateSunlight(*vmanip, a, sunlight, light_sources, ndef);
+        printf("light_sources: %d\t\tunlight_from: %d\n", light_sources.size(), unlight_from.size());
+               vmanip->unspreadLight(bank, unlight_from, light_sources, ndef);
+               vmanip->spreadLight(bank, light_sources, ndef);
+       }
+}
+
+
+/*class EmergeManager {
+public:
+       int seed;
+       int water_level;
+       BiomeDefManager *biomedef;
+
+       //mapgen objects here
+
+       void addBlockToQueue();
+
+
+       //mapgen helper methods
+       int getGroundLevelAtPoint(u64 mseed, v2s16 p);
+       bool isBlockUnderground(u64 mseed, v3s16 blockpos);
+       u32 getBlockSeed(u64 mseed, v3s16 p);
+};*/
+
+EmergeManager::EmergeManager(IGameDef *gamedef) {
+       this->seed = 0;
+       this->water_level = 0;
+       this->np_terrain  = &nparams_mtdefault;
+       this->np_bgroup   = &nparams_def_bgroup;
+       this->np_heat     = &nparams_def_heat;
+       this->np_humidity = &nparams_def_humidity;
+
+       this->biomedef = new BiomeDefManager(gamedef);
+}
+
+
+EmergeManager::~EmergeManager() {
+       delete biomedef;
+}
+
+
+void EmergeManager::addBlockToQueue() {
+
+}
+
+
+Biome *EmergeManager::getBiomeAtPoint(v3s16 p) {
+       float bgroup   = NoisePerlin2D(np_bgroup,   p.X, p.Y, seed);
+       float heat     = NoisePerlin2D(np_heat,     p.X, p.Y, seed);
+       float humidity = NoisePerlin2D(np_humidity, p.X, p.Y, seed);
+       return biomedef->getBiome(bgroup, heat, humidity);
+}
+
+
+//FIXME:  This assumes y == 0, that is, always in a non-hell/non-sky biome
+int EmergeManager::getGroundLevelAtPoint(v2s16 p) {
+       float terrain = NoisePerlin2D(np_terrain, p.X, p.Y, seed);
+       Biome *biome = getBiomeAtPoint(v3s16(p.X, p.Y, 0));
+       return biome->getSurfaceHeight(terrain);
+}
+
+
+bool EmergeManager::isBlockUnderground(v3s16 blockpos) {
+       /*
+       v2s16 p = v2s16((blockpos.X * MAP_BLOCKSIZE) + MAP_BLOCKSIZE / 2,
+                                       (blockpos.Y * MAP_BLOCKSIZE) + MAP_BLOCKSIZE / 2);
+       int ground_level = getGroundLevelAtPoint(p);
+       return blockpos.Y * (MAP_BLOCKSIZE + 1) <= min(water_level, ground_level);
+       */
+
+       //yuck, but then again, should i bother being accurate?
+       //the height of the nodes in a single block is quite variable
+       return false; //blockpos.Y * (MAP_BLOCKSIZE + 1) <= water_level;
+}
+
+
+u32 EmergeManager::getBlockSeed(v3s16 p) {
+       return (u32)(seed & 0xFFFFFFFF) +
+               p.Z * 38134234 +
+               p.Y * 42123 +
+               p.Y * 23;
+}
+
+
+/////////////////////////////////// legacy static functions for farmesh
+
+
+s16 Mapgen::find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision) {
+       //just need to return something
+       s16 level = 5;
+       return level;
+}
+
+
+bool Mapgen::get_have_beach(u64 seed, v2s16 p2d) {
+       double sandnoise = noise2d_perlin(
+                       0.2+(float)p2d.X/250, 0.7+(float)p2d.Y/250,
+                       seed+59420, 3, 0.50);
+
+       return (sandnoise > 0.15);
+}
+
+
+double Mapgen::tree_amount_2d(u64 seed, v2s16 p) {
+       double noise = noise2d_perlin(
+                       0.5+(float)p.X/125, 0.5+(float)p.Y/125,
+                       seed+2, 4, 0.66);
+       double zeroval = -0.39;
+       if(noise < zeroval)
+               return 0;
+       else
+               return 0.04 * (noise-zeroval) / (1.0-zeroval);
+}
+
+
+#if 0 /// BIG COMMENT
 namespace mapgen
 {
 
@@ -121,6 +410,7 @@ static s16 find_stone_level(VoxelManipulator &vmanip, v2s16 p2d,
 }
 #endif
 
+
 #if 0
 
 static void make_papyrus(VoxelManipulator &vmanip, v3s16 p0,
@@ -190,7 +480,7 @@ static void make_room1(VoxelManipulator &vmanip, v3s16 roomsize, v3s16 roomplace
                        vmanip.m_data[vi] = MapNode(ndef->getId("mapgen_cobble"));
                }
        }
-       
+
        // Make +-Z walls
        for(s16 x=0; x<roomsize.X; x++)
        for(s16 y=0; y<roomsize.Y; y++)
@@ -214,7 +504,7 @@ static void make_room1(VoxelManipulator &vmanip, v3s16 roomsize, v3s16 roomplace
                        vmanip.m_data[vi] = MapNode(ndef->getId("mapgen_cobble"));
                }
        }
-       
+
        // Make +-Y walls (floor and ceiling)
        for(s16 z=0; z<roomsize.Z; z++)
        for(s16 x=0; x<roomsize.X; x++)
@@ -238,7 +528,7 @@ static void make_room1(VoxelManipulator &vmanip, v3s16 roomsize, v3s16 roomplace
                        vmanip.m_data[vi] = MapNode(ndef->getId("mapgen_cobble"));
                }
        }
-       
+
        // Fill with air
        for(s16 z=1; z<roomsize.Z-1; z++)
        for(s16 y=1; y<roomsize.Y-1; y++)
@@ -401,9 +691,9 @@ static void make_corridor(VoxelManipulator &vmanip, v3s16 doorplace,
                if(partcount >= partlength)
                {
                        partcount = 0;
-                       
+
                        dir = random_turn(random, dir);
-                       
+
                        partlength = random.range(1,length);
 
                        make_stairs = 0;
@@ -443,7 +733,7 @@ public:
        {
                m_dir = dir;
        }
-       
+
        bool findPlaceForDoor(v3s16 &result_place, v3s16 &result_dir)
        {
                for(u32 i=0; i<100; i++)
@@ -540,7 +830,7 @@ public:
                        if(doordir == v3s16(0,0,-1)) // Z-
                                roomplace = doorplace + v3s16(-roomsize.X/2,-1,-roomsize.Z+1);
 #endif
-                       
+
                        // Check fit
                        bool fits = true;
                        for(s16 z=1; z<roomsize.Z-1; z++)
@@ -587,7 +877,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
        v3s16 areasize = vmanip.m_area.getExtent();
        v3s16 roomsize;
        v3s16 roomplace;
-       
+
        /*
                Find place for first room
        */
@@ -627,20 +917,20 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
        // No place found
        if(fits == false)
                return;
-       
+
        /*
                Stores the center position of the last room made, so that
                a new corridor can be started from the last room instead of
                the new room, if chosen so.
        */
        v3s16 last_room_center = roomplace+v3s16(roomsize.X/2,1,roomsize.Z/2);
-       
+
        u32 room_count = random.range(2,7);
        for(u32 i=0; i<room_count; i++)
        {
                // Make a room to the determined place
                make_room1(vmanip, roomsize, roomplace, ndef);
-               
+
                v3s16 room_center = roomplace + v3s16(roomsize.X/2,1,roomsize.Z/2);
 
                // Place torch at room center (for testing)
@@ -649,7 +939,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
                // Quit if last room
                if(i == room_count-1)
                        break;
-               
+
                // Determine walker start position
 
                bool start_in_last_room = (random.range(0,2)!=0);
@@ -667,7 +957,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
                        // Store center of current room as the last one
                        last_room_center = room_center;
                }
-               
+
                // Create walker and find a place for a door
                RoomWalker walker(vmanip, walker_start_place, random, ndef);
                v3s16 doorplace;
@@ -675,20 +965,20 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
                bool r = walker.findPlaceForDoor(doorplace, doordir);
                if(r == false)
                        return;
-               
+
                if(random.range(0,1)==0)
                        // Make the door
                        make_door1(vmanip, doorplace, doordir, ndef);
                else
                        // Don't actually make a door
                        doorplace -= doordir;
-               
+
                // Make a random corridor starting from the door
                v3s16 corridor_end;
                v3s16 corridor_end_dir;
                make_corridor(vmanip, doorplace, doordir, corridor_end,
                                corridor_end_dir, random, ndef);
-               
+
                // Find a place for a random sized room
                roomsize = v3s16(random.range(4,8),random.range(4,6),random.range(4,8));
                walker.setPos(corridor_end);
@@ -703,7 +993,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random,
                else
                        // Don't actually make a door
                        roomplace -= doordir;
-               
+
        }
 }
 #endif
@@ -926,7 +1216,7 @@ s16 find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision)
                        }
                }
        }
-       
+
        // This is more like the actual ground level
        level += dec[i-1]/2;
 
@@ -1024,7 +1314,7 @@ bool block_is_underground(u64 seed, v3s16 blockpos)
                        seed, v2s16(blockpos.X, blockpos.Z));*/
        // Nah, this is just a heuristic, just return something
        s16 minimum_groundlevel = WATER_LEVEL;
-       
+
        if(blockpos.Y*MAP_BLOCKSIZE + MAP_BLOCKSIZE <= minimum_groundlevel)
                return true;
        else
@@ -1132,9 +1422,9 @@ BiomeType get_biome(u64 seed, v2s16 p2d)
        double d = noise2d_perlin(
                        0.6+(float)p2d.X/250, 0.2+(float)p2d.Y/250,
                        seed+9130, 3, 0.50);
-       if(d > 0.45) 
+       if(d > 0.45)
                return BT_DESERT;
-       if(d > 0.35 && (noise2d( p2d.X, p2d.Y, int(seed) ) + 1.0) > ( 0.45 - d ) * 20.0  ) 
+       if(d > 0.35 && (noise2d( p2d.X, p2d.Y, int(seed) ) + 1.0) > ( 0.45 - d ) * 20.0  )
                return BT_DESERT;
        return BT_NORMAL;
 };
@@ -1169,7 +1459,7 @@ void make_block(BlockMakeData *data)
        // Hack: use minimum block coordinates for old code that assumes
        // a single block
        v3s16 blockpos = data->blockpos_requested;
-       
+
        /*dstream<<"makeBlock(): ("<<blockpos.X<<","<<blockpos.Y<<","
                        <<blockpos.Z<<")"<<std::endl;*/
 
@@ -1177,7 +1467,7 @@ void make_block(BlockMakeData *data)
        v3s16 blockpos_max = data->blockpos_max;
        v3s16 blockpos_full_min = blockpos_min - v3s16(1,1,1);
        v3s16 blockpos_full_max = blockpos_max + v3s16(1,1,1);
-       
+
        ManualMapVoxelManipulator &vmanip = *(data->vmanip);
        // Area of central chunk
        v3s16 node_min = blockpos_min*MAP_BLOCKSIZE;
@@ -1193,10 +1483,10 @@ void make_block(BlockMakeData *data)
        int volume_blocks = (blockpos_max.X - blockpos_min.X + 1)
                        * (blockpos_max.Y - blockpos_min.Y + 1)
                        * (blockpos_max.Z - blockpos_max.Z + 1);
-       
+
        int volume_nodes = volume_blocks *
                        MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
-       
+
        // Generated surface area
        //double gen_area_nodes = MAP_BLOCKSIZE*MAP_BLOCKSIZE * rel_volume;
 
@@ -1207,7 +1497,7 @@ void make_block(BlockMakeData *data)
                Create a block-specific seed
        */
        u32 blockseed = get_blockseed(data->seed, full_node_min);
-       
+
        /*
                Cache some ground type values for speed
        */
@@ -1253,13 +1543,13 @@ void make_block(BlockMakeData *data)
        {
 #if 1
        TimeTaker timer1("Generating ground level");
-       
+
        for(s16 x=node_min.X; x<=node_max.X; x++)
        for(s16 z=node_min.Z; z<=node_max.Z; z++)
        {
                // Node position
                v2s16 p2d = v2s16(x,z);
-               
+
                /*
                        Skip of already generated
                */
@@ -1274,7 +1564,7 @@ void make_block(BlockMakeData *data)
 
                // Use perlin noise for ground height
                surface_y_f = base_rock_level_2d(data->seed, p2d);
-               
+
                /*// Experimental stuff
                {
                        float a = highlands_level_2d(data->seed, p2d);
@@ -1284,7 +1574,7 @@ void make_block(BlockMakeData *data)
 
                // Convert to integer
                s16 surface_y = (s16)surface_y_f;
-               
+
                // Log it
                if(surface_y > stone_surface_max_y)
                        stone_surface_max_y = surface_y;
@@ -1316,9 +1606,9 @@ void make_block(BlockMakeData *data)
                }
        }
 #endif
-       
+
        }//timer1
-       
+
        // Limit dirt flow area by 1 because mud is flown into neighbors.
        assert(central_area_size.X == central_area_size.Z);
        s16 mudflow_minpos = 0-max_spread_amount+1;
@@ -1375,7 +1665,7 @@ void make_block(BlockMakeData *data)
                        tunnel_routepoints = ps.range(10, ps.range(15,30));
                }
                bool large_cave_is_flat = (ps.range(0,1) == 0);
-               
+
                v3f main_direction(0,0,0);
 
                // Allowed route area size in nodes
@@ -1391,7 +1681,7 @@ void make_block(BlockMakeData *data)
                s16 more = max_spread_amount - max_tunnel_diameter/2 - insure;
                ar += v3s16(1,0,1) * more * 2;
                of -= v3s16(1,0,1) * more;
-               
+
                s16 route_y_min = 0;
                // Allow half a diameter + 7 over stone surface
                s16 route_y_max = -of.Y + stone_surface_max_y + max_tunnel_diameter/2 + 7;
@@ -1434,7 +1724,7 @@ void make_block(BlockMakeData *data)
                        if(coming_from_surface)
                                route_start_y_min = -of.Y + stone_surface_max_y + 10;
                }*/
-               
+
                route_start_y_min = rangelim(route_start_y_min, 0, ar.Y-1);
                route_start_y_max = rangelim(route_start_y_max, route_start_y_min, ar.Y-1);
 
@@ -1451,11 +1741,11 @@ void make_block(BlockMakeData *data)
                MapNode airnode(CONTENT_AIR);
                MapNode waternode(c_water_source);
                MapNode lavanode(c_lava_source);
-               
+
                /*
                        Generate some tunnel starting from orp
                */
-               
+
                for(u16 j=0; j<tunnel_routepoints; j++)
                {
                        if(j%dswitchint==0 && large_cave == false)
@@ -1467,12 +1757,12 @@ void make_block(BlockMakeData *data)
                                );
                                main_direction *= (float)ps.range(0, 10)/10;
                        }
-                       
+
                        // Randomize size
                        s16 min_d = min_tunnel_diameter;
                        s16 max_d = max_tunnel_diameter;
                        s16 rs = ps.range(min_d, max_d);
-                       
+
                        // Every second section is rough
                        bool randomize_xz = (ps2.range(1,2) == 1);
 
@@ -1495,13 +1785,13 @@ void make_block(BlockMakeData *data)
                        }
 
                        v3f vec;
-                       
+
                        vec = v3f(
                                (float)(ps.next()%(maxlen.X*1))-(float)maxlen.X/2,
                                (float)(ps.next()%(maxlen.Y*1))-(float)maxlen.Y/2,
                                (float)(ps.next()%(maxlen.Z*1))-(float)maxlen.Z/2
                        );
-               
+
                        // Jump downward sometimes
                        if(!large_cave && ps.range(0,12) == 0)
                        {
@@ -1511,7 +1801,7 @@ void make_block(BlockMakeData *data)
                                        (float)(ps.next()%(maxlen.Z*1))-(float)maxlen.Z/2
                                );
                        }
-                       
+
                        /*if(large_cave){
                                v3f p = orp + vec;
                                s16 h = find_ground_level_clever(vmanip,
@@ -1573,12 +1863,12 @@ void make_block(BlockMakeData *data)
                                                        s16 x = cp.X + x0;
                                                        v3s16 p(x,y,z);
                                                        p += of;
-                                                       
+
                                                        if(vmanip.m_area.contains(p) == false)
                                                                continue;
-                                                       
+
                                                        u32 i = vmanip.m_area.index(p);
-                                                       
+
                                                        if(large_cave)
                                                        {
                                                                if(full_node_min.Y < WATER_LEVEL &&
@@ -1602,7 +1892,7 @@ void make_block(BlockMakeData *data)
                                                                vmanip.m_data[i].getContent() == c_water_source ||
                                                                vmanip.m_data[i].getContent() == c_lava_source)
                                                                        continue;
-                                                               
+
                                                                vmanip.m_data[i] = airnode;
 
                                                                // Set tunnel flag
@@ -1615,12 +1905,12 @@ void make_block(BlockMakeData *data)
 
                        orp = rp;
                }
-       
+
        }
 
        }//timer1
 #endif
-       
+
 #if 1
        {
        // 15ms @cs=8
@@ -1629,13 +1919,13 @@ void make_block(BlockMakeData *data)
        /*
                Add mud to the central chunk
        */
-       
+
        for(s16 x=node_min.X; x<=node_max.X; x++)
        for(s16 z=node_min.Z; z<=node_max.Z; z++)
        {
                // Node position in 2d
                v2s16 p2d = v2s16(x,z);
-               
+
                // Randomize mud amount
                s16 mud_add_amount = get_mud_add_amount(data->seed, p2d) / 2.0 + 0.5;
 
@@ -1660,7 +1950,7 @@ void make_block(BlockMakeData *data)
                                surface_y + mud_add_amount <= WATER_LEVEL+2){
                        addnode = MapNode(c_sand);
                }
-               
+
                if(bt == BT_DESERT){
                        if(surface_y > 20){
                                mud_add_amount = MYMAX(0, mud_add_amount - (surface_y - 20)/5);
@@ -1691,7 +1981,7 @@ void make_block(BlockMakeData *data)
                        {
                                if(mudcount >= mud_add_amount)
                                        break;
-                                       
+
                                MapNode &n = vmanip.m_data[i];
                                n = addnode;
                                mudcount++;
@@ -1756,7 +2046,7 @@ void make_block(BlockMakeData *data)
        /*
                Flow mud away from steep edges
        */
-       
+
        // Iterate a few times
        for(s16 k=0; k<3; k++)
        {
@@ -1773,7 +2063,7 @@ void make_block(BlockMakeData *data)
 
                // Node position in 2d
                v2s16 p2d = v2s16(node_min.X, node_min.Z) + v2s16(x,z);
-               
+
                v3s16 em = vmanip.m_area.getExtent();
                u32 i = vmanip.m_area.index(v3s16(p2d.X, node_max.Y, p2d.Y));
                s16 y=node_max.Y;
@@ -1794,7 +2084,7 @@ void make_block(BlockMakeData *data)
                                                n->getContent() == c_dirt_with_grass ||
                                                n->getContent() == c_gravel)
                                        break;
-                                       
+
                                vmanip.m_area.add_y(em, i, -1);
                        }
 
@@ -1813,7 +2103,7 @@ void make_block(BlockMakeData *data)
                        {
                                // Make it exactly mud
                                n->setContent(c_dirt);
-                               
+
                                /*
                                        Don't flow it if the stuff under it is not mud
                                */
@@ -1851,7 +2141,7 @@ void make_block(BlockMakeData *data)
                        }
 
                        // Drop mud on side
-                       
+
                        for(u32 di=0; di<4; di++)
                        {
                                v3s16 dirp = dirs4[di];
@@ -1894,7 +2184,7 @@ void make_block(BlockMakeData *data)
                                // Loop one up so that we're in air
                                vmanip.m_area.add_y(em, i2, 1);
                                n2 = &vmanip.m_data[i2];
-                               
+
                                bool old_is_water = (n->getContent() == c_water_source);
                                // Move mud to new place
                                if(!dropped_to_unknown) {
@@ -1912,7 +2202,7 @@ void make_block(BlockMakeData *data)
                }
                }
        }
-       
+
        }
 
        }//timer1
@@ -1940,7 +2230,7 @@ void make_block(BlockMakeData *data)
                        for(s16 y=full_node_max.Y; y>=full_node_min.Y; y--)
                        {
                                if(y == full_node_max.Y){
-                                       water_found = 
+                                       water_found =
                                                (vmanip.m_data[i].getContent() == c_water_source ||
                                                vmanip.m_data[i].getContent() == c_lava_source);
                                }
@@ -1982,7 +2272,7 @@ void make_block(BlockMakeData *data)
        {
                // Node position in 2d
                v2s16 p2d = v2s16(x,z);
-               
+
                /*
                        Find the lowest surface to which enough light ends up
                        to make grass grow.
@@ -2008,7 +2298,7 @@ void make_block(BlockMakeData *data)
                        else
                                surface_y = full_node_min.Y;
                }
-               
+
                u32 i = vmanip.m_area.index(p2d.X, surface_y, p2d.Y);
                MapNode *n = &vmanip.m_data[i];
                if(n->getContent() == c_dirt){
@@ -2113,7 +2403,7 @@ void make_block(BlockMakeData *data)
                                        else
                                                vmanip.m_data[i] = n_stone;
                                }
-                       
+
                                vmanip->m_area.add_y(em, i, 1);
                        }
                }
@@ -2168,7 +2458,7 @@ void make_block(BlockMakeData *data)
        /*
                Add dungeons
        */
-       
+
        //if(node_min.Y < approx_groundlevel)
        //if(myrand() % 3 == 0)
        //if(myrand() % 3 == 0 && node_min.Y < approx_groundlevel)
@@ -2182,7 +2472,7 @@ void make_block(BlockMakeData *data)
                // Dungeon generator doesn't modify places which have this set
                vmanip->clearFlag(VMANIP_FLAG_DUNGEON_INSIDE
                                | VMANIP_FLAG_DUNGEON_PRESERVE);
-               
+
                // Set all air and water to be untouchable to make dungeons open
                // to caves and open air
                for(s16 x=full_node_min.X; x<=full_node_max.X; x++)
@@ -2204,12 +2494,12 @@ void make_block(BlockMakeData *data)
                                }
                        }
                }
-               
+
                PseudoRandom random(blockseed+2);
 
                // Add it
                make_dungeon1(vmanip, random, ndef);
-               
+
                // Convert some cobble to mossy cobble
                for(s16 x=full_node_min.X; x<=full_node_max.X; x++)
                for(s16 z=full_node_min.Z; z<=full_node_max.Z; z++)
@@ -2257,7 +2547,7 @@ void make_block(BlockMakeData *data)
                        make_nc(vmanip, ncrandom, ndef);
                }
        }
-       
+
        /*
                Add top and bottom side of water to transforming_liquid queue
        */
@@ -2346,7 +2636,7 @@ void make_block(BlockMakeData *data)
                                                if(current_depth == 0 && y <= WATER_LEVEL+2
                                                                && possibly_have_sand)
                                                        have_sand = true;
-                                               
+
                                                if(current_depth < 4)
                                                {
                                                        if(have_sand)
@@ -2384,7 +2674,7 @@ void make_block(BlockMakeData *data)
                /*
                        Calculate some stuff
                */
-               
+
                float surface_humidity = surface_humidity_2d(data->seed, p2d_center);
                bool is_jungle = surface_humidity > 0.75;
                // Amount of trees
@@ -2521,7 +2811,7 @@ void make_block(BlockMakeData *data)
                /*
                        Add some kind of random stones
                */
-               
+
                u32 random_stone_count = gen_area_nodes *
                                randomstone_amount_2d(data->seed, p2d_center);
                // Put in random places on part of division
@@ -2555,7 +2845,7 @@ void make_block(BlockMakeData *data)
                /*
                        Add larger stones
                */
-               
+
                u32 large_stone_count = gen_area_nodes *
                                largestone_amount_2d(data->seed, p2d_center);
                //u32 large_stone_count = 1;
@@ -2612,7 +2902,7 @@ void make_block(BlockMakeData *data)
                                                if(mineralrandom.next()%8 == 0)
                                                        vmanip.m_data[vi] = MapNode(c_mese);
                                }
-                                       
+
                        }
                }
                /*
@@ -2742,7 +3032,7 @@ void make_block(BlockMakeData *data)
 
                voxalgo::clearLightAndCollectSources(vmanip, a, bank, ndef,
                                light_sources, unlight_from);
-               
+
                bool inexistent_top_provides_sunlight = !block_is_underground;
                voxalgo::SunlightPropagateResult res = voxalgo::propagateSunlight(
                                vmanip, a, inexistent_top_provides_sunlight,
@@ -2756,6 +3046,8 @@ void make_block(BlockMakeData *data)
        }
 }
 
+#endif ///BIG COMMENT
+
 BlockMakeData::BlockMakeData():
        no_op(false),
        vmanip(NULL),
@@ -2768,6 +3060,6 @@ BlockMakeData::~BlockMakeData()
        delete vmanip;
 }
 
-}; // namespace mapgen
+//}; // namespace mapgen
 
 
index 8986ddab0cb2898e9e92d0d4fc08ebe83150c449..d6e932ca0290dd441edbad659f204801b92ff87e 100644 (file)
@@ -22,12 +22,121 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 
 #include "irrlichttypes_extrabloated.h"
 #include "util/container.h" // UniqueQueue
+#include "gamedef.h"
+#include "mapnode.h"
+#include "noise.h"
 
-struct BlockMakeData;
+class BiomeDefManager;
+class Biome;
+
+//struct BlockMakeData;
 class MapBlock;
 class ManualMapVoxelManipulator;
 class INodeDefManager;
 
+struct BlockMakeData {
+       bool no_op;
+       ManualMapVoxelManipulator *vmanip;
+       u64 seed;
+       v3s16 blockpos_min;
+       v3s16 blockpos_max;
+       v3s16 blockpos_requested;
+       UniqueQueue<v3s16> transforming_liquid;
+       INodeDefManager *nodedef;
+
+       BlockMakeData();
+       ~BlockMakeData();
+};
+
+class Mapgen {
+public:
+       BlockMakeData *data;
+       ManualMapVoxelManipulator *vmanip;
+       INodeDefManager *ndef;
+       BiomeDefManager *biomedef;
+
+       int ystride;
+       int zstride;
+
+       v3s16 csize;
+       int seed;
+       int water_level;
+
+       Noise *noise_terrain;
+       Noise *noise_bgroup;
+       Noise *noise_heat;
+       Noise *noise_humidity;
+
+       v3s16 node_min;
+       v3s16 node_max;
+
+       float *map_terrain;
+       float *map_bgroup;
+       float *map_heat;
+       float *map_humidity;
+
+       bool generating;
+       int id;
+
+       NoiseParams *np_terrain;
+       NoiseParams *np_bgroup;
+       NoiseParams *np_heat;
+       NoiseParams *np_humidity;
+
+       //should these be broken off into a "commonly used nodes" class?
+       MapNode n_air;
+       MapNode n_water;
+       MapNode n_lava;
+
+       Mapgen(BiomeDefManager *biomedef, int mapgenid=0, u64 seed=0);
+       Mapgen(BiomeDefManager *biomedef, int mapgenid, u64 seed,
+                  NoiseParams *np_terrain, NoiseParams *np_bgroup,
+                  NoiseParams *np_heat,    NoiseParams *np_humidity);
+       void initMapgen(BiomeDefManager *biomedef, int mapgenid, u64 seed,
+                          NoiseParams *np_terrain, NoiseParams *np_bgroup,
+                          NoiseParams *np_heat,    NoiseParams *np_humidity);
+       ~Mapgen();
+
+       void makeChunk(BlockMakeData *data);
+       void updateLiquid(v3s16 node_min, v3s16 node_max);
+       void updateLighting(v3s16 node_min, v3s16 node_max);
+
+       //Legacy functions for Farmesh (pending removal)
+       static bool get_have_beach(u64 seed, v2s16 p2d);
+       static double tree_amount_2d(u64 seed, v2s16 p);
+       static s16 find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision);
+};
+
+class EmergeManager {
+public:
+       //settings
+       u64 seed;
+       int water_level;
+       NoiseParams *np_terrain;
+       NoiseParams *np_bgroup;
+       NoiseParams *np_heat;
+       NoiseParams *np_humidity;
+
+       //biome manager
+       BiomeDefManager *biomedef;
+
+       //mapgen objects here
+
+       EmergeManager(IGameDef *gamedef);
+       ~EmergeManager();
+       void addBlockToQueue();
+
+
+
+       //mapgen helper methods
+       Biome *getBiomeAtPoint(v3s16 p);
+       int getGroundLevelAtPoint(v2s16 p);
+       bool isBlockUnderground(v3s16 blockpos);
+       u32 getBlockSeed(v3s16 p);
+};
+
+
+/*
 namespace mapgen
 {
        // Finds precise ground level at any position
@@ -41,10 +150,9 @@ namespace mapgen
 
        // Main map generation routine
        void make_block(BlockMakeData *data);
-       
-       /*
-               These are used by FarMesh
-       */
+
+
+       //These are used by FarMesh
        bool get_have_beach(u64 seed, v2s16 p2d);
        double tree_amount_2d(u64 seed, v2s16 p);
 
@@ -64,6 +172,6 @@ namespace mapgen
        };
 
 }; // namespace mapgen
-
+*/
 #endif
 
index 36fa798fd4492a2c734d220e554314f5ce607d45..560c6090d1a6b81f45b76dc3cad69964fb07673b 100644 (file)
@@ -106,7 +106,7 @@ void NodeBox::deSerialize(std::istream &is)
 /*
        TileDef
 */
-       
+
 void TileDef::serialize(std::ostream &os) const
 {
        writeU8(os, 0); // version
@@ -173,7 +173,7 @@ void ContentFeatures::reset()
        has_after_destruct = false;
        /*
                Actual data
-               
+
                NOTE: Most of this is always overridden by the default values given
                      in builtin.lua
        */
@@ -354,7 +354,7 @@ public:
                        ContentFeatures &f = m_content_features[i];
                        f.reset(); // Reset to defaults
                }
-               
+
                // Set CONTENT_AIR
                {
                        ContentFeatures f;
@@ -541,11 +541,11 @@ public:
                bool new_style_water = g_settings->getBool("new_style_water");
                bool new_style_leaves = g_settings->getBool("new_style_leaves");
                bool opaque_water = g_settings->getBool("opaque_water");
-               
+
                for(u16 i=0; i<=MAX_CONTENT; i++)
                {
                        ContentFeatures *f = &m_content_features[i];
-                       
+
                        // Figure out the actual tiles to use
                        TileDef tiledef[6];
                        for(u32 j=0; j<6; j++)
index e75fbf4bd27e688b1499ad95f61c4fc903e75b47..5cb4be29a1d7ce862f800b33a9bed7366696d01c 100644 (file)
@@ -21,89 +21,116 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "noise.h"
 #include <iostream>
 #include "debug.h"
+#include "util/numeric.h"
 
-#define NOISE_MAGIC_X 1619
-#define NOISE_MAGIC_Y 31337
-#define NOISE_MAGIC_Z 52591
+#define NOISE_MAGIC_X    1619
+#define NOISE_MAGIC_Y    31337
+#define NOISE_MAGIC_Z    52591
 #define NOISE_MAGIC_SEED 1013
 
-double cos_lookup[16] = {
-       1.0,0.9238,0.7071,0.3826,0,-0.3826,-0.7071,-0.9238,
-       1.0,-0.9238,-0.7071,-0.3826,0,0.3826,0.7071,0.9238
+float cos_lookup[16] = {
+       1.0,  0.9238,  0.7071,  0.3826, 0, -0.3826, -0.7071, -0.9238,
+       1.0, -0.9238, -0.7071, -0.3826, 0,  0.3826,  0.7071,  0.9238
 };
 
-double dotProduct(double vx, double vy, double wx, double wy){
-    return vx*wx+vy*wy;
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+//noise poly:  p(n) = 60493n^3 + 19990303n + 137612589
+float noise2d(int x, int y, int seed) {
+       int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y
+                       + NOISE_MAGIC_SEED * seed) & 0x7fffffff;
+       n = (n >> 13) ^ n;
+       n = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
+       return 1.f - (float)n / 0x40000000;
 }
-double easeCurve(double t){
-    return t * t * t * (6. * t * t - 15. * t + 10.);
+
+
+float noise3d(int x, int y, int z, int seed) {
+       int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y + NOISE_MAGIC_Z * z
+                       + NOISE_MAGIC_SEED * seed) & 0x7fffffff;
+       n = (n >> 13) ^ n;
+       n = (n * (n * n * 60493 + 19990303) + 1376312589) & 0x7fffffff;
+       return 1.f - (float)n / 0x40000000;
 }
-double linearInterpolation(double x0, double x1, double t){
-    return x0+(x1-x0)*t;
+
+
+float dotProduct(float vx, float vy, float wx, float wy) {
+       return vx * wx + vy * wy;
 }
-double biLinearInterpolation(double x0y0, double x1y0, double x0y1, double x1y1, double x, double y){
-    double tx = easeCurve(x);
-    double ty = easeCurve(y);
-       /*double tx = x;
-       double ty = y;*/
-    double u = linearInterpolation(x0y0,x1y0,tx);
-    double v = linearInterpolation(x0y1,x1y1,tx);
-    return linearInterpolation(u,v,ty);
+
+
+inline float linearInterpolation(float v0, float v1, float t) {
+    return v0 + (v1 - v0) * t;
 }
 
-double triLinearInterpolation(
-               double v000, double v100, double v010, double v110,
-               double v001, double v101, double v011, double v111,
-               double x, double y, double z)
-{
-    /*double tx = easeCurve(x);
-    double ty = easeCurve(y);
-    double tz = easeCurve(z);*/
-    double tx = x;
-    double ty = y;
-    double tz = z;
-       return(
-               v000*(1-tx)*(1-ty)*(1-tz) +
-               v100*tx*(1-ty)*(1-tz) +
-               v010*(1-tx)*ty*(1-tz) +
-               v110*tx*ty*(1-tz) +
-               v001*(1-tx)*(1-ty)*tz +
-               v101*tx*(1-ty)*tz +
-               v011*(1-tx)*ty*tz +
-               v111*tx*ty*tz
-       );
+
+float biLinearInterpolation(float v00, float v10,
+                                                       float v01, float v11,
+                                                       float x, float y) {
+    float tx = easeCurve(x);
+    float ty = easeCurve(y);
+    float u = linearInterpolation(v00, v10, tx);
+    float v = linearInterpolation(v01, v11, tx);
+    return linearInterpolation(u, v, ty);
 }
 
-double noise2d(int x, int y, int seed)
-{
-       int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y
-                       + NOISE_MAGIC_SEED * seed) & 0x7fffffff;
-       n = (n>>13)^n;
-       n = (n * (n*n*60493+19990303) + 1376312589) & 0x7fffffff;
-       return 1.0 - (double)n/1073741824;
+
+float biLinearInterpolationNoEase(float x0y0, float x1y0,
+                                                                 float x0y1, float x1y1,
+                                                                 float x, float y) {
+    float u = linearInterpolation(x0y0, x1y0, x);
+    float v = linearInterpolation(x0y1, x1y1, x);
+    return linearInterpolation(u, v, y);
 }
 
-double noise3d(int x, int y, int z, int seed)
+
+float triLinearInterpolation(
+               float v000, float v100, float v010, float v110,
+               float v001, float v101, float v011, float v111,
+               float x, float y, float z) {
+       float u = biLinearInterpolationNoEase(v000, v100, v010, v110, x, y);
+       float v = biLinearInterpolationNoEase(v001, v101, v011, v111, x, y);
+       return linearInterpolation(u, v, z);
+}
+
+
+#if 0
+float triLinearInterpolation(
+               float v000, float v100, float v010, float v110,
+               float v001, float v101, float v011, float v111,
+               float x, float y, float z)
 {
-       int n = (NOISE_MAGIC_X * x + NOISE_MAGIC_Y * y + NOISE_MAGIC_Z * z
-                       + NOISE_MAGIC_SEED * seed) & 0x7fffffff;
-       n = (n>>13)^n;
-       n = (n * (n*n*60493+19990303) + 1376312589) & 0x7fffffff;
-       return 1.0 - (double)n/1073741824;
+       /*float tx = easeCurve(x);
+       float ty = easeCurve(y);
+       float tz = easeCurve(z);*/
+       float tx = x;
+       float ty = y;
+       float tz = z;
+       return(
+               v000 * (1 - tx) * (1 - ty) * (1 - tz) +
+               v100 * tx * (1 - ty) * (1 - tz) +
+               v010 * (1 - tx) * ty * (1 - tz) +
+               v110 * tx * ty * (1 - tz) +
+               v001 * (1 - tx) * (1 - ty) * tz +
+               v101 * tx * (1 - ty) * tz +
+               v011 * (1 - tx) * ty * tz +
+               v111 * tx * ty * tz
+       );
 }
+#endif
+
 
 #if 0
-double noise2d_gradient(double x, double y, int seed)
+float noise2d_gradient(float x, float y, int seed)
 {
        // Calculate the integer coordinates
        int x0 = (x > 0.0 ? (int)x : (int)x - 1);
        int y0 = (y > 0.0 ? (int)y : (int)y - 1);
        // Calculate the remaining part of the coordinates
-       double xl = x - (double)x0;
-       double yl = y - (double)y0;
+       float xl = x - (float)x0;
+       float yl = y - (float)y0;
        // Calculate random cosine lookup table indices for the integer corners.
        // They are looked up as unit vector gradients from the lookup table.
        int n00 = (int)((noise2d(x0, y0, seed)+1)*8);
@@ -111,119 +138,126 @@ double noise2d_gradient(double x, double y, int seed)
        int n01 = (int)((noise2d(x0, y0+1, seed)+1)*8);
        int n11 = (int)((noise2d(x0+1, y0+1, seed)+1)*8);
        // Make a dot product for the gradients and the positions, to get the values
-       double s = dotProduct(cos_lookup[n00], cos_lookup[(n00+12)%16], xl, yl);
-       double u = dotProduct(-cos_lookup[n10], cos_lookup[(n10+12)%16], 1.-xl, yl);
-       double v = dotProduct(cos_lookup[n01], -cos_lookup[(n01+12)%16], xl, 1.-yl);
-       double w = dotProduct(-cos_lookup[n11], -cos_lookup[(n11+12)%16], 1.-xl, 1.-yl);
+       float s = dotProduct(cos_lookup[n00], cos_lookup[(n00+12)%16], xl, yl);
+       float u = dotProduct(-cos_lookup[n10], cos_lookup[(n10+12)%16], 1.-xl, yl);
+       float v = dotProduct(cos_lookup[n01], -cos_lookup[(n01+12)%16], xl, 1.-yl);
+       float w = dotProduct(-cos_lookup[n11], -cos_lookup[(n11+12)%16], 1.-xl, 1.-yl);
        // Interpolate between the values
        return biLinearInterpolation(s,u,v,w,xl,yl);
 }
 #endif
 
-#if 1
-double noise2d_gradient(double x, double y, int seed)
+
+float noise2d_gradient(float x, float y, int seed)
 {
        // Calculate the integer coordinates
-       int x0 = (x > 0.0 ? (int)x : (int)x - 1);
-       int y0 = (y > 0.0 ? (int)y : (int)y - 1);
+       int x0 = myfloor(x);
+       int y0 = myfloor(y);
        // Calculate the remaining part of the coordinates
-       double xl = x - (double)x0;
-       double yl = y - (double)y0;
-       // Get values for corners of cube
-       double v00 = noise2d(x0, y0, seed);
-       double v10 = noise2d(x0+1, y0, seed);
-       double v01 = noise2d(x0, y0+1, seed);
-       double v11 = noise2d(x0+1, y0+1, seed);
+       float xl = x - (float)x0;
+       float yl = y - (float)y0;
+       // Get values for corners of square
+       float v00 = noise2d(x0, y0, seed);
+       float v10 = noise2d(x0+1, y0, seed);
+       float v01 = noise2d(x0, y0+1, seed);
+       float v11 = noise2d(x0+1, y0+1, seed);
        // Interpolate
        return biLinearInterpolation(v00,v10,v01,v11,xl,yl);
 }
-#endif
 
-double noise3d_gradient(double x, double y, double z, int seed)
+
+float noise3d_gradient(float x, float y, float z, int seed)
 {
        // Calculate the integer coordinates
-       int x0 = (x > 0.0 ? (int)x : (int)x - 1);
-       int y0 = (y > 0.0 ? (int)y : (int)y - 1);
-       int z0 = (z > 0.0 ? (int)z : (int)z - 1);
+       int x0 = myfloor(x);
+       int y0 = myfloor(y);
+       int z0 = myfloor(z);
        // Calculate the remaining part of the coordinates
-       double xl = x - (double)x0;
-       double yl = y - (double)y0;
-       double zl = z - (double)z0;
+       float xl = x - (float)x0;
+       float yl = y - (float)y0;
+       float zl = z - (float)z0;
        // Get values for corners of cube
-       double v000 = noise3d(x0, y0, z0, seed);
-       double v100 = noise3d(x0+1, y0, z0, seed);
-       double v010 = noise3d(x0, y0+1, z0, seed);
-       double v110 = noise3d(x0+1, y0+1, z0, seed);
-       double v001 = noise3d(x0, y0, z0+1, seed);
-       double v101 = noise3d(x0+1, y0, z0+1, seed);
-       double v011 = noise3d(x0, y0+1, z0+1, seed);
-       double v111 = noise3d(x0+1, y0+1, z0+1, seed);
+       float v000 = noise3d(x0,     y0,     z0,     seed);
+       float v100 = noise3d(x0 + 1, y0,     z0,     seed);
+       float v010 = noise3d(x0,     y0 + 1, z0,     seed);
+       float v110 = noise3d(x0 + 1, y0 + 1, z0,     seed);
+       float v001 = noise3d(x0,     y0,     z0 + 1, seed);
+       float v101 = noise3d(x0 + 1, y0,     z0 + 1, seed);
+       float v011 = noise3d(x0,     y0 + 1, z0 + 1, seed);
+       float v111 = noise3d(x0 + 1, y0 + 1, z0 + 1, seed);
        // Interpolate
-       return triLinearInterpolation(v000,v100,v010,v110,v001,v101,v011,v111,xl,yl,zl);
+       return triLinearInterpolation(v000, v100, v010, v110,
+                                                                 v001, v101, v011, v111,
+                                                                 xl, yl, zl);
 }
 
-double noise2d_perlin(double x, double y, int seed,
-               int octaves, double persistence)
+
+float noise2d_perlin(float x, float y, int seed,
+               int octaves, float persistence)
 {
-       double a = 0;
-       double f = 1.0;
-       double g = 1.0;
-       for(int i=0; i<octaves; i++)
+       float a = 0;
+       float f = 1.0;
+       float g = 1.0;
+       for (int i = 0; i < octaves; i++)
        {
-               a += g * noise2d_gradient(x*f, y*f, seed+i);
+               a += g * noise2d_gradient(x * f, y * f, seed + i);
                f *= 2.0;
                g *= persistence;
        }
        return a;
 }
 
-double noise2d_perlin_abs(double x, double y, int seed,
-               int octaves, double persistence)
+
+float noise2d_perlin_abs(float x, float y, int seed,
+               int octaves, float persistence)
 {
-       double a = 0;
-       double f = 1.0;
-       double g = 1.0;
-       for(int i=0; i<octaves; i++)
+       float a = 0;
+       float f = 1.0;
+       float g = 1.0;
+       for (int i = 0; i < octaves; i++)
        {
-               a += g * fabs(noise2d_gradient(x*f, y*f, seed+i));
+               a += g * fabs(noise2d_gradient(x * f, y * f, seed + i));
                f *= 2.0;
                g *= persistence;
        }
        return a;
 }
 
-double noise3d_perlin(double x, double y, double z, int seed,
-               int octaves, double persistence)
+
+float noise3d_perlin(float x, float y, float z, int seed,
+               int octaves, float persistence)
 {
-       double a = 0;
-       double f = 1.0;
-       double g = 1.0;
-       for(int i=0; i<octaves; i++)
+       float a = 0;
+       float f = 1.0;
+       float g = 1.0;
+       for (int i = 0; i < octaves; i++)
        {
-               a += g * noise3d_gradient(x*f, y*f, z*f, seed+i);
+               a += g * noise3d_gradient(x * f, y * f, z * f, seed + i);
                f *= 2.0;
                g *= persistence;
        }
        return a;
 }
 
-double noise3d_perlin_abs(double x, double y, double z, int seed,
-               int octaves, double persistence)
+
+float noise3d_perlin_abs(float x, float y, float z, int seed,
+               int octaves, float persistence)
 {
-       double a = 0;
-       double f = 1.0;
-       double g = 1.0;
-       for(int i=0; i<octaves; i++)
+       float a = 0;
+       float f = 1.0;
+       float g = 1.0;
+       for (int i = 0; i < octaves; i++)
        {
-               a += g * fabs(noise3d_gradient(x*f, y*f, z*f, seed+i));
+               a += g * fabs(noise3d_gradient(x * f, y * f, z * f, seed + i));
                f *= 2.0;
                g *= persistence;
        }
        return a;
 }
 
+
 // -1->0, 0->1, 1->0
-double contour(double v)
+float contour(float v)
 {
        v = fabs(v);
        if(v >= 1.0)
@@ -231,195 +265,276 @@ double contour(double v)
        return (1.0-v);
 }
 
-double noise3d_param(const NoiseParams &param, double x, double y, double z)
-{
-       double s = param.pos_scale;
-       x /= s;
-       y /= s;
-       z /= s;
 
-       if(param.type == NOISE_CONSTANT_ONE)
-       {
-               return 1.0;
-       }
-       else if(param.type == NOISE_PERLIN)
-       {
-               return param.noise_scale*noise3d_perlin(x,y,z, param.seed,
-                               param.octaves,
-                               param.persistence);
-       }
-       else if(param.type == NOISE_PERLIN_ABS)
-       {
-               return param.noise_scale*noise3d_perlin_abs(x,y,z, param.seed,
-                               param.octaves,
-                               param.persistence);
-       }
-       else if(param.type == NOISE_PERLIN_CONTOUR)
-       {
-               return contour(param.noise_scale*noise3d_perlin(x,y,z,
-                               param.seed, param.octaves,
-                               param.persistence));
-       }
-       else if(param.type == NOISE_PERLIN_CONTOUR_FLIP_YZ)
-       {
-               return contour(param.noise_scale*noise3d_perlin(x,z,y,
-                               param.seed, param.octaves,
-                               param.persistence));
-       }
-       else assert(0);
-}
+///////////////////////// [ New perlin stuff ] ////////////////////////////
 
-/*
-       NoiseBuffer
-*/
 
-NoiseBuffer::NoiseBuffer():
-       m_data(NULL)
-{
+Noise::Noise(NoiseParams *np, int seed, int sx, int sy) {
+       int nlx, nly;
+       float ofactor;
+
+       //maximum possible spread value factor
+       ofactor = (float)(1 << (np->octaves - 1));
+
+       //noise lattice point count
+       //(int)(sz * spread * ofactor) is # of lattice points crossed due to length
+       // + 2 for the two initial endpoints
+       // + 1 for potentially crossing a boundary due to offset
+       nlx = (int)(sx * ofactor / np->spread.X) + 3;
+       nly = (int)(sy * ofactor / np->spread.Y) + 3;
+
+       this->np   = np;
+       this->seed = seed;
+       this->sx   = sx;
+       this->sy   = sy;
+       this->sz   = 0;
+       this->noisebuf = new float[nlx * nly];
+       this->buf      = new float[sx * sy];
+       this->result   = new float[sx * sy];
 }
 
-NoiseBuffer::~NoiseBuffer()
-{
-       clear();
+
+Noise::Noise(NoiseParams *np, int seed, int sx, int sy, int sz) {
+       int nlx, nly, nlz;
+       float ofactor;
+
+       ofactor = (float)(1 << (np->octaves - 1));
+       nlx = (int)(sx * ofactor / np->spread.X) + 3;
+       nly = (int)(sy * ofactor / np->spread.Y) + 3;
+       nlz = (int)(sz * ofactor / np->spread.Z) + 3;
+
+       this->np   = np;
+       this->seed = seed;
+       this->sx   = sx;
+       this->sy   = sy;
+       this->sz   = sz;
+       this->noisebuf = new float[nlx * nly * nlz];
+       this->buf      = new float[sx * sy * sz];
+       this->result   = new float[sx * sy * sz];
 }
 
-void NoiseBuffer::clear()
-{
-       if(m_data)
-               delete[] m_data;
-       m_data = NULL;
-       m_size_x = 0;
-       m_size_y = 0;
-       m_size_z = 0;
+
+Noise::~Noise() {
+       delete[] buf;
+       delete[] result;
+       delete[] noisebuf;
 }
 
-void NoiseBuffer::create(const NoiseParams &param,
-               double first_x, double first_y, double first_z,
-               double last_x, double last_y, double last_z,
-               double samplelength_x, double samplelength_y, double samplelength_z)
-{
-       clear();
-       
-       m_start_x = first_x - samplelength_x;
-       m_start_y = first_y - samplelength_y;
-       m_start_z = first_z - samplelength_z;
-       m_samplelength_x = samplelength_x;
-       m_samplelength_y = samplelength_y;
-       m_samplelength_z = samplelength_z;
-
-       m_size_x = (last_x - m_start_x)/samplelength_x + 2;
-       m_size_y = (last_y - m_start_y)/samplelength_y + 2;
-       m_size_z = (last_z - m_start_z)/samplelength_z + 2;
-
-       m_data = new double[m_size_x*m_size_y*m_size_z];
-
-       for(int x=0; x<m_size_x; x++)
-       for(int y=0; y<m_size_y; y++)
-       for(int z=0; z<m_size_z; z++)
-       {
-               double xd = (m_start_x + (double)x*m_samplelength_x);
-               double yd = (m_start_y + (double)y*m_samplelength_y);
-               double zd = (m_start_z + (double)z*m_samplelength_z);
-               double a = noise3d_param(param, xd,yd,zd);
-               intSet(x,y,z, a);
+
+/*
+ * NB:  This algorithm is not optimal in terms of space complexity.  The entire
+ * integer lattice of noise points could be done as 2 lines instead, and for 3D,
+ * 2 lines + 2 planes.
+ * However, this would require the noise calls to be interposed with the
+ * interpolation loops, which may trash the icache, leading to lower overall
+ * performance.
+ * Another optimization that could save half as many noise calls is to carry over
+ * values from the previous noise lattice as midpoints in the new lattice for the
+ * next octave.
+ */
+void Noise::gradientMap2D(float x, float y, float step_x, float step_y, int seed) {
+       float v00, v01, v10, v11, u, v, orig_u;
+       int index, i, j, x0, y0, noisex, noisey;
+       int nlx, nly;
+
+       x0 = floor(x);
+       y0 = floor(y);
+       u = x - (float)x0;
+       v = y - (float)y0;
+       orig_u = u;
+
+       //calculate noise point lattice
+
+       nlx = (int)(u + sx * step_x) + 2;
+       nly = (int)(v + sy * step_y) + 2;
+       index = 0;
+       for (j = 0; j != nly; j++)
+               for (i = 0; i != nlx; i++)
+                       noisebuf[index++] = noise2d(x0 + i, y0 + j, seed);
+
+       //calculate interpolations
+       noisey = 0;
+       for (j = 0; j != sy; j++) {
+               v00 = noisebuf[noisey * nlx];
+               v10 = noisebuf[noisey * nlx + 1];
+               v01 = noisebuf[(noisey + 1) * nlx];
+               v11 = noisebuf[(noisey + 1) * nlx + 1];
+
+               u = orig_u;
+               noisex = 0;
+               for (i = 0; i != sx; i++) {
+                       buf[j * sx + i] = biLinearInterpolation(v00, v10, v01, v11, u, v);
+                       u += step_x;
+                       if (u >= 1.0) {
+                               u -= 1.0;
+                               noisex++;
+                               v00 = v10;
+                               v01 = v11;
+                               v10 = noisebuf[noisey * nlx + noisex + 1];
+                               v11 = noisebuf[(noisey + 1) * nlx + noisex + 1];
+                       }
+               }
+
+               v += step_y;
+               if (v >= 1.0) {
+                       v -= 1.0;
+                       noisey++;
+               }
        }
 }
 
-void NoiseBuffer::multiply(const NoiseParams &param)
-{
-       assert(m_data != NULL);
 
-       for(int x=0; x<m_size_x; x++)
-       for(int y=0; y<m_size_y; y++)
-       for(int z=0; z<m_size_z; z++)
-       {
-               double xd = (m_start_x + (double)x*m_samplelength_x);
-               double yd = (m_start_y + (double)y*m_samplelength_y);
-               double zd = (m_start_z + (double)z*m_samplelength_z);
-               double a = noise3d_param(param, xd,yd,zd);
-               intMultiply(x,y,z, a);
+void Noise::gradientMap3D(float x, float y, float z,
+                                                 float step_x, float step_y, float step_z,
+                                                 int seed) {
+       float v000, v010, v100, v110;
+       float v001, v011, v101, v111;
+       float u, v, w, orig_u, orig_w;
+       int index, i, j, k, x0, y0, z0, noisex, noisey, noisez;
+       int nlx, nly, nlz;
+
+       x0 = floor(x);
+       y0 = floor(y);
+       z0 = floor(z);
+       u = x - (float)x0;
+       v = y - (float)y0;
+       w = z - (float)z0;
+       orig_u = u;
+       orig_w = w;
+
+       //calculate noise point lattice
+       nlx = (int)(u + sx * step_x) + 2;
+       nly = (int)(v + sy * step_y) + 2;
+       nlz = (int)(v + sy * step_z) + 2;
+       index = 0;
+       for (k = 0; k != nlz; k++)
+               for (j = 0; j != nly; j++)
+                       for (i = 0; i != nlx; i++)
+                               noisebuf[index++] = noise3d(x0 + i, y0 + j, z0 + k, seed);
+
+#define index(x, y, z) ((z) * nly * nlx + (y) * nlx + (x))
+
+       //calculate interpolations
+       noisey = 0;
+       noisez = 0;
+       for (k = 0; k != sz; k++) {
+               v000 = noisebuf[index(0, noisey,     noisez)];
+               v100 = noisebuf[index(1, noisey,     noisez)];
+               v010 = noisebuf[index(0, noisey + 1, noisez)];
+               v110 = noisebuf[index(1, noisey + 1, noisez)];
+               v001 = noisebuf[index(0, noisey,     noisez + 1)];
+               v101 = noisebuf[index(1, noisey,     noisez + 1)];
+               v011 = noisebuf[index(0, noisey + 1, noisez + 1)];
+               v111 = noisebuf[index(1, noisey + 1, noisez + 1)];
+
+               w = orig_w;
+               noisey = 0;
+               for (j = 0; j != sy; j++) {
+                       v000 = noisebuf[index(0, noisey,     noisez)];
+                       v100 = noisebuf[index(1, noisey,     noisez)];
+                       v010 = noisebuf[index(0, noisey + 1, noisez)];
+                       v110 = noisebuf[index(1, noisey + 1, noisez)];
+                       v001 = noisebuf[index(0, noisey,     noisez + 1)];
+                       v101 = noisebuf[index(1, noisey,     noisez + 1)];
+                       v011 = noisebuf[index(0, noisey + 1, noisez + 1)];
+                       v111 = noisebuf[index(1, noisey + 1, noisez + 1)];
+
+                       u = orig_u;
+                       noisex = 0;
+                       for (i = 0; i != sx; i++) {
+                               buf[j * sx + i] = triLinearInterpolation(
+                                                                       v000, v100, v010, v110,
+                                                                       v001, v101, v011, v111,
+                                                                       u, v, w);
+                               u += step_x;
+                               if (u >= 1.0) {
+                                       u -= 1.0;
+                                       noisex++;
+                                       v000 = v100;
+                                       v010 = v110;
+                                       v100 = noisebuf[index(noisex + 1, noisey,     noisez)];
+                                       v110 = noisebuf[index(noisex + 1, noisey + 1, noisez)];
+                                       v001 = v101;
+                                       v011 = v111;
+                                       v101 = noisebuf[index(noisex + 1, noisey,     noisez + 1)];
+                                       v111 = noisebuf[index(noisex + 1, noisey + 1, noisez + 1)];
+                               }
+                       }
+
+                       v += step_y;
+                       if (v >= 1.0) {
+                               v -= 1.0;
+                               noisey++;
+                       }
+               }
+
+               w += step_z;
+               if (w >= 1.0) {
+                       w -= 1.0;
+                       noisez++;
+               }
        }
 }
 
-// Deprecated
-void NoiseBuffer::create(int seed, int octaves, double persistence,
-               bool abs,
-               double first_x, double first_y, double first_z,
-               double last_x, double last_y, double last_z,
-               double samplelength_x, double samplelength_y, double samplelength_z)
-{
-       NoiseParams param;
-       param.type = abs ? NOISE_PERLIN_ABS : NOISE_PERLIN;
-       param.seed = seed;
-       param.octaves = octaves;
-       param.persistence = persistence;
-
-       create(param, first_x, first_y, first_z,
-                       last_x, last_y, last_z,
-                       samplelength_x, samplelength_y, samplelength_z);
-}
 
-void NoiseBuffer::intSet(int x, int y, int z, double d)
-{
-       int i = m_size_x*m_size_y*z + m_size_x*y + x;
-       assert(i >= 0);
-       assert(i < m_size_x*m_size_y*m_size_z);
-       m_data[i] = d;
-}
+float *Noise::perlinMap2D(float x, float y) {
+       float a = 0.0, f = 1.0, g = 1.0;
+       int i, j, index, oct;
 
-void NoiseBuffer::intMultiply(int x, int y, int z, double d)
-{
-       int i = m_size_x*m_size_y*z + m_size_x*y + x;
-       assert(i >= 0);
-       assert(i < m_size_x*m_size_y*m_size_z);
-       m_data[i] = m_data[i] * d;
-}
+       x /= np->spread.X;
+       y /= np->spread.Y;
 
-double NoiseBuffer::intGet(int x, int y, int z)
-{
-       int i = m_size_x*m_size_y*z + m_size_x*y + x;
-       assert(i >= 0);
-       assert(i < m_size_x*m_size_y*m_size_z);
-       return m_data[i];
-}
+       memset(result, 0, sizeof(float) * sx * sy);
 
-double NoiseBuffer::get(double x, double y, double z)
-{
-       x -= m_start_x;
-       y -= m_start_y;
-       z -= m_start_z;
-       x /= m_samplelength_x;
-       y /= m_samplelength_y;
-       z /= m_samplelength_z;
-       // Calculate the integer coordinates
-       int x0 = (x > 0.0 ? (int)x : (int)x - 1);
-       int y0 = (y > 0.0 ? (int)y : (int)y - 1);
-       int z0 = (z > 0.0 ? (int)z : (int)z - 1);
-       // Calculate the remaining part of the coordinates
-       double xl = x - (double)x0;
-       double yl = y - (double)y0;
-       double zl = z - (double)z0;
-       // Get values for corners of cube
-       double v000 = intGet(x0,   y0,   z0);
-       double v100 = intGet(x0+1, y0,   z0);
-       double v010 = intGet(x0,   y0+1, z0);
-       double v110 = intGet(x0+1, y0+1, z0);
-       double v001 = intGet(x0,   y0,   z0+1);
-       double v101 = intGet(x0+1, y0,   z0+1);
-       double v011 = intGet(x0,   y0+1, z0+1);
-       double v111 = intGet(x0+1, y0+1, z0+1);
-       // Interpolate
-       return triLinearInterpolation(v000,v100,v010,v110,v001,v101,v011,v111,xl,yl,zl);
+       for (oct = 0; oct < np->octaves; oct++) {
+               gradientMap2D(x * f, y * f,
+                       f / np->spread.X, f / np->spread.Y,
+                       seed + np->seed + oct);
+
+               index = 0;
+               for (j = 0; j != sy; j++) {
+                       for (i = 0; i != sx; i++) {
+                               result[index] += g * buf[index];
+                               index++;
+                       }
+               }
+
+               f *= 2.0;
+               g *= np->persist;
+       }
+
+       return result;
 }
 
-/*bool NoiseBuffer::contains(double x, double y, double z)
-{
-       x -= m_start_x;
-       y -= m_start_y;
-       z -= m_start_z;
-       x /= m_samplelength_x;
-       y /= m_samplelength_y;
-       z /= m_samplelength_z;
-       if(x <= 0.0 || x >= m_size_x)
-}*/
 
+float *Noise::perlinMap3D(float x, float y, float z) {
+       float a = 0.0, f = 1.0, g = 1.0;
+       int i, j, k, index, oct;
+
+       x /= np->spread.X;
+       y /= np->spread.Y;
+       z /= np->spread.Z;
+
+       memset(result, 0, sizeof(float) * sx * sy * sz);
+
+       for (oct = 0; oct < np->octaves; oct++) {
+               gradientMap3D(x * f, y * f, z * f,
+                       f / np->spread.X, f / np->spread.Y, f / np->spread.Z,
+                       seed + np->seed + oct);
+
+               index = 0;
+               for (k = 0; k != sz; k++) {
+                       for (j = 0; j != sy; j++) {
+                               for (i = 0; i != sx; i++) {
+                                       result[index] += g * buf[index];
+                                       index++;
+                               }
+                       }
+               }
+
+               f *= 2.0;
+               g *= np->persist;
+       }
+
+       return result;
+}
index 670c2eddca014b4c3a488d525872177c9734a2bb..6e5120003f21e94c4d9fa2aa6e63d12f328b4b36 100644 (file)
@@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #define NOISE_HEADER
 
 #include "debug.h"
+#include "irr_v3d.h"
 
 class PseudoRandom
 {
@@ -59,91 +60,69 @@ private:
        int m_next;
 };
 
-double easeCurve(double t);
-// Return value: -1 ... 1
-double noise2d(int x, int y, int seed);
-double noise3d(int x, int y, int z, int seed);
+struct NoiseParams {
+       float offset;
+       float scale;
+       v3f spread;
+       int seed;
+       int octaves;
+       float persist;
+};
 
-double noise2d_gradient(double x, double y, int seed);
-double noise3d_gradient(double x, double y, double z, int seed);
 
-double noise2d_perlin(double x, double y, int seed,
-               int octaves, double persistence);
+class Noise {
+public:
+       NoiseParams *np;
+       int seed;
+       int sx;
+       int sy;
+       int sz;
+       float *noisebuf;
+       float *buf;
+       float *result;
+
+       Noise(NoiseParams *np, int seed, int sx, int sy);
+       Noise(NoiseParams *np, int seed, int sx, int sy, int sz);
+       ~Noise();
+
+       void gradientMap2D(
+               float x, float y,
+               float step_x, float step_y,
+               int seed);
+       void gradientMap3D(
+               float x, float y, float z,
+               float step_x, float step_y, float step_z,
+               int seed);
+       float *perlinMap2D(float x, float y);
+       float *perlinMap3D(float x, float y, float z);
+};
 
-double noise2d_perlin_abs(double x, double y, int seed,
-               int octaves, double persistence);
+// Return value: -1 ... 1
+float noise2d(int x, int y, int seed);
+float noise3d(int x, int y, int z, int seed);
 
-double noise3d_perlin(double x, double y, double z, int seed,
-               int octaves, double persistence);
+float noise2d_gradient(float x, float y, int seed);
+float noise3d_gradient(float x, float y, float z, int seed);
 
-double noise3d_perlin_abs(double x, double y, double z, int seed,
-               int octaves, double persistence);
+float noise2d_perlin(float x, float y, int seed,
+               int octaves, float persistence);
 
-enum NoiseType
-{
-       NOISE_CONSTANT_ONE,
-       NOISE_PERLIN,
-       NOISE_PERLIN_ABS,
-       NOISE_PERLIN_CONTOUR,
-       NOISE_PERLIN_CONTOUR_FLIP_YZ,
-};
+float noise2d_perlin_abs(float x, float y, int seed,
+               int octaves, float persistence);
 
-struct NoiseParams
-{
-       NoiseType type;
-       int seed;
-       int octaves;
-       double persistence;
-       double pos_scale;
-       double noise_scale; // Useful for contour noises
-       
-       NoiseParams(NoiseType type_=NOISE_PERLIN, int seed_=0,
-                       int octaves_=3, double persistence_=0.5,
-                       double pos_scale_=100.0, double noise_scale_=1.0):
-               type(type_),
-               seed(seed_),
-               octaves(octaves_),
-               persistence(persistence_),
-               pos_scale(pos_scale_),
-               noise_scale(noise_scale_)
-       {
-       }
-};
+float noise3d_perlin(float x, float y, float z, int seed,
+               int octaves, float persistence);
 
-double noise3d_param(const NoiseParams &param, double x, double y, double z);
+float noise3d_perlin_abs(float x, float y, float z, int seed,
+               int octaves, float persistence);
 
-class NoiseBuffer
-{
-public:
-       NoiseBuffer();
-       ~NoiseBuffer();
-       
-       void clear();
-       void create(const NoiseParams &param,
-                       double first_x, double first_y, double first_z,
-                       double last_x, double last_y, double last_z,
-                       double samplelength_x, double samplelength_y, double samplelength_z);
-       void multiply(const NoiseParams &param);
-       // Deprecated
-       void create(int seed, int octaves, double persistence,
-                       bool abs,
-                       double first_x, double first_y, double first_z,
-                       double last_x, double last_y, double last_z,
-                       double samplelength_x, double samplelength_y, double samplelength_z);
-
-       void intSet(int x, int y, int z, double d);
-       void intMultiply(int x, int y, int z, double d);
-       double intGet(int x, int y, int z);
-       double get(double x, double y, double z);
-       //bool contains(double x, double y, double z);
+inline float easeCurve(float t) {
+       return t * t * t * (t * (6.f * t - 15.f) + 10.f);
+}
 
-private:
-       double *m_data;
-       double m_start_x, m_start_y, m_start_z;
-       double m_samplelength_x, m_samplelength_y, m_samplelength_z;
-       int m_size_x, m_size_y, m_size_z;
-};
+#define NoisePerlin2D(np, x, y, s) ((np)->offset + (np)->scale * \
+               noise2d_perlin((float)(x) * (np)->spread.X, (float)(y) * (np)->spread.Y, \
+               (s) + (np)->seed, (np)->octaves, (np)->persist))
 
 #endif
 
index 959885d325c1cb8bca172b6aac8c274a53218642..69ee48a7630a93f01b1445f1e9ea7a6c28286696 100644 (file)
@@ -3240,8 +3240,8 @@ class LuaPerlinNoise
 private:
        int seed;
        int octaves;
-       double persistence;
-       double scale;
+       float persistence;
+       float scale;
        static const char className[];
        static const luaL_reg methods[];
 
@@ -3273,8 +3273,8 @@ private:
        }
 
 public:
-       LuaPerlinNoise(int a_seed, int a_octaves, double a_persistence,
-                       double a_scale):
+       LuaPerlinNoise(int a_seed, int a_octaves, float a_persistence,
+                       float a_scale):
                seed(a_seed),
                octaves(a_octaves),
                persistence(a_persistence),
@@ -3292,8 +3292,8 @@ public:
        {
                int seed = luaL_checkint(L, 1);
                int octaves = luaL_checkint(L, 2);
-               double persistence = luaL_checknumber(L, 3);
-               double scale = luaL_checknumber(L, 4);
+               float persistence = luaL_checknumber(L, 3);
+               float scale = luaL_checknumber(L, 4);
                LuaPerlinNoise *o = new LuaPerlinNoise(seed, octaves, persistence, scale);
                *(void **)(lua_newuserdata(L, sizeof(void *))) = o;
                luaL_getmetatable(L, className);
@@ -3999,8 +3999,8 @@ private:
 
                int seeddiff = luaL_checkint(L, 2);
                int octaves = luaL_checkint(L, 3);
-               double persistence = luaL_checknumber(L, 4);
-               double scale = luaL_checknumber(L, 5);
+               float persistence = luaL_checknumber(L, 4);
+               float scale = luaL_checknumber(L, 5);
 
                LuaPerlinNoise *n = new LuaPerlinNoise(seeddiff + int(env->getServerMap().getSeed()), octaves, persistence, scale);
                *(void **)(lua_newuserdata(L, sizeof(void *))) = n;
index a7767842d7127c1e86977ea5fd3cf217f80fd13a..a3c0b66eddf67233a3eaa4130a0578198236de39 100644 (file)
@@ -39,6 +39,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "itemdef.h"
 #include "craftdef.h"
 #include "mapgen.h"
+#include "biome.h"
 #include "content_mapnode.h"
 #include "content_nodemeta.h"
 #include "content_abm.h"
@@ -80,7 +81,7 @@ public:
                        *m_flag = false;
                }
        }
-       
+
 private:
        bool *m_flag;
 };
@@ -105,7 +106,7 @@ public:
                        *m_ignorevariable = VoxelArea();
                }
        }
-       
+
 private:
        VoxelArea *m_ignorevariable;
 };
@@ -129,7 +130,7 @@ void * ServerThread::Thread()
                                //TimeTaker timer("AsyncRunStep()");
                                m_server->AsyncRunStep();
                        }
-               
+
                        //infostream<<"Running m_server->Receive()"<<std::endl;
                        m_server->Receive();
                }
@@ -149,7 +150,7 @@ void * ServerThread::Thread()
                        m_server->setAsyncFatalError(e.what());
                }
        }
-       
+
        END_DEBUG_EXCEPTION_HANDLER(errorstream)
 
        return NULL;
@@ -168,7 +169,11 @@ void * EmergeThread::Thread()
        bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info");
 
        v3s16 last_tried_pos(-32768,-32768,-32768); // For error output
-       
+
+       ServerMap &map = ((ServerMap&)m_server->m_env->getMap());
+       EmergeManager *emerge = m_server->m_emerge;
+       Mapgen *mapgen = new Mapgen( m_server->m_emerge->biomedef,/*mapgenid*/ 0, map.getSeed()); ////////fix this...!
+
        /*
                Get block info from queue, emerge them and send them
                to clients.
@@ -180,12 +185,12 @@ void * EmergeThread::Thread()
                QueuedBlockEmerge *qptr = m_server->m_emerge_queue.pop();
                if(qptr == NULL)
                        break;
-               
+
                SharedPtr<QueuedBlockEmerge> q(qptr);
 
                v3s16 &p = q->pos;
                v2s16 p2d(p.X,p.Z);
-               
+
                last_tried_pos = p;
 
                /*
@@ -193,18 +198,18 @@ void * EmergeThread::Thread()
                */
                if(blockpos_over_limit(p))
                        continue;
-                       
+
                //infostream<<"EmergeThread::Thread(): running"<<std::endl;
 
                //TimeTaker timer("block emerge");
-               
+
                /*
                        Try to emerge it from somewhere.
 
                        If it is only wanted as optional, only loading from disk
                        will be allowed.
                */
-               
+
                /*
                        Check if any peer wants it as non-optional. In that case it
                        will be generated.
@@ -224,17 +229,17 @@ void * EmergeThread::Thread()
                                u8 flags = i.getNode()->getValue();
                                if((flags & BLOCK_EMERGE_FLAG_FROMDISK) == false)
                                        only_from_disk = false;
-                               
+
                        }
                }
-               
+
                if(enable_mapgen_debug_info)
                        infostream<<"EmergeThread: p="
                                        <<"("<<p.X<<","<<p.Y<<","<<p.Z<<") "
                                        <<"only_from_disk="<<only_from_disk<<std::endl;
-               
-               ServerMap &map = ((ServerMap&)m_server->m_env->getMap());
-                       
+
+
+
                MapBlock *block = NULL;
                bool got_block = true;
                core::map<v3s16, MapBlock*> modified_blocks;
@@ -243,17 +248,17 @@ void * EmergeThread::Thread()
                        Try to fetch block from memory or disk.
                        If not found and asked to generate, initialize generator.
                */
-               
+
                bool started_generate = false;
-               mapgen::BlockMakeData data;
+               BlockMakeData data;
 
                {
                        JMutexAutoLock envlock(m_server->m_env_mutex);
-                       
+
                        // Load sector if it isn't loaded
                        if(map.getSectorNoGenerateNoEx(p2d) == NULL)
                                map.loadSectorMeta(p2d);
-                       
+
                        // Attempt to load block
                        block = map.getBlockNoCreateNoEx(p);
                        if(!block || block->isDummy() || !block->isGenerated())
@@ -264,7 +269,7 @@ void * EmergeThread::Thread()
 
                                block = map.loadBlock(p);
                        }
-                       
+
                        // If could not load and allowed to generate, start generation
                        // inside this same envlock
                        if(only_from_disk == false &&
@@ -287,16 +292,17 @@ void * EmergeThread::Thread()
                                                SPT_AVG);
                                TimeTaker t("mapgen::make_block()");
 
-                               mapgen::make_block(&data);
+                               mapgen->makeChunk(&data);
+                               //mapgen::make_block(&data);
 
                                if(enable_mapgen_debug_info == false)
                                        t.stop(true); // Hide output
                        }
-                       
+
                        do{ // enable break
                                // Lock environment again to access the map
                                JMutexAutoLock envlock(m_server->m_env_mutex);
-                               
+
                                ScopeProfiler sp(g_profiler, "EmergeThread: after "
                                                "mapgen::make_block (envlock)", SPT_AVG);
 
@@ -306,7 +312,7 @@ void * EmergeThread::Thread()
 
                                // Get central block
                                block = map.getBlockNoCreateNoEx(p);
-                               
+
                                // If block doesn't exist, don't try doing anything with it
                                // This happens if the block is not in generation boundaries
                                if(!block)
@@ -319,7 +325,7 @@ void * EmergeThread::Thread()
                                v3s16 minp = data.blockpos_min*MAP_BLOCKSIZE;
                                v3s16 maxp = data.blockpos_max*MAP_BLOCKSIZE +
                                                v3s16(1,1,1)*(MAP_BLOCKSIZE-1);
-                               
+
                                /*
                                        Ignore map edit events, they will not need to be
                                        sent to anybody because the block hasn't been sent
@@ -332,11 +338,11 @@ void * EmergeThread::Thread()
                                {
                                        TimeTaker timer("on_generated");
                                        scriptapi_environment_on_generated(m_server->m_lua,
-                                                       minp, maxp, mapgen::get_blockseed(data.seed, minp));
+                                                       minp, maxp, emerge->getBlockSeed(minp));
                                        /*int t = timer.stop(true);
                                        dstream<<"on_generated took "<<t<<"ms"<<std::endl;*/
                                }
-                               
+
                                if(enable_mapgen_debug_info)
                                        infostream<<"EmergeThread: ended up with: "
                                                        <<analyze_block(block)<<std::endl;
@@ -348,11 +354,11 @@ void * EmergeThread::Thread()
 
                if(block == NULL)
                        got_block = false;
-                       
+
                /*
                        Set sent status of modified blocks on clients
                */
-       
+
                // NOTE: Server's clients are also behind the connection mutex
                JMutexAutoLock lock(m_server->m_con_mutex);
 
@@ -363,17 +369,17 @@ void * EmergeThread::Thread()
                {
                        modified_blocks.insert(p, block);
                }
-               
+
                /*
                        Set the modified blocks unsent for all the clients
                */
-               
+
                for(core::map<u16, RemoteClient*>::Iterator
                                i = m_server->m_clients.getIterator();
                                i.atEnd() == false; i++)
                {
                        RemoteClient *client = i.getNode()->getValue();
-                       
+
                        if(modified_blocks.size() > 0)
                        {
                                // Remove block from sent history
@@ -434,14 +440,14 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                core::array<PrioritySortedBlockTransfer> &dest)
 {
        DSTACK(__FUNCTION_NAME);
-       
+
        /*u32 timer_result;
        TimeTaker timer("RemoteClient::GetNextBlocks", &timer_result);*/
-       
+
        // Increment timers
        m_nothing_to_send_pause_timer -= dtime;
        m_nearest_unsent_reset_timer += dtime;
-       
+
        if(m_nothing_to_send_pause_timer >= 0)
                return;
 
@@ -459,7 +465,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
        }
 
        //TimeTaker timer("RemoteClient::GetNextBlocks");
-       
+
        v3f playerpos = player->getPosition();
        v3f playerspeed = player->getSpeed();
        v3f playerspeeddir(0,0,0);
@@ -471,7 +477,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
        v3s16 center_nodepos = floatToInt(playerpos_predicted, BS);
 
        v3s16 center = getNodeBlockPos(center_nodepos);
-       
+
        // Camera position and direction
        v3f camera_pos = player->getEyePosition();
        v3f camera_dir = v3f(0,0,1);
@@ -484,7 +490,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
        /*
                Get the starting value of the block finder radius.
        */
-               
+
        if(m_last_center != center)
        {
                m_nearest_unsent_d = 0;
@@ -493,7 +499,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
 
        /*infostream<<"m_nearest_unsent_reset_timer="
                        <<m_nearest_unsent_reset_timer<<std::endl;*/
-                       
+
        // Reset periodically to workaround for some bugs or stuff
        if(m_nearest_unsent_reset_timer > 20.0)
        {
@@ -514,7 +520,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
 
        /*
                Check the time from last addNode/removeNode.
-               
+
                Decrease send rate if player is building stuff.
        */
        m_time_from_building += dtime;
@@ -524,12 +530,12 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                max_simul_sends_usually
                        = LIMITED_MAX_SIMULTANEOUS_BLOCK_SENDS;
        }
-       
+
        /*
                Number of blocks sending + number of blocks selected for sending
        */
        u32 num_blocks_selected = m_blocks_sending.size();
-       
+
        /*
                next time d will be continued from the d from which the nearest
                unsent block was found this time.
@@ -541,28 +547,28 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
 
        s16 d_max = g_settings->getS16("max_block_send_distance");
        s16 d_max_gen = g_settings->getS16("max_block_generate_distance");
-       
+
        // Don't loop very much at a time
        s16 max_d_increment_at_time = 2;
        if(d_max > d_start + max_d_increment_at_time)
                d_max = d_start + max_d_increment_at_time;
        /*if(d_max_gen > d_start+2)
                d_max_gen = d_start+2;*/
-       
+
        //infostream<<"Starting from "<<d_start<<std::endl;
 
        s32 nearest_emerged_d = -1;
        s32 nearest_emergefull_d = -1;
        s32 nearest_sent_d = -1;
        bool queue_is_full = false;
-       
+
        s16 d;
        for(d = d_start; d <= d_max; d++)
        {
                /*errorstream<<"checking d="<<d<<" for "
                                <<server->getPlayerName(peer_id)<<std::endl;*/
                //infostream<<"RemoteClient::SendBlocks(): d="<<d<<std::endl;
-               
+
                /*
                        If m_nearest_unsent_d was changed by the EmergeThread
                        (it can change it to 0 through SetBlockNotSent),
@@ -581,12 +587,12 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                */
                core::list<v3s16> list;
                getFacePositions(list, d);
-               
+
                core::list<v3s16>::Iterator li;
                for(li=list.begin(); li!=list.end(); li++)
                {
                        v3s16 p = *li + center;
-                       
+
                        /*
                                Send throttling
                                - Don't allow too many simultaneous transfers
@@ -594,10 +600,10 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
 
                                Also, don't send blocks that are already flying.
                        */
-                       
+
                        // Start with the usual maximum
                        u16 max_simul_dynamic = max_simul_sends_usually;
-                       
+
                        // If block is very close, allow full maximum
                        if(d <= BLOCK_SEND_DISABLE_LIMITS_MAX_D)
                                max_simul_dynamic = max_simul_sends_setting;
@@ -608,11 +614,11 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                                queue_is_full = true;
                                goto queue_full_break;
                        }
-                       
+
                        // Don't send blocks that are currently being transferred
                        if(m_blocks_sending.find(p) != NULL)
                                continue;
-               
+
                        /*
                                Do not go over-limit
                        */
@@ -623,10 +629,10 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                        || p.Z < -MAP_GENERATION_LIMIT / MAP_BLOCKSIZE
                        || p.Z > MAP_GENERATION_LIMIT / MAP_BLOCKSIZE)
                                continue;
-               
+
                        // If this is true, inexistent block will be made from scratch
                        bool generate = d <= d_max_gen;
-                       
+
                        {
                                /*// Limit the generating area vertically to 2/3
                                if(abs(p.Y - center.Y) > d_max_gen - d_max_gen / 3)
@@ -655,7 +661,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                                v2s16 p2d_nodes_center(
                                        MAP_BLOCKSIZE*p.X,
                                        MAP_BLOCKSIZE*p.Z);
-                               
+
                                // Get ground height in nodes
                                s16 gh = server->m_env->getServerMap().findGroundLevel(
                                                p2d_nodes_center);
@@ -697,7 +703,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                                Check if map has this block
                        */
                        MapBlock *block = server->m_env->getMap().getBlockNoCreateNoEx(p);
-                       
+
                        bool surely_not_found_on_disk = false;
                        bool block_is_invalid = false;
                        if(block != NULL)
@@ -711,13 +717,13 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                                {
                                        surely_not_found_on_disk = true;
                                }
-                               
+
                                // Block is valid if lighting is up-to-date and data exists
                                if(block->isValid() == false)
                                {
                                        block_is_invalid = true;
                                }
-                               
+
                                /*if(block->isFullyGenerated() == false)
                                {
                                        block_is_invalid = true;
@@ -775,13 +781,13 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                                if(server->m_emerge_queue.peerItemCount(peer_id) < max_emerge)
                                {
                                        //infostream<<"Adding block to emerge queue"<<std::endl;
-                                       
+
                                        // Add it to the emerge queue and trigger the thread
-                                       
+
                                        u8 flags = 0;
                                        if(generate == false)
                                                flags |= BLOCK_EMERGE_FLAG_FROMDISK;
-                                       
+
                                        server->m_emerge_queue.addBlock(peer_id, p, flags);
                                        server->m_emergethread.trigger();
 
@@ -791,7 +797,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
                                        if(nearest_emergefull_d == -1)
                                                nearest_emergefull_d = d;
                                }
-                               
+
                                // get next one.
                                continue;
                        }
@@ -816,7 +822,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
 queue_full_break:
 
        //infostream<<"Stopped at "<<d<<std::endl;
-       
+
        // If nothing was found for sending and nothing was queued for
        // emerging, continue next time browsing from here
        if(nearest_emerged_d != -1){
@@ -871,7 +877,7 @@ void RemoteClient::SentBlock(v3s16 p)
 void RemoteClient::SetBlockNotSent(v3s16 p)
 {
        m_nearest_unsent_d = 0;
-       
+
        if(m_blocks_sending.find(p) != NULL)
                m_blocks_sending.remove(p);
        if(m_blocks_sent.find(p) != NULL)
@@ -881,7 +887,7 @@ void RemoteClient::SetBlockNotSent(v3s16 p)
 void RemoteClient::SetBlocksNotSent(core::map<v3s16, MapBlock*> &blocks)
 {
        m_nearest_unsent_d = 0;
-       
+
        for(core::map<v3s16, MapBlock*>::Iterator
                        i = blocks.getIterator();
                        i.atEnd()==false; i++)
@@ -937,6 +943,7 @@ Server::Server(
        m_rollback(NULL),
        m_rollback_sink_enabled(true),
        m_enable_rollback_recording(false),
+       m_emerge(NULL),
        m_lua(NULL),
        m_itemdef(createItemDefManager()),
        m_nodedef(createNodeDefManager()),
@@ -955,7 +962,7 @@ Server::Server(
        m_objectdata_timer = 0.0;
        m_emergethread_trigger_timer = 0.0;
        m_savemap_timer = 0.0;
-       
+
        m_env_mutex.Init();
        m_con_mutex.Init();
        m_step_dtime_mutex.Init();
@@ -963,10 +970,10 @@ Server::Server(
 
        if(path_world == "")
                throw ServerError("Supplied empty world path");
-       
+
        if(!gamespec.isValid())
                throw ServerError("Supplied invalid gamespec");
-       
+
        infostream<<"Server created for gameid \""<<m_gamespec.id<<"\"";
        if(m_simple_singleplayer_mode)
                infostream<<" in simple singleplayer mode"<<std::endl;
@@ -976,6 +983,9 @@ Server::Server(
        infostream<<"- config: "<<m_path_config<<std::endl;
        infostream<<"- game:   "<<m_gamespec.path<<std::endl;
 
+       // Create emerge manager
+       m_emerge = new EmergeManager(this);
+
        // Create rollback manager
        std::string rollback_path = m_path_world+DIR_DELIM+"rollback.txt";
        m_rollback = createRollbackManager(rollback_path, this);
@@ -1075,21 +1085,24 @@ Server::Server(
                        throw ModError("Failed to load and run "+scriptpath);
                }
        }
-       
+
        // Read Textures and calculate sha1 sums
        fillMediaCache();
 
        // Apply item aliases in the node definition manager
        m_nodedef->updateAliases(m_itemdef);
 
+       // Add default biomes after nodedef had its aliases added
+       m_emerge->biomedef->addDefaultBiomes();
+
        // Initialize Environment
-       
-       m_env = new ServerEnvironment(new ServerMap(path_world, this), m_lua,
+
+       m_env = new ServerEnvironment(new ServerMap(path_world, this, m_emerge), m_lua,
                        this, this);
-       
+
        // Give environment reference to scripting api
        scriptapi_add_environment(m_lua, m_env);
-       
+
        // Register us to receive map edit events
        m_env->getMap().addEventReceiver(this);
 
@@ -1119,7 +1132,7 @@ Server::~Server()
        */
        {
                JMutexAutoLock conlock(m_con_mutex);
-               
+
                std::wstring line = L"*** Server shutting down";
 
                /*
@@ -1168,12 +1181,12 @@ Server::~Server()
                infostream<<"Server: Saving environment metadata"<<std::endl;
                m_env->saveMeta(m_path_world);
        }
-               
+
        /*
                Stop threads
        */
        stop();
-       
+
        /*
                Delete clients
        */
@@ -1184,19 +1197,21 @@ Server::~Server()
                        i = m_clients.getIterator();
                        i.atEnd() == false; i++)
                {
+
                        // Delete client
                        delete i.getNode()->getValue();
                }
        }
-       
+
        // Delete things in the reverse order of creation
        delete m_env;
        delete m_rollback;
+       delete m_emerge;
        delete m_event;
        delete m_itemdef;
        delete m_nodedef;
        delete m_craftdef;
-       
+
        // Deinitialize scripting
        infostream<<"Server: Deinitializing scripting"<<std::endl;
        script_deinit(m_lua);
@@ -1218,7 +1233,7 @@ void Server::start(unsigned short port)
 
        // Stop thread if already running
        m_thread.stop();
-       
+
        // Initialize connection
        m_con.SetTimeoutMs(30);
        m_con.Serve(port);
@@ -1226,7 +1241,7 @@ void Server::start(unsigned short port)
        // Start thread
        m_thread.setRun(true);
        m_thread.Start();
-       
+
        // ASCII art for the win!
        actionstream
        <<"        .__               __                   __   "<<std::endl
@@ -1243,7 +1258,7 @@ void Server::start(unsigned short port)
 void Server::stop()
 {
        DSTACK(__FUNCTION_NAME);
-       
+
        infostream<<"Server: Stopping and waiting threads"<<std::endl;
 
        // Stop threads (set run=false first so both start stopping)
@@ -1251,7 +1266,7 @@ void Server::stop()
        m_emergethread.setRun(false);
        m_thread.stop();
        m_emergethread.stop();
-       
+
        infostream<<"Server: Threads stopped"<<std::endl;
 }
 
@@ -1275,28 +1290,28 @@ void Server::step(float dtime)
 void Server::AsyncRunStep()
 {
        DSTACK(__FUNCTION_NAME);
-       
+
        g_profiler->add("Server::AsyncRunStep (num)", 1);
-       
+
        float dtime;
        {
                JMutexAutoLock lock1(m_step_dtime_mutex);
                dtime = m_step_dtime;
        }
-       
+
        {
                // Send blocks to clients
                SendBlocks(dtime);
        }
-       
+
        if(dtime < 0.001)
                return;
-       
+
        g_profiler->add("Server::AsyncRunStep with dtime (num)", 1);
 
        //infostream<<"Server steps "<<dtime<<std::endl;
        //infostream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl;
-       
+
        {
                JMutexAutoLock lock1(m_step_dtime_mutex);
                m_step_dtime -= dtime;
@@ -1308,14 +1323,14 @@ void Server::AsyncRunStep()
        {
                m_uptime.set(m_uptime.get() + dtime);
        }
-       
+
        {
                // Process connection's timeouts
                JMutexAutoLock lock2(m_con_mutex);
                ScopeProfiler sp(g_profiler, "Server: connection timeout processing");
                m_con.RunTimeouts(dtime);
        }
-       
+
        {
                // This has to be called so that the client list gets synced
                // with the peer list of the connection
@@ -1362,7 +1377,7 @@ void Server::AsyncRunStep()
                ScopeProfiler sp2(g_profiler, "SEnv step avg", SPT_AVG);
                m_env->step(dtime);
        }
-               
+
        const float map_timer_and_unload_dtime = 2.92;
        if(m_map_timer_and_unload_interval.step(dtime, map_timer_and_unload_dtime))
        {
@@ -1372,7 +1387,7 @@ void Server::AsyncRunStep()
                m_env->getMap().timerUpdate(map_timer_and_unload_dtime,
                                g_settings->getFloat("server_unload_unused_data_timeout"));
        }
-       
+
        /*
                Do background stuff
        */
@@ -1419,27 +1434,27 @@ void Server::AsyncRunStep()
                        }
                }
        }
-       
+
        /* Transform liquids */
        m_liquid_transform_timer += dtime;
        if(m_liquid_transform_timer >= 1.00)
        {
                m_liquid_transform_timer -= 1.00;
-               
+
                JMutexAutoLock lock(m_env_mutex);
 
                ScopeProfiler sp(g_profiler, "Server: liquid transform");
 
                core::map<v3s16, MapBlock*> modified_blocks;
                m_env->getMap().transformLiquids(modified_blocks);
-#if 0          
+#if 0
                /*
                        Update lighting
                */
                core::map<v3s16, MapBlock*> lighting_modified_blocks;
                ServerMap &map = ((ServerMap&)m_env->getMap());
                map.updateLighting(modified_blocks, lighting_modified_blocks);
-               
+
                // Add blocks modified by lighting to modified_blocks
                for(core::map<v3s16, MapBlock*>::Iterator
                                i = lighting_modified_blocks.getIterator();
@@ -1452,7 +1467,7 @@ void Server::AsyncRunStep()
                /*
                        Set the modified blocks unsent for all the clients
                */
-               
+
                JMutexAutoLock lock2(m_con_mutex);
 
                for(core::map<u16, RemoteClient*>::Iterator
@@ -1460,7 +1475,7 @@ void Server::AsyncRunStep()
                                i.atEnd() == false; i++)
                {
                        RemoteClient *client = i.getNode()->getValue();
-                       
+
                        if(modified_blocks.size() > 0)
                        {
                                // Remove block from sent history
@@ -1478,7 +1493,7 @@ void Server::AsyncRunStep()
                        counter = 0.0;
 
                        JMutexAutoLock lock2(m_con_mutex);
-                       
+
                        if(m_clients.size() != 0)
                                infostream<<"Players:"<<std::endl;
                        for(core::map<u16, RemoteClient*>::Iterator
@@ -1541,18 +1556,18 @@ void Server::AsyncRunStep()
                                        client->m_known_objects, removed_objects);
                        m_env->getAddedActiveObjects(pos, radius,
                                        client->m_known_objects, added_objects);
-                       
+
                        // Ignore if nothing happened
                        if(removed_objects.size() == 0 && added_objects.size() == 0)
                        {
                                //infostream<<"active objects: none changed"<<std::endl;
                                continue;
                        }
-                       
+
                        std::string data_buffer;
 
                        char buf[4];
-                       
+
                        // Handle removed objects
                        writeU16((u8*)buf, removed_objects.size());
                        data_buffer.append(buf, 2);
@@ -1567,7 +1582,7 @@ void Server::AsyncRunStep()
                                // Add to data buffer for sending
                                writeU16((u8*)buf, i.getNode()->getKey());
                                data_buffer.append(buf, 2);
-                               
+
                                // Remove from known objects
                                client->m_known_objects.remove(i.getNode()->getKey());
 
@@ -1585,7 +1600,7 @@ void Server::AsyncRunStep()
                                // Get object
                                u16 id = i.getNode()->getKey();
                                ServerActiveObject* obj = m_env->getActiveObject(id);
-                               
+
                                // Get object type
                                u8 type = ACTIVEOBJECT_TYPE_INVALID;
                                if(obj == NULL)
@@ -1599,7 +1614,7 @@ void Server::AsyncRunStep()
                                data_buffer.append(buf, 2);
                                writeU8((u8*)buf, type);
                                data_buffer.append(buf, 1);
-                               
+
                                if(obj)
                                        data_buffer.append(serializeLongString(
                                                        obj->getClientInitializationData(client->net_proto_version)));
@@ -1649,7 +1664,7 @@ void Server::AsyncRunStep()
                                all_known_objects[id] = true;
                        }
                }
-               
+
                m_env->setKnownActiveObjects(whatever);
 #endif
 
@@ -1674,7 +1689,7 @@ void Server::AsyncRunStep()
                        ActiveObjectMessage aom = m_env->getActiveObjectMessage();
                        if(aom.id == 0)
                                break;
-                       
+
                        core::list<ActiveObjectMessage>* message_list = NULL;
                        core::map<u16, core::list<ActiveObjectMessage>* >::Node *n;
                        n = buffered_messages.find(aom.id);
@@ -1689,7 +1704,7 @@ void Server::AsyncRunStep()
                        }
                        message_list->push_back(aom);
                }
-               
+
                // Route data to every client
                for(core::map<u16, RemoteClient*>::Iterator
                        i = m_clients.getIterator();
@@ -1796,7 +1811,7 @@ void Server::AsyncRunStep()
                while(m_unsent_map_edit_queue.size() != 0)
                {
                        MapEditEvent* event = m_unsent_map_edit_queue.pop_front();
-                       
+
                        // Players far away from the change are stored here.
                        // Instead of sending the changes, MapBlocks are set not sent
                        // for them.
@@ -1848,7 +1863,7 @@ void Server::AsyncRunStep()
                                infostream<<"WARNING: Server: Unknown MapEditEvent "
                                                <<((u32)event->type)<<std::endl;
                        }
-                       
+
                        /*
                                Set blocks not sent to far players
                        */
@@ -1892,7 +1907,7 @@ void Server::AsyncRunStep()
                        verbosestream<<"Server: MapEditEvents:"<<std::endl;
                        prof.print(verbosestream);
                }
-               
+
        }
 
        /*
@@ -1905,7 +1920,7 @@ void Server::AsyncRunStep()
                if(counter >= 2.0)
                {
                        counter = 0.0;
-                       
+
                        m_emergethread.trigger();
 
                        // Update m_enable_rollback_recording here too
@@ -1928,13 +1943,13 @@ void Server::AsyncRunStep()
                        //Ban stuff
                        if(m_banmanager.isModified())
                                m_banmanager.save();
-                       
+
                        // Save changed parts of map
                        m_env->getMap().save(MOD_STATE_WRITE_NEEDED);
 
                        // Save players
                        m_env->serializePlayers(m_path_world);
-                       
+
                        // Save environment metadata
                        m_env->saveMeta(m_path_world);
                }
@@ -1968,7 +1983,7 @@ void Server::Receive()
        catch(con::PeerNotFoundException &e)
        {
                //NOTE: This is not needed anymore
-               
+
                // The peer has been disconnected.
                // Find the associated player and remove it.
 
@@ -1988,9 +2003,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
        // Environment is locked first.
        JMutexAutoLock envlock(m_env_mutex);
        JMutexAutoLock conlock(m_con_mutex);
-       
+
        ScopeProfiler sp(g_profiler, "Server::ProcessData");
-       
+
        try{
                Address address = m_con.GetPeerAddress(peer_id);
                std::string addr_s = address.serializeString();
@@ -2014,7 +2029,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                <<peer_id<<" not found"<<std::endl;
                return;
        }
-       
+
        std::string addr_s = m_con.GetPeerAddress(peer_id).serializeString();
 
        u8 peer_ser_ver = getClient(peer_id)->serialization_version;
@@ -2026,7 +2041,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                return;
 
        ToServerCommand command = (ToServerCommand)readU16(&data[0]);
-       
+
        if(command == TOSERVER_INIT)
        {
                // [0] u16 TOSERVER_INIT
@@ -2052,7 +2067,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 
                //peer->serialization_version = deployed;
                getClient(peer_id)->pending_serialization_version = deployed;
-               
+
                if(deployed == SER_FMT_VER_INVALID)
                {
                        actionstream<<"Server: A mismatched client tried to connect from "
@@ -2067,7 +2082,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        );
                        return;
                }
-               
+
                /*
                        Read and check network protocol version
                */
@@ -2123,7 +2138,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        );
                        return;
                }
-               
+
                if(g_settings->getBool("strict_protocol_version_checking"))
                {
                        if(net_proto_version != LATEST_PROTOCOL_VERSION)
@@ -2148,7 +2163,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                /*
                        Set up player
                */
-               
+
                // Get player name
                char playername[PLAYERNAME_SIZE];
                for(u32 i=0; i<PLAYERNAME_SIZE-1; i++)
@@ -2156,7 +2171,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        playername[i] = data[3+i];
                }
                playername[PLAYERNAME_SIZE-1] = 0;
-               
+
                if(playername[0]=='\0')
                {
                        actionstream<<"Server: Player with an empty name "
@@ -2200,10 +2215,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        SendAccessDenied(m_con, peer_id, L"Invalid password hash");
                        return;
                }
-               
+
                std::string checkpwd; // Password hash to check against
                bool has_auth = scriptapi_get_auth(m_lua, playername, &checkpwd, NULL);
-               
+
                // If no authentication info exists for user, create it
                if(!has_auth){
                        if(!isSingleplayer() &&
@@ -2224,7 +2239,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 
                        scriptapi_create_auth(m_lua, playername, initial_password);
                }
-               
+
                has_auth = scriptapi_get_auth(m_lua, playername, &checkpwd, NULL);
 
                if(!has_auth){
@@ -2249,7 +2264,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                        L"Running in simple singleplayer mode.");
                        return;
                }
-               
+
                // Enforce user limit.
                // Don't enforce for users that have some admin right
                if(m_clients.size() >= g_settings->getU16("max_users") &&
@@ -2287,7 +2302,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                        writeV3S16(&reply[2+1], floatToInt(playersao->getPlayer()->getPosition()+v3f(0,BS/2,0), BS));
                        writeU64(&reply[2+1+6], m_env->getServerMap().getSeed());
                        writeF1000(&reply[2+1+6+8], g_settings->getFloat("dedicated_server_step"));
-                       
+
                        // Send as reliable
                        m_con.Send(peer_id, 0, reply, true);
                }
@@ -2325,16 +2340,16 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 
                // Send item definitions
                SendItemDef(m_con, peer_id, m_itemdef);
-               
+
                // Send node definitions
                SendNodeDef(m_con, peer_id, m_nodedef, client->net_proto_version);
-               
+
                // Send media announcement
                sendMediaAnnouncement(peer_id);
-               
+
                // Send privileges
                SendPlayerPrivileges(peer_id);
-               
+
                // Send inventory formspec
                SendPlayerInventoryFormspec(peer_id);
 
@@ -2345,10 +2360,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                // Send HP
                if(g_settings->getBool("enable_damage"))
                        SendPlayerHP(peer_id);
-               
+
                // Send detached inventories
                sendDetachedInventories(peer_id);
-               
+
                // Show death screen if necessary
                if(player->hp == 0)
                        SendDeathscreen(m_con, peer_id, false, v3f(0,0,0));
@@ -2359,20 +2374,20 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                        m_env->getTimeOfDay(), g_settings->getFloat("time_speed"));
                        m_con.Send(peer_id, 0, data, true);
                }
-               
+
                // Note things in chat if not in simple singleplayer mode
                if(!m_simple_singleplayer_mode)
                {
                        // Send information about server to player in chat
                        SendChatMessage(peer_id, getStatusString());
-                       
+
                        // Send information about joining in chat
                        {
                                std::wstring name = L"unknown";
                                Player *player = m_env->getPlayer(peer_id);
                                if(player != NULL)
                                        name = narrow_to_wide(player->getName());
-                               
+
                                std::wstring message;
                                message += L"*** ";
                                message += name;
@@ -2380,7 +2395,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                BroadcastChatMessage(message);
                        }
                }
-               
+
                // Warnings about protocol version can be issued here
                if(getClient(peer_id)->net_proto_version < LATEST_PROTOCOL_VERSION)
                {
@@ -2423,7 +2438,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                " Skipping incoming command="<<command<<std::endl;
                return;
        }
-       
+
        Player *player = m_env->getPlayer(peer_id);
        if(player == NULL){
                infostream<<"Server::ProcessData(): Cancelling: "
@@ -2444,7 +2459,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
        {
                if(datasize < 2+12+12+4+4)
                        return;
-       
+
                u32 start = 0;
                v3s32 ps = readV3S32(&data[start+2]);
                v3s32 ss = readV3S32(&data[start+2+12]);
@@ -2472,7 +2487,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                player->control.sneak = (bool)(keyPressed&64);
                player->control.LMB = (bool)(keyPressed&128);
                player->control.RMB = (bool)(keyPressed&256);
-               
+
                /*infostream<<"Server::ProcessData(): Moved player "<<peer_id<<" to "
                                <<"("<<position.X<<","<<position.Y<<","<<position.Z<<")"
                                <<" pitch="<<pitch<<" yaw="<<yaw<<std::endl;*/
@@ -2481,7 +2496,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
        {
                if(datasize < 2+1)
                        return;
-               
+
                /*
                        [0] u16 command
                        [2] u8 count
@@ -2507,7 +2522,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
        {
                if(datasize < 2+1)
                        return;
-               
+
                /*
                        [0] u16 command
                        [2] u8 count
@@ -2688,7 +2703,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                return;
                        }
                }
-               
+
                // Do the action
                a->apply(this, playersao, this);
                // Eat the action
@@ -2704,11 +2719,11 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                u8 buf[6];
                std::string datastring((char*)&data[2], datasize-2);
                std::istringstream is(datastring, std::ios_base::binary);
-               
+
                // Read stuff
                is.read((char*)buf, 2);
                u16 len = readU16(buf);
-               
+
                std::wstring message;
                for(u16 i=0; i<len; i++)
                {
@@ -2722,21 +2737,21 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
 
                // Get player name of this client
                std::wstring name = narrow_to_wide(player->getName());
-               
+
                // Run script hook
                bool ate = scriptapi_on_chat_message(m_lua, player->getName(),
                                wide_to_narrow(message));
                // If script ate the message, don't proceed
                if(ate)
                        return;
-               
+
                // Line to send to players
                std::wstring line;
                // Whether to send to the player that sent the line
                bool send_to_sender = false;
                // Whether to send to other players
                bool send_to_others = false;
-               
+
                // Commands are implemented in Lua, so only catch invalid
                // commands that were not "eaten" and send an error back
                if(message[0] == L'/')
@@ -2761,7 +2776,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                send_to_sender = true;
                        }
                }
-               
+
                if(line != L"")
                {
                        if(send_to_others)
@@ -2888,9 +2903,9 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
        {
                if(player->hp != 0 || !g_settings->getBool("enable_damage"))
                        return;
-               
+
                RespawnPlayer(peer_id);
-               
+
                actionstream<<player->getName()<<" respawns at "
                                <<PP(player->getPosition()/BS)<<std::endl;
 
@@ -2900,7 +2915,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
        else if(command == TOSERVER_REQUEST_MEDIA) {
                std::string datastring((char*)&data[2], datasize-2);
                std::istringstream is(datastring, std::ios_base::binary);
-               
+
                core::list<MediaRequest> tosend;
                u16 numfiles = readU16(is);
 
@@ -3194,7 +3209,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                }
                        }
                } // action == 2
-               
+
                /*
                        3: place block or right-click object
                */
@@ -3230,7 +3245,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                                // Apply returned ItemStack
                                playersao->setWieldedItem(item);
                        }
-                       
+
                        // If item has node placement prediction, always send the above
                        // node to make sure the client knows what exactly happened
                        if(item.getDefinition(m_itemdef).node_placement_prediction != ""){
@@ -3291,7 +3306,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
        {
                std::string datastring((char*)&data[2], datasize-2);
                std::istringstream is(datastring, std::ios_base::binary);
-               
+
                v3s16 p = readV3S16(is);
                std::string formname = deSerializeString(is);
                int num = readU16(is);
@@ -3324,7 +3339,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
        {
                std::string datastring((char*)&data[2], datasize-2);
                std::istringstream is(datastring, std::ios_base::binary);
-               
+
                std::string formname = deSerializeString(is);
                int num = readU16(is);
                std::map<std::string, std::string> fields;
@@ -3341,7 +3356,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
                infostream<<"Server::ProcessData(): Ignoring "
                                "unknown command "<<command<<std::endl;
        }
-       
+
        } //try
        catch(SendFailedException &e)
        {
@@ -3427,7 +3442,7 @@ void Server::setInventoryModified(const InventoryLocation &loc)
                MapBlock *block = m_env->getMap().getBlockNoCreateNoEx(blockpos);
                if(block)
                        block->raiseModified(MOD_STATE_WRITE_NEEDED);
-               
+
                setBlockNotSent(blockpos);
        }
        break;
@@ -3446,11 +3461,11 @@ core::list<PlayerInfo> Server::getPlayerInfo()
        DSTACK(__FUNCTION_NAME);
        JMutexAutoLock envlock(m_env_mutex);
        JMutexAutoLock conlock(m_con_mutex);
-       
+
        core::list<PlayerInfo> list;
 
        core::list<Player*> players = m_env->getPlayers();
-       
+
        core::list<Player*>::Iterator i;
        for(i = players.begin();
                        i != players.end(); i++)
@@ -3488,7 +3503,7 @@ void Server::peerAdded(con::Peer *peer)
        DSTACK(__FUNCTION_NAME);
        verbosestream<<"Server::peerAdded(): peer->id="
                        <<peer->id<<std::endl;
-       
+
        PeerChange c;
        c.type = PEER_ADDED;
        c.peer_id = peer->id;
@@ -3501,7 +3516,7 @@ void Server::deletingPeer(con::Peer *peer, bool timeout)
        DSTACK(__FUNCTION_NAME);
        verbosestream<<"Server::deletingPeer(): peer->id="
                        <<peer->id<<", timeout="<<timeout<<std::endl;
-       
+
        PeerChange c;
        c.type = PEER_REMOVED;
        c.peer_id = peer->id;
@@ -3622,7 +3637,7 @@ void Server::SendNodeDef(con::Connection &con, u16 peer_id,
 void Server::SendInventory(u16 peer_id)
 {
        DSTACK(__FUNCTION_NAME);
-       
+
        PlayerSAO *playersao = getPlayerSAO(peer_id);
        assert(playersao);
 
@@ -3636,11 +3651,11 @@ void Server::SendInventory(u16 peer_id)
        playersao->getInventory()->serialize(os);
 
        std::string s = os.str();
-       
+
        SharedBuffer<u8> data(s.size()+2);
        writeU16(&data[0], TOCLIENT_INVENTORY);
        memcpy(&data[2], s.c_str(), s.size());
-       
+
        // Send as reliable
        m_con.Send(peer_id, 0, data, true);
 }
@@ -3648,18 +3663,18 @@ void Server::SendInventory(u16 peer_id)
 void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
 {
        DSTACK(__FUNCTION_NAME);
-       
+
        std::ostringstream os(std::ios_base::binary);
        u8 buf[12];
-       
+
        // Write command
        writeU16(buf, TOCLIENT_CHAT_MESSAGE);
        os.write((char*)buf, 2);
-       
+
        // Write length
        writeU16(buf, message.size());
        os.write((char*)buf, 2);
-       
+
        // Write string
        for(u32 i=0; i<message.size(); i++)
        {
@@ -3667,7 +3682,7 @@ void Server::SendChatMessage(u16 peer_id, const std::wstring &message)
                writeU16(buf, w);
                os.write((char*)buf, 2);
        }
-       
+
        // Make data buffer
        std::string s = os.str();
        SharedBuffer<u8> data((u8*)s.c_str(), s.size());
@@ -3730,7 +3745,7 @@ void Server::SendMovePlayer(u16 peer_id)
        writeV3F1000(os, player->getPosition());
        writeF1000(os, player->getPitch());
        writeF1000(os, player->getYaw());
-       
+
        {
                v3f pos = player->getPosition();
                f32 pitch = player->getPitch();
@@ -3758,7 +3773,7 @@ void Server::SendPlayerPrivileges(u16 peer_id)
 
        std::set<std::string> privs;
        scriptapi_get_auth(m_lua, player->getName(), NULL, &privs);
-       
+
        std::ostringstream os(std::ios_base::binary);
        writeU16(os, TOCLIENT_PRIVILEGES);
        writeU16(os, privs.size());
@@ -3920,7 +3935,7 @@ void Server::sendRemoveNode(v3s16 p, u16 ignore_id,
                // Don't send if it's the same one
                if(client->peer_id == ignore_id)
                        continue;
-               
+
                if(far_players)
                {
                        // Get player
@@ -4008,7 +4023,7 @@ void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver)
        DSTACK(__FUNCTION_NAME);
 
        v3s16 p = block->getPos();
-       
+
 #if 0
        // Analyze it a bit
        bool completely_air = true;
@@ -4033,7 +4048,7 @@ void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver)
        /*
                Create a packet with the block in the right format
        */
-       
+
        std::ostringstream os(std::ios_base::binary);
        block->serialize(os, ver, false);
        std::string s = os.str();
@@ -4049,7 +4064,7 @@ void Server::SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver)
 
        /*infostream<<"Server: Sending block ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
                        <<":  \tpacket size: "<<replysize<<std::endl;*/
-       
+
        /*
                Send packet
        */
@@ -4068,7 +4083,7 @@ void Server::SendBlocks(float dtime)
        core::array<PrioritySortedBlockTransfer> queue;
 
        s32 total_sending = 0;
-       
+
        {
                ScopeProfiler sp(g_profiler, "Server: selecting blocks for sending");
 
@@ -4085,10 +4100,10 @@ void Server::SendBlocks(float dtime)
                                continue;
 
                        total_sending += client->SendingCount();
-                       
+
                        if(client->serialization_version == SER_FMT_VER_INVALID)
                                continue;
-                       
+
                        client->GetNextBlocks(this, dtime, queue);
                }
        }
@@ -4104,7 +4119,7 @@ void Server::SendBlocks(float dtime)
                if(total_sending >= g_settings->getS32
                                ("max_simultaneous_block_sends_server_total"))
                        break;
-               
+
                PrioritySortedBlockTransfer q = queue[i];
 
                MapBlock *block = NULL;
@@ -4132,7 +4147,7 @@ void Server::fillMediaCache()
        DSTACK(__FUNCTION_NAME);
 
        infostream<<"Server: Calculating media file checksums"<<std::endl;
-       
+
        // Collect all media file paths
        std::list<std::string> paths;
        for(std::vector<ModSpec>::iterator i = m_mods.begin();
@@ -4145,7 +4160,7 @@ void Server::fillMediaCache()
        }
        std::string path_all = "textures";
        paths.push_back(path_all + DIR_DELIM + "all");
-       
+
        // Collect media file information from paths into cache
        for(std::list<std::string>::iterator i = paths.begin();
                        i != paths.end(); i++)
@@ -4265,7 +4280,7 @@ void Server::sendMediaAnnouncement(u16 peer_id)
                        string sha1_digest
                }
        */
-       
+
        writeU16(os, TOCLIENT_ANNOUNCE_MEDIA);
        writeU16(os, file_announcements.size());
 
@@ -4466,7 +4481,7 @@ void Server::sendDetachedInventories(u16 peer_id)
 void Server::DiePlayer(u16 peer_id)
 {
        DSTACK(__FUNCTION_NAME);
-       
+
        PlayerSAO *playersao = getPlayerSAO(peer_id);
        assert(playersao);
 
@@ -4506,7 +4521,7 @@ void Server::RespawnPlayer(u16 peer_id)
 void Server::UpdateCrafting(u16 peer_id)
 {
        DSTACK(__FUNCTION_NAME);
-       
+
        Player* player = m_env->getPlayer(peer_id);
        assert(player);
 
@@ -4702,7 +4717,7 @@ bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
        ServerMap *map = (ServerMap*)(&m_env->getMap());
        // Disable rollback report sink while reverting
        BoolScopeSet rollback_scope_disable(&m_rollback_sink_enabled, false);
-       
+
        // Fail if no actions to handle
        if(actions.empty()){
                log->push_back("Nothing to do.");
@@ -4711,7 +4726,7 @@ bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
 
        int num_tried = 0;
        int num_failed = 0;
-       
+
        for(std::list<RollbackAction>::const_iterator
                        i = actions.begin();
                        i != actions.end(); i++)
@@ -4734,7 +4749,7 @@ bool Server::rollbackRevertActions(const std::list<RollbackAction> &actions,
                                log->push_back(os.str());
                }
        }
-       
+
        infostream<<"Map::rollbackRevertActions(): "<<num_failed<<"/"<<num_tried
                        <<" failed"<<std::endl;
 
@@ -4825,14 +4840,14 @@ v3f findSpawnPos(ServerMap &map)
        //return v3f(50,50,50)*BS;
 
        v3s16 nodepos;
-       
+
 #if 0
        nodepos = v2s16(0,0);
        groundheight = 20;
 #endif
 
 #if 1
-       s16 water_level = g_settings->getS16("water_level");
+       s16 water_level = map.m_emerge->water_level; //g_settings->getS16("default_water_level");
 
        // Try to find a good place a few times
        for(s32 i=0; i<1000; i++)
@@ -4856,7 +4871,7 @@ v3f findSpawnPos(ServerMap &map)
                        //infostream<<"-> Underwater"<<std::endl;
                        continue;
                }
-               
+
                nodepos = v3s16(nodepos2d.X, groundheight-2, nodepos2d.Y);
                bool is_good = false;
                s32 air_count = 0;
@@ -4881,7 +4896,7 @@ v3f findSpawnPos(ServerMap &map)
                }
        }
 #endif
-       
+
        return intToFloat(nodepos, BS);
 }
 
@@ -4954,7 +4969,7 @@ void Server::handlePeerChange(PeerChange &c)
 {
        JMutexAutoLock envlock(m_env_mutex);
        JMutexAutoLock conlock(m_con_mutex);
-       
+
        if(c.type == PEER_ADDED)
        {
                /*
@@ -4984,7 +4999,7 @@ void Server::handlePeerChange(PeerChange &c)
                n = m_clients.find(c.peer_id);
                // The client should exist
                assert(n != NULL);
-               
+
                /*
                        Mark objects to be not known by the client
                */
@@ -4997,7 +5012,7 @@ void Server::handlePeerChange(PeerChange &c)
                        // Get object
                        u16 id = i.getNode()->getKey();
                        ServerActiveObject* obj = m_env->getActiveObject(id);
-                       
+
                        if(obj && obj->m_known_by_count > 0)
                                obj->m_known_by_count--;
                }
@@ -5032,7 +5047,7 @@ void Server::handlePeerChange(PeerChange &c)
                                        message += L" (timed out)";
                        }
                }
-               
+
                /* Run scripts and remove from environment */
                {
                        if(player != NULL)
@@ -5075,18 +5090,18 @@ void Server::handlePeerChange(PeerChange &c)
                                                <<os.str()<<std::endl;
                        }
                }
-               
+
                // Delete client
                delete m_clients[c.peer_id];
                m_clients.remove(c.peer_id);
 
                // Send player info to all remaining clients
                //SendPlayerInfos();
-               
+
                // Send leave chat message to all remaining clients
                if(message.length() != 0)
                        BroadcastChatMessage(message);
-               
+
        } // PEER_REMOVED
        else
        {
@@ -5111,7 +5126,7 @@ void Server::handlePeerChanges()
 void dedicated_server_loop(Server &server, bool &kill)
 {
        DSTACK(__FUNCTION_NAME);
-       
+
        verbosestream<<"dedicated_server_loop()"<<std::endl;
 
        IntervalLimiter m_profiler_interval;
index 26e47d36c9195f35930cb8f5565ed458ed26db22..a60be2c0b52483ec3d9d925a5660829cc99428e8 100644 (file)
@@ -739,6 +739,9 @@ private:
        bool m_rollback_sink_enabled;
        bool m_enable_rollback_recording; // Updated once in a while
 
+       // Emerge manager
+       EmergeManager *m_emerge;
+
        // Scripting
        // Envlock and conlock should be locked when using Lua
        lua_State *m_lua;
index 1a29ef00a398fd4460e90d8c2b2b6d5da06978d1..eec546b1a912c89aa3f2faaec3eca9c5e353eba3 100644 (file)
@@ -574,10 +574,7 @@ public:
                        set(name, "false");
        }
 
-       void setS32(std::string name, s32 value)
-       {
-               set(name, itos(value));
-       }
+
 
        void setFloat(std::string name, float value)
        {
@@ -598,6 +595,16 @@ public:
                set(name, os.str());
        }
 
+       void setS16(std::string name, s16 value)
+       {
+               set(name, itos(value));
+       }
+
+       void setS32(std::string name, s32 value)
+       {
+               set(name, itos(value));
+       }
+
        void setU64(std::string name, u64 value)
        {
                std::ostringstream os;
index 5ed4d0e999d1fc03e987d9dd109534a04027b944..a028f1ff242ed191ecfb3cc498b1b7df64877394 100644 (file)
@@ -120,6 +120,7 @@ inline s16 rangelim(s16 i, s16 max)
 }
 
 #define rangelim(d, min, max) ((d) < (min) ? (min) : ((d)>(max)?(max):(d)))
+#define myfloor(x) ((x) > 0.0 ? (int)(x) : (int)(x) - 1)
 
 inline v3s16 arealim(v3s16 p, s16 d)
 {
index e7155dfacce367165b2735744203a61cabc12ef5..c2a5efb4b7de6b1289c490e92d32ca59ef2062bc 100644 (file)
@@ -72,7 +72,7 @@ public:
                MaxEdge(p)
        {
        }
-       
+
        /*
                Modifying methods
        */
@@ -106,14 +106,14 @@ public:
                if(p.Y > MaxEdge.Y) MaxEdge.Y = p.Y;
                if(p.Z > MaxEdge.Z) MaxEdge.Z = p.Z;
        }
-       
+
        // Pad with d nodes
        void pad(v3s16 d)
        {
                MinEdge -= d;
                MaxEdge += d;
        }
-       
+
        /*void operator+=(v3s16 off)
        {
                MinEdge += off;
@@ -202,7 +202,7 @@ public:
                }
 
                assert(contains(a));
-               
+
                // Take back area, XY inclusive
                {
                        v3s16 min(MinEdge.X, MinEdge.Y, a.MaxEdge.Z+1);
@@ -258,7 +258,7 @@ public:
                }
 
        }
-       
+
        /*
                Translates position from virtual coordinates to array index
        */
@@ -274,7 +274,7 @@ public:
        {
                return index(p.X, p.Y, p.Z);
        }
-       
+
        // Translate index in the X coordinate
        void add_x(const v3s16 &extent, u32 &i, s16 a)
        {
@@ -343,7 +343,7 @@ class VoxelManipulator /*: public NodeContainer*/
 public:
        VoxelManipulator();
        virtual ~VoxelManipulator();
-       
+
        /*
                Virtuals from NodeContainer
        */
@@ -430,7 +430,7 @@ public:
        void setNode(v3s16 p, const MapNode &n)
        {
                emerge(p);
-               
+
                m_data[m_area.index(p)] = n;
                m_flags[m_area.index(p)] &= ~VOXELFLAG_INEXISTENT;
                m_flags[m_area.index(p)] &= ~VOXELFLAG_NOT_LOADED;
@@ -457,10 +457,10 @@ public:
                //dstream<<"operator[] p=("<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;
                if(isValidPosition(p) == false)
                        emerge(VoxelArea(p));
-               
+
                return m_data[m_area.index(p)];
        }*/
-       
+
        /*
                Set stuff if available without an emerge.
                Return false if failed.
@@ -496,7 +496,7 @@ public:
 
        void print(std::ostream &o, INodeDefManager *nodemgr,
                        VoxelPrintMode mode=VOXELPRINT_MATERIAL);
-       
+
        void addArea(VoxelArea area);
 
        /*
@@ -505,7 +505,7 @@ public:
        */
        void copyFrom(MapNode *src, VoxelArea src_area,
                        v3s16 from_pos, v3s16 to_pos, v3s16 size);
-       
+
        // Copy data
        void copyTo(MapNode *dst, VoxelArea dst_area,
                        v3s16 dst_pos, v3s16 from_pos, v3s16 size);
@@ -523,15 +523,15 @@ public:
        void unspreadLight(enum LightBank bank,
                        core::map<v3s16, u8> & from_nodes,
                        core::map<v3s16, bool> & light_sources, INodeDefManager *nodemgr);
-       
+
        void spreadLight(enum LightBank bank, v3s16 p, INodeDefManager *nodemgr);
        void spreadLight(enum LightBank bank,
                        core::map<v3s16, bool> & from_nodes, INodeDefManager *nodemgr);
-       
+
        /*
                Virtual functions
        */
-       
+
        /*
                Get the contents of the requested area from somewhere.
                Shall touch only nodes that have VOXELFLAG_NOT_LOADED
@@ -565,7 +565,7 @@ public:
                MaxEdge is 1 higher than maximum allowed position
        */
        VoxelArea m_area;
-       
+
        /*
                NULL if data size is 0 (extent (0,0,0))
                Data is stored as [z*h*w + y*h + x]
@@ -576,7 +576,7 @@ public:
                Flags of all nodes
        */
        u8 *m_flags;
-       
+
        //TODO: Use these or remove them
        //TODO: Would these make any speed improvement?
        //bool m_pressure_route_valid;
index 1af934f80ddb8146bd4aeb1db34fc7ba7e5b1e55..795530d40eede907d58b2ac00ce14ec8922ff5c2 100644 (file)
@@ -86,10 +86,10 @@ SunlightPropagateResult propagateSunlight(VoxelManipulator &v, VoxelArea a,
        required_a.pad(v3s16(0,1,0));
        // Make sure we have access to it
        v.emerge(a);
-       
+
        s16 max_y = a.MaxEdge.Y;
        s16 min_y = a.MinEdge.Y;
-       
+
        for(s32 x=a.MinEdge.X; x<=a.MaxEdge.X; x++)
        for(s32 z=a.MinEdge.Z; z<=a.MaxEdge.Z; z++)
        {
@@ -125,11 +125,11 @@ SunlightPropagateResult propagateSunlight(VoxelManipulator &v, VoxelArea a,
 
                        if(incoming_light > old_light)
                                n.setLight(LIGHTBANK_DAY, incoming_light, ndef);
-                       
+
                        if(diminish_light(incoming_light) != 0)
                                light_sources.insert(p, true);
                }
-               
+
                // Check validity of sunlight at top of block below if it
                // hasn't already been proven invalid
                if(bottom_sunlight_valid)