7bdc95c60a
* splitting up and genericizing some code, localizing default-dependent stuff in one file * make cooling lava an API as well * split out spring code, start roughing in mineclone support * ooh, at some point altitude checking was added to ABM definitions. Awesome. * fix crash in flow through * adding mapgen spring clay. Mineclone2 and Mineclone5 both need to accept pull requests fixing bugs before this will work
99 lines
3.3 KiB
Lua
99 lines
3.3 KiB
Lua
local data = dynamic_liquid.mapgen_data
|
|
|
|
dynamic_liquid.mapgen_prefill = function(def)
|
|
|
|
local water_level = def.liquid_level
|
|
local c_water = minetest.get_content_id(def.liquid)
|
|
local c_air = minetest.get_content_id("air")
|
|
local waternodes = {}
|
|
|
|
local fill_to = function (vi, data, area)
|
|
if area:containsi(vi) and area:position(vi).y <= water_level then
|
|
if data[vi] == c_air then
|
|
data[vi] = c_water
|
|
table.insert(waternodes, vi)
|
|
end
|
|
end
|
|
end
|
|
|
|
-- local count = 0
|
|
local drop_liquid = function(vi, data, area, min_y)
|
|
if data[vi] ~= c_water then
|
|
-- we only care about water.
|
|
return
|
|
end
|
|
local start = vi -- remember the water node we started from
|
|
local ystride = area.ystride
|
|
vi = vi - ystride
|
|
if data[vi] ~= c_air then
|
|
-- if there's no air below this water node, give up immediately.
|
|
return
|
|
end
|
|
vi = vi - ystride -- There's air below the water, so move down one.
|
|
while data[vi] == c_air and area:position(vi).y > min_y do
|
|
-- the min_y check is here to ensure that we don't put water into the mapgen
|
|
-- border zone below our current map chunk where it might get erased by future mapgen activity.
|
|
-- if there's more air, keep going.
|
|
vi = vi - ystride
|
|
end
|
|
vi = vi + ystride -- Move back up one. vi is now pointing at the last air node above the first non-air node.
|
|
data[vi] = c_water
|
|
data[start] = c_air
|
|
-- count = count + 1
|
|
-- if count % 100 == 0 then
|
|
-- minetest.chat_send_all("dropped water " .. (start-vi)/ystride .. " at " .. minetest.pos_to_string(area:position(vi)))
|
|
-- end
|
|
end
|
|
|
|
minetest.register_on_generated(function(minp, maxp, seed)
|
|
if minp.y > water_level then
|
|
-- we're in the sky.
|
|
return
|
|
end
|
|
|
|
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
|
|
local area = VoxelArea:new{MinEdge=emin, MaxEdge=emax}
|
|
vm:get_data(data)
|
|
local maxp_y = maxp.y
|
|
local minp_y = minp.y
|
|
|
|
if maxp_y > -70 then
|
|
local top = vector.new(maxp.x, math.min(maxp_y, water_level), maxp.z) -- prevents flood fill from affecting any water above sea level
|
|
for vi in area:iterp(minp, top) do
|
|
if data[vi] == c_water then
|
|
table.insert(waternodes, vi)
|
|
end
|
|
end
|
|
|
|
while table.getn(waternodes) > 0 do
|
|
local vi = table.remove(waternodes)
|
|
local below = vi - area.ystride
|
|
local left = vi - area.zstride
|
|
local right = vi + area.zstride
|
|
local front = vi - 1
|
|
local back = vi + 1
|
|
|
|
fill_to(below, data, area)
|
|
fill_to(left, data, area)
|
|
fill_to(right, data, area)
|
|
fill_to(front, data, area)
|
|
fill_to(back, data, area)
|
|
end
|
|
else
|
|
-- Caves sometimes generate with liquid nodes hovering in mid air.
|
|
-- This immediately drops them straight down as far as they can go, reducing the ABM thrashing.
|
|
-- We only iterate down to minp.y+1 because anything at minp.y will never be dropped farther anyway.
|
|
for vi in area:iter(minp.x, minp_y+1, minp.z, maxp.x, maxp_y, maxp.z) do
|
|
-- fortunately, area:iter iterates through y columns going upward. Just what we need!
|
|
-- We could possibly be a bit more efficient by remembering how far we dropped then
|
|
-- last liquid node in a column and moving stuff down that far,
|
|
-- but for now let's keep it simple.
|
|
drop_liquid(vi, data, area, minp_y)
|
|
end
|
|
end
|
|
|
|
vm:set_data(data)
|
|
vm:write_to_map()
|
|
vm:update_liquids()
|
|
end)
|
|
end |