aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkwolekr <mirrorisim@gmail.com>2012-11-25 21:16:48 -0500
committerPerttu Ahola <celeron55@gmail.com>2013-01-21 21:41:33 +0200
commit11afcbff69c95915e5142bc4b55636ff6358ece9 (patch)
tree1e6a3242e83443b665d9b781c84abad4e662f83d
parent736b386554a6b385a34f40c0411c6e466ebec30a (diff)
downloadminetest-11afcbff69c95915e5142bc4b55636ff6358ece9.tar.gz
minetest-11afcbff69c95915e5142bc4b55636ff6358ece9.tar.bz2
minetest-11afcbff69c95915e5142bc4b55636ff6358ece9.zip
The new mapgen, noise functions, et al.
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/biome.cpp229
-rw-r--r--src/biome.h79
-rw-r--r--src/defaultsettings.cpp2
-rw-r--r--src/environment.cpp12
-rw-r--r--src/environment.h3
-rw-r--r--src/farmesh.cpp6
-rw-r--r--src/guiPauseMenu.cpp506
-rw-r--r--src/guiPauseMenu.h120
-rw-r--r--src/map.cpp47
-rw-r--r--src/map.h22
-rw-r--r--src/mapgen.cpp442
-rw-r--r--src/mapgen.h120
-rw-r--r--src/nodedef.cpp10
-rw-r--r--src/noise.cpp695
-rw-r--r--src/noise.h129
-rw-r--r--src/scriptapi.cpp16
-rw-r--r--src/server.cpp419
-rw-r--r--src/server.h3
-rw-r--r--src/settings.h15
-rw-r--r--src/util/numeric.h1
-rw-r--r--src/voxel.h34
-rw-r--r--src/voxelalgorithms.cpp8
23 files changed, 1887 insertions, 1032 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ac39e43e3..995d031e3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -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
index 000000000..4b240d5a5
--- /dev/null
+++ b/src/biome.cpp
@@ -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
index 000000000..5e43ab6d7
--- /dev/null
+++ b/src/biome.h
@@ -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
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp
index 5a1b76b4a..38b9accd1 100644
--- a/src/defaultsettings.cpp
+++ b/src/defaultsettings.cpp
@@ -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");
diff --git a/src/environment.cpp b/src/environment.cpp
index 3f94484fe..51255b918 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -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)
{
diff --git a/src/environment.h b/src/environment.h
index d17edeacd..d1e61967f 100644
--- a/src/environment.h
+++ b/src/environment.h
@@ -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
diff --git a/src/farmesh.cpp b/src/farmesh.cpp
index bd08acadc..23f3db5f6 100644
--- a/src/farmesh.cpp
+++ b/src/farmesh.cpp
@@ -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
diff --git a/src/guiPauseMenu.cpp b/src/guiPauseMenu.cpp
index c800cf952..f6cbf248f 100644
--- a/src/guiPauseMenu.cpp
+++ b/src/guiPauseMenu.cpp
@@ -1,253 +1,253 @@
-/*
-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;
-}
-
+/*
+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;
+}
+
diff --git a/src/guiPauseMenu.h b/src/guiPauseMenu.h
index e28159a93..4b15fc74f 100644
--- a/src/guiPauseMenu.h
+++ b/src/guiPauseMenu.h
@@ -1,60 +1,60 @@
-/*
-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
-
+/*
+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
+
diff --git a/src/map.cpp b/src/map.cpp
index 6147bb635..0896c9b4f 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -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;
}
diff --git a/src/map.h b/src/map.h
index 30cf626bb..3097d15b9 100644
--- 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;
diff --git a/src/mapgen.cpp b/src/mapgen.cpp
index ae0c551cb..7271b7652 100644
--- a/src/mapgen.cpp
+++ b/src/mapgen.cpp
@@ -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
diff --git a/src/mapgen.h b/src/mapgen.h
index 8986ddab0..d6e932ca0 100644
--- a/src/mapgen.h
+++ b/src/mapgen.h
@@ -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
diff --git a/src/nodedef.cpp b/src/nodedef.cpp
index 36fa798fd..560c6090d 100644
--- a/src/nodedef.cpp
+++ b/src/nodedef.cpp
@@ -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++)
diff --git a/src/noise.cpp b/src/noise.cpp
index e75fbf4bd..5cb4be29a 100644
--- a/src/noise.cpp
+++ b/src/noise.cpp
@@ -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;
+}
diff --git a/src/noise.h b/src/noise.h
index 670c2eddc..6e5120003 100644
--- a/src/noise.h
+++ b/src/noise.h
@@ -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
diff --git a/src/scriptapi.cpp b/src/scriptapi.cpp
index 959885d32..69ee48a76 100644
--- a/src/scriptapi.cpp
+++ b/src/scriptapi.cpp
@@ -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;
diff --git a/src/server.cpp b/src/server.cpp
index a7767842d..a3c0b66ed 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -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;
diff --git a/src/server.h b/src/server.h
index 26e47d36c..a60be2c0b 100644
--- a/src/server.h
+++ b/src/server.h
@@ -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;
diff --git a/src/settings.h b/src/settings.h
index 1a29ef00a..eec546b1a 100644
--- a/src/settings.h
+++ b/src/settings.h
@@ -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;
diff --git a/src/util/numeric.h b/src/util/numeric.h
index 5ed4d0e99..a028f1ff2 100644
--- a/src/util/numeric.h
+++ b/src/util/numeric.h
@@ -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)
{
diff --git a/src/voxel.h b/src/voxel.h
index e7155dfac..c2a5efb4b 100644
--- a/src/voxel.h
+++ b/src/voxel.h
@@ -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;
diff --git a/src/voxelalgorithms.cpp b/src/voxelalgorithms.cpp
index 1af934f80..795530d40 100644
--- a/src/voxelalgorithms.cpp
+++ b/src/voxelalgorithms.cpp
@@ -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)