mirror of
https://github.com/ShadMOrdre/lib_materials.git
synced 2024-11-05 10:00:39 +01:00
254 lines
8.7 KiB
Lua
254 lines
8.7 KiB
Lua
--[[
|
|
1. We choose a random position in the same way plants are placed. That's the root for our lake.
|
|
2. From there we go lx in the x direction and lz in the z direction. That gives us a rectangle.
|
|
3. We check the sides of the rectangle for air and itterate down until the rectangle is closed.
|
|
4. Now we repeat this itteration, but search for the opposite, not for solid nodes but for air.
|
|
5. As soon as we found the lower limit, we check if the bottom is sealed. Now we have some jar.
|
|
6. Now as we made sure no water can escape we can replace all air inside the volume with water.
|
|
--]]
|
|
|
|
--lib_lakes = {}
|
|
|
|
local c_air = minetest.get_content_id("air")
|
|
local c_ignore = minetest.get_content_id("ignore")
|
|
local c_lava = minetest.get_content_id("default:lava_source")
|
|
local c_water = minetest.get_content_id("lib_materials:fluid_water_source")
|
|
local c_ice = minetest.get_content_id("lib_materials:ice_default")
|
|
local c_murky = minetest.get_content_id("lib_materials:fluid_water_murky_source")
|
|
local c_dirty = minetest.get_content_id("lib_materials:fluid_water_dirty_source")
|
|
local c_muddy = minetest.get_content_id("lib_materials:fluid_water_river_muddy_source")
|
|
local c_quick_source = minetest.get_content_id("lib_materials:fluid_quicksand_source")
|
|
local c_quick = minetest.get_content_id("lib_materials:quicksand")
|
|
local c_mud_wet = minetest.get_content_id("lib_materials:mud_wet")
|
|
local c_mud_dried = minetest.get_content_id("lib_materials:dirt_mud_dried")
|
|
local c_fluid_id
|
|
|
|
--
|
|
-- Find position
|
|
--
|
|
|
|
minetest.register_on_generated(function(minp, maxp, seed)
|
|
if maxp.y <= 1024 and minp.y >= -32 then
|
|
local perlin1 = minetest.get_perlin(318, 3, 0.6, 100)
|
|
-- Lua Voxel Machine
|
|
local vm = minetest.get_voxel_manip()
|
|
local vm_minp, vm_maxp = vm:read_from_map({x=minp.x, y=minp.y, z=minp.z-16}, {x=maxp.x+16, y=maxp.y+16, z=maxp.z+16})
|
|
local a = VoxelArea:new{MinEdge=vm_minp, MaxEdge=vm_maxp}
|
|
local data = vm:get_data()
|
|
-- Assume X and Z lengths are equal
|
|
local divlen = 32
|
|
local divs = (maxp.x-minp.x)/divlen+1;
|
|
for divx=0,divs-1 do
|
|
for divz=0,divs-1 do
|
|
local x0 = minp.x + math.floor((divx+0)*divlen)
|
|
local z0 = minp.z + math.floor((divz+0)*divlen)
|
|
local x1 = minp.x + math.floor((divx+1)*divlen)
|
|
local z1 = minp.z + math.floor((divz+1)*divlen)
|
|
-- Determine amount from perlin noise
|
|
local amount = math.floor(perlin1:get2d({x=x0, y=z0}) * 5 + 10)
|
|
-- Find random positions based on this random
|
|
local pr = PseudoRandom(seed+486)
|
|
for i=0,amount do
|
|
local x = pr:next(x0, x1)
|
|
local z = pr:next(z0, z1)
|
|
local ground_y = nil
|
|
-- Prevent from starting underground
|
|
local nn = minetest.get_node({x=x,y=maxp.y,z=z}).name
|
|
if nn ~= "air" and nn ~= "ignore" then
|
|
return
|
|
end
|
|
-- Find groundlevel
|
|
for y=maxp.y,minp.y,-1 do
|
|
local nn = minetest.get_node({x=x,y=y,z=z}).name
|
|
if nn ~= "air" and nn~= "ignore" then
|
|
--local is_leaves = minetest.registered_nodes[nn].groups.leaves
|
|
--if is_leaves == nil or is_leaves == 0 then
|
|
-- ground_y = y
|
|
-- break
|
|
--end
|
|
local is_leaves = minetest.registered_nodes[nn].groups.leaves
|
|
local is_plant = minetest.registered_nodes[nn].groups.plant
|
|
local is_le_plant = minetest.registered_nodes[nn].groups.lib_ecology_plant
|
|
local is_flora = minetest.registered_nodes[nn].groups.flora
|
|
local is_flower = minetest.registered_nodes[nn].groups.flower
|
|
local is_growing = minetest.registered_nodes[nn].groups.growing
|
|
if is_leaves == nil or is_leaves == 0 then
|
|
ground_y = y
|
|
break
|
|
end
|
|
-- or is_plant == nil or is_plant == 0 or is_le_plant == nil or is_le_plant == 0 or is_flora == nil or is_flora == 0 or is_flower == nil or is_flower == 0 or is_growing == nil or is_growing == 0 then
|
|
end
|
|
end
|
|
if ground_y and ground_y >= 2 then
|
|
local p = {x=x,y=ground_y,z=z}
|
|
local ground_name = minetest.get_node(p)
|
|
local node_name = minetest.get_node(p).name
|
|
if ground_name == "default:water_source" or ground_name == "lib_materials:fluid_water_source" then
|
|
return
|
|
end
|
|
local ground_name = minetest.get_node(p)
|
|
local node_name = minetest.get_node(p).name
|
|
if ground_name == "default:water_source" or ground_name == "lib_materials:fluid_water_source" then
|
|
return
|
|
end
|
|
local lx = pr:next(10,30)
|
|
local lz = pr:next(10,30)
|
|
--if string.match(node_name, "lib_materials:dirt_sandy") then
|
|
-- c_fluid_id = c_quick_source
|
|
--end
|
|
--if string.match(node_name, "lib_materials:sand") then
|
|
-- c_fluid_id = c_quick
|
|
--end
|
|
if string.match(node_name, "lib_materials:dirt_with_rainforest_litter") then
|
|
c_fluid_id = c_murky
|
|
end
|
|
if string.match(node_name, "lib_materials:dirt_mud_01") then
|
|
c_fluid_id = c_muddy
|
|
end
|
|
if string.match(node_name, "lib_materials:dirt_clayey") then
|
|
c_fluid_id = c_muddy
|
|
end
|
|
if string.match(node_name, "lib_materials:sand_desert") then
|
|
c_fluid_id = c_mud_dried
|
|
end
|
|
if string.match(node_name, "lib_materials:sand") then
|
|
c_fluid_id = c_mud_dried
|
|
end
|
|
--if string.match(node_name, "lib_materials:dirt_with_grass_warm_semihumid_coastal") or string.match(node_name, "lib_materials:dirt_with_grass_temperate_semihumid_coastal") then
|
|
-- c_fluid_id = c_dirty
|
|
--end
|
|
--if string.match(node_name, "lib_materials:dirt_with_grass_warm_semihumid_lowland") or string.match(node_name, "lib_materials:dirt_with_grass_temperate_semihumid_lowland") then
|
|
-- c_fluid_id = c_dirty
|
|
--end
|
|
--if string.match(node_name, "lib_materials:dirt_with_grass_warm_semihumid_shelf") or string.match(node_name, "lib_materials:dirt_with_grass_temperate_semihumid_shelf") then
|
|
-- c_fluid_id = c_dirty
|
|
--end
|
|
--if string.match(node_name, "lib_materials:dirt_with_grass_warm_semihumid_highland") or string.match(node_name, "lib_materials:dirt_with_grass_temperate_semihumid_highland") then
|
|
-- c_fluid_id = c_dirty
|
|
--end
|
|
if string.match(node_name, "lib_materials:stone_greenstone") then
|
|
c_fluid_id = c_lava
|
|
end
|
|
if string.match(node_name, "snow") then
|
|
c_fluid_id = c_ice
|
|
end
|
|
if ground_y >= lib_materials.minheight_snow then
|
|
c_fluid_id = c_ice
|
|
end
|
|
-- if c_water == "" then
|
|
|
|
-- else
|
|
-- c_water = minetest.get_content_id("default:river_water_source")
|
|
-- end
|
|
lib_materials.lakes_fill(data, a, p, lx, lz)
|
|
--c_fluid_id = ""
|
|
end
|
|
|
|
end
|
|
end
|
|
end
|
|
-- Write to map
|
|
vm:set_data(data)
|
|
vm:write_to_map(data)
|
|
vm:update_map()
|
|
end
|
|
end)
|
|
|
|
--
|
|
-- Make lake
|
|
--
|
|
|
|
-- TODO: combine functions into one
|
|
local function check_x(data, a, x, y, z, lx, lz)
|
|
for xi = 0, lx do
|
|
local vi = a:index(x+xi, y, z)
|
|
if data[vi] == c_air or data[vi] == c_ignore then
|
|
return true
|
|
end
|
|
local vii = a:index(x+xi, y, z+lz)
|
|
if data[vii] == c_air or data[vii] == c_ignore then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
local function check_z(data, a, x, y, z, lx, lz)
|
|
for zi = 0, lz do
|
|
local vi = a:index(x, y, z+zi)
|
|
if data[vi] == c_air or data[vi] == c_ignore then
|
|
return true
|
|
end
|
|
local vii = a:index(x+lx, y, z+zi)
|
|
if data[vii] == c_air or data[vii] == c_ignore then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
local function leak(data, a, j, lx, lz)
|
|
for xi = 0, lx do
|
|
for zi = 0, lz do
|
|
local vi = a:index(xi, -j, zi)
|
|
if data[vi] == c_air or data[vi] == c_ignore then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function lib_materials.lakes_fill(data, a, pos, lx, lz)
|
|
local x, y, z = pos.x, pos.y, pos.z
|
|
local water_a = VoxelArea:new{MinEdge={x=0, y=-32, z=0}, MaxEdge={x=lx, y=0, z=lz}}
|
|
local water_buffer = {}
|
|
-- Find upper start
|
|
local i = 0
|
|
while i <= 16 do
|
|
if check_x(data, a, x, y-i, z, lx, lz) or check_z(data, a, x, y-i, z, lx, lz) then
|
|
i = i + 1
|
|
else
|
|
break
|
|
end
|
|
end
|
|
if i >= 16 then return end
|
|
-- Itterate downwards
|
|
local j = i
|
|
while j <= (i+16) do
|
|
if check_x(data, a, x, y-j, z, lx, lz) or check_z(data, a, x, y-j, z, lx, lz) then
|
|
j = j - 1
|
|
break
|
|
else
|
|
j = j + 1
|
|
end
|
|
end
|
|
if j >= i+16 then return end
|
|
-- print ('[lib_lakes] i = '.. i ..'')
|
|
-- print ('[lib_lakes] j = '.. j ..'')
|
|
-- Check bottom
|
|
if leak(data, a, j, lx, lz) then return end
|
|
-- Add volume to buffer
|
|
for xi = 0, lx do
|
|
for yi = -i, -j, -1 do
|
|
for zi = 0, lz do
|
|
water_buffer[water_a:index(xi, yi, zi)] = true
|
|
end
|
|
end
|
|
end
|
|
-- Add the water
|
|
for xi = water_a.MinEdge.x, water_a.MaxEdge.x do
|
|
for yi = water_a.MinEdge.y, water_a.MaxEdge.y do
|
|
for zi = water_a.MinEdge.z, water_a.MaxEdge.z do
|
|
if a:contains(x+xi, y+yi, z+zi) then
|
|
local vi = a:index(x+xi, y+yi, z+zi)
|
|
if data[vi] == c_air or data[vi] == c_ignore then
|
|
if water_buffer[water_a:index(xi, yi, zi)] then
|
|
data[vi] = c_fluid_id
|
|
-- print ('[lib_lakes] Wasser auf (' .. x+xi .. ',' .. y+yi .. ',' .. z+zi .. ')')
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|