From c8be58a65ce5f06bc23353b41caf9495e3b9d484 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Mon, 28 Feb 2011 02:01:40 +0200 Subject: [PATCH] A third try on terrain generation. No trees yet. --- data/mud.png | Bin 1586 -> 763 bytes src/client.cpp | 4 + src/client.h | 5 + src/clientserver.h | 1 + src/main.cpp | 182 ++++++++- src/map.cpp | 929 ++++++++++++++++++++++++++++++++++----------- src/map.h | 11 + src/mapblock.cpp | 1 + src/noise.cpp | 35 +- src/noise.h | 6 + src/server.cpp | 52 ++- src/tile.cpp | 2 +- src/utility.h | 20 + 13 files changed, 998 insertions(+), 250 deletions(-) diff --git a/data/mud.png b/data/mud.png index 7cb9c89a637584b4e53c82a7c6eb1ec7109befae..8a72bea90aeb27e7741092499c72cae48dd4d264 100644 GIT binary patch delta 740 zcmVPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L z01EH`01EH{Laa2H00007bV*G`2ipQ04mC0f|ODEhL22W55C(SATm{z7PHR$7WFO`S%a? zcDFkm-P0_EFaPeW@)MnIImOF)`tB~M{{CEdA~Z1XNyZcJz=N3! z7s5#eD{Krcm$fd(8OBOqR>j@1F`l#Dqa>hlCM|nNLxGEM?4aHMHAaNC-CA_JGsE=} zb}u+!ZfK5W%70F-!B$71-IIXRhpJU|Zv{>`GALU;1`^kE(R}@fr-TERmPBrrWsBjk z`*GuUyFSj5Lejf%EkqQTK!2lsHH{mN9YW>PZ^racU!Ffc z^97u%2{Z6b)4Vk5t*WaAbYEtW3%s^#>=<=lKBbYEF?nhAW#84(nQO~t^gIx2(MYvO znUv<*DdHxw+H8=%l*_yaNQ>;m%y?D#%x^<<%K|kCZj2qsmEI76q@_6Y3X}A|)7bg= zxUFK_Mt@vbL|Mftz{AZM6L9##+%~`ec`{ebTon?T7a@8*#`r8$*4yE07e_EGmtvgY z-CexCEhkCjw@*T(c<6{k;dbvDigCW+R7YUheYc4x55BG=%Zlx`QhcW6*u1=w_wQo` zT7bM?c-ztnjS%7L4O=V3X058~aA+8^mIj8*M_p6n$BfSMABvmg@qTS4Q>idFl;NcJ z=IyX`RA^$)2&i*|w7o^-*AJ_V>DPL|6XR4f2tGF^C$%!pQx6>GC}@Gso#C;IJo*l& WP-s5laF@UU0000_-}~PC4=Mb- zCz@KD0stmLAJ5hNHZ$yTM*K|HggXOZ3=}K;y|~K;HygYd_n2W(N(mttV}uZdP!I$P z00964fB=912s~@VCrSY!0Aqj04-!kfDGG<2RUGpVzRQivgMAj}(tFLMbMMCqjgH1f~=b0x{+`qLjbS4M-_J z1vY{`BaC875Wx^5&KEO^D1ij?IuN6f5?&utYaJ`E5I?++&lCPA6vozrkn!cK!dARW;7ZAqYmil;Xk8x zOex()Ljl;>&otgTV{MB@b^GU|kY#+M@6QhfTqKscG$EO}~h?Y0SX~b!+=X-vW2P^CC zOE1gUWNA;A{T|`yqmErDI$N!&=)c?jWchZ_!nMl>&VLnMmSVE1;auPnn|(q-;%E9DAfn*VT5@WtYVs_RuFy`_69T&H;7zq$%~PLRE~nZ{ai_oo0qY?o}pv zkx_0ntu5BM^m2$(uI=?IY4OK7d;Vx^iKuUnpIhX(Q?OX->^C>e_eEm+nW#%geM*X3 zOHoAh%n6^m_38d?NK2AgJM`c5va@ghJwKDMqkkYKL6vbCr9@%nFQnfi|&H}rRuSHf>1##()ElxLbrMJId zpVWIcqWS5hyFCZ5_|9(3mo~82t0k>9i@%W^D{WTTtUK&jvi`KGJSuF}X1pZ4Lf6^< zV{gGVrQ1uJBfEk0s5W! A1poj5 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: "< "+message); } + u64 getMapSeed(){ return m_map_seed; } + private: // Virtual methods from con::PeerHandler @@ -311,6 +313,9 @@ private: //u32 m_daynight_ratio; Queue 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< dim(640,480); + video::IImage *img = driver->createImage(video::ECF_A8R8G8B8, dim); + assert(img); + for(u32 y=0; ygetMapSeed(), 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 { @@ -2252,6 +2364,10 @@ int main(int argc, char *argv[]) */ g_input->step(dtime); + /* + Misc. stuff + */ + /* Player speed control */ @@ -3020,16 +3136,6 @@ int main(int argc, char *argv[]) driver->draw3DBox(*i, video::SColor(255,0,0,0)); } - /* - Draw crosshair - */ - driver->draw2DLine(displaycenter - core::vector2d(10,0), - displaycenter + core::vector2d(10,0), - video::SColor(255,255,255,255)); - driver->draw2DLine(displaycenter - core::vector2d(0,10), - displaycenter + core::vector2d(0,10), - video::SColor(255,255,255,255)); - /* Frametime log */ @@ -3048,6 +3154,31 @@ int main(int argc, char *argv[]) } } + /* + Draw map plot + */ + if(g_show_map_plot && g_map_plot_texture) + { + core::dimension2d drawdim(640,480); + core::rect dest(v2s32(0,0), drawdim); + dest += v2s32( + (screensize.X-drawdim.Width)/2, + (screensize.Y-drawdim.Height)/2 + ); + core::rect source(v2s32(0,0), g_map_plot_texture->getSize()); + driver->draw2DImage(g_map_plot_texture, dest, source); + } + + /* + Draw crosshair + */ + driver->draw2DLine(displaycenter - core::vector2d(10,0), + displaycenter + core::vector2d(10,0), + video::SColor(255,255,255,255)); + driver->draw2DLine(displaycenter - core::vector2d(0,10), + displaycenter + core::vector2d(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 & modified_blocks) while(m_transforming_liquid.size() != 0) { + try + { + /* Get a queued transforming liquid node */ @@ -1680,9 +1683,12 @@ void Map::transformLiquids(core::map & 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="<0, 0->1, 1->0 +double contour(double v) +{ + 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)+653876, 7, 0.55); +#else + double base = 0; +#endif + +#if 1 + double higher = 50. * noise2d_perlin( + 0.5+(float)p.X/250., 0.5+(float)p.Y/250., + seed+39292, 6, 0.63); + /*double higher = 50. * noise2d_perlin_abs( + 0.5+(float)p.X/250., 0.5+(float)p.Y/250., + 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="< 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=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, <<"("<= surface_y_max + d_up + && block_low_y_f > WATER_LEVEL + d_up) + { + //dstream<<"BT_SKY"< 0) + dstream<<"lighting "<::Iterator i = changed_blocks.getIterator(); i.atEnd() == false; i++) { MapBlock *block = i.getNode()->getValue(); modified_blocks.insert(block->getPos(), block); } - - /*dstream<<"lighting "<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"< reply(2+1+6); + SharedBuffer 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);