aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client.cpp4
-rw-r--r--src/client.h5
-rw-r--r--src/clientserver.h1
-rw-r--r--src/main.cpp182
-rw-r--r--src/map.cpp881
-rw-r--r--src/map.h11
-rw-r--r--src/mapblock.cpp1
-rw-r--r--src/noise.cpp35
-rw-r--r--src/noise.h6
-rw-r--r--src/server.cpp52
-rw-r--r--src/tile.cpp2
-rw-r--r--src/utility.h20
12 files changed, 974 insertions, 226 deletions
diff --git a/src/client.cpp b/src/client.cpp
index 3ea666549..fe1669ddd 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -510,6 +510,10 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
assert(player != NULL);
player->setPosition(playerpos_f);
}
+
+ // Get map seed
+ m_map_seed = readU64(&data[2+1+6]);
+ dstream<<"Client: received map seed: "<<m_map_seed<<std::endl;
// Reply to server
u32 replysize = 2;
diff --git a/src/client.h b/src/client.h
index fb1e70722..d6496d9df 100644
--- a/src/client.h
+++ b/src/client.h
@@ -252,6 +252,8 @@ public:
(std::wstring)L"<"+name+L"> "+message);
}
+ u64 getMapSeed(){ return m_map_seed; }
+
private:
// Virtual methods from con::PeerHandler
@@ -311,6 +313,9 @@ private:
//u32 m_daynight_ratio;
Queue<std::wstring> m_chat_queue;
+
+ // The seed returned by the server in TOCLIENT_INIT is stored here
+ u64 m_map_seed;
};
#endif // !SERVER
diff --git a/src/clientserver.h b/src/clientserver.h
index 893bbc1e0..52b4e520e 100644
--- a/src/clientserver.h
+++ b/src/clientserver.h
@@ -34,6 +34,7 @@ enum ToClientCommand
[0] u16 TOSERVER_INIT
[2] u8 deployed version
[3] v3s16 player's position + v3f(0,BS/2,0) floatToInt'd
+ [4] u64 map seed (new as of 2011-02-27)
*/
TOCLIENT_BLOCKDATA = 0x20, //TODO: Multiple blocks
diff --git a/src/main.cpp b/src/main.cpp
index 2c059840e..be3776623 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -253,11 +253,9 @@ Doing now (most important at the top):
* not done
=== Next
-* Continue making the scripting system:
- * Make updateNodeMesh for a less verbose mesh update on add/removenode
- * Switch to using a safe way for the self and env pointers
- * Make some global environment hooks, like node placed and general
- on_step()
+* Make a system for pregenerating quick information for mapblocks, so
+ that the client can show them as cubes before they are actually sent
+ or even generated.
=== Fixmes
* Check the fixmes in the list above
@@ -274,6 +272,11 @@ Doing now (most important at the top):
with the ones in utility.h
=== Features
+* Continue making the scripting system:
+ * Make updateNodeMesh for a less verbose mesh update on add/removenode
+ * Switch to using a safe way for the self and env pointers
+ * Make some global environment hooks, like node placed and general
+ on_step()
* Map should make the appropriate MapEditEvents
* Add a global Lua spawn handler and such
* Get rid of MapBlockObjects
@@ -490,6 +493,9 @@ Inventory local_inventory;
u16 g_selected_item = 0;
+bool g_show_map_plot = false;
+bool g_refresh_map_plot = true;
+
/*
Debug streams
*/
@@ -606,6 +612,15 @@ public:
if(event.KeyInput.PressedDown)
{
//dstream<<"Pressed key: "<<(char)event.KeyInput.Key<<std::endl;
+ if(g_show_map_plot)
+ {
+ if(event.KeyInput.Key == irr::KEY_ESCAPE
+ || event.KeyInput.Key == irr::KEY_KEY_M)
+ {
+ g_show_map_plot = false;
+ }
+ return true;
+ }
/*
Launch menus
@@ -679,6 +694,16 @@ public:
<<std::endl;
debug_stacks_print();
}
+
+ // Map plot
+ if(event.KeyInput.Key == irr::KEY_KEY_M)
+ {
+ dstream<<"Map plot requested"<<std::endl;
+ g_show_map_plot = !g_show_map_plot;
+ if(g_show_map_plot)
+ g_refresh_map_plot = true;
+ }
+
}
}
@@ -1110,8 +1135,8 @@ void updateViewingRange(f32 frametime_in, Client *client)
f32 wanted_frametime_change = wanted_frametime - frametime;
//dstream<<"wanted_frametime_change="<<wanted_frametime_change<<std::endl;
- // If needed frametime change is very small, just return
- if(fabs(wanted_frametime_change) < wanted_frametime*0.2)
+ // If needed frametime change is small, just return
+ if(fabs(wanted_frametime_change) < wanted_frametime*0.4)
{
//dstream<<"ignoring small wanted_frametime_change"<<std::endl;
return;
@@ -1239,6 +1264,93 @@ void draw_hotbar(video::IVideoDriver *driver, gui::IGUIFont *font,
}
}
+video::ITexture *g_map_plot_texture = NULL;
+float g_map_plot_texture_scale = 2;
+
+void updateMapPlotTexture(v2f centerpos, video::IVideoDriver* driver,
+ Client *client)
+{
+ assert(driver);
+ assert(client);
+
+ core::dimension2d<u32> dim(640,480);
+ video::IImage *img = driver->createImage(video::ECF_A8R8G8B8, dim);
+ assert(img);
+ for(u32 y=0; y<dim.Height; y++)
+ for(u32 x=0; x<dim.Width; x++)
+ {
+ v2f pf = v2f(x, dim.Height-y) - v2f(dim.Width, dim.Height)/2;
+ pf *= g_map_plot_texture_scale;
+ pf += centerpos;
+ double h = base_rock_level_2d(client->getMapSeed(), pf);
+ video::SColor c;
+ //double d1 = 50;
+ /*s32 ux = x - centerpos.X / g_map_plot_texture_scale;
+ s32 uy = y - centerpos.Y / g_map_plot_texture_scale;*/
+
+ // Screen coordinates that are based on multiples of
+ // 1000/g_map_plot_texture_scale and never negative
+ u32 ux = x + (u32)(1000/g_map_plot_texture_scale) * 10;
+ u32 uy = y + (u32)(1000/g_map_plot_texture_scale) * 10;
+ // Offset to center of image
+ ux -= dim.Width/2;
+ uy -= dim.Height/2;
+
+ if(uy % (u32)(1000/g_map_plot_texture_scale) == 0
+ || ux % (u32)(1000/g_map_plot_texture_scale) == 0)
+ c.set(255, 255, 255, 255);
+ else if(uy % (u32)(100/g_map_plot_texture_scale) == 0
+ || ux % (u32)(100/g_map_plot_texture_scale) == 0)
+ c.set(255, 160, 160, 160);
+ else if(h < WATER_LEVEL - 0.5) // Water
+ c.set(255, 50, 50, 255);
+ else if(h < WATER_LEVEL + 2) // Sand
+ c.set(255, 237, 201, 175);
+#if 1
+ else if(h < WATER_LEVEL + 10) // Green
+ c.set(255, 50, 150, 50);
+ else if(h < WATER_LEVEL + 20) // Greenish yellow
+ c.set(255, 110, 185, 50);
+ else if(h < WATER_LEVEL + 50) // Yellow
+ c.set(255, 220, 220, 50);
+ else if(h < WATER_LEVEL + 100) // White
+ c.set(255, 180, 180, 180);
+ else
+ c.set(255, 255, 255, 255);
+#endif
+ /*else if(h < WATER_LEVEL + d1)
+ {
+ h -= WATER_LEVEL;
+ u32 a = (u32)(h / d1 * 255);
+ if(a > 255)
+ a = 255;
+ c.set(255, 0, a, 0);
+ }*/
+#if 0
+ else
+ {
+ h -= WATER_LEVEL;
+ h /= 20.0;
+ h = 1.0 - exp(-h);
+
+ video::SColor c1(255,200,200,50);
+ video::SColor c2(255,0,150,0);
+ c = c1.getInterpolated(c2, h);
+
+ /*u32 a = (u32)(h*255);
+ if(a > 255)
+ a = 255;
+ a = 255-a;
+ c.set(255, a, a, a);*/
+ }
+#endif
+ img->setPixel(x, y, c);
+ }
+ g_map_plot_texture = driver->addTexture("map_plot", img);
+ img->drop();
+ assert(g_map_plot_texture);
+}
+
// Chat data
struct ChatLine
{
@@ -2253,6 +2365,10 @@ int main(int argc, char *argv[])
g_input->step(dtime);
/*
+ Misc. stuff
+ */
+
+ /*
Player speed control
*/
@@ -3021,16 +3137,6 @@ int main(int argc, char *argv[])
}
/*
- Draw crosshair
- */
- driver->draw2DLine(displaycenter - core::vector2d<s32>(10,0),
- displaycenter + core::vector2d<s32>(10,0),
- video::SColor(255,255,255,255));
- driver->draw2DLine(displaycenter - core::vector2d<s32>(0,10),
- displaycenter + core::vector2d<s32>(0,10),
- video::SColor(255,255,255,255));
-
- /*
Frametime log
*/
if(g_settings.getBool("frametime_graph") == true)
@@ -3048,6 +3154,31 @@ int main(int argc, char *argv[])
}
}
+ /*
+ Draw map plot
+ */
+ if(g_show_map_plot && g_map_plot_texture)
+ {
+ core::dimension2d<u32> drawdim(640,480);
+ core::rect<s32> dest(v2s32(0,0), drawdim);
+ dest += v2s32(
+ (screensize.X-drawdim.Width)/2,
+ (screensize.Y-drawdim.Height)/2
+ );
+ core::rect<s32> source(v2s32(0,0), g_map_plot_texture->getSize());
+ driver->draw2DImage(g_map_plot_texture, dest, source);
+ }
+
+ /*
+ Draw crosshair
+ */
+ driver->draw2DLine(displaycenter - core::vector2d<s32>(10,0),
+ displaycenter + core::vector2d<s32>(10,0),
+ video::SColor(255,255,255,255));
+ driver->draw2DLine(displaycenter - core::vector2d<s32>(0,10),
+ displaycenter + core::vector2d<s32>(0,10),
+ video::SColor(255,255,255,255));
+
} // timer
//timer10.stop();
@@ -3077,8 +3208,23 @@ int main(int argc, char *argv[])
drawtime = drawtimer.stop(true);
/*
- Drawing ends
+ End of drawing
+ */
+
+ /*
+ Refresh map plot if player has moved considerably
*/
+ if(g_refresh_map_plot)
+ {
+ static v3f old_player_pos = v3f(1,1,1) * 10000000;
+ v3f p = client.getPlayerPosition() / BS;
+ if(old_player_pos.getDistanceFrom(p) > 4 * g_map_plot_texture_scale)
+ {
+ updateMapPlotTexture(v2f(p.X,p.Z), driver, &client);
+ old_player_pos = p;
+ }
+ g_refresh_map_plot = false;
+ }
static s16 lastFPS = 0;
//u16 fps = driver->getFPS();
diff --git a/src/map.cpp b/src/map.cpp
index 8e71212b0..7b16834e2 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -1422,6 +1422,9 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
while(m_transforming_liquid.size() != 0)
{
+ try
+ {
+
/*
Get a queued transforming liquid node
*/
@@ -1680,9 +1683,12 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
}
loopcount++;
- //if(loopcount >= 100000)
- if(loopcount >= initial_size * 1)
+ if(loopcount >= initial_size * 1 || loopcount >= 1000)
break;
+
+ }catch(InvalidPositionException &e)
+ {
+ }
}
//dstream<<"Map::transformLiquids(): loopcount="<<loopcount<<std::endl;
}
@@ -1698,8 +1704,8 @@ ServerMap::ServerMap(std::string savedir):
//m_chunksize = 64;
//m_chunksize = 16; // Too slow
- m_chunksize = 8; // Takes a few seconds
- //m_chunksize = 4;
+ //m_chunksize = 8; // Takes a few seconds
+ m_chunksize = 4; // Too small?
//m_chunksize = 2;
// TODO: Save to and load from a file
@@ -1954,61 +1960,288 @@ double tree_amount_2d(u64 seed, v2s16 p)
#define AVERAGE_MUD_AMOUNT 4
-double base_rock_level_2d(u64 seed, v2s16 p)
+double get_mud_amount(u64 seed, v2f p)
+{
+ return ((float)AVERAGE_MUD_AMOUNT + 2.5 * noise2d_perlin(
+ 0.5+p.X/200, 0.5+p.Y/200,
+ seed+1, 5, 0.65));
+}
+
+// -1->0, 0->1, 1->0
+double contour(double v)
{
- // The base ground level
- double base = (double)WATER_LEVEL - (double)AVERAGE_MUD_AMOUNT
- + 25. * noise2d_perlin(
+ v = fabs(v);
+ if(v >= 1.0)
+ return 0.0;
+ return (1.0-v);
+}
+
+// -1->0, -r->1, 0->1, r->1, 1->0
+double contour_flat_top(double v, double r)
+{
+ v = fabs(v);
+ if(v >= 1.0)
+ return 0.0;
+ double rmax = 0.999;
+ if(r >= rmax)
+ r = rmax;
+ if(v <= r)
+ return 1.0;
+ v -= r;
+ return ((1.0-r)-v) / (1.0-r);
+ //return easeCurve(((1.0-r)-v) / (1.0-r));
+}
+
+double base_rock_level_2d(u64 seed, v2f p)
+{
+ // The ground level (return value)
+ double h = WATER_LEVEL;
+
+ // Raises from 0 when parameter is -1...1
+ /*double m2 = contour_flat_top(-0.8 + 2.0 * noise2d_perlin(
+ 0.0+(float)p.X/1500., 0.0+(float)p.Y/1500.,
+ (seed>>32)+34758, 5, 0.55), 0.10);*/
+ /*double m2 = 1.0;
+ if(m2 > 0.0001)
+ {
+ // HUGE mountains
+ double m1 = 200.0 + 300.0 * noise2d_perlin(
+ 0.0+(float)p.X/1000., 0.0+(float)p.Y/1000.,
+ (seed>>32)+98525, 8, 0.5);
+ h += m1 * m2;
+ //h += 30 * m2;
+ }*/
+
+ // Huge mountains
+ double m3 = 150.0 - 800.0 * noise2d_perlin_abs(
+ 0.5+(float)p.X/2000., 0.5+(float)p.Y/2000.,
+ (seed>>32)+985251, 9, 0.5);
+ if(m3 > h)
+ h = m3;
+
+ /*double tm2 = contour_flat_top(-1.0 + 3.0 * noise2d_perlin(
+ 0.0+(float)p.X/300., 0.0+(float)p.Y/300.,
+ (seed>>32)+78593, 5, 0.55), 0.15);
+ h += 30 * tm2;*/
+
+#if 1
+ {
+ double a1 = 30 - 100. * noise2d_perlin_abs(
+ 0.5+(float)p.X/250., 0.5+(float)p.Y/250.,
+ seed+850342, 5, 0.63);
+ double d = 15;
+ if(a1 > d)
+ a1 = d + sqrt(a1-d);
+ if(a1 > h)
+ h = a1;
+ }
+#endif
+
+#if 1
+ double base = 35. * noise2d_perlin(
0.5+(float)p.X/500., 0.5+(float)p.Y/500.,
- (seed>>32)+654879876, 6, 0.6);
+ (seed>>32)+653876, 7, 0.55);
+#else
+ double base = 0;
+#endif
- /*// A bit hillier one
- double base2 = WATER_LEVEL - 4.0 + 40. * noise2d_perlin(
- 0.5+(float)p.X/250., 0.5+(float)p.Y/250.,
- (seed>>27)+90340, 6, 0.69);
- if(base2 > base)
- base = base2;*/
#if 1
- // Higher ground level
- double higher = (double)WATER_LEVEL + 25. + 45. * noise2d_perlin(
+ double higher = 50. * noise2d_perlin(
0.5+(float)p.X/250., 0.5+(float)p.Y/250.,
- seed+85039, 5, 0.69);
- //higher = 30; // For debugging
-
- // Limit higher to at least base
- if(higher < base)
- higher = base;
-
- // Steepness factor of cliffs
- double b = 1.0 + 1.0 * noise2d_perlin(
+ seed+39292, 6, 0.63);
+ /*double higher = 50. * noise2d_perlin_abs(
0.5+(float)p.X/250., 0.5+(float)p.Y/250.,
- seed-932, 7, 0.7);
- b = rangelim(b, 0.0, 1000.0);
- b = pow(b, 5);
- b *= 7;
- b = rangelim(b, 3.0, 1000.0);
- //dstream<<"b="<<b<<std::endl;
- //double b = 20;
-
- // Offset to more low
- double a_off = -0.2;
- // High/low selector
- /*double a = 0.5 + b * (a_off + noise2d_perlin(
- 0.5+(float)p.X/500., 0.5+(float)p.Y/500.,
- seed-359, 6, 0.7));*/
- double a = (double)0.5 + b * (a_off + noise2d_perlin(
- 0.5+(float)p.X/250., 0.5+(float)p.Y/250.,
- seed-359, 5, 0.60));
- // Limit
- a = rangelim(a, 0.0, 1.0);
+ seed+85039, 5, 0.63);*/
+
+ if(higher > base)
+ {
+ // Steepness factor of cliffs
+ double b = 1.0 + 1.0 * noise2d_perlin(
+ 0.5+(float)p.X/250., 0.5+(float)p.Y/250.,
+ seed-932, 7, 0.7);
+ b = rangelim(b, 0.0, 1000.0);
+ b = pow(b, 5);
+ b *= 7;
+ b = rangelim(b, 3.0, 1000.0);
+ //dstream<<"b="<<b<<std::endl;
+ //double b = 20;
+
+ // Offset to more low
+ //double a_off = -0.30;
+ double a_off = -0.00;
+ // High/low selector
+ double a = (double)0.5 + b * (a_off + noise2d_perlin(
+ 0.5+(float)p.X/250., 0.5+(float)p.Y/250.,
+ seed-359, 5, 0.6));
+ // Limit
+ a = rangelim(a, 0.0, 1.0);
+ //a = easeCurve(a);
+
+ //dstream<<"a="<<a<<std::endl;
+
+ h += base*(1.0-a) + higher*a;
+ }
+ else
+ {
+ h += base;
+ }
+#else
+ h += base;
+#endif
- //dstream<<"a="<<a<<std::endl;
+ return h;
+}
+
+double base_rock_level_2d(u64 seed, v2s16 p)
+{
+ return base_rock_level_2d(seed, v2f((float)p.X, (float)p.Y));
+}
+
+v2f base_ground_turbulence(u64 seed, v3f p)
+{
+ double f = 12;
+
+ double v1 = f * noise3d_perlin(
+ 0.5+p.X/200,
+ 0.5+p.Y/200,
+ 0.5+p.Z/200,
+ seed+4045, 5, 0.7);
+
+ double v2 = f * noise3d_perlin(
+ 0.5+p.X/200,
+ 0.5+p.Y/200,
+ 0.5+p.Z/200,
+ seed+9495, 5, 0.7);
- double h = base*(1.0-a) + higher*a;
+ return v2f(v1, v2);
+}
+
+bool is_carved(u64 seed, v3f p)
+{
+#if 1
+ double v1 = noise3d_perlin_abs(
+ 0.5+p.X/200,
+ 0.5+p.Y/200,
+ 0.5+p.Z/200,
+ seed+657890854, 5, 0.7);
+
+ if(v1 > 1.5)
+ return true;
+#endif
+
+#if 0
+ double v2 = noise3d_perlin_abs(
+ 0.5+p.X/200,
+ 0.5+p.Y/200,
+ 0.5+p.Z/200,
+ seed+657890854, 5, 0.7);
+#if 0
+ double v3 = noise3d_perlin_abs(
+ 0.5+p.X/200,
+ 0.5+p.Y/200,
+ 0.5+p.Z/200,
+ seed+657890854, 5, 0.7);
#else
- double h = base;
+ double v3 = 1.0;
#endif
- return h;
+ double v23 = v2*v3;
+ if(v23 > 0.7)
+ return true;
+#endif
+
+ double f = 10.0;
+ double y_div = 1.5;
+
+ double v4 = contour(f*noise3d_perlin(
+ 0.5+p.X/200,
+ 0.5+p.Y/200*y_div,
+ 0.5+p.Z/200,
+ seed+87592, 5, 0.7));
+ // Tilted 90 degrees
+ double v5 = contour(f*noise3d_perlin(
+ 0.5+p.X/200,
+ 0.5+p.Z/200,
+ 0.5+p.Y/200*y_div,
+ seed+98594, 5, 0.7));
+
+ double v45 = v4*v5;
+ if(v45 > 2.5/f)
+ return true;
+
+ return false;
+}
+
+/*
+ if depth_guess!=NULL, it is set to a guessed value of how deep
+ underground the position is.
+*/
+bool is_base_ground(u64 seed, v3f p, double *depth_guess=NULL)
+{
+#if 0
+ // This is used for testing the output of the cave function
+ {
+ if(depth_guess)
+ *depth_guess = 10;
+ if(p.Y > 50)
+ return false;
+ return is_carved(seed, p);
+ }
+#endif
+
+ v2f t = base_ground_turbulence(seed, p);
+
+ double surface_y_f = base_rock_level_2d(seed, v2f(p.X+t.X, p.Z+t.Y));
+
+ /*if(depth_guess)
+ *depth_guess = surface_y_f - p.Y;*/
+
+ if(depth_guess)
+ {
+ // Find highest surface near current
+ v3f dirs[4] = {
+ v3f(1,-1,0),
+ v3f(-1,-1,0),
+ v3f(0,-1,1),
+ v3f(0,-1,-1)
+ };
+ double s2 = surface_y_f;
+ for(u32 i=0; i<4; i++)
+ {
+ v3f dir = dirs[i];
+ v2f l = v2f(p.X+t.X+dir.X, p.Z+t.Y+dir.Z);
+ double s = base_rock_level_2d(seed, l);
+ if(s > s2)
+ s2 = s;
+ }
+ *depth_guess = s2 - p.Y;
+ }
+
+ /*if(depth_guess)
+ {
+ // Check a bit lower also, take highest surface
+ v2f t2 = base_ground_turbulence(seed, p + v3f(0,-2,0));
+ double s2 = base_rock_level_2d(seed, v2f(p.X+t2.X, p.Z+t2.Y));
+ if(s2 > surface_y_f)
+ *depth_guess = s2 - p.Y;
+ else
+ *depth_guess = surface_y_f - p.Y;
+ }*/
+
+ /*if(depth_guess)
+ {
+ // Guess surface point
+ v3f p2(p.X, surface_y_f, p.Z);
+ v2f t2 = base_ground_turbulence
+ double u1 =
+ double s1 = base_rock_level_2d(seed, v2f(p.X+v1,p.Z+v2));
+ }*/
+
+ bool is_ground = (p.Y <= surface_y_f);
+
+ if(is_carved(seed, p))
+ is_ground = false;
+
+ return is_ground;
}
#define VMANIP_FLAG_DUNGEON VOXELFLAG_CHECKED1
@@ -2023,6 +2256,11 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
{
DSTACK(__FUNCTION_NAME);
+ // Shall be not used now
+ //assert(0);
+
+#if 0
+
/*
Don't generate if already fully generated
*/
@@ -2163,7 +2401,8 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
{
// 22ms @cs=8
- //TimeTaker timer1("ground level");
+ TimeTaker timer1("ground level");
+ dstream<<"Generating base ground..."<<std::endl;
for(s16 x=0; x<sectorpos_bigbase_size*MAP_BLOCKSIZE; x++)
for(s16 z=0; z<sectorpos_bigbase_size*MAP_BLOCKSIZE; z++)
@@ -2172,7 +2411,79 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
v2s16 p2d = sectorpos_bigbase*MAP_BLOCKSIZE + v2s16(x,z);
/*
- Skip of already generated
+ Skip if already generated
+ */
+ {
+ v3s16 p(p2d.X, y_nodes_min, p2d.Y);
+ if(vmanip.m_data[vmanip.m_area.index(p)].d != CONTENT_AIR)
+ continue;
+ }
+
+ v2f p2df(p2d.X, p2d.Y);
+
+ {
+ // Use fast index incrementing
+ v3s16 em = vmanip.m_area.getExtent();
+ s16 min = y_nodes_min;
+ s16 max = y_nodes_max;
+ /*s16 min = -10;
+ s16 max = 20;*/
+ //float surface_y_f = base_rock_level_2d(m_seed, p2df);
+ u32 i = vmanip.m_area.index(v3s16(p2d.X, min, p2d.Y));
+ for(s16 y=min; y<=max; y++)
+ {
+#if 1
+ bool is = is_base_ground(m_seed, v3f(p2df.X,y,p2df.Y));
+ if(is)
+ vmanip.m_data[i].d = CONTENT_STONE;
+ else
+ vmanip.m_data[i].d = CONTENT_AIR;
+#endif
+#if 0
+ double v = noise3d_perlin(
+ 0.5+(float)p2d.X/200,
+ 0.5+(float)y/200,
+ 0.5+(float)p2d.Y/200,
+ m_seed+293, 6, 0.55);
+ if(v > 0.0)
+ vmanip.m_data[i].d = CONTENT_STONE;
+ else
+ vmanip.m_data[i].d = CONTENT_AIR;
+#endif
+#if 0
+ /*double v1 = 5 * noise3d_perlin(
+ 0.5+(float)p2df.X/200,
+ 0.5+(float)y/200,
+ 0.5+(float)p2df.Y/200,
+ m_seed+293, 6, 0.55);
+
+ double v2 = 5 * noise3d_perlin(
+ 0.5+(float)p2df.X/200,
+ 0.5+(float)y/200,
+ 0.5+(float)p2df.Y/200,
+ m_seed+293, 6, 0.55);*/
+
+ double v1 = 0;
+ double v2 = 0;
+
+ float surface_y_f = base_rock_level_2d(m_seed, p2df+v2f(v1,v2));
+
+ if(y <= surface_y_f)
+ vmanip.m_data[i].d = CONTENT_STONE;
+ else
+ vmanip.m_data[i].d = CONTENT_AIR;
+#endif
+
+ vmanip.m_area.add_y(em, i, 1);
+ }
+ }
+
+#if 0
+ // Node position
+ v2s16 p2d = sectorpos_bigbase*MAP_BLOCKSIZE + v2s16(x,z);
+
+ /*
+ Skip if already generated
*/
{
v3s16 p(p2d.X, y_nodes_min, p2d.Y);
@@ -2214,6 +2525,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
vmanip.m_area.add_y(em, i, 1);
}
}
+#endif
}
}//timer1
@@ -2235,8 +2547,8 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
/*
Loop this part, it will make stuff look older and newer nicely
*/
- //for(u32 i_age=0; i_age<1; i_age++)
- for(u32 i_age=0; i_age<2; i_age++)
+ u32 age_count = 2;
+ for(u32 i_age=0; i_age<age_count; i_age++)
{ // Aging loop
{
@@ -2732,9 +3044,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
v2s16 p2d = sectorpos_base*MAP_BLOCKSIZE + v2s16(x,z);
// Randomize mud amount
- s16 mud_add_amount = (s16)(2.5 + 2.0 * noise2d_perlin(
- 0.5+(float)p2d.X/200, 0.5+(float)p2d.Y/200,
- m_seed+1, 3, 0.55));
+ s16 mud_add_amount = get_mud_amount(m_seed, v2f(p2d.X,p2d.Y))/age_count;
// Find ground level
s16 surface_y = find_ground_level_clever(vmanip, p2d);
@@ -2777,7 +3087,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
}//timer1
{
// 340ms @cs=8
- TimeTaker timer1("flow mud");
+ //TimeTaker timer1("flow mud");
/*
Flow mud away from steep edges
@@ -3447,57 +3757,6 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
}
#endif
-#if 0
- for(s16 x=lighting_min_d+1;
- x<=lighting_max_d-1;
- x++)
- for(s16 z=lighting_min_d+1;
- z<=lighting_max_d-1;
- z++)
- {
- // Node position in 2d
- v2s16 p2d = sectorpos_base*MAP_BLOCKSIZE + v2s16(x,z);
-
- /*
- Apply initial sunlight
- */
- {
- u8 light = LIGHT_SUN;
- v3s16 em = vmanip.m_area.getExtent();
- s16 y_start = y_nodes_max;
- u32 i = vmanip.m_area.index(v3s16(p2d.X, y_start, p2d.Y));
- for(s16 y=y_start; y>=y_nodes_min; y--)
- {
- MapNode *n = &vmanip.m_data[i];
-
- if(light_propagates_content(n->d) == false)
- {
- light = 0;
- }
- else if(light != LIGHT_SUN
- || sunlight_propagates_content(n->d) == false)
- {
- if(light > 0)
- light--;
- }
-
- n->setLight(LIGHTBANK_DAY, light);
- n->setLight(LIGHTBANK_NIGHT, 0);
-
- // This doesn't take much time
- if(light != 0)
- {
- // Insert light source
- light_sources.insert(v3s16(p2d.X, y, p2d.Y), true);
- }
-
- // Increment index by y
- vmanip.m_area.add_y(em, i, -1);
- }
- }
- }
-#endif
-
}//timer1
// Spread light around
@@ -3533,6 +3792,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
}
}
+#endif
/*
Create chunk metadata
@@ -3581,6 +3841,9 @@ MapChunk* ServerMap::generateChunk(v2s16 chunkpos1,
<<"("<<chunkpos1.X<<","<<chunkpos1.Y<<")"
<<std::endl;
+ // Shall be not used now
+ //assert(0);
+
/*for(s16 x=-1; x<=1; x++)
for(s16 y=-1; y<=1; y++)*/
for(s16 x=-0; x<=0; x++)
@@ -3709,13 +3972,6 @@ MapSector * ServerMap::emergeSector(v2s16 p2d,
<<p2d.X<<","<<p2d.Y<<" and chunk is already generated. "
<<std::endl;
-#if 0
- dstream<<"WARNING: Creating an empty sector."<<std::endl;
-
- return createSector(p2d);
-
-#endif
-
#if 1
dstream<<"WARNING: Forcing regeneration of chunk."<<std::endl;
@@ -3731,7 +3987,14 @@ MapSector * ServerMap::emergeSector(v2s16 p2d,
dstream<<"ERROR: Could not get sector from anywhere."<<std::endl;
- assert(0);
+ //assert(0);
+#endif
+
+#if 1
+ dstream<<"WARNING: Creating an empty sector."<<std::endl;
+
+ return createSector(p2d);
+
#endif
/*
@@ -3765,6 +4028,7 @@ MapBlock * ServerMap::generateBlock(
v2s16 p2d(p.X, p.Z);
s16 block_y = p.Y;
v2s16 p2d_nodes = p2d * MAP_BLOCKSIZE;
+ v3s16 p_nodes = p * MAP_BLOCKSIZE;
/*
Do not generate over-limit
@@ -3797,99 +4061,324 @@ MapBlock * ServerMap::generateBlock(
s32 lowest_ground_y = 32767;
s32 highest_ground_y = -32768;
-
- for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
- for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
+
+ enum{
+ BT_GROUND,
+ BT_SURFACE,
+ BT_SKY
+ } block_type = BT_SURFACE;
+
+ {// ground_timer (0ms or ~100ms)
+ //TimeTaker ground_timer("Ground generation");
+
+ /*
+ Approximate whether this block is a surface block, an air
+ block or a ground block.
+
+ This shall never mark a surface block as non-surface.
+ */
+
{
- //dstream<<"generateBlock: x0="<<x0<<", z0="<<z0<<std::endl;
+ /*
+ Estimate surface at different positions of the block, to
+ try to accomodate the effect of turbulence.
+ */
+ v3f checklist[] = {
+ v3f(0,0,0),
+ v3f(0,1,0),
+ v3f(0,1,1),
+ v3f(0,0,1),
+ v3f(1,0,0),
+ v3f(1,1,0),
+ v3f(1,1,1),
+ v3f(1,0,1),
+ v3f(0.5,0.5,0.5),
+ };
+ v3f p_nodes_f = intToFloat(p_nodes, 1);
+ float surface_y_max = -1000000;
+ float surface_y_min = 1000000;
+ for(u32 i=0; i<sizeof(checklist)/sizeof(checklist[0]); i++)
+ {
+ v3f p_map_f = p_nodes_f + checklist[i]*MAP_BLOCKSIZE;
- //s16 surface_y = 0;
+ double depth_guess;
+ bool is_ground = is_base_ground(m_seed, p_map_f, &depth_guess);
+
+ // Estimate the surface height
+ float surface_y_f = p_map_f.Y + depth_guess;
- s16 surface_y = base_rock_level_2d(m_seed, p2d_nodes+v2s16(x0,z0))
- + AVERAGE_MUD_AMOUNT;
+ if(surface_y_f > surface_y_max)
+ surface_y_max = surface_y_f;
+ if(surface_y_f < surface_y_min)
+ surface_y_min = surface_y_f;
+ }
- if(surface_y < lowest_ground_y)
- lowest_ground_y = surface_y;
- if(surface_y > highest_ground_y)
- highest_ground_y = surface_y;
+ float block_low_y_f = p_nodes_f.Y;
+ float block_high_y_f = p_nodes_f.Y + MAP_BLOCKSIZE;
- s32 surface_depth = AVERAGE_MUD_AMOUNT;
+ /*dstream<<"surface_y_max="<<surface_y_max
+ <<", surface_y_min="<<surface_y_min
+ <<", block_low_y_f="<<block_low_y_f
+ <<", block_high_y_f="<<block_high_y_f
+ <<std::endl;*/
- for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
+ // A fuzzyness value
+ // Must accomodate mud and turbulence holes
+ float d_down = 16;
+ // Must accomodate a bit less
+ float d_up = 5;
+
+ if(block_high_y_f < surface_y_min - d_down)
{
- s16 real_y = block_y * MAP_BLOCKSIZE + y0;
- MapNode n;
- /*
- Calculate lighting
-
- NOTE: If there are some man-made structures above the
- newly created block, they won't be taken into account.
- */
- if(real_y > surface_y)
- n.setLight(LIGHTBANK_DAY, LIGHT_SUN);
+ //dstream<<"BT_GROUND"<<std::endl;
+ // A ground block
+ //block_type = BT_GROUND;
+ // Handled as surface because of caves
+ block_type = BT_SURFACE;
+ }
+ else if(block_low_y_f >= surface_y_max + d_up
+ && block_low_y_f > WATER_LEVEL + d_up)
+ {
+ //dstream<<"BT_SKY"<<std::endl;
+ // A sky block
+ block_type = BT_SKY;
+ }
+ else
+ {
+ //dstream<<"BT_SURFACE"<<std::endl;
+ // A surface block
+ block_type = BT_SURFACE;
+ }
- /*
- Calculate material
- */
+ if(block_type == BT_GROUND || block_type == BT_SKY)
+ {
+ lowest_ground_y = surface_y_min;
+ highest_ground_y = surface_y_max;
+ }
+ }
+
+ if(block_type == BT_SURFACE)
+ {
+ /*
+ Generate ground precisely
+ */
+
+ for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
+ for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
+ {
+ //dstream<<"generateBlock: x0="<<x0<<", z0="<<z0<<std::endl;
- // If node is over heightmap y, it's air or water
- if(real_y > surface_y)
- {
- // If under water level, it's water
- if(real_y < WATER_LEVEL)
- {
- n.d = water_material;
- n.setLight(LIGHTBANK_DAY,
- diminish_light(LIGHT_SUN, WATER_LEVEL-real_y+1));
- /*
- Add to transforming liquid queue (in case it'd
- start flowing)
- */
- v3s16 real_pos = v3s16(x0,y0,z0) + p*MAP_BLOCKSIZE;
- m_transforming_liquid.push_back(real_pos);
- }
- // else air
- else
- n.d = CONTENT_AIR;
- }
- // Else it's ground or dungeons (air)
- else
+ //s16 surface_y = 0;
+
+ /*s16 surface_y = base_rock_level_2d(m_seed, p2d_nodes+v2s16(x0,z0))
+ + AVERAGE_MUD_AMOUNT;
+
+ if(surface_y < lowest_ground_y)
+ lowest_ground_y = surface_y;
+ if(surface_y > highest_ground_y)
+ highest_ground_y = surface_y;*/
+
+ v2s16 real_p2d = v2s16(x0,z0) + p2d*MAP_BLOCKSIZE;
+
+ //s32 surface_depth = AVERAGE_MUD_AMOUNT;
+ s16 surface_depth = get_mud_amount(m_seed, v2f(real_p2d.X,real_p2d.Y));
+
+ for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
{
- // If it's surface_depth under ground, it's stone
- if(real_y <= surface_y - surface_depth)
+ #if 1
+ s16 real_y = block_y * MAP_BLOCKSIZE + y0;
+ v3s16 real_pos = v3s16(x0,y0,z0) + p_nodes;
+ MapNode n;
+ /*
+ Calculate lighting
+
+ NOTE: If there are some man-made structures above the
+ newly created block, they won't be taken into account.
+ */
+ /*if(real_y > surface_y)
+ n.setLight(LIGHTBANK_DAY, LIGHT_SUN);*/
+
+ /*
+ Calculate material
+ */
+
+ double depth_guess;
+ bool is_ground = is_base_ground(m_seed,
+ intToFloat(real_pos, 1), &depth_guess);
+
+ // Estimate the surface height
+ float surface_y_f = (float)real_y + depth_guess;
+ s16 surface_y = real_y + depth_guess;
+
+ // Get some statistics of surface height
+ if(surface_y < lowest_ground_y)
+ lowest_ground_y = surface_y;
+ if(surface_y > highest_ground_y)
+ highest_ground_y = surface_y;
+
+ // If node is not ground, it's air or water
+ if(is_ground == false)
{
- n.d = CONTENT_STONE;
+ // If under water level, it's water
+ if(real_y < WATER_LEVEL)
+ {
+ n.d = water_material;
+ n.setLight(LIGHTBANK_DAY,
+ diminish_light(LIGHT_SUN, WATER_LEVEL-real_y+1));
+ /*
+ Add to transforming liquid queue (in case it'd
+ start flowing)
+ */
+ m_transforming_liquid.push_back(real_pos);
+ }
+ // else air
+ else
+ n.d = CONTENT_AIR;
}
+ // Else it's ground or dungeons (air)
else
{
- // It is mud if it is under the first ground
- // level or under water
- if(real_y < WATER_LEVEL || real_y <= surface_y - 1)
+ // If it's surface_depth under ground, it's stone
+ if((float)real_y <= surface_y_f - surface_depth - 0.75)
{
- n.d = CONTENT_MUD;
+ n.d = CONTENT_STONE;
+ }
+ else if(surface_y_f <= WATER_LEVEL + 2.0)
+ {
+ n.d = CONTENT_SAND;
}
else
{
- n.d = CONTENT_GRASS;
+ /*// It is mud if it is under the first ground
+ // level or under water
+ if(real_y < WATER_LEVEL || real_y <= surface_y - 1)
+ {
+ n.d = CONTENT_MUD;
+ }
+ else
+ {
+ n.d = CONTENT_GRASS;
+ }*/
+
+ n.d = CONTENT_MUD;
+
+ /*// If under water level, it's mud
+ if(real_y < WATER_LEVEL)
+ n.d = CONTENT_MUD;
+ // Only the topmost node is grass
+ else if(real_y <= surface_y - 1)
+ n.d = CONTENT_MUD;
+ else
+ n.d = CONTENT_GRASS;*/
}
+ }
- //n.d = CONTENT_MUD;
+ block->setNode(v3s16(x0,y0,z0), n);
+ #endif
+ #if 0
+ s16 real_y = block_y * MAP_BLOCKSIZE + y0;
+ MapNode n;
+ /*
+ Calculate lighting
- /*// If under water level, it's mud
+ NOTE: If there are some man-made structures above the
+ newly created block, they won't be taken into account.
+ */
+ if(real_y > surface_y)
+ n.setLight(LIGHTBANK_DAY, LIGHT_SUN);
+
+ /*
+ Calculate material
+ */
+
+ // If node is over heightmap y, it's air or water
+ if(real_y > surface_y)
+ {
+ // If under water level, it's water
if(real_y < WATER_LEVEL)
- n.d = CONTENT_MUD;
- // Only the topmost node is grass
- else if(real_y <= surface_y - 1)
- n.d = CONTENT_MUD;
+ {
+ n.d = water_material;
+ n.setLight(LIGHTBANK_DAY,
+ diminish_light(LIGHT_SUN, WATER_LEVEL-real_y+1));
+ /*
+ Add to transforming liquid queue (in case it'd
+ start flowing)
+ */
+ v3s16 real_pos = v3s16(x0,y0,z0) + p*MAP_BLOCKSIZE;
+ m_transforming_liquid.push_back(real_pos);
+ }
+ // else air
else
- n.d = CONTENT_GRASS;*/
+ n.d = CONTENT_AIR;
}
+ // Else it's ground or dungeons (air)
+ else
+ {
+ // If it's surface_depth under ground, it's stone
+ if(real_y <= surface_y - surface_depth)
+ {
+ n.d = CONTENT_STONE;
+ }
+ else
+ {
+ // It is mud if it is under the first ground
+ // level or under water
+ if(real_y < WATER_LEVEL || real_y <= surface_y - 1)
+ {
+ n.d = CONTENT_MUD;
+ }
+ else
+ {
+ n.d = CONTENT_GRASS;
+ }
+
+ //n.d = CONTENT_MUD;
+
+ /*// If under water level, it's mud
+ if(real_y < WATER_LEVEL)
+ n.d = CONTENT_MUD;
+ // Only the topmost node is grass
+ else if(real_y <= surface_y - 1)
+ n.d = CONTENT_MUD;
+ else
+ n.d = CONTENT_GRASS;*/
+ }
+ }
+
+ block->setNode(v3s16(x0,y0,z0), n);
+ #endif
}
+ }
+ }// BT_SURFACE
+ else // BT_GROUND, BT_SKY or anything else
+ {
+ MapNode n_fill;
+ if(block_type == BT_GROUND)
+ {
+ n_fill.d = CONTENT_STONE;
+ }
+ else if(block_type == BT_SKY)
+ {
+ n_fill.d = CONTENT_AIR;
+ n_fill.setLight(LIGHTBANK_DAY, LIGHT_SUN);
+ }
+ else // fallback
+ {
+ n_fill.d = CONTENT_MESE;
+ }
- block->setNode(v3s16(x0,y0,z0), n);
+
+ for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
+ for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
+ for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
+ {
+ //MapNode n = block->getNode(v3s16(x0,y0,z0));
+ block->setNode(v3s16(x0,y0,z0), n_fill);
}
}
+ }// ground_timer
+
/*
Calculate some helper variables
*/
@@ -3945,7 +4434,7 @@ MapBlock * ServerMap::generateBlock(
}
// Fill table
-#if 1
+#if 0
{
/*
Initialize orp and ors. Try to find if some neighboring
@@ -4087,7 +4576,8 @@ continue_generating:
// Partly underground = cave
else if(!completely_underground)
{
- do_generate_dungeons = (rand() % 100 <= (s32)(caves_amount*100));
+ //do_generate_dungeons = (rand() % 100 <= (s32)(caves_amount*100));
+ do_generate_dungeons = false;
}
// Found existing dungeon underground
else if(found_existing && completely_underground)
@@ -4239,8 +4729,8 @@ continue_generating:
/*
Add coal
*/
- u16 coal_amount = 30;
- u16 coal_rareness = 60 / coal_amount;
+ u16 coal_amount = 60;
+ u16 coal_rareness = 120 / coal_amount;
if(coal_rareness == 0)
coal_rareness = 1;
if(myrand()%coal_rareness == 0)
@@ -4271,9 +4761,8 @@ continue_generating:
/*
Add iron
*/
- //TODO: change to iron_amount or whatever
- u16 iron_amount = 15;
- u16 iron_rareness = 60 / iron_amount;
+ u16 iron_amount = 40;
+ u16 iron_rareness = 80 / iron_amount;
if(iron_rareness == 0)
iron_rareness = 1;
if(myrand()%iron_rareness == 0)
@@ -4330,8 +4819,17 @@ continue_generating:
*/
sector->insertBlock(block);
- // Lighting is invalid after generation.
- block->setLightingExpired(true);
+ // Lighting is invalid after generation for surface blocks
+ if(block_type == BT_SURFACE)
+ {
+ block->setLightingExpired(true);
+ lighting_invalidated_blocks.insert(p, block);
+ }
+ // Lighting is not invalid for other blocks
+ else
+ {
+ block->setLightingExpired(false);
+ }
#if 0
/*
@@ -4536,7 +5034,9 @@ MapBlock * ServerMap::emergeBlock(
if(does_not_exist)
{
block = generateBlock(p, block, sector, changed_blocks,
- lighting_invalidated_blocks);
+ lighting_invalidated_blocks);
+
+ lighting_expired = block->getLightingExpired();
}
if(lighting_expired)
@@ -4548,6 +5048,7 @@ MapBlock * ServerMap::emergeBlock(
Initially update sunlight
*/
+ if(lighting_expired)
{
core::map<v3s16, bool> light_sources;
bool black_air_left = false;
diff --git a/src/map.h b/src/map.h
index 1cebef634..0692f2b23 100644
--- a/src/map.h
+++ b/src/map.h
@@ -40,6 +40,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "voxel.h"
#include "mapchunk.h"
+/*
+ Some exposed functions
+*/
+
+double base_rock_level_2d(u64 seed, v2f p);
+
+/*
+*/
+
#define MAPTYPE_BASE 0
#define MAPTYPE_SERVER 1
#define MAPTYPE_CLIENT 2
@@ -531,6 +540,8 @@ public:
bool isSavingEnabled(){ return m_map_saving_enabled; }
+ u64 getSeed(){ return m_seed; }
+
private:
// Seed used for all kinds of randomness
u64 m_seed;
diff --git a/src/mapblock.cpp b/src/mapblock.cpp
index d489ec8ac..9594b2961 100644
--- a/src/mapblock.cpp
+++ b/src/mapblock.cpp
@@ -34,6 +34,7 @@ MapBlock::MapBlock(NodeContainer *parent, v3s16 pos, bool dummy):
m_pos(pos),
changed(true),
is_underground(false),
+ m_lighting_expired(true),
m_day_night_differs(false),
m_objects(this)
{
diff --git a/src/noise.cpp b/src/noise.cpp
index 63682e1e4..bc5148545 100644
--- a/src/noise.cpp
+++ b/src/noise.cpp
@@ -92,8 +92,7 @@ double noise3d(int x, int y, int z, int seed)
return 1.0 - (double)n/1073741824;
}
-#if 0
-// This is too slow
+#if 1
double noise2d_gradient(double x, double y, int seed)
{
// Calculate the integer coordinates
@@ -118,7 +117,7 @@ double noise2d_gradient(double x, double y, int seed)
}
#endif
-#if 1
+#if 0
double noise2d_gradient(double x, double y, int seed)
{
// Calculate the integer coordinates
@@ -175,6 +174,21 @@ double noise2d_perlin(double x, double y, int seed,
return a;
}
+double noise2d_perlin_abs(double x, double y, int seed,
+ int octaves, double persistence)
+{
+ double a = 0;
+ double f = 1.0;
+ double g = 1.0;
+ for(int i=0; i<octaves; 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)
{
@@ -190,3 +204,18 @@ double noise3d_perlin(double x, double y, double z, int seed,
return a;
}
+double noise3d_perlin_abs(double x, double y, double z, int seed,
+ int octaves, double persistence)
+{
+ double a = 0;
+ double f = 1.0;
+ double g = 1.0;
+ for(int i=0; i<octaves; i++)
+ {
+ a += g * fabs(noise3d_gradient(x*f, y*f, z*f, seed+i));
+ f *= 2.0;
+ g *= persistence;
+ }
+ return a;
+}
+
diff --git a/src/noise.h b/src/noise.h
index 63974e86a..88b995b1e 100644
--- a/src/noise.h
+++ b/src/noise.h
@@ -32,8 +32,14 @@ double noise3d_gradient(double x, double y, double z, int seed);
double noise2d_perlin(double x, double y, int seed,
int octaves, double persistence);
+double noise2d_perlin_abs(double x, double y, int seed,
+ int octaves, double persistence);
+
double noise3d_perlin(double x, double y, double z, int seed,
int octaves, double persistence);
+double noise3d_perlin_abs(double x, double y, double z, int seed,
+ int octaves, double persistence);
+
#endif
diff --git a/src/server.cpp b/src/server.cpp
index 24f22c6b3..e4c92e356 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -167,6 +167,26 @@ void * EmergeThread::Thread()
only_from_disk,
changed_blocks,
lighting_invalidated_blocks);
+
+ /*
+ While we're at it, generate some other blocks too
+ */
+ try
+ {
+ map.emergeBlock(
+ p+v3s16(0,1,0),
+ only_from_disk,
+ changed_blocks,
+ lighting_invalidated_blocks);
+ map.emergeBlock(
+ p+v3s16(0,-1,0),
+ only_from_disk,
+ changed_blocks,
+ lighting_invalidated_blocks);
+ }
+ catch(InvalidPositionException &e)
+ {
+ }
}
// If it is a dummy, block was not found on disk
@@ -208,23 +228,25 @@ void * EmergeThread::Thread()
Collect a list of blocks that have been modified in
addition to the fetched one.
*/
-
- // Add all the "changed blocks" to modified_blocks
- for(core::map<v3s16, MapBlock*>::Iterator i = changed_blocks.getIterator();
- i.atEnd() == false; i++)
- {
- MapBlock *block = i.getNode()->getValue();
- modified_blocks.insert(block->getPos(), block);
- }
- /*dstream<<"lighting "<<lighting_invalidated_blocks.size()
- <<" blocks"<<std::endl;*/
+ if(lighting_invalidated_blocks.size() > 0)
+ dstream<<"lighting "<<lighting_invalidated_blocks.size()
+ <<" blocks"<<std::endl;
- //TimeTaker timer("** updateLighting");
+ // 50-100ms for single block generation
+ //TimeTaker timer("** EmergeThread updateLighting");
// Update lighting without locking the environment mutex,
// add modified blocks to changed blocks
map.updateLighting(lighting_invalidated_blocks, modified_blocks);
+
+ // Add all from changed_blocks to modified_blocks
+ for(core::map<v3s16, MapBlock*>::Iterator i = changed_blocks.getIterator();
+ i.atEnd() == false; i++)
+ {
+ MapBlock *block = i.getNode()->getValue();
+ modified_blocks.insert(block->getPos(), block);
+ }
}
// If we got no block, there should be no invalidated blocks
else
@@ -551,7 +573,8 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
{
//TODO: Get value from somewhere
// Allow only one block in emerge queue
- if(server->m_emerge_queue.peerItemCount(peer_id) < 1)
+ //if(server->m_emerge_queue.peerItemCount(peer_id) < 1)
+ if(server->m_emerge_queue.peerItemCount(peer_id) < 2)
{
//dstream<<"Adding block to emerge queue"<<std::endl;
@@ -1681,10 +1704,11 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
// Now answer with a TOCLIENT_INIT
- SharedBuffer<u8> reply(2+1+6);
+ SharedBuffer<u8> reply(2+1+6+8);
writeU16(&reply[0], TOCLIENT_INIT);
writeU8(&reply[2], deployed);
- writeV3S16(&reply[3], floatToInt(player->getPosition()+v3f(0,BS/2,0), BS));
+ writeV3S16(&reply[2+1], floatToInt(player->getPosition()+v3f(0,BS/2,0), BS));
+ writeU64(&reply[2+1+6], m_env.getServerMap().getSeed());
// Send as reliable
m_con.Send(peer_id, 0, reply, true);
diff --git a/src/tile.cpp b/src/tile.cpp
index cfbb68249..1f4456653 100644
--- a/src/tile.cpp
+++ b/src/tile.cpp
@@ -486,7 +486,7 @@ void TextureSource::buildMainAtlas()
sourcelist.push_back("sand.png^mineral_iron.png");
// Padding to disallow texture bleeding
- s32 padding = 8;
+ s32 padding = 16;
/*
First pass: generate almost everything
diff --git a/src/utility.h b/src/utility.h
index 2b878b82b..ce43f26a3 100644
--- a/src/utility.h
+++ b/src/utility.h
@@ -39,6 +39,18 @@ extern const v3s16 g_26dirs[26];
// 26th is (0,0,0)
extern const v3s16 g_27dirs[27];
+inline void writeU64(u8 *data, u64 i)
+{
+ data[0] = ((i>>56)&0xff);
+ data[1] = ((i>>48)&0xff);
+ data[2] = ((i>>40)&0xff);
+ data[3] = ((i>>32)&0xff);
+ data[4] = ((i>>24)&0xff);
+ data[5] = ((i>>16)&0xff);
+ data[6] = ((i>> 8)&0xff);
+ data[7] = ((i>> 0)&0xff);
+}
+
inline void writeU32(u8 *data, u32 i)
{
data[0] = ((i>>24)&0xff);
@@ -58,6 +70,14 @@ inline void writeU8(u8 *data, u8 i)
data[0] = ((i>> 0)&0xff);
}
+inline u64 readU64(u8 *data)
+{
+ return ((u64)data[0]<<56) | ((u64)data[1]<<48)
+ | ((u64)data[2]<<40) | ((u64)data[3]<<32)
+ | ((u64)data[4]<<24) | ((u64)data[5]<<16)
+ | ((u64)data[6]<<8) | ((u64)data[7]<<0);
+}
+
inline u32 readU32(u8 *data)
{
return (data[0]<<24) | (data[1]<<16) | (data[2]<<8) | (data[3]<<0);