2020-04-14 21:11:54 +02:00
mapgen_rivers = { }
2020-04-09 21:13:38 +02:00
2020-04-14 21:11:54 +02:00
local modpath = minetest.get_modpath ( minetest.get_current_modname ( ) ) .. ' / '
2020-04-09 21:13:38 +02:00
2020-04-14 21:11:54 +02:00
dofile ( modpath .. ' settings.lua ' )
2020-04-09 21:13:38 +02:00
2020-04-14 21:11:54 +02:00
local blocksize = mapgen_rivers.blocksize
local sea_level = mapgen_rivers.sea_level
local riverbed_slope = mapgen_rivers.riverbed_slope
2020-04-12 09:40:10 +02:00
2020-04-14 21:11:54 +02:00
local make_polygons = dofile ( modpath .. ' polygons.lua ' )
2020-04-12 09:40:10 +02:00
2020-04-14 21:11:54 +02:00
local transform_quadri = dofile ( modpath .. ' geometry.lua ' )
2020-04-09 21:13:38 +02:00
2020-04-13 10:31:38 +02:00
local function interp ( v00 , v01 , v11 , v10 , xf , zf )
2020-04-12 09:40:10 +02:00
local v0 = v01 * xf + v00 * ( 1 - xf )
local v1 = v11 * xf + v10 * ( 1 - xf )
2020-04-09 21:13:38 +02:00
return v1 * zf + v0 * ( 1 - zf )
end
local data = { }
local function generate ( minp , maxp , seed )
local c_stone = minetest.get_content_id ( " default:stone " )
local c_dirt = minetest.get_content_id ( " default:dirt " )
local c_lawn = minetest.get_content_id ( " default:dirt_with_grass " )
local c_sand = minetest.get_content_id ( " default:sand " )
local c_water = minetest.get_content_id ( " default:water_source " )
local c_rwater = minetest.get_content_id ( " default:river_water_source " )
local vm , emin , emax = minetest.get_mapgen_object ( " voxelmanip " )
vm : get_data ( data )
local a = VoxelArea : new ( { MinEdge = emin , MaxEdge = emax } )
local ystride = a.ystride -- Tip : the ystride of a VoxelArea is the number to add to the array index to get the index of the position above. It's faster because it avoids to completely recalculate the index.
2020-04-13 15:01:54 +02:00
2020-04-14 21:11:54 +02:00
local polygons = make_polygons ( minp , maxp )
2020-04-09 21:13:38 +02:00
2020-04-12 16:42:03 +02:00
local i = 1
for x = minp.x , maxp.x do
for z = minp.z , maxp.z do
2020-04-13 09:54:04 +02:00
local poly = polygons [ i ]
if poly then
2020-04-14 21:11:54 +02:00
local xf , zf = transform_quadri ( poly.x , poly.z , x / blocksize , z / blocksize )
2020-04-12 16:42:03 +02:00
local i00 , i01 , i11 , i10 = unpack ( poly.i )
2020-04-09 21:13:38 +02:00
2020-04-13 12:15:10 +02:00
local is_river = false
2020-04-14 17:53:36 +02:00
local depth_factor = 0
2020-04-13 12:15:10 +02:00
local r_west , r_north , r_east , r_south = unpack ( poly.rivers )
if xf >= r_east then
is_river = true
2020-04-14 17:53:36 +02:00
depth_factor = xf - r_east
2020-04-13 12:15:10 +02:00
xf = 1
elseif xf <= r_west then
is_river = true
2020-04-14 17:53:36 +02:00
depth_factor = r_west - xf
2020-04-13 12:15:10 +02:00
xf = 0
end
if zf >= r_south then
is_river = true
2020-04-14 17:53:36 +02:00
depth_factor = zf - r_south
2020-04-13 12:15:10 +02:00
zf = 1
elseif zf <= r_north then
is_river = true
2020-04-14 17:53:36 +02:00
depth_factor = r_north - zf
2020-04-13 12:15:10 +02:00
zf = 0
end
2020-04-13 15:01:54 +02:00
if not is_river then
local c_NW , c_NE , c_SE , c_SW = unpack ( poly.river_corners )
if xf + zf <= c_NW then
is_river = true
2020-04-14 17:53:36 +02:00
depth_factor = c_NW - xf - zf
2020-04-13 15:01:54 +02:00
xf , zf = 0 , 0
elseif 1 - xf + zf <= c_NE then
is_river = true
2020-04-14 17:53:36 +02:00
depth_factor = c_NE - 1 + xf - zf
2020-04-13 15:01:54 +02:00
xf , zf = 1 , 0
elseif 2 - xf - zf <= c_SE then
is_river = true
2020-04-14 17:53:36 +02:00
depth_factor = c_SE - 2 + xf + zf
2020-04-13 15:01:54 +02:00
xf , zf = 1 , 1
elseif xf + 1 - zf <= c_SW then
is_river = true
2020-04-14 17:53:36 +02:00
depth_factor = c_SW - xf - 1 + zf
2020-04-13 15:01:54 +02:00
xf , zf = 0 , 1
end
end
2020-04-13 12:15:10 +02:00
if not is_river then
xf = ( xf - r_west ) / ( r_east - r_west )
zf = ( zf - r_north ) / ( r_south - r_north )
end
2020-04-13 10:31:38 +02:00
local vdem = poly.dem
2020-04-13 12:27:24 +02:00
local terrain_height = math.floor ( 0.5 + interp (
2020-04-13 10:31:38 +02:00
vdem [ 1 ] ,
vdem [ 2 ] ,
vdem [ 3 ] ,
vdem [ 4 ] ,
2020-04-09 21:13:38 +02:00
xf , zf
) )
2020-04-14 17:53:36 +02:00
local lake_height = math.max ( math.floor ( poly.lake ) , terrain_height )
if is_river then
terrain_height = math.min ( math.max ( lake_height , sea_level ) - math.floor ( 1 + depth_factor * riverbed_slope ) , terrain_height )
end
2020-04-09 21:13:38 +02:00
local is_lake = lake_height > terrain_height
local ivm = a : index ( x , minp.y - 1 , z )
if terrain_height >= minp.y then
for y = minp.y , math.min ( maxp.y , terrain_height ) do
if y == terrain_height then
if is_lake or y <= sea_level then
data [ ivm ] = c_sand
else
data [ ivm ] = c_lawn
end
else
data [ ivm ] = c_stone
end
ivm = ivm + ystride
end
end
if lake_height > sea_level then
if is_lake and lake_height > minp.y then
for y = math.max ( minp.y , terrain_height + 1 ) , math.min ( maxp.y , lake_height ) do
data [ ivm ] = c_rwater
ivm = ivm + ystride
end
end
else
for y = math.max ( minp.y , terrain_height + 1 ) , math.min ( maxp.y , sea_level ) do
data [ ivm ] = c_water
ivm = ivm + ystride
end
end
end
2020-04-12 16:42:03 +02:00
i = i + 1
2020-04-09 21:13:38 +02:00
end
end
vm : set_data ( data )
minetest.generate_ores ( vm , minp , maxp )
vm : set_lighting ( { day = 0 , night = 0 } )
vm : calc_lighting ( )
vm : update_liquids ( )
vm : write_to_map ( )
end
minetest.register_on_generated ( generate )