aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPerttu Ahola <celeron55@gmail.com>2011-06-25 16:32:09 +0300
committerPerttu Ahola <celeron55@gmail.com>2011-06-25 16:32:09 +0300
commitaed9e809a19bffdf911f75dd9d718efb8decd2c1 (patch)
treebce949a0722a7bf007f4c50822dc3f69292e3c05 /src
parente8a731adc502d19a8ae3bfeee5b985f90ab8a507 (diff)
downloadminetest-aed9e809a19bffdf911f75dd9d718efb8decd2c1.tar.gz
minetest-aed9e809a19bffdf911f75dd9d718efb8decd2c1.tar.bz2
minetest-aed9e809a19bffdf911f75dd9d718efb8decd2c1.zip
mapgen stuff
Diffstat (limited to 'src')
-rw-r--r--src/defaultsettings.cpp1
-rw-r--r--src/environment.cpp2
-rw-r--r--src/map.cpp535
-rw-r--r--src/mapblock_mesh.cpp4
-rw-r--r--src/noise.h39
-rw-r--r--src/server.cpp2
-rw-r--r--src/utility.h5
7 files changed, 392 insertions, 196 deletions
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp
index 289be0a06..74d323237 100644
--- a/src/defaultsettings.cpp
+++ b/src/defaultsettings.cpp
@@ -92,5 +92,6 @@ void set_default_settings()
g_settings.setDefault("server_unload_unused_sectors_timeout", "60");
g_settings.setDefault("server_map_save_interval", "60");
g_settings.setDefault("full_block_send_enable_min_time_from_building", "2.0");
+ //g_settings.setDefault("dungeon_rarity", "0.025");
}
diff --git a/src/environment.cpp b/src/environment.cpp
index 9bbba08b0..cd255341f 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -619,6 +619,7 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
{
v3s16 p = p0 + block->getPosRelative();
MapNode n = block->getNodeNoEx(p0);
+#if 1
// Test something:
// Convert all mud under proper day lighting to grass
if(n.d == CONTENT_MUD)
@@ -634,6 +635,7 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
}
}
}
+#endif
}
}
diff --git a/src/map.cpp b/src/map.cpp
index fe6b7a701..cb0967c35 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -2169,6 +2169,7 @@ void make_randomstone(VoxelManipulator &vmanip, v3s16 p0)
}
#endif
+#if 0
void make_largestone(VoxelManipulator &vmanip, v3s16 p0)
{
MapNode stonenode(CONTENT_STONE);
@@ -2250,6 +2251,7 @@ void make_largestone(VoxelManipulator &vmanip, v3s16 p0)
vmanip.m_data[vi] = stonenode;
}
}
+#endif
/*
Dungeon making routines
@@ -2375,39 +2377,79 @@ void make_hole1(VoxelManipulator &vmanip, v3s16 place)
void make_door1(VoxelManipulator &vmanip, v3s16 doorplace, v3s16 doordir)
{
make_hole1(vmanip, doorplace);
+ // Place torch (for testing)
+ //vmanip.m_data[vmanip.m_area.index(doorplace)] = MapNode(CONTENT_TORCH);
+}
+
+v3s16 rand_ortho_dir(PseudoRandom &random)
+{
+ if(random.next()%2==0)
+ return random.next()%2 ? v3s16(-1,0,0) : v3s16(1,0,0);
+ else
+ return random.next()%2 ? v3s16(0,0,-1) : v3s16(0,0,1);
}
-v3s16 rand_ortho_dir()
+v3s16 turn_xz(v3s16 olddir, int t)
{
- if(myrand()%2==0)
- return myrand()%2 ? v3s16(-1,0,0) : v3s16(1,0,0);
+ v3s16 dir;
+ if(t == 0)
+ {
+ // Turn right
+ dir.X = olddir.Z;
+ dir.Z = -olddir.X;
+ dir.Y = olddir.Y;
+ }
else
- return myrand()%2 ? v3s16(0,0,-1) : v3s16(0,0,1);
+ {
+ // Turn left
+ dir.X = -olddir.Z;
+ dir.Z = olddir.X;
+ dir.Y = olddir.Y;
+ }
+ return dir;
+}
+
+v3s16 random_turn(PseudoRandom &random, v3s16 olddir)
+{
+ int turn = random.range(0,2);
+ v3s16 dir;
+ if(turn == 0)
+ {
+ // Go straight
+ dir = olddir;
+ }
+ else if(turn == 1)
+ // Turn right
+ dir = turn_xz(olddir, 0);
+ else
+ // Turn left
+ dir = turn_xz(olddir, 1);
+ return dir;
}
void make_corridor(VoxelManipulator &vmanip, v3s16 doorplace, v3s16 doordir,
- v3s16 &result_place, v3s16 &result_dir)
+ v3s16 &result_place, v3s16 &result_dir, PseudoRandom &random)
{
make_hole1(vmanip, doorplace);
v3s16 p0 = doorplace;
v3s16 dir = doordir;
u32 length;
- if(myrand()%2)
- length = myrand_range(1,13);
+ if(random.next()%2)
+ length = random.range(1,13);
else
- length = myrand_range(1,6);
- u32 partlength = myrand_range(1,length);
+ length = random.range(1,6);
+ length = random.range(1,13);
+ u32 partlength = random.range(1,length);
u32 partcount = 0;
s16 make_stairs = 0;
- if(myrand()%2 == 0 && partlength >= 3)
- make_stairs = myrand()%2 ? 1 : -1;
+ if(random.next()%2 == 0 && partlength >= 3)
+ make_stairs = random.next()%2 ? 1 : -1;
for(u32 i=0; i<length; i++)
{
- v3s16 dir0 = dir;
- // If first part of stairs, don't go up or down yet (wouldn't fit)
- if(partcount == 0)
- dir0.Y = 0;
- v3s16 p = p0 + dir0;
+ v3s16 p = p0 + dir;
+ if(partcount != 0)
+ p.Y += make_stairs;
+
/*// If already empty
if(vmanip.getNodeNoExNoEmerge(p).d
== CONTENT_AIR
@@ -2415,49 +2457,54 @@ void make_corridor(VoxelManipulator &vmanip, v3s16 doorplace, v3s16 doordir,
== CONTENT_AIR)
{
}*/
- if(make_stairs)
+
+ if(vmanip.m_area.contains(p) == true
+ && vmanip.m_area.contains(p+v3s16(0,1,0)) == true)
{
- make_fill(vmanip, p+v3s16(-1,-1,-1), v3s16(3,5,3),
- VMANIP_FLAG_DUNGEON_UNTOUCHABLE, MapNode(CONTENT_COBBLE), 0);
- make_fill(vmanip, p, v3s16(1,3,1), 0, MapNode(CONTENT_AIR),
- VMANIP_FLAG_DUNGEON_INSIDE);
+ if(make_stairs)
+ {
+ make_fill(vmanip, p+v3s16(-1,-1,-1), v3s16(3,5,3),
+ VMANIP_FLAG_DUNGEON_UNTOUCHABLE, MapNode(CONTENT_COBBLE), 0);
+ make_fill(vmanip, p, v3s16(1,2,1), 0, MapNode(CONTENT_AIR),
+ VMANIP_FLAG_DUNGEON_INSIDE);
+ make_fill(vmanip, p-dir, v3s16(1,2,1), 0, MapNode(CONTENT_AIR),
+ VMANIP_FLAG_DUNGEON_INSIDE);
+ }
+ else
+ {
+ make_fill(vmanip, p+v3s16(-1,-1,-1), v3s16(3,4,3),
+ VMANIP_FLAG_DUNGEON_UNTOUCHABLE, MapNode(CONTENT_COBBLE), 0);
+ make_hole1(vmanip, p);
+ /*make_fill(vmanip, p, v3s16(1,2,1), 0, MapNode(CONTENT_AIR),
+ VMANIP_FLAG_DUNGEON_INSIDE);*/
+ }
+
+ p0 = p;
}
else
{
- make_fill(vmanip, p+v3s16(-1,-1,-1), v3s16(3,4,3),
- VMANIP_FLAG_DUNGEON_UNTOUCHABLE, MapNode(CONTENT_COBBLE), 0);
- make_hole1(vmanip, p);
- /*make_fill(vmanip, p, v3s16(1,2,1), 0, MapNode(CONTENT_AIR),
- VMANIP_FLAG_DUNGEON_INSIDE);*/
+ // Can't go here, turn away
+ dir = turn_xz(dir, random.range(0,1));
+ make_stairs = -make_stairs;
+ partcount = 0;
+ partlength = random.range(1,length);
+ continue;
}
- p0 = p;
+
partcount++;
if(partcount >= partlength)
{
partcount = 0;
- v3s16 newdir = rand_ortho_dir();
- partlength = myrand_range(1,7);
- make_stairs = 0;
- if(myrand()%2 == 0 && partlength >= 3)
- make_stairs = myrand()%2 ? 1 : -1;
+ dir = random_turn(random, dir);
+
+ partlength = random.range(1,length);
- if(make_stairs != 0)
- {
- if(newdir.X == 0 && dir.X != 0)
- dir = newdir;
- if(newdir.Z == 0 && dir.Z != 0)
- dir = newdir;
- }
- else
- {
- dir = newdir;
- }
- dir.Y = make_stairs;
+ make_stairs = 0;
+ if(random.next()%2 == 0 && partlength >= 3)
+ make_stairs = random.next()%2 ? 1 : -1;
}
}
- //p0.Y -= make_stairs;
- dir.Y = 0;
result_place = p0;
result_dir = dir;
}
@@ -2466,16 +2513,17 @@ class RoomWalker
{
public:
- RoomWalker(VoxelManipulator &vmanip_, v3s16 pos):
+ RoomWalker(VoxelManipulator &vmanip_, v3s16 pos, PseudoRandom &random):
vmanip(vmanip_),
- m_pos(pos)
+ m_pos(pos),
+ m_random(random)
{
randomizeDir();
}
void randomizeDir()
{
- m_dir = rand_ortho_dir();
+ m_dir = rand_ortho_dir(m_random);
}
void setPos(v3s16 pos)
@@ -2561,13 +2609,13 @@ public:
v3s16 roomplace;
// X east, Z north, Y up
if(doordir == v3s16(1,0,0)) // X+
- roomplace = doorplace + v3s16(0,-1,-roomsize.Z/2+myrand_range(-roomsize.Z/2,roomsize.Z/2));
+ roomplace = doorplace + v3s16(0,-1,-roomsize.Z/2+m_random.range(-roomsize.Z/2+1,roomsize.Z/2-1));
if(doordir == v3s16(-1,0,0)) // X-
- roomplace = doorplace + v3s16(-roomsize.X+1,-1,-roomsize.Z/2+myrand_range(-roomsize.Z/2,roomsize.Z/2));
+ roomplace = doorplace + v3s16(-roomsize.X+1,-1,-roomsize.Z/2+m_random.range(-roomsize.Z/2+1,roomsize.Z/2-1));
if(doordir == v3s16(0,0,1)) // Z+
- roomplace = doorplace + v3s16(-roomsize.X/2+myrand_range(-roomsize.X/2,roomsize.X/2),-1,0);
+ roomplace = doorplace + v3s16(-roomsize.X/2+m_random.range(-roomsize.X/2+1,roomsize.X/2-1),-1,0);
if(doordir == v3s16(0,0,-1)) // Z-
- roomplace = doorplace + v3s16(-roomsize.X/2+myrand_range(-roomsize.X/2,roomsize.X/2),-1,-roomsize.Z+1);
+ roomplace = doorplace + v3s16(-roomsize.X/2+m_random.range(-roomsize.X/2+1,roomsize.X/2-1),-1,-roomsize.Z+1);
// Check fit
bool fits = true;
@@ -2604,58 +2652,133 @@ public:
private:
VoxelManipulator &vmanip;
v3s16 m_pos;
- v3s16 m_dir;
+ v3s16 m_dir;
+ PseudoRandom &m_random;
};
-void make_dungeon1(VoxelManipulator &vmanip)
+void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random)
{
v3s16 areasize = vmanip.m_area.getExtent();
v3s16 roomsize;
v3s16 roomplace;
- roomsize = v3s16(myrand_range(4,8),myrand_range(4,6),myrand_range(4,8));
- roomplace = vmanip.m_area.MinEdge + v3s16(
- myrand_range(0,areasize.X-roomsize.X-1),
- myrand_range(0,areasize.Y-roomsize.Y-1),
- myrand_range(0,areasize.Z-roomsize.Z-1));
+ /*
+ Find place for first room
+ */
+ bool fits = false;
+ for(u32 i=0; i<100; i++)
+ {
+ roomsize = v3s16(random.range(4,8),random.range(4,6),random.range(4,8));
+ roomplace = vmanip.m_area.MinEdge + v3s16(
+ random.range(0,areasize.X-roomsize.X-1),
+ random.range(0,areasize.Y-roomsize.Y-1),
+ random.range(0,areasize.Z-roomsize.Z-1));
+ /*
+ Check that we're not putting the room to an unknown place,
+ otherwise it might end up floating in the air
+ */
+ fits = true;
+ for(s16 z=1; z<roomsize.Z-1; z++)
+ for(s16 y=1; y<roomsize.Y-1; y++)
+ for(s16 x=1; x<roomsize.X-1; x++)
+ {
+ v3s16 p = roomplace + v3s16(x,y,z);
+ u32 vi = vmanip.m_area.index(p);
+ if(vmanip.m_flags[vi] & VMANIP_FLAG_DUNGEON_INSIDE)
+ {
+ fits = false;
+ break;
+ }
+ if(vmanip.m_data[vi].d == CONTENT_IGNORE)
+ {
+ fits = false;
+ break;
+ }
+ }
+ if(fits)
+ break;
+ }
+ // No place found
+ if(fits == false)
+ return;
+
+ /*
+ Stores the center position of the last room made, so that
+ a new corridor can be started from the last room instead of
+ the new room, if chosen so.
+ */
+ v3s16 last_room_center = roomplace+v3s16(roomsize.X/2,1,roomsize.Z/2);
- u32 room_count = myrand_range(2,7);
+ u32 room_count = random.range(2,7);
for(u32 i=0; i<room_count; i++)
{
+ // Make a room to the determined place
make_room1(vmanip, roomsize, roomplace);
+
+ v3s16 room_center = roomplace + v3s16(roomsize.X/2,1,roomsize.Z/2);
+
+ // Place torch at room center (for testing)
+ //vmanip.m_data[vmanip.m_area.index(room_center)] = MapNode(CONTENT_TORCH);
- RoomWalker walker(vmanip, roomplace+v3s16(roomsize.X/2,1,roomsize.Z/2));
+ // Quit if last room
+ if(i == room_count-1)
+ break;
+
+ // Determine walker start position
+
+ bool start_in_last_room = (random.range(0,1)==0);
+ //bool start_in_last_room = true;
+
+ v3s16 walker_start_place;
+
+ if(start_in_last_room)
+ {
+ walker_start_place = last_room_center;
+ }
+ else
+ {
+ walker_start_place = room_center;
+ // Store center of current room as the last one
+ last_room_center = room_center;
+ }
+
+ // Create walker and find a place for a door
+ RoomWalker walker(vmanip, walker_start_place, random);
v3s16 doorplace;
v3s16 doordir;
bool r = walker.findPlaceForDoor(doorplace, doordir);
if(r == false)
- {
- //dstream<<"walker.findPlaceForDoor failed"<<std::endl;
return;
- }
- //dstream<<"walker.findPlaceForDoor succeeded"<<std::endl;
- make_door1(vmanip, doorplace, doordir);
-
+ if(random.range(0,1)==0)
+ // Make the door
+ make_door1(vmanip, doorplace, doordir);
+ else
+ // Don't actually make a door
+ doorplace -= doordir;
+
+ // Make a random corridor starting from the door
v3s16 corridor_end;
v3s16 corridor_end_dir;
- make_corridor(vmanip, doorplace, doordir, corridor_end, corridor_end_dir);
+ make_corridor(vmanip, doorplace, doordir, corridor_end,
+ corridor_end_dir, random);
- roomsize = v3s16(myrand_range(4,8),myrand_range(4,6),myrand_range(4,8));
+ // Find a place for a random sized room
+ roomsize = v3s16(random.range(4,8),random.range(4,6),random.range(4,8));
walker.setPos(corridor_end);
walker.setDir(corridor_end_dir);
r = walker.findPlaceForRoomDoor(roomsize, doorplace, doordir, roomplace);
if(r == false)
- {
- //dstream<<"walker.findPlaceForRoomDoor failed"<<std::endl;
return;
- }
- //dstream<<"walker.findPlaceForRoomDoor succeeded"<<std::endl;
- make_door1(vmanip, doorplace, doordir);
+
+ if(random.range(0,1)==0)
+ // Make the door
+ make_door1(vmanip, doorplace, doordir);
+ else
+ // Don't actually make a door
+ roomplace -= doordir;
+
}
-
- make_room1(vmanip, roomsize, roomplace);
-
}
/*
@@ -2664,6 +2787,7 @@ void make_dungeon1(VoxelManipulator &vmanip)
// This affects the shape of the contour
//#define CAVE_NOISE_SCALE 10.0
+//#define CAVE_NOISE_SCALE 7.5
#define CAVE_NOISE_SCALE 5.0
NoiseParams get_cave_noise1_params(u64 seed)
@@ -2720,7 +2844,7 @@ bool val_is_ground(double ground_noise1_val, v3s16 p, u64 seed)
{
//return ((double)p.Y < ground_noise1_val);
- double f = 1.0 + noise2d_perlin(
+ double f = 0.8 + noise2d_perlin(
0.5+(float)p.X/250, 0.5+(float)p.Z/250,
seed+920381, 3, 0.5);
if(f < 0.01)
@@ -3020,7 +3144,7 @@ void addRandomObjects(MapBlock *block)
block->m_static_objects.insert(0, s_obj);
delete obj;
}
- if(myrand() % 300 == 0)
+ if(myrand() % 1000 == 0)
{
v3f pos_f = intToFloat(p+block->getPosRelative(), BS);
pos_f.Y -= BS*0.4;
@@ -3078,18 +3202,18 @@ void makeBlock(BlockMakeData *data)
s16 approx_ground_depth = approx_groundlevel - (node_min.Y+MAP_BLOCKSIZE/2);
- /*s16 minimum_groundlevel = (s16)get_sector_minimum_ground_level(
+ s16 minimum_groundlevel = (s16)get_sector_minimum_ground_level(
data->seed, v2s16(blockpos.X, blockpos.Z));
- // Minimum amount of ground above the central block
- s16 minimum_ground_depth = minimum_groundlevel - node_max.Y;*/
-
+ // Minimum amount of ground above the top of the central block
+ s16 minimum_ground_depth = minimum_groundlevel - node_max.Y;
+
s16 maximum_groundlevel = (s16)get_sector_maximum_ground_level(
data->seed, v2s16(blockpos.X, blockpos.Z), 1);
- // Minimum amount of ground above the central block
+ // Maximum amount of ground above the bottom of the central block
s16 maximum_ground_depth = maximum_groundlevel - node_min.Y;
/*
- Special case for high air or water
+ Special case for high air or water: Just fill with air and water.
*/
if(maximum_ground_depth < -20)
{
@@ -3121,6 +3245,18 @@ void makeBlock(BlockMakeData *data)
// We're done
return;
}
+
+ /*
+ If block is deep underground, this is set to true and ground
+ density noise is not generated, for speed optimization.
+ */
+ bool all_is_ground_except_caves = (minimum_ground_depth > 16);
+
+ /*
+ Create a block-specific seed
+ */
+ u32 blockseed = (data->seed%0x100000000) + full_node_min.Z*38134234
+ + full_node_min.Y*42123 + full_node_min.X*23;
/*
Make some 3D noise
@@ -3145,8 +3281,7 @@ void makeBlock(BlockMakeData *data)
noisebuf_cave.create(get_cave_noise1_params(data->seed),
minpos_f.X, minpos_f.Y, minpos_f.Z,
maxpos_f.X, maxpos_f.Y, maxpos_f.Z,
- 4, 4, 4);
- //3.5, 3.5, 3.5);
+ 4, 3, 4);
noisebuf_cave.multiply(get_cave_noise2_params(data->seed));
@@ -3158,16 +3293,17 @@ void makeBlock(BlockMakeData *data)
v3f sl = v3f(4.0, 4.0, 4.0);
/*
- Density
+ Density noise
*/
- //noisebuf_ground.create(data->seed+983240, 6, 0.60, false,
- noisebuf_ground.create(get_ground_noise1_params(data->seed),
- minpos_f.X, minpos_f.Y, minpos_f.Z,
- maxpos_f.X, maxpos_f.Y, maxpos_f.Z,
- sl.X, sl.Y, sl.Z);
+ if(all_is_ground_except_caves == false)
+ //noisebuf_ground.create(data->seed+983240, 6, 0.60, false,
+ noisebuf_ground.create(get_ground_noise1_params(data->seed),
+ minpos_f.X, minpos_f.Y, minpos_f.Z,
+ maxpos_f.X, maxpos_f.Y, maxpos_f.Z,
+ sl.X, sl.Y, sl.Z);
/*
- Content
+ Ground property noise
*/
sl = v3f(2.5, 2.5, 2.5);
noisebuf_ground_crumbleness.create(
@@ -3200,42 +3336,22 @@ void makeBlock(BlockMakeData *data)
// Only modify places that have no content
if(vmanip.m_data[i].d == CONTENT_IGNORE)
{
- if(noisebuf_cave.get(x,y,z) > CAVE_NOISE_THRESHOLD)
+ // First priority: make air and water.
+ // This avoids caves inside water.
+ if(all_is_ground_except_caves == false
+ && val_is_ground(noisebuf_ground.get(x,y,z),
+ v3s16(x,y,z), data->seed) == false)
+ {
+ if(y <= WATER_LEVEL)
+ vmanip.m_data[i] = MapNode(CONTENT_WATERSOURCE);
+ else
+ vmanip.m_data[i] = MapNode(CONTENT_AIR);
+ }
+ else if(noisebuf_cave.get(x,y,z) > CAVE_NOISE_THRESHOLD)
vmanip.m_data[i] = MapNode(CONTENT_AIR);
- else if(val_is_ground(noisebuf_ground.get(x,y,z),
- v3s16(x,y,z), data->seed))
- vmanip.m_data[i] = MapNode(CONTENT_STONE);
- else if(y <= WATER_LEVEL)
- vmanip.m_data[i] = MapNode(CONTENT_WATERSOURCE);
else
- vmanip.m_data[i] = MapNode(CONTENT_AIR);
- }
-
- /*if(noisebuf_cave.get(x,y,z) > CAVE_NOISE_THRESHOLD)
- {
- // Only modify places that have no content
- if(vmanip.m_data[i].d == CONTENT_IGNORE)
- vmanip.m_data[i] = MapNode(CONTENT_AIR);
- }
- else if(is_ground(noisebuf_ground.get(x,y,z), y))
- {
- // Only modify places that have no content
- if(vmanip.m_data[i].d == CONTENT_IGNORE)
vmanip.m_data[i] = MapNode(CONTENT_STONE);
}
- else if(y <= WATER_LEVEL)
- {
- // Only modify places that have air or no content
- if(vmanip.m_data[i].d == CONTENT_IGNORE
- || vmanip.m_data[i].d == CONTENT_AIR)
- vmanip.m_data[i] = MapNode(CONTENT_WATERSOURCE);
- }
- else
- {
- // Only modify places that have no content
- if(vmanip.m_data[i].d == CONTENT_IGNORE)
- vmanip.m_data[i] = MapNode(CONTENT_AIR);
- }*/
data->vmanip.m_area.add_y(em, i, 1);
}
@@ -3247,22 +3363,24 @@ void makeBlock(BlockMakeData *data)
*/
{
+ PseudoRandom mineralrandom(blockseed);
+
/*
Add meseblocks
*/
for(s16 i=0; i<approx_ground_depth/4; i++)
{
- if(myrand()%50 == 0)
+ if(mineralrandom.next()%50 == 0)
{
- s16 x = myrand_range(node_min.X+1, node_max.X-1);
- s16 y = myrand_range(node_min.Y+1, node_max.Y-1);
- s16 z = myrand_range(node_min.Z+1, node_max.Z-1);
+ s16 x = mineralrandom.range(node_min.X+1, node_max.X-1);
+ s16 y = mineralrandom.range(node_min.Y+1, node_max.Y-1);
+ s16 z = mineralrandom.range(node_min.Z+1, node_max.Z-1);
for(u16 i=0; i<27; i++)
{
v3s16 p = v3s16(x,y,z) + g_27dirs[i];
u32 vi = vmanip.m_area.index(p);
if(vmanip.m_data[vi].d == CONTENT_STONE)
- if(myrand()%8 == 0)
+ if(mineralrandom.next()%8 == 0)
vmanip.m_data[vi] = MapNode(CONTENT_MESE);
}
@@ -3272,14 +3390,14 @@ void makeBlock(BlockMakeData *data)
Add others
*/
{
- u16 a = myrand_range(0,15);
+ u16 a = mineralrandom.range(0,15);
a = a*a*a;
u16 amount = 20 * a/1000;
for(s16 i=0; i<amount; i++)
{
- s16 x = myrand_range(node_min.X+1, node_max.X-1);
- s16 y = myrand_range(node_min.Y+1, node_max.Y-1);
- s16 z = myrand_range(node_min.Z+1, node_max.Z-1);
+ s16 x = mineralrandom.range(node_min.X+1, node_max.X-1);
+ s16 y = mineralrandom.range(node_min.Y+1, node_max.Y-1);
+ s16 z = mineralrandom.range(node_min.Z+1, node_max.Z-1);
u8 base_content = CONTENT_STONE;
MapNode new_content(CONTENT_IGNORE);
@@ -3310,7 +3428,7 @@ void makeBlock(BlockMakeData *data)
u32 vi = vmanip.m_area.index(p);
if(vmanip.m_data[vi].d == base_content)
{
- if(myrand()%sparseness == 0)
+ if(mineralrandom.next()%sparseness == 0)
vmanip.m_data[vi] = new_content;
}
}
@@ -3326,21 +3444,21 @@ void makeBlock(BlockMakeData *data)
u16 coal_rareness = 60 / coal_amount;
if(coal_rareness == 0)
coal_rareness = 1;
- if(myrand()%coal_rareness == 0)
+ if(mineralrandom.next()%coal_rareness == 0)
{
- u16 a = myrand() % 16;
+ u16 a = mineralrandom.next() % 16;
u16 amount = coal_amount * a*a*a / 1000;
for(s16 i=0; i<amount; i++)
{
- s16 x = myrand_range(node_min.X+1, node_max.X-1);
- s16 y = myrand_range(node_min.Y+1, node_max.Y-1);
- s16 z = myrand_range(node_min.Z+1, node_max.Z-1);
+ s16 x = mineralrandom.range(node_min.X+1, node_max.X-1);
+ s16 y = mineralrandom.range(node_min.Y+1, node_max.Y-1);
+ s16 z = mineralrandom.range(node_min.Z+1, node_max.Z-1);
for(u16 i=0; i<27; i++)
{
v3s16 p = v3s16(x,y,z) + g_27dirs[i];
u32 vi = vmanip.m_area.index(p);
if(vmanip.m_data[vi].d == CONTENT_STONE)
- if(myrand()%8 == 0)
+ if(mineralrandom.next()%8 == 0)
vmanip.m_data[vi] = MapNode(CONTENT_STONE, MINERAL_COAL);
}
}
@@ -3352,21 +3470,21 @@ void makeBlock(BlockMakeData *data)
u16 iron_rareness = 60 / iron_amount;
if(iron_rareness == 0)
iron_rareness = 1;
- if(myrand()%iron_rareness == 0)
+ if(mineralrandom.next()%iron_rareness == 0)
{
- u16 a = myrand() % 16;
+ u16 a = mineralrandom.next() % 16;
u16 amount = iron_amount * a*a*a / 1000;
for(s16 i=0; i<amount; i++)
{
- s16 x = myrand_range(node_min.X+1, node_max.X-1);
- s16 y = myrand_range(node_min.Y+1, node_max.Y-1);
- s16 z = myrand_range(node_min.Z+1, node_max.Z-1);
+ s16 x = mineralrandom.range(node_min.X+1, node_max.X-1);
+ s16 y = mineralrandom.range(node_min.Y+1, node_max.Y-1);
+ s16 z = mineralrandom.range(node_min.Z+1, node_max.Z-1);
for(u16 i=0; i<27; i++)
{
v3s16 p = v3s16(x,y,z) + g_27dirs[i];
u32 vi = vmanip.m_area.index(p);
if(vmanip.m_data[vi].d == CONTENT_STONE)
- if(myrand()%8 == 0)
+ if(mineralrandom.next()%8 == 0)
vmanip.m_data[vi] = MapNode(CONTENT_STONE, MINERAL_IRON);
}
}
@@ -3416,7 +3534,12 @@ void makeBlock(BlockMakeData *data)
//if(node_min.Y < approx_groundlevel)
//if(myrand() % 3 == 0)
//if(myrand() % 3 == 0 && node_min.Y < approx_groundlevel)
- if(myrand() % 100 == 0 && node_min.Y < approx_groundlevel)
+ //if(myrand() % 100 == 0 && node_min.Y < approx_groundlevel)
+ //float dungeon_rarity = g_settings.getFloat("dungeon_rarity");
+ float dungeon_rarity = 0.02;
+ if(((noise3d(blockpos.X,blockpos.Y,blockpos.Z,data->seed)+1.0)/2.0)
+ < dungeon_rarity
+ && node_min.Y < approx_groundlevel)
{
// Dungeon generator doesn't modify places which have this set
data->vmanip.clearFlag(VMANIP_FLAG_DUNGEON_INSIDE
@@ -3433,7 +3556,7 @@ void makeBlock(BlockMakeData *data)
// Use fast index incrementing
v3s16 em = vmanip.m_area.getExtent();
u32 i = vmanip.m_area.index(v3s16(p2d.X, full_node_max.Y, p2d.Y));
- for(s16 y=node_max.Y; y>=full_node_min.Y; y--)
+ for(s16 y=full_node_max.Y; y>=full_node_min.Y; y--)
{
if(vmanip.m_data[i].d == CONTENT_AIR)
vmanip.m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE;
@@ -3444,18 +3567,11 @@ void makeBlock(BlockMakeData *data)
}
}
- /*s16 x = myrand_range(node_min.X, node_max.X);
- s16 z = myrand_range(node_min.Z, node_max.Z);
- s16 y = myrand_range(node_min.Y, node_max.Y);*/
+ PseudoRandom random(blockseed+2);
+
// Add it
- make_dungeon1(data->vmanip);
+ make_dungeon1(data->vmanip, random);
- // Take different seed for every dungeon for not blending their
- // mossyness together
- //u32 mossyseed = z*38134234+y*42123+x*23;
- u32 mossyseed = full_node_min.Z*38134234
- +full_node_min.Y*42123+full_node_min.X*23;
-
// Convert some cobble to mossy cobble
for(s16 x=full_node_min.X; x<=full_node_max.X; x++)
for(s16 z=full_node_min.Z; z<=full_node_max.Z; z++)
@@ -3466,20 +3582,27 @@ void makeBlock(BlockMakeData *data)
// Use fast index incrementing
v3s16 em = vmanip.m_area.getExtent();
u32 i = vmanip.m_area.index(v3s16(p2d.X, full_node_max.Y, p2d.Y));
- for(s16 y=node_max.Y; y>=full_node_min.Y; y--)
+ for(s16 y=full_node_max.Y; y>=full_node_min.Y; y--)
{
- // No mossy in dry places
- // (noisebuf not used because it's smaller in size)
- if(noise3d_param(get_ground_wetness_params(data->seed), x,y,z)
- < -0.6)
- continue;
- double d = noise3d_perlin((float)x/4.,
- (float)y/4.,(float)z/4.,
- mossyseed, 2, 0.9);
- if(d < 0.0)
- continue;
+ // (noisebuf not used because it doesn't contain the
+ // full area)
+ double wetness = noise3d_param(
+ get_ground_wetness_params(data->seed), x,y,z);
+ double d = noise3d_perlin((float)x/2.5,
+ (float)y/2.5,(float)z/2.5,
+ blockseed, 2, 1.4);
if(vmanip.m_data[i].d == CONTENT_COBBLE)
- vmanip.m_data[i].d = CONTENT_MOSSYCOBBLE;
+ {
+ if(d < wetness/3.0)
+ {
+ vmanip.m_data[i].d = CONTENT_MOSSYCOBBLE;
+ }
+ }
+ /*else if(vmanip.m_flags[i] & VMANIP_FLAG_DUNGEON_INSIDE)
+ {
+ if(wetness > 1.2)
+ vmanip.m_data[i].d = CONTENT_MUD;
+ }*/
data->vmanip.m_area.add_y(em, i, -1);
}
}
@@ -3533,7 +3656,8 @@ void makeBlock(BlockMakeData *data)
If close to ground level
*/
- if(abs(approx_ground_depth) < 20)
+ //if(abs(approx_ground_depth) < 30)
+ if(minimum_ground_depth < 5 && maximum_ground_depth > -5)
{
/*
Add grass and mud
@@ -3547,14 +3671,14 @@ void makeBlock(BlockMakeData *data)
{
bool possibly_have_sand = get_have_sand(data->seed, p2d);
bool have_sand = false;
- u32 mud_count = 0;
+ u32 current_depth = 0;
bool air_detected = false;
bool water_detected = false;
// Use fast index incrementing
s16 start_y = node_max.Y+2;
v3s16 em = vmanip.m_area.getExtent();
u32 i = vmanip.m_area.index(v3s16(p2d.X, start_y, p2d.Y));
- for(s16 y=start_y; y>=node_min.Y-2; y--)
+ for(s16 y=start_y; y>=node_min.Y-3; y--)
{
if(vmanip.m_data[i].d == CONTENT_WATERSOURCE)
water_detected = true;
@@ -3568,24 +3692,37 @@ void makeBlock(BlockMakeData *data)
|| vmanip.m_data[i].d == CONTENT_GRAVEL
) && (air_detected || water_detected))
{
- if(mud_count == 0 && y <= WATER_LEVEL+2
+ if(current_depth == 0 && y <= WATER_LEVEL+2
&& possibly_have_sand)
have_sand = true;
-
- if(have_sand)
+
+ if(current_depth < 4)
{
- vmanip.m_data[i] = MapNode(CONTENT_SAND);
+ if(have_sand)
+ {
+ vmanip.m_data[i] = MapNode(CONTENT_SAND);
+ }
+ #if 1
+ else if(current_depth==0 && !water_detected
+ && y >= WATER_LEVEL && air_detected)
+ vmanip.m_data[i] = MapNode(CONTENT_GRASS);
+ #endif
+ else
+ vmanip.m_data[i] = MapNode(CONTENT_MUD);
}
- else if(mud_count==0 && !water_detected && y >= WATER_LEVEL)
- vmanip.m_data[i] = MapNode(CONTENT_GRASS);
else
- vmanip.m_data[i] = MapNode(CONTENT_MUD);
+ {
+ if(vmanip.m_data[i].d == CONTENT_MUD
+ || vmanip.m_data[i].d == CONTENT_GRASS)
+ vmanip.m_data[i] = MapNode(CONTENT_STONE);
+ }
- mud_count++;
- if(mud_count >= 4)
+ current_depth++;
+
+ if(current_depth >= 8)
break;
}
- else if(mud_count != 0)
+ else if(current_depth != 0)
break;
data->vmanip.m_area.add_y(em, i, -1);
@@ -3599,11 +3736,12 @@ void makeBlock(BlockMakeData *data)
// Amount of trees
u32 tree_count = block_area_nodes * tree_amount_2d(data->seed, p2d_center);
+ PseudoRandom treerandom(blockseed);
// Put trees in random places on part of division
for(u32 i=0; i<tree_count; i++)
{
- s16 x = myrand_range(node_min.X, node_max.X);
- s16 z = myrand_range(node_min.Z, node_max.Z);
+ s16 x = treerandom.range(node_min.X, node_max.X);
+ s16 z = treerandom.range(node_min.Z, node_max.Z);
//s16 y = find_ground_level(data->vmanip, v2s16(x,z));
s16 y = find_ground_level_from_noise(data->seed, v2s16(x,z), 4);
// Don't make a tree under water level
@@ -3800,15 +3938,17 @@ MapBlock* ServerMap::finishBlockMake(BlockMakeData *data,
/*
Blit generated stuff to map
+ NOTE: blitBackAll adds nearly everything to changed_blocks
*/
{
// 70ms @cs=8
//TimeTaker timer("finishBlockMake() blitBackAll");
data->vmanip.blitBackAll(&changed_blocks);
}
-
- //dstream<<"changed_blocks.size()="<<changed_blocks.size()<<std::endl;
-
+#if 1
+ dstream<<"finishBlockMake: changed_blocks.size()="
+ <<changed_blocks.size()<<std::endl;
+#endif
/*
Copy transforming liquid information
*/
@@ -3854,15 +3994,20 @@ MapBlock* ServerMap::finishBlockMake(BlockMakeData *data,
/*
Update lighting
*/
+
core::map<v3s16, MapBlock*> lighting_update_blocks;
+ // Center block
lighting_update_blocks.insert(block->getPos(), block);
- /*for(core::map<v3s16, MapBlock*>::Iterator
- i = modified_blocks.getIterator();
+#if 0
+ // All modified blocks
+ for(core::map<v3s16, MapBlock*>::Iterator
+ i = changed_blocks.getIterator();
i.atEnd() == false; i++)
{
lighting_update_blocks.insert(i.getNode()->getKey(),
i.getNode()->getValue());
- }*/
+ }
+#endif
updateLighting(lighting_update_blocks, changed_blocks);
/*
@@ -3977,6 +4122,8 @@ MapBlock * ServerMap::generateBlock(
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
<<std::endl;*/
+ TimeTaker timer("generateBlock");
+
//MapBlock *block = original_dummy;
v2s16 p2d(p.X, p.Z);
diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp
index a8624e8f3..d4921c2c5 100644
--- a/src/mapblock_mesh.cpp
+++ b/src/mapblock_mesh.cpp
@@ -347,7 +347,9 @@ u8 getSmoothLight(v3s16 p, VoxelManipulator &vmanip, u32 daynight_ratio)
for(u32 i=0; i<8; i++)
{
MapNode n = vmanip.getNodeNoEx(p - dirs8[i]);
- if(content_features(n.d).param_type == CPT_LIGHT)
+ if(content_features(n.d).param_type == CPT_LIGHT
+ // Fast-style leaves look better this way
+ && content_features(n.d).solidness != 2)
{
light += decode_light(n.getLightBlend(daynight_ratio));
light_count++;
diff --git a/src/noise.h b/src/noise.h
index 6e4fedbc4..c8d8985c6 100644
--- a/src/noise.h
+++ b/src/noise.h
@@ -20,6 +20,45 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#ifndef NOISE_HEADER
#define NOISE_HEADER
+#include "debug.h"
+
+class PseudoRandom
+{
+public:
+ PseudoRandom(): m_next(0)
+ {
+ }
+ PseudoRandom(int seed): m_next(seed)
+ {
+ }
+ void seed(int seed)
+ {
+ m_next = seed;
+ }
+ // Returns 0...32767
+ int next()
+ {
+ m_next = m_next * 1103515245 + 12345;
+ return((unsigned)(m_next/65536) % 32768);
+ }
+ int range(int min, int max)
+ {
+ if(max-min > 32768/10)
+ {
+ //dstream<<"WARNING: PseudoRandom::range: max > 32767"<<std::endl;
+ assert(0);
+ }
+ if(min > max)
+ {
+ assert(0);
+ return max;
+ }
+ return (next()%(max-min+1))+min;
+ }
+private:
+ int m_next;
+};
+
double easeCurve(double t);
// Return value: -1 ... 1
diff --git a/src/server.cpp b/src/server.cpp
index 3036aef26..49eb15731 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -1720,7 +1720,7 @@ void Server::AsyncRunStep()
// Don't send too many at a time
count++;
- if(count >= 2 && m_unsent_map_edit_queue.size() < 50)
+ if(count >= 1 && m_unsent_map_edit_queue.size() < 100)
break;
}
}
diff --git a/src/utility.h b/src/utility.h
index 534aea483..497f79fa0 100644
--- a/src/utility.h
+++ b/src/utility.h
@@ -1741,6 +1741,11 @@ void mysrand(unsigned seed);
inline int myrand_range(int min, int max)
{
+ if(max-min > MYRAND_MAX)
+ {
+ dstream<<"WARNING: myrand_range: max-min > MYRAND_MAX"<<std::endl;
+ assert(0);
+ }
if(min > max)
{
assert(0);