From 231386d50192a798fd30d49ae758da254f4a9db1 Mon Sep 17 00:00:00 2001 From: Perttu Ahola <celeron55@gmail.com> Date: Mon, 28 Feb 2011 14:51:57 +0200 Subject: [PATCH] tweaked mapgen --- data/grass.png | Bin 876 -> 874 bytes data/mud.png | Bin 763 -> 758 bytes src/main.cpp | 8 +- src/map.cpp | 195 +++++++++++++++++++++++++++++++------------------ src/map.h | 1 + 5 files changed, 130 insertions(+), 74 deletions(-) diff --git a/data/grass.png b/data/grass.png index 47d7b11fe953ceb517ac7886d9fe1dba91317eac..bfe80aec2ff2f3a483125366505c1111969162df 100644 GIT binary patch delta 790 zcmV+x1L^$i2I>ZoVSfxC2KfQ6!~g&S>PbXFR5;5e$XjmXQ~-eC-}dp{NgT&<XrLY1 z8EMJ`5=d--6|fLCfyD0M6=^_4GwC&L65Da&9NY2b@WA)@X}|vdqY6eoZfMafjdCY( zY!g{EyuV%2Ha)IpQw{^$^o_CSu#CT9n?CdWkfF~mNA&st!hd2hPVlj~{(6FI3D)bB z=FqWS7v$R`Qg+zBNh+V%A1gEwqDS)?!qh0!7RRu;{`ihccJ!*pFl<(<jQPa`H|RKI zHHUr8IE)CBgi+)n+7fh2N3<tel{2<%R{04fbX?6~HgefyCAu$oe><k{A<Ig(4>eMr z(ciKc_F2iGX@690%ldWCS+!WM&)ciy<~G3!&b)072*ae3XCmLmGa9ZxP7v!&&D3+C zgQtf*<*8>rpI|G8n;+(2_Nd07?|bq?jU}KeY<7o%T;+&G<gtjxygU|Ij=?<i*{ln~ z@WkWlfHqaAp(B~PC<}~Uk=6%puC5p?&?{M!l_kkCVSh9-Y1EPNRHNy8;_(%t3y?+6 zA`F?1ChT@+KK=E?>SaaQ<mkt&qmctmQ!&&a27%B$RI71!cSl|1ER%rbt0njUr1-8z z90&MQ6WbFAp&1CrV`wJ~YL7D#tk)Ic$iko62uG6dYpUvz*@cN8Iw-xOI(HbRi}?Ph znERDvQ-2=0{5E9l`;12}ojRdmu=*rvHAT})qJ>MZpOHmFltj><5T{xaO-zDVU|BFU z8oQ#P>`ENhME7(q<A6qKIF?6V<b1e^QMSRu{T6-m+z?Mk#FGiduH-e{(hX;737!>j z{ceuzTdH%1X_|Cr!6I3*`g@0OD|A&0qUir{bbpx6MpT8t%(Li@iXcch<TjhE=8r$W zAP*h?etuzgVKTp*Vf_5d)o-%t5KfC>m;`}E7+YAjpxQ&HS{wpg*MqjA9vXJp3EeUf zmWFuUp16NLkt{vp#3tQHnzF`nO~#Wcnjv{fH(;22_-@YUFDc>F#j|~OuPOfl`8jmo UXb+WmCjbBd07*qoM6N<$g6l7fj{pDw delta 792 zcmV+z1Lyqe2J8lqVSfN663=K{qyPW{>`6pHR5;5e$V+nLL;!%{UsAWMhb3EzWrrk8 z2$?DfRkNT9)|`P`u;U8sxB^##B@2eC83sF(vEzpnS+-u5+RcJ*`58a``bGzVj}u9h zHaKo;+<~O5Tkan|qiYqOF`zh~*`;ej&*6G<!zTU2a`A$B@qcPaZz&Kqm*JElHg`86 zo-J6dQcgwBc3H6B9I2`v+m~#sC-Os$A;y?-a)FQr<*vsu9qzumrLKB<tuU<t^A9=6 zRfrRG6lu#LZwRA^(R9i%_7L3>4BN!&j&x*%j?H{tp@oT$K!*<Nw8R(+zI+H!3bM2$ zU9?oy3G+EyvVTuYv|&(n9jn!zR(D9xWBpul_mE%*E$j6GVM&_m#Ka%qSuM9;hltg> zCH5S24^N9d$5N3bBL-)O`)?DF3f)>LrO1m0TR@#V?20p)&M|)e?K?e-Lza&Pwj;0& zm+khzD6;S!fsQnsdvt4|ZLpN4R{;SbXB*7AYDkYqrhnH7K`3Y`2x4fJViMdU`yu6C zaXB6{4o2*@9dG|!GGER)oHEQqs%T41(=_M?gpx?pLw5%6-@T*FbFODT)5|M9{+;1_ zFiCv8NaA<`Aq)%Yc+idL&pA#gSS=f(z{ZaTSZ>M7OG{lo5nT!V@epm+RIS34F5=Di z7cBm**?$}l+}w?beV;IJ={aI(lf_>(ouO$|O*C^+=7}ml5zit}C8BI9;<3a}ENmN8 zW3nqUj$O&X6BwS!=ZR0F4IJt7vd?&Zf5CZR@i^aMZk|pgQNUz0V!thUPPg>u6HNua zJ>>3-38m_&PCe2V^sQtzz2fn0%FsDu(g@=C|9@~TO*9$O<bn&&rY|7yXB3&kCT;oS z_XSna^ZuU|(UoBGD#rTZ$D3d3w!?BeOiSVqZN?LcbOcRq(CH4BA+GB|S5co^(yYXk z7Q!|V&)bs4Q$=#^GMNo{*;KTL7Tc8sqX<Kkd`dT9NnU?5;lqcFaqQp?eA4HX{{VvJ WaS_U}$Npdd0000<MNUMnLSTY&nR;9R diff --git a/data/mud.png b/data/mud.png index 8a72bea90aeb27e7741092499c72cae48dd4d264..975065c4bf003ac8810de4bad887e3124659ffb5 100644 GIT binary patch delta 674 zcmV;T0$u(41@;AyV1FD8As5ngluG~r0(MD6K~yNu1;N>J+f)Dm(7Q-?leKzH98U@< zL#ORi`3t^+59SS+frr+qv8SYwC135jE9b!9etk1c=G`wJ+vD+AO0?zrtbW|ErZJ<^ z+x?S>!RhlCqnyY7j)iEQrH^}h`{QppaH2ud;*`bC0_Ro69Df0&A{%5)u--_!o+5<Q zT&?r{_eMEJdI#e$TqKj`hlC1Lkh$~S>Gz4Fpy_tBd#(tQum1E3LSl#J`zm3tRwAQB zXihkw<WRMf>@<T3g9fJCH+Vua=koZOB>{72GDz4(lB~w_@p0#$pSwklETdKFk|N>q z(rSyg1dkDXeSguhfK3hbt@Uvn7d)QhpNn3wL}~Q2vr|9pSA4k&(b9S_JI>-Bt+#Pc z<1`;z02k+S&=hx$?1bRa8ie9}bLPO1g>d!sN$VcmZtp(4X9cLGM+7+8wBMw<R`M!= z9+nH3F;vVuWLfBre<qQL=vcRN{cqch#@rejh2?;Z1%FehSWKo-$$rMx<NLz{n5*@w z=mCiHtP*;x=S+YT2U|jB&zaJ8!ZOS;N23i;Xl97hOF4FaQGTt2>I4@S;o!;w03Ol` zVrXGa^)Y*R3)Br!TT?XV1%>~;MDWU0+ME7s9|=FK)?x<!@h;x%Hh#q8=`Y3;G<0Z0 z;g^eP0)K?_CB<4eBM$vt1RZd);f58@$8zS8p2qgu3;yYCGD9W6xL<nH1+^amN7pN~ zhOymN)%E2pDKsVsG)^Zi(GO`D6^})h9PaP5)0HB*4JnR$r|ZknhFk@vgdlKkm`raV z{`B!aCF-T=13(#86q0{Bl_5E6>p}-8$Pj6LkQ-UeA}2ijA1?B2W0o7z-T(jq07*qo IM6N<$f(^`2!T<mO delta 679 zcmV;Y0$Ba_1^We%V1FA9H8LrUdyW7A0((hBK~yNu1;N{L+C~@v;C~O&?g|}{g#cr_ zjooyn<K&{#=}Yt>`oz8J<R%v_B!t#uzycjtdsMy;{rSgcQ11En5A}ApJ2g-W_rHEx zv8J|C+x6YkEQK%s?yT|?oo+eB%X#|lE~x(gTz4WgFz-pm6Myf(gP98#!bt@yYz!@z zwJygQ#!6pS#oe(np0nPgB%pC7Eqh2qfs1hLpxys9MufKAT6DWJ!}Sq%FF0UsXpUvd zPOiaLN1@%5fYXPnRdsI#PB=0sTRjF6*K^T){fDQ71D2LVZkA<>;jsI0<9EA0&XMEn z?Kow5BI-kHJbzwsJVf~TViN&P1?Jj8lBNYu$M}~;8;MkF{L`(Ky?j{mVnOl3PoR7x zk{&HrX~*KUkTp#4x8rC+(z|diL==}mqkT1v8;%`9<<oD*^iW@(KR)vXoT~{l@J-Xa zH0rIYs|IvmW{?ZKwrlJdbzeTEk(e=gY4v5_)zX=3%YSC{JP>QqNVQ0rl;+wg;wG}% zY>>W`%e)6ji|oYAcvbn#Z$os;0yPP4j2+08-VlMLr8x8olk~sS*!lRltzz3oTv$X| z#VNqU%^4GL_`=*azyEnMSIk@$5}6kvdOgPYEL7Ip;cFL1Ff5m1oZ#JEyuK|bN#wUr zLZo=;h<`-kcJCUBalYVGM_}1~w}~eYzOEz7itV;ie5U2tyu6b4?_&j8fV^LL+tLb+ z5aH?#TPwt7t*Yv9Xc)4V28PT>Q{%^s&hj6Mo8<9+Z6;HxFgKLpr1$3Suys^uV$TSu zbAz<KMda5HtBmQ_dcYIoR5J)ZHzp^wGR{*E93bW>Xo1e1;jxQ6`VOa1Xg=a_m%so3 N002ovPDHLkV1m0@Sk?dl diff --git a/src/main.cpp b/src/main.cpp index 2c9e9cf75..01dd93ffc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -253,7 +253,8 @@ Doing now (most important at the top): * not done === Next -* Somehow generate trees +* Generate trees better + - Add a "trees_added" flag to sector, or something === Fixmes * Check the fixmes in the list above @@ -275,7 +276,6 @@ Doing now (most important at the top): * 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 * Other players could be sent to clients as LuaCAOs @@ -1306,7 +1306,9 @@ void updateMapPlotTexture(v2f centerpos, video::IVideoDriver* driver, 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 + else if(h < WATER_LEVEL + 2 + && get_have_sand(client->getMapSeed(), pf)) + // Sand c.set(255, 237, 201, 175); #if 1 else if(h < WATER_LEVEL + 10) // Green diff --git a/src/map.cpp b/src/map.cpp index bca56a6fe..6ba0f0d1d 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1875,9 +1875,9 @@ void make_tree(VoxelManipulator &vmanip, v3s16 p0) MapNode treenode(CONTENT_TREE); MapNode leavesnode(CONTENT_LEAVES); - vmanip.emerge(VoxelArea(p0-v3s16(2,0,2),p0+v3s16(2,6,2))); + vmanip.emerge(VoxelArea(p0-v3s16(2,0,2),p0+v3s16(2,7+2,2))); - s16 trunk_h = myrand_range(3, 6); + s16 trunk_h = myrand_range(4, 7); v3s16 p1 = p0; for(s16 ii=0; ii<trunk_h; ii++) { @@ -1960,15 +1960,23 @@ double tree_amount_2d(u64 seed, v2s16 p) return 0.04 * (noise-zeroval) / (1.0-zeroval); } -#define AVERAGE_MUD_AMOUNT 4 +#define AVERAGE_MUD_AMOUNT 4.0 double get_mud_amount(u64 seed, v2f p) { - return ((float)AVERAGE_MUD_AMOUNT + 2.5 * noise2d_perlin( + return ((float)AVERAGE_MUD_AMOUNT + 3.0 * noise2d_perlin( 0.5+p.X/200, 0.5+p.Y/200, seed+1, 5, 0.65)); } +bool get_have_sand(u64 seed, v2f p) +{ + double sandnoise = noise2d_perlin( + 0.5+(float)p.X/500, 0.5+(float)p.Y/500, + seed+59420, 3, 0.50); + return (sandnoise > -0.15); +} + // -1->0, 0->1, 1->0 double contour(double v) { @@ -2014,46 +2022,52 @@ double base_rock_level_2d(u64 seed, v2f p) //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 + // Huge mountains + double m3 = 150.0 - 500.0 * noise2d_perlin_abs( + 0.324+(float)p.X/2000., 0.423+(float)p.Y/2000., + (seed>>32)+985251, 9, 0.55); + if(m3 > h) + h = m3; +#endif + +#if 1 + // Some kind of hill chains or something { - 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 a1 = 30 - 130. * noise2d_perlin_abs( + 0.5+(float)p.X/500., 0.5+(float)p.Y/500., + seed+850342, 6, 0.63); double d = 15; if(a1 > d) a1 = d + sqrt(a1-d); - if(a1 > h) - h = a1; + /*if(a1 > h) + h = a1;*/ + if(a1 > 0) + h += a1; } #endif #if 1 - double base = 35. * noise2d_perlin( + double base = -5. + 25. * noise2d_perlin( 0.5+(float)p.X/500., 0.5+(float)p.Y/500., - (seed>>32)+653876, 7, 0.55); + (seed>>32)+653876, 7, 0.6); #else double base = 0; #endif #if 1 - double higher = 50. * noise2d_perlin( + double higher = 40. * noise2d_perlin( 0.5+(float)p.X/250., 0.5+(float)p.Y/250., - seed+39292, 6, 0.63); + seed+39292, 7, 0.55); /*double higher = 50. * noise2d_perlin_abs( 0.5+(float)p.X/250., 0.5+(float)p.Y/250., seed+85039, 5, 0.63);*/ + //higher = 25; if(higher > base) { @@ -2062,24 +2076,43 @@ double base_rock_level_2d(u64 seed, v2f p) 0.5+(float)p.X/250., 0.5+(float)p.Y/250., seed-932, 7, 0.7); b = rangelim(b, 0.0, 1000.0); +#if 1 b = pow(b, 5); - b *= 7; + b *= 16; 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)); + seed-359, 6, 0.70)); +#endif +#if 0 + /*b = pow(b, 5); + b *= 2; + b = rangelim(b, 3.0, 20.0);*/ + //b = 10.0; + double a = -1.5 + 5.0 * (noise2d_perlin_abs( + 0.5+(float)p.X/500., 0.5+(float)p.Y/500., + seed-359, 6, 0.6)); + a *= 3.0; + /*double a = 5.0 * (noise2d_perlin( + 0.5+(float)p.X/250., 0.5+(float)p.Y/250., + seed-359, 5, 0.6));*/ + //a = contour_flat_top(a, 0.2); +#endif // Limit a = rangelim(a, 0.0, 1.0); - //a = easeCurve(a); + a = easeCurve(a); //dstream<<"a="<<a<<std::endl; + + /*double h2 = higher * a; + if(h2 > h) + h = h2;*/ h += base*(1.0-a) + higher*a; } @@ -2101,21 +2134,34 @@ double base_rock_level_2d(u64 seed, v2s16 p) v2f base_ground_turbulence(u64 seed, v3f p) { - double f = 12; +#if 1 + double f = 20; + + double vv = 1.0 - 1.0 * noise3d_perlin_abs( + 0.5+p.X/500, + 0.5+p.Y/500, + 0.5+p.Z/500, + seed+1324031, 4, 0.5); + //double vve = 1.0 - exp(-MYMAX(0, vv*2.0)); + double vve = MYMAX(0, vv); + //dstream<<"vve="<<vve<<std::endl; 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); + seed+4045, 6, 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); + seed+9495, 6, 0.7); - return v2f(v1, v2); + return v2f(v1*vve, v2*vve); +#else + return v2f(0,0); +#endif } bool is_carved(u64 seed, v3f p) @@ -2127,30 +2173,10 @@ bool is_carved(u64 seed, v3f p) 0.5+p.Z/200, seed+657890854, 5, 0.7); - if(v1 > 1.5) + if(v1 > 1.45) 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 v3 = 1.0; -#endif - double v23 = v2*v3; - if(v23 > 0.7) - return true; -#endif - double f = 10.0; double y_div = 1.5; @@ -2173,6 +2199,16 @@ bool is_carved(u64 seed, v3f p) return false; } +bool is_underground_mud(u64 seed, v3f p) +{ + double v1 = noise3d_perlin_abs( + 0.5+p.X/50, + 0.5+p.Y/50, + 0.5+p.Z/50, + seed+83401, 5, 0.75); + return (v1 > 1.3); +} + /* if depth_guess!=NULL, it is set to a guessed value of how deep underground the position is. @@ -2189,6 +2225,16 @@ bool is_base_ground(u64 seed, v3f p, double *depth_guess=NULL) return is_carved(seed, p); } #endif +#if 0 + // This is used for testing the output of the underground mud function + { + if(depth_guess) + *depth_guess = 10; + if(p.Y > 50) + return false; + return is_underground_mud(seed, p); + } +#endif v2f t = base_ground_turbulence(seed, p); @@ -2201,16 +2247,19 @@ bool is_base_ground(u64 seed, v3f p, double *depth_guess=NULL) { // Find highest surface near current v3f dirs[4] = { - v3f(1,-1,0), - v3f(-1,-1,0), - v3f(0,-1,1), - v3f(0,-1,-1) + v3f(1,0,0), + v3f(-1,0,0), + v3f(0,0,1), + v3f(0,0,-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); + // Get turbulence at around there + v2f t2 = base_ground_turbulence(seed, p+dir); + // Get ground height + v2f l = v2f(p.X+t2.X+dir.X, p.Z+t2.Y+dir.Z); double s = base_rock_level_2d(seed, l); if(s > s2) s2 = s; @@ -2239,9 +2288,11 @@ bool is_base_ground(u64 seed, v3f p, double *depth_guess=NULL) }*/ bool is_ground = (p.Y <= surface_y_f); - + +#if 1 if(is_carved(seed, p)) is_ground = false; +#endif return is_ground; } @@ -3357,11 +3408,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos, v2s16 p2d = sectorpos_base*MAP_BLOCKSIZE + v2s16(x,z); // Determine whether to have sand here - double sandnoise = noise2d_perlin( - 0.5+(float)p2d.X/500, 0.5+(float)p2d.Y/500, - m_seed+59420, 3, 0.50); - - bool have_sand = (sandnoise > -0.15); + bool have_sand = get_have_sand(p2d); if(have_sand == false) continue; @@ -4134,9 +4181,7 @@ MapBlock * ServerMap::generateBlock( { //dstream<<"BT_GROUND"<<std::endl; // A ground block - //block_type = BT_GROUND; - // Handled as surface because of caves - block_type = BT_SURFACE; + block_type = BT_GROUND; } else if(block_low_y_f >= surface_y_max + d_up && block_low_y_f > WATER_LEVEL + d_up) @@ -4152,14 +4197,14 @@ MapBlock * ServerMap::generateBlock( block_type = BT_SURFACE; } - if(block_type == BT_GROUND || block_type == BT_SKY) + 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) + if(block_type == BT_SURFACE || block_type == BT_GROUND) { /* Generate ground precisely @@ -4204,9 +4249,11 @@ MapBlock * ServerMap::generateBlock( Calculate material */ + v3f real_pos_f = intToFloat(real_pos, 1); + v2f real_pos_f_2d(real_pos_f.X, real_pos_f.Z); double depth_guess; bool is_ground = is_base_ground(m_seed, - intToFloat(real_pos, 1), &depth_guess); + real_pos_f, &depth_guess); // Estimate the surface height float surface_y_f = (float)real_y + depth_guess; @@ -4243,9 +4290,13 @@ MapBlock * ServerMap::generateBlock( // If it's surface_depth under ground, it's stone if((float)real_y <= surface_y_f - surface_depth - 0.75) { - n.d = CONTENT_STONE; + if(is_underground_mud(m_seed, real_pos_f)) + n.d = CONTENT_MUD; + else + n.d = CONTENT_STONE; } - else if(surface_y_f <= WATER_LEVEL + 2.0) + else if(surface_y_f <= WATER_LEVEL + 2.1 + && get_have_sand(m_seed, real_pos_f_2d)) { n.d = CONTENT_SAND; } @@ -4357,7 +4408,7 @@ MapBlock * ServerMap::generateBlock( MapNode n_fill; if(block_type == BT_GROUND) { - n_fill.d = CONTENT_STONE; + //n_fill.d = CONTENT_STONE; } else if(block_type == BT_SKY) { @@ -4838,13 +4889,14 @@ MapBlock * ServerMap::generateBlock( /* Add trees */ +#if 1 if(some_part_underground && !completely_underground) { MapVoxelManipulator vm(this); double a = tree_amount_2d(m_seed, v2s16(p_nodes.X+8, p_nodes.Z+8)); u16 tree_count = (u16)(a*MAP_BLOCKSIZE*MAP_BLOCKSIZE); - for(u16 i=0; i<tree_count; i++) + for(u16 i=0; i<tree_count/2; i++) { v3s16 tree_p = p_nodes + v3s16( myrand_range(0,MAP_BLOCKSIZE-1), @@ -4854,7 +4906,7 @@ MapBlock * ServerMap::generateBlock( double depth_guess; /*bool is_ground =*/ is_base_ground(m_seed, intToFloat(tree_p, 1), &depth_guess); - tree_p.Y += depth_guess; + tree_p.Y += (depth_guess - 0.5); if(tree_p.Y <= WATER_LEVEL) continue; make_tree(vm, tree_p); @@ -4862,6 +4914,7 @@ MapBlock * ServerMap::generateBlock( vm.blitBack(changed_blocks); } +#endif #if 0 /* diff --git a/src/map.h b/src/map.h index 0692f2b23..62df56461 100644 --- a/src/map.h +++ b/src/map.h @@ -45,6 +45,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ double base_rock_level_2d(u64 seed, v2f p); +bool get_have_sand(u64 seed, v2f p); /* */ -- GitLab