added sand to map generator
parent
6545ea12e9
commit
7f2aa30bf2
BIN
data/sand.png
BIN
data/sand.png
Binary file not shown.
Before Width: | Height: | Size: 659 B After Width: | Height: | Size: 1.3 KiB |
BIN
data/water.png
BIN
data/water.png
Binary file not shown.
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
@ -39,6 +39,7 @@ configure_file(
|
||||||
)
|
)
|
||||||
|
|
||||||
set(common_SRCS
|
set(common_SRCS
|
||||||
|
noise.cpp
|
||||||
mineral.cpp
|
mineral.cpp
|
||||||
porting.cpp
|
porting.cpp
|
||||||
materials.cpp
|
materials.cpp
|
||||||
|
|
|
@ -32,5 +32,7 @@ typedef core::vector2d<s32> v2s32;
|
||||||
typedef core::vector2d<u32> v2u32;
|
typedef core::vector2d<u32> v2u32;
|
||||||
typedef core::vector2d<f32> v2f32;
|
typedef core::vector2d<f32> v2f32;
|
||||||
|
|
||||||
|
typedef unsigned long long u64;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
42
src/main.cpp
42
src/main.cpp
|
@ -315,43 +315,45 @@ FEATURE: The map could be generated procedually:
|
||||||
- Simulate rock falling from cliffs when water has removed
|
- Simulate rock falling from cliffs when water has removed
|
||||||
enough solid rock from the bottom
|
enough solid rock from the bottom
|
||||||
|
|
||||||
Doing now:
|
Doing now (most important at the top):
|
||||||
----------
|
--------------------------------------
|
||||||
# maybe done
|
# maybe done
|
||||||
* not done
|
* not done
|
||||||
|
|
||||||
|
* Perlin noise stuff sucks in heightmap generation, fix it
|
||||||
|
* Create perlin noise functions and use them to get natural randomness
|
||||||
|
in everything. No need for attributes or fractal terrain.
|
||||||
|
* Do something about AttributeDatabase/List being too slow
|
||||||
|
- Remove it
|
||||||
|
* Save chunk metadata on disk
|
||||||
* Remove all kinds of systems that are made redundant by the new map
|
* Remove all kinds of systems that are made redundant by the new map
|
||||||
generator
|
generator
|
||||||
- Sector heightmaps? At least they should be made redundant.
|
- Sector heightmaps? At least they should be made redundant.
|
||||||
- Sector objects
|
- Sector objects
|
||||||
* Do something about AttributeDatabase/List being too slow
|
* Fix the strange mineral occurences
|
||||||
* Save chunk metadata on disk
|
- Do they appear anymore?
|
||||||
* Change water side textures so that buggy water doesn't look bad
|
|
||||||
* Make server find the spawning place from the real map data, not from
|
* Make server find the spawning place from the real map data, not from
|
||||||
the heightmap
|
the heightmap
|
||||||
* only_from_disk doesn't work that well anymore
|
- But the changing borders of chunk have to be avoided, because
|
||||||
|
there is time to generate only one chunk.
|
||||||
|
* only_from_disk might not work anymore - check and fix it.
|
||||||
* Make the generator to run in background and not blocking block
|
* Make the generator to run in background and not blocking block
|
||||||
placement and transfer
|
placement and transfer
|
||||||
* Fix the strange mineral occurences
|
|
||||||
* When the map is generated and a place is found for the player, the
|
|
||||||
first chunk is actually still volatile and will have stuff still
|
|
||||||
changed after spawning, which creates a lot of glitches.
|
|
||||||
- This is partly fixed by now allowing only 2-sector deeep
|
|
||||||
modification of volatile chunks. But it should still be fixed?
|
|
||||||
- How about checking that the neighbors are fully generated too and
|
|
||||||
generate them when the middle piece is needed
|
|
||||||
- This is very slow
|
|
||||||
- How about just enabling changed_blocks properly
|
|
||||||
- This is probably a good idea
|
|
||||||
- The server has to make sure the spawn point is not at the
|
|
||||||
changing borders of a chunk
|
|
||||||
* Add some kind of erosion and other stuff that now is possible
|
* Add some kind of erosion and other stuff that now is possible
|
||||||
* Make client to fetch stuff asynchronously
|
* Make client to fetch stuff asynchronously
|
||||||
- Needs method SyncProcessData
|
- Needs method SyncProcessData
|
||||||
* What is the problem with the server constantly saving one or a few
|
* What is the problem with the server constantly saving one or a few
|
||||||
blocks? List the first saved block, maybe it explains.
|
blocks? List the first saved block, maybe it explains.
|
||||||
|
- Does it still do this?
|
||||||
* Water doesn't start flowing after map generation like it should
|
* Water doesn't start flowing after map generation like it should
|
||||||
* Better water generation
|
- Are there still problems?
|
||||||
|
* Better water generation (spread it to underwater caverns)
|
||||||
|
* When generating a chunk and the neighboring chunk doesn't have mud
|
||||||
|
and stuff yet and the ground is fairly flat, the mud will flow to
|
||||||
|
the other chunk making nasty straight walls when the other chunk
|
||||||
|
is generated. Fix it.
|
||||||
|
* Save map seed to a metafile (with version information)
|
||||||
|
- Remove master heightmap
|
||||||
|
|
||||||
======================================================================
|
======================================================================
|
||||||
|
|
||||||
|
|
358
src/map.cpp
358
src/map.cpp
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
#include "voxel.h"
|
#include "voxel.h"
|
||||||
#include "porting.h"
|
#include "porting.h"
|
||||||
#include "mineral.h"
|
#include "mineral.h"
|
||||||
|
#include "noise.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Map
|
Map
|
||||||
|
@ -1731,7 +1732,8 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
||||||
|
|
||||||
ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp):
|
ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp):
|
||||||
Map(dout_server),
|
Map(dout_server),
|
||||||
m_heightmap(NULL)
|
m_heightmap(NULL),
|
||||||
|
m_seed(0)
|
||||||
{
|
{
|
||||||
|
|
||||||
//m_chunksize = 64;
|
//m_chunksize = 64;
|
||||||
|
@ -1740,6 +1742,12 @@ ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp):
|
||||||
//m_chunksize = 4;
|
//m_chunksize = 4;
|
||||||
//m_chunksize = 2;
|
//m_chunksize = 2;
|
||||||
|
|
||||||
|
// TODO: Save to and load from a file
|
||||||
|
m_seed = (((u64)myrand()<<0)%0x7fff)
|
||||||
|
+ (((u64)myrand()<<16)%0x7fff)
|
||||||
|
+ (((u64)myrand()<<32)%0x7fff)
|
||||||
|
+ (((u64)myrand()<<48)%0x7fff);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Experimental and debug stuff
|
Experimental and debug stuff
|
||||||
*/
|
*/
|
||||||
|
@ -1979,6 +1987,8 @@ ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp):
|
||||||
dstream<<DTIME<<"Initializing new map."<<std::endl;
|
dstream<<DTIME<<"Initializing new map."<<std::endl;
|
||||||
|
|
||||||
// Create master heightmap
|
// Create master heightmap
|
||||||
|
// NOTE: Yes, that is a magic number down there. It specifies
|
||||||
|
// the size of the internal FixedHeightmaps.
|
||||||
m_heightmap = new UnlimitedHeightmap
|
m_heightmap = new UnlimitedHeightmap
|
||||||
(32, &m_padb);
|
(32, &m_padb);
|
||||||
|
|
||||||
|
@ -2029,7 +2039,7 @@ ServerMap::~ServerMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Some helper functions
|
Some helper functions for the map generator
|
||||||
*/
|
*/
|
||||||
|
|
||||||
s16 find_ground_level(VoxelManipulator &vmanip, v2s16 p2d)
|
s16 find_ground_level(VoxelManipulator &vmanip, v2s16 p2d)
|
||||||
|
@ -2053,6 +2063,29 @@ s16 find_ground_level(VoxelManipulator &vmanip, v2s16 p2d)
|
||||||
return y_nodes_min;
|
return y_nodes_min;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
s16 find_ground_level_clever(VoxelManipulator &vmanip, v2s16 p2d)
|
||||||
|
{
|
||||||
|
v3s16 em = vmanip.m_area.getExtent();
|
||||||
|
s16 y_nodes_max = vmanip.m_area.MaxEdge.Y;
|
||||||
|
s16 y_nodes_min = vmanip.m_area.MinEdge.Y;
|
||||||
|
u32 i = vmanip.m_area.index(v3s16(p2d.X, y_nodes_max, p2d.Y));
|
||||||
|
s16 y;
|
||||||
|
for(y=y_nodes_max; y>=y_nodes_min; y--)
|
||||||
|
{
|
||||||
|
MapNode &n = vmanip.m_data[i];
|
||||||
|
if(content_walkable(n.d)
|
||||||
|
&& n.d != CONTENT_TREE
|
||||||
|
&& n.d != CONTENT_LEAVES)
|
||||||
|
break;
|
||||||
|
|
||||||
|
vmanip.m_area.add_y(em, i, -1);
|
||||||
|
}
|
||||||
|
if(y >= y_nodes_min)
|
||||||
|
return y;
|
||||||
|
else
|
||||||
|
return y_nodes_min;
|
||||||
|
}
|
||||||
|
|
||||||
void make_tree(VoxelManipulator &vmanip, v3s16 p0)
|
void make_tree(VoxelManipulator &vmanip, v3s16 p0)
|
||||||
{
|
{
|
||||||
MapNode treenode(CONTENT_TREE);
|
MapNode treenode(CONTENT_TREE);
|
||||||
|
@ -2123,6 +2156,49 @@ void make_tree(VoxelManipulator &vmanip, v3s16 p0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Noise functions. Make sure seed is mangled differently in each one.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Amount of trees per area in nodes
|
||||||
|
double tree_amount_2d(u64 seed, v2s16 p)
|
||||||
|
{
|
||||||
|
double noise = noise2d_perlin(
|
||||||
|
0.5+(float)p.X/500, 0.5+(float)p.Y/500,
|
||||||
|
seed+2, 4, 0.55);
|
||||||
|
double zeroval = -0.3;
|
||||||
|
if(noise < zeroval)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return 0.05 * (noise-zeroval) / (0.5-zeroval);
|
||||||
|
}
|
||||||
|
|
||||||
|
double base_rock_level_2d(u64 seed, v2s16 p)
|
||||||
|
{
|
||||||
|
return -4. + 25. * noise2d_perlin(
|
||||||
|
0.5+(float)p.X/500., 0.5+(float)p.Y/500.,
|
||||||
|
seed, 6, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
double highlands_level_2d(u64 seed, v2s16 p)
|
||||||
|
{
|
||||||
|
double a = noise2d_perlin(
|
||||||
|
0.5+(float)p.X/1000., 0.5+(float)p.Y/1000.,
|
||||||
|
seed-359, 6, 0.55);
|
||||||
|
if(a > 0.2)
|
||||||
|
{
|
||||||
|
return 35. + 10. * noise2d_perlin(
|
||||||
|
0.5+(float)p.X/500., 0.5+(float)p.Y/500.,
|
||||||
|
seed+85039, 6, 0.55);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return -100000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This is the main map generation method
|
||||||
|
*/
|
||||||
|
|
||||||
MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
core::map<v3s16, MapBlock*> &changed_blocks)
|
core::map<v3s16, MapBlock*> &changed_blocks)
|
||||||
{
|
{
|
||||||
|
@ -2185,8 +2261,8 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Relative values to control amount of stuff in one chunk
|
// Relative values to control amount of stuff in one chunk
|
||||||
u32 relative_area = (u32)sectorpos_base_size*MAP_BLOCKSIZE
|
/*u32 relative_area = (u32)sectorpos_base_size*MAP_BLOCKSIZE
|
||||||
*(u32)sectorpos_base_size*MAP_BLOCKSIZE;
|
*(u32)sectorpos_base_size*MAP_BLOCKSIZE;*/
|
||||||
u32 relative_volume = (u32)sectorpos_base_size*MAP_BLOCKSIZE
|
u32 relative_volume = (u32)sectorpos_base_size*MAP_BLOCKSIZE
|
||||||
*(u32)sectorpos_base_size*MAP_BLOCKSIZE
|
*(u32)sectorpos_base_size*MAP_BLOCKSIZE
|
||||||
*(u32)h_blocks*MAP_BLOCKSIZE;
|
*(u32)h_blocks*MAP_BLOCKSIZE;
|
||||||
|
@ -2234,12 +2310,6 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Clear all light emitted
|
|
||||||
*/
|
|
||||||
|
|
||||||
core::map<v3s16, u8> unlight_from;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Now we have a big empty area.
|
Now we have a big empty area.
|
||||||
|
|
||||||
|
@ -2281,22 +2351,17 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
|
|
||||||
// Ground height at this point
|
// Ground height at this point
|
||||||
float surface_y_f = 0.0;
|
float surface_y_f = 0.0;
|
||||||
/*
|
|
||||||
A hack to get the ground height from the sector.
|
// Use perlin noise for ground height
|
||||||
Do this better.
|
surface_y_f = base_rock_level_2d(m_seed, p2d);
|
||||||
*/
|
|
||||||
|
// Experimental stuff
|
||||||
{
|
{
|
||||||
v2s16 sectorpos = getContainerPos(p2d, MAP_BLOCKSIZE);
|
float a = highlands_level_2d(m_seed, p2d);
|
||||||
v2s16 sector_relpos = p2d - sectorpos*MAP_BLOCKSIZE;
|
if(a > surface_y_f)
|
||||||
MapSector *sector = getSectorNoGenerate(sectorpos);
|
surface_y_f = a;
|
||||||
assert(sector);
|
|
||||||
float h = sector->getGroundHeight(sector_relpos);
|
|
||||||
if(h > GROUNDHEIGHT_VALID_MINVALUE)
|
|
||||||
surface_y_f = h;
|
|
||||||
else
|
|
||||||
dstream<<"WARNING: "<<__FUNCTION_NAME
|
|
||||||
<<": sector->getGroundHeight returned bad height"<<std::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert to integer
|
// Convert to integer
|
||||||
s16 surface_y = (s16)surface_y_f;
|
s16 surface_y = (s16)surface_y_f;
|
||||||
|
|
||||||
|
@ -2327,6 +2392,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
stone_obstacle_amount = myrand_range(0, myrand_range(20, 150));
|
stone_obstacle_amount = myrand_range(0, myrand_range(20, 150));
|
||||||
else
|
else
|
||||||
stone_obstacle_amount = myrand_range(0, myrand_range(20, 50));
|
stone_obstacle_amount = myrand_range(0, myrand_range(20, 50));
|
||||||
|
|
||||||
//u32 stone_obstacle_amount =
|
//u32 stone_obstacle_amount =
|
||||||
// myrand_range(0, myrand_range(20, myrand_range(80,150)));
|
// myrand_range(0, myrand_range(20, myrand_range(80,150)));
|
||||||
|
|
||||||
|
@ -2364,6 +2430,11 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
myrand_range(0, maxheight_randomized),
|
myrand_range(0, maxheight_randomized),
|
||||||
myrand_range(5, stone_obstacle_max_size)
|
myrand_range(5, stone_obstacle_max_size)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Don't make stupid small rectable bumps
|
||||||
|
if(ob_size.Y < 5)
|
||||||
|
continue;
|
||||||
|
|
||||||
/*v2s16 ob_place(
|
/*v2s16 ob_place(
|
||||||
myrand_range(0, sectorpos_base_size*MAP_BLOCKSIZE-1),
|
myrand_range(0, sectorpos_base_size*MAP_BLOCKSIZE-1),
|
||||||
myrand_range(0, sectorpos_base_size*MAP_BLOCKSIZE-1)
|
myrand_range(0, sectorpos_base_size*MAP_BLOCKSIZE-1)
|
||||||
|
@ -2477,11 +2548,13 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
/*
|
/*
|
||||||
Make dungeons
|
Make dungeons
|
||||||
*/
|
*/
|
||||||
u32 dungeons_count = relative_volume / 200000;
|
u32 dungeons_count = relative_volume / 400000;
|
||||||
u32 bruises_count = relative_volume * stone_surface_max_y / 200000 / 50;
|
u32 bruises_count = relative_volume * stone_surface_max_y / 200000 / 50;
|
||||||
|
/*u32 dungeons_count = 0;
|
||||||
|
u32 bruises_count = 0;*/
|
||||||
for(u32 jj=0; jj<dungeons_count+bruises_count; jj++)
|
for(u32 jj=0; jj<dungeons_count+bruises_count; jj++)
|
||||||
{
|
{
|
||||||
s16 min_tunnel_diameter = 3;
|
s16 min_tunnel_diameter = 2;
|
||||||
s16 max_tunnel_diameter = 6;
|
s16 max_tunnel_diameter = 6;
|
||||||
u16 tunnel_routepoints = 15;
|
u16 tunnel_routepoints = 15;
|
||||||
|
|
||||||
|
@ -2519,6 +2592,11 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
s16 route_y_min = 0;
|
s16 route_y_min = 0;
|
||||||
//s16 route_y_max = ar.Y-1;
|
//s16 route_y_max = ar.Y-1;
|
||||||
s16 route_y_max = -of.Y + stone_surface_max_y + max_tunnel_diameter/2;
|
s16 route_y_max = -of.Y + stone_surface_max_y + max_tunnel_diameter/2;
|
||||||
|
if(bruise_surface == false)
|
||||||
|
{
|
||||||
|
// Don't go through surface too often
|
||||||
|
route_y_max -= myrand_range(0, max_tunnel_diameter);
|
||||||
|
}
|
||||||
route_y_max = rangelim(route_y_max, 0, ar.Y-1);
|
route_y_max = rangelim(route_y_max, 0, ar.Y-1);
|
||||||
|
|
||||||
if(bruise_surface)
|
if(bruise_surface)
|
||||||
|
@ -2773,7 +2851,8 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
Add mud to the central chunk
|
Add mud to the central chunk
|
||||||
*/
|
*/
|
||||||
|
|
||||||
s16 mud_add_amount = myrand_range(1, 5);
|
//s16 mud_add_amount = myrand_range(2, 4);
|
||||||
|
//s16 mud_add_amount = 0;
|
||||||
|
|
||||||
for(s16 x=0; x<sectorpos_base_size*MAP_BLOCKSIZE; x++)
|
for(s16 x=0; x<sectorpos_base_size*MAP_BLOCKSIZE; x++)
|
||||||
for(s16 z=0; z<sectorpos_base_size*MAP_BLOCKSIZE; z++)
|
for(s16 z=0; z<sectorpos_base_size*MAP_BLOCKSIZE; z++)
|
||||||
|
@ -2781,6 +2860,11 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
// Node position in 2d
|
// Node position in 2d
|
||||||
v2s16 p2d = sectorpos_base*MAP_BLOCKSIZE + v2s16(x,z);
|
v2s16 p2d = sectorpos_base*MAP_BLOCKSIZE + v2s16(x,z);
|
||||||
|
|
||||||
|
// Randomize mud amount
|
||||||
|
s16 mud_add_amount = (s16)(3.5 + 2. * noise2d_perlin(
|
||||||
|
0.5+(float)p2d.X/200, 0.5+(float)p2d.Y/200,
|
||||||
|
m_seed+1, 3, 0.55));
|
||||||
|
|
||||||
// Find ground level
|
// Find ground level
|
||||||
s16 surface_y = find_ground_level(vmanip, p2d);
|
s16 surface_y = find_ground_level(vmanip, p2d);
|
||||||
|
|
||||||
|
@ -2806,11 +2890,12 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
u32 i = vmanip.m_area.index(v3s16(p2d.X, y_start, p2d.Y));
|
u32 i = vmanip.m_area.index(v3s16(p2d.X, y_start, p2d.Y));
|
||||||
for(s16 y=y_start; y<=y_nodes_max; y++)
|
for(s16 y=y_start; y<=y_nodes_max; y++)
|
||||||
{
|
{
|
||||||
|
if(mudcount >= mud_add_amount)
|
||||||
|
break;
|
||||||
|
|
||||||
MapNode &n = vmanip.m_data[i];
|
MapNode &n = vmanip.m_data[i];
|
||||||
n.d = CONTENT_MUD;
|
n.d = CONTENT_MUD;
|
||||||
mudcount++;
|
mudcount++;
|
||||||
if(mudcount >= mud_add_amount)
|
|
||||||
break;
|
|
||||||
|
|
||||||
vmanip.m_area.add_y(em, i, 1);
|
vmanip.m_area.add_y(em, i, 1);
|
||||||
}
|
}
|
||||||
|
@ -2828,7 +2913,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Iterate a few times
|
// Iterate a few times
|
||||||
for(s16 k=0; k<4; k++)
|
for(s16 k=0; k<3; k++)
|
||||||
{
|
{
|
||||||
|
|
||||||
/*for(s16 x=0-max_spread_amount+1;
|
/*for(s16 x=0-max_spread_amount+1;
|
||||||
|
@ -2865,7 +2950,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
u32 i = vmanip.m_area.index(v3s16(p2d.X, y_nodes_max, p2d.Y));
|
u32 i = vmanip.m_area.index(v3s16(p2d.X, y_nodes_max, p2d.Y));
|
||||||
s16 y=y_nodes_max;
|
s16 y=y_nodes_max;
|
||||||
|
|
||||||
for(;;)
|
for(;; y--)
|
||||||
{
|
{
|
||||||
MapNode *n = NULL;
|
MapNode *n = NULL;
|
||||||
// Find mud
|
// Find mud
|
||||||
|
@ -2890,6 +2975,20 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
if(n->d != CONTENT_MUD && n->d != CONTENT_GRASS)
|
if(n->d != CONTENT_MUD && n->d != CONTENT_GRASS)
|
||||||
continue;*/
|
continue;*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Don't flow it if the stuff under it is not mud
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
u32 i2 = i;
|
||||||
|
vmanip.m_area.add_y(em, i2, -1);
|
||||||
|
// Cancel if out of area
|
||||||
|
if(vmanip.m_area.contains(i2) == false)
|
||||||
|
continue;
|
||||||
|
MapNode *n2 = &vmanip.m_data[i2];
|
||||||
|
if(n2->d != CONTENT_MUD && n2->d != CONTENT_GRASS)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Make it exactly mud
|
// Make it exactly mud
|
||||||
n->d = CONTENT_MUD;
|
n->d = CONTENT_MUD;
|
||||||
|
|
||||||
|
@ -2904,61 +3003,58 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Theck that upper is air or doesn't exist.
|
// Theck that upper is air or doesn't exist.
|
||||||
// Only drop mud if upper doesn't contain anything that
|
// Cancel dropping if upper keeps it in place
|
||||||
// would keep the mud in place.
|
|
||||||
u32 i3 = i;
|
u32 i3 = i;
|
||||||
vmanip.m_area.add_y(em, i3, 1);
|
vmanip.m_area.add_y(em, i3, 1);
|
||||||
if(vmanip.m_area.contains(i3) == false
|
if(vmanip.m_area.contains(i3) == true
|
||||||
|| content_walkable(vmanip.m_data[i3].d) == false)
|
&& content_walkable(vmanip.m_data[i3].d) == true)
|
||||||
{
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Drop mud on side
|
// Drop mud on side
|
||||||
|
|
||||||
for(u32 di=0; di<4; di++)
|
for(u32 di=0; di<4; di++)
|
||||||
{
|
{
|
||||||
v3s16 dirp = dirs4[di];
|
v3s16 dirp = dirs4[di];
|
||||||
u32 i2 = i;
|
u32 i2 = i;
|
||||||
// Move to side
|
// Move to side
|
||||||
vmanip.m_area.add_p(em, i2, dirp);
|
vmanip.m_area.add_p(em, i2, dirp);
|
||||||
// Fail if out of area
|
// Fail if out of area
|
||||||
if(vmanip.m_area.contains(i2) == false)
|
if(vmanip.m_area.contains(i2) == false)
|
||||||
continue;
|
continue;
|
||||||
// Check that side is air
|
// Check that side is air
|
||||||
MapNode *n2 = &vmanip.m_data[i2];
|
MapNode *n2 = &vmanip.m_data[i2];
|
||||||
if(content_walkable(n2->d))
|
if(content_walkable(n2->d))
|
||||||
continue;
|
continue;
|
||||||
// Check that under side is air
|
// Check that under side is air
|
||||||
|
vmanip.m_area.add_y(em, i2, -1);
|
||||||
|
// Fail if out of area
|
||||||
|
if(vmanip.m_area.contains(i2) == false)
|
||||||
|
continue;
|
||||||
|
n2 = &vmanip.m_data[i2];
|
||||||
|
if(content_walkable(n2->d))
|
||||||
|
continue;
|
||||||
|
// Loop further down until not air
|
||||||
|
do{
|
||||||
vmanip.m_area.add_y(em, i2, -1);
|
vmanip.m_area.add_y(em, i2, -1);
|
||||||
// Fail if out of area
|
// Fail if out of area
|
||||||
if(vmanip.m_area.contains(i2) == false)
|
if(vmanip.m_area.contains(i2) == false)
|
||||||
continue;
|
continue;
|
||||||
n2 = &vmanip.m_data[i2];
|
n2 = &vmanip.m_data[i2];
|
||||||
if(content_walkable(n2->d))
|
}while(content_walkable(n2->d) == false);
|
||||||
continue;
|
// Loop one up so that we're in air
|
||||||
// Loop further down until not air
|
vmanip.m_area.add_y(em, i2, 1);
|
||||||
do{
|
n2 = &vmanip.m_data[i2];
|
||||||
vmanip.m_area.add_y(em, i2, -1);
|
|
||||||
// Fail if out of area
|
|
||||||
if(vmanip.m_area.contains(i2) == false)
|
|
||||||
continue;
|
|
||||||
n2 = &vmanip.m_data[i2];
|
|
||||||
}while(content_walkable(n2->d) == false);
|
|
||||||
// Loop one up so that we're in air
|
|
||||||
vmanip.m_area.add_y(em, i2, 1);
|
|
||||||
n2 = &vmanip.m_data[i2];
|
|
||||||
|
|
||||||
// Move mud to new place
|
// Move mud to new place
|
||||||
*n2 = *n;
|
*n2 = *n;
|
||||||
// Set old place to be air
|
// Set old place to be air
|
||||||
*n = MapNode(CONTENT_AIR);
|
*n = MapNode(CONTENT_AIR);
|
||||||
|
|
||||||
// Done
|
// Done
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Continue from next y
|
|
||||||
y--;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3054,6 +3150,67 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
|
|
||||||
} // Aging loop
|
} // Aging loop
|
||||||
|
|
||||||
|
{//TimeTaker timer1("convert mud to sand");
|
||||||
|
|
||||||
|
/*
|
||||||
|
Convert mud to sand
|
||||||
|
*/
|
||||||
|
|
||||||
|
//s16 mud_add_amount = myrand_range(2, 4);
|
||||||
|
//s16 mud_add_amount = 0;
|
||||||
|
|
||||||
|
/*for(s16 x=0; x<sectorpos_base_size*MAP_BLOCKSIZE; x++)
|
||||||
|
for(s16 z=0; z<sectorpos_base_size*MAP_BLOCKSIZE; z++)*/
|
||||||
|
for(s16 x=0-max_spread_amount+1;
|
||||||
|
x<sectorpos_base_size*MAP_BLOCKSIZE+max_spread_amount-1;
|
||||||
|
x++)
|
||||||
|
for(s16 z=0-max_spread_amount+1;
|
||||||
|
z<sectorpos_base_size*MAP_BLOCKSIZE+max_spread_amount-1;
|
||||||
|
z++)
|
||||||
|
{
|
||||||
|
// Node position in 2d
|
||||||
|
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.0);
|
||||||
|
|
||||||
|
if(have_sand == false)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Find ground level
|
||||||
|
s16 surface_y = find_ground_level_clever(vmanip, p2d);
|
||||||
|
|
||||||
|
if(surface_y > WATER_LEVEL + 2)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
{
|
||||||
|
v3s16 em = vmanip.m_area.getExtent();
|
||||||
|
s16 y_start = surface_y;
|
||||||
|
u32 i = vmanip.m_area.index(v3s16(p2d.X, y_start, p2d.Y));
|
||||||
|
u32 not_sand_counter = 0;
|
||||||
|
for(s16 y=y_start; y>=y_nodes_min; y--)
|
||||||
|
{
|
||||||
|
MapNode *n = &vmanip.m_data[i];
|
||||||
|
if(n->d == CONTENT_MUD || n->d == CONTENT_GRASS)
|
||||||
|
n->d = CONTENT_SAND;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
not_sand_counter++;
|
||||||
|
if(not_sand_counter > 3)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
vmanip.m_area.add_y(em, i, -1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}//timer1
|
||||||
{
|
{
|
||||||
// 1ms @cs=8
|
// 1ms @cs=8
|
||||||
//TimeTaker timer1("plant trees");
|
//TimeTaker timer1("plant trees");
|
||||||
|
@ -3062,9 +3219,56 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
Plant some trees
|
Plant some trees
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
u32 tree_max = relative_area / 60;
|
// Divide area into parts
|
||||||
|
s16 div = 8;
|
||||||
u32 count = myrand_range(0, tree_max);
|
s16 sidelen = sectorpos_base_size*MAP_BLOCKSIZE / div;
|
||||||
|
double area = sidelen * sidelen;
|
||||||
|
for(s16 x0=0; x0<div; x0++)
|
||||||
|
for(s16 z0=0; z0<div; z0++)
|
||||||
|
{
|
||||||
|
// Center position of part of division
|
||||||
|
v2s16 p2d_center(
|
||||||
|
sectorpos_base.X*MAP_BLOCKSIZE + sidelen/2 + sidelen*x0,
|
||||||
|
sectorpos_base.Y*MAP_BLOCKSIZE + sidelen/2 + sidelen*z0
|
||||||
|
);
|
||||||
|
// Minimum edge of part of division
|
||||||
|
v2s16 p2d_min(
|
||||||
|
sectorpos_base.X*MAP_BLOCKSIZE + sidelen*x0,
|
||||||
|
sectorpos_base.Y*MAP_BLOCKSIZE + sidelen*z0
|
||||||
|
);
|
||||||
|
// Maximum edge of part of division
|
||||||
|
v2s16 p2d_max(
|
||||||
|
sectorpos_base.X*MAP_BLOCKSIZE + sidelen + sidelen*x0 - 1,
|
||||||
|
sectorpos_base.Y*MAP_BLOCKSIZE + sidelen + sidelen*z0 - 1
|
||||||
|
);
|
||||||
|
// Amount of trees
|
||||||
|
u32 tree_count = area * tree_amount_2d(m_seed, p2d_center);
|
||||||
|
// Put trees in random places on part of division
|
||||||
|
for(u32 i=0; i<tree_count; i++)
|
||||||
|
{
|
||||||
|
s16 x = myrand_range(p2d_min.X, p2d_max.X);
|
||||||
|
s16 z = myrand_range(p2d_min.Y, p2d_max.Y);
|
||||||
|
s16 y = find_ground_level(vmanip, v2s16(x,z));
|
||||||
|
// Don't make a tree under water level
|
||||||
|
if(y < WATER_LEVEL)
|
||||||
|
continue;
|
||||||
|
v3s16 p(x,y,z);
|
||||||
|
/*
|
||||||
|
Trees grow only on mud and grass
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
u32 i = vmanip.m_area.index(v3s16(p));
|
||||||
|
MapNode *n = &vmanip.m_data[i];
|
||||||
|
if(n->d != CONTENT_MUD && n->d != CONTENT_GRASS)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
p.Y++;
|
||||||
|
// Make a tree
|
||||||
|
make_tree(vmanip, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*u32 tree_max = relative_area / 60;
|
||||||
|
//u32 count = myrand_range(0, tree_max);
|
||||||
for(u32 i=0; i<count; i++)
|
for(u32 i=0; i<count; i++)
|
||||||
{
|
{
|
||||||
s16 x = myrand_range(0, sectorpos_base_size*MAP_BLOCKSIZE-1);
|
s16 x = myrand_range(0, sectorpos_base_size*MAP_BLOCKSIZE-1);
|
||||||
|
@ -3078,7 +3282,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos,
|
||||||
v3s16 p(x,y+1,z);
|
v3s16 p(x,y+1,z);
|
||||||
// Make a tree
|
// Make a tree
|
||||||
make_tree(vmanip, p);
|
make_tree(vmanip, p);
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
}//timer1
|
}//timer1
|
||||||
|
|
|
@ -538,6 +538,9 @@ private:
|
||||||
MapParams m_params;
|
MapParams m_params;
|
||||||
PointAttributeDatabase m_padb;
|
PointAttributeDatabase m_padb;
|
||||||
|
|
||||||
|
// Seed used for all kinds of randomness
|
||||||
|
u64 m_seed;
|
||||||
|
|
||||||
std::string m_savedir;
|
std::string m_savedir;
|
||||||
bool m_map_saving_enabled;
|
bool m_map_saving_enabled;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*
|
/*
|
||||||
Minetest-c55
|
Minetest-c55
|
||||||
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
|
Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|
|
@ -57,6 +57,9 @@ void initializeMaterialProperties()
|
||||||
g_material_properties[CONTENT_WOOD].setDiggingProperties("",
|
g_material_properties[CONTENT_WOOD].setDiggingProperties("",
|
||||||
DiggingProperties(true, 1.0, 0));
|
DiggingProperties(true, 1.0, 0));
|
||||||
|
|
||||||
|
g_material_properties[CONTENT_SAND].setDiggingProperties("",
|
||||||
|
DiggingProperties(true, 0.5, 0));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Add MesePick to everything
|
Add MesePick to everything
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue