MineClone2/mods/MAPGEN/mcl_villages/foundation.lua

194 lines
7.4 KiB
Lua
Raw Normal View History

local foundation_materials = {}
foundation_materials["mcl_core:sand"] = "mcl_core:sandstone"
--"mcl_core:sandstonecarved"
2024-07-19 14:56:06 +02:00
local function is_air(node)
return not node or node.name == "air" or node.name == "ignore"
end
local function is_solid(node)
if not node or node.name == "air" or node.name == "ignore" then return false end
--if string.find(node.name,"leaf") then return false end
--if string.find(node.name,"tree") then return false end
local ndef = minetest.registered_nodes[node.name]
return ndef and ndef.walkable
end
2024-07-20 02:10:25 +02:00
local function make_solid(lvm, cp, with, except)
local cur = lvm:get_node_at(cp)
if not is_solid(cur) or (except and cur.name == except) then
lvm:set_node_at(cp, {name=with})
end
end
2024-07-19 14:56:06 +02:00
local function excavate(lvm,xi,yi,zi,pr)
local pos, n, c = vector.new(xi,yi,zi), nil, 0
local node = lvm:get_node_at(pos)
if is_air(node) then return false end -- already empty, nothing to do
pos.y = pos.y-1
if not is_air(lvm:get_node_at(pos)) then return false end -- below is solid, do not clear above anymore
-- count empty nodes below otherwise
for x = xi-1,xi+1 do
for z = zi-1,zi+1 do
pos.x, pos.z = x, z
if is_air(lvm:get_node_at(pos)) then c = c + 1 end
end
end
2024-07-19 14:56:06 +02:00
-- try to completely remove trees overhead
if not string.find(node.name, "leaf") and not string.find(node.name, "tree") then
-- stop randomly depending on fill, to narrow down the caves
2024-07-20 02:10:25 +02:00
if pr:next(0,31)^2 > c * 100 then return false end
2024-07-19 14:56:06 +02:00
end
lvm:set_node_at(vector.new(xi, yi, zi),{name="air"})
return true -- modified
end
local function grow_foundation(lvm,xi,yi,zi,pr,surface_mat,platform_mat)
local pos, n, c = vector.new(xi,yi,zi), nil, 0
if is_solid(lvm:get_node_at(pos)) then return false end -- already solid, nothing to do
pos.y = pos.y+1
local cur = lvm:get_node_at(pos)
if not is_solid(cur) then return false end -- above is empty, do not fill below
if cur and cur.name and cur.name ~= surface_mat then platform_mat = cur.name end
if pr:next(1,5) == 5 then -- randomly switch to stone sometimes
platform_mat = "mcl_core:stone"
end
-- count solid nodes above otherwise
for x = xi-1,xi+1 do
for z = zi-1,zi+1 do
pos.x, pos.z = x, z
if is_solid(lvm:get_node_at(pos)) then c = c + 1 end
end
end
2024-07-19 14:56:06 +02:00
-- stop randomly depending on fill, to narrow down the foundation
2024-07-20 02:10:25 +02:00
if pr:next(0,31)^2 > c * 100 then return false end
2024-07-19 14:56:06 +02:00
lvm:set_node_at(vector.new(xi, yi, zi),{name=platform_mat})
return true -- modified
end
-------------------------------------------------------------------------------
2021-04-16 13:35:03 +02:00
-- function clear space above baseplate
-------------------------------------------------------------------------------
2024-07-19 14:56:06 +02:00
function mcl_villages.terraform(settlement_info, pr)
--local lvm, emin, emax = minetest.get_mapgen_object("voxelmanip")
local lvm = VoxelManip()
2021-01-29 19:49:33 +01:00
for i, built_house in ipairs(settlement_info) do
-- pick right schematic_info to current built_house
2024-07-19 14:56:06 +02:00
for j, schem in ipairs(mcl_villages.schematic_table) do
2021-01-29 19:49:33 +01:00
if settlement_info[i]["name"] == schem["name"] then
schematic_data = schem
break
end
end
2021-04-16 13:35:03 +02:00
local pos = settlement_info[i]["pos"]
2024-07-20 02:10:25 +02:00
local fwidth, fheight, fdepth = schematic_data["hwidth"], schematic_data["hheight"], schematic_data["hdepth"]
local surface_mat = settlement_info[i]["surface_mat"]
2024-07-20 02:10:25 +02:00
if settlement_info[i]["rotat"] == "90" or settlement_info[i]["rotat"] == "270" then
fwidth, fdepth = fdepth, fwidth
end
2024-07-19 14:56:06 +02:00
lvm:read_from_map(vector.new(pos.x-2, pos.y-20, pos.z-2), vector.new(pos.x+fwidth+2, pos.y+fheight+20, pos.z+fdepth+2))
lvm:get_data()
2024-07-20 02:10:25 +02:00
mcl_villages.foundation(lvm, pos, fwidth, fheight, fdepth, surface_mat, pr)
lvm:write_to_map(false)
end
end
function mcl_villages.foundation(lvm, pos, fwidth, fheight, fdepth, surface_mat, pr)
-- TODO: further optimize by using raw data arrays instead of set_node_at. But OK for a first draft.
local platform_mat = foundation_materials[surface_mat] or "mcl_core:dirt"
-- excavate the needed volume, some headroom, and add a baseplate
local p2 = vector.new(pos)
for xi = pos.x,pos.x+fwidth-1 do
for zi = pos.z,pos.z+fdepth-1 do
lvm:set_node_at(vector.new(xi, pos.y+1, zi),{name="air"})
-- pos.y+2 to pos.y+5 are filled larger below!
for yi = pos.y+6,pos.y+fheight do
lvm:set_node_at(vector.new(xi, yi, zi),{name="air"})
2024-07-19 14:56:06 +02:00
end
2024-07-20 02:10:25 +02:00
make_solid(lvm, vector.new(xi, pos.y, zi), surface_mat, platform_mat)
make_solid(lvm, vector.new(xi, pos.y - 1, zi), platform_mat)
2024-07-19 14:56:06 +02:00
end
2024-07-20 02:10:25 +02:00
end
-- slightly widen the cave, to make easier to enter for mobs
for xi = pos.x-1,pos.x+fwidth do
for zi = pos.z-1,pos.z+fdepth do
for yi = pos.y+2,pos.y+5 do
lvm:set_node_at(vector.new(xi, yi, zi),{name="air"})
2024-07-19 14:56:06 +02:00
end
end
2024-07-20 02:10:25 +02:00
end
-- some extra gaps
for xi = pos.x-2,pos.x+fwidth+1 do
for zi = pos.z-2,pos.z+fdepth+1 do
if pr:next(1,4) == 1 then
for yi = pos.y+3,pos.y+5 do
lvm:set_node_at(vector.new(xi, yi, zi),{name="air"})
2024-07-19 14:56:06 +02:00
end
end
end
2024-07-20 02:10:25 +02:00
end
-- slightly widen the baseplate, to make easier to enter for mobs
for xi = pos.x,pos.x+fwidth-1 do
make_solid(lvm, vector.new(xi, pos.y-1, pos.z-1), surface_mat, platform_mat)
make_solid(lvm, vector.new(xi, pos.y-1, pos.z), platform_mat)
make_solid(lvm, vector.new(xi, pos.y-1, pos.z+fdepth-1), platform_mat)
make_solid(lvm, vector.new(xi, pos.y-1, pos.z+fdepth), surface_mat, platform_mat)
end
for zi = pos.z,pos.z+fdepth-1 do
make_solid(lvm, vector.new(pos.x-1, pos.y-1, zi), surface_mat, platform_mat)
make_solid(lvm, vector.new(pos.x, pos.y-1, zi), platform_mat)
make_solid(lvm, vector.new(pos.x+fwidth-1, pos.y-1, zi), platform_mat)
make_solid(lvm, vector.new(pos.x+fwidth, pos.y-1, zi), surface_mat, platform_mat)
end
-- make some additional steps, along both x sides
for xi = pos.x,pos.x+fwidth-1 do
local cp = vector.new(xi, pos.y-3, pos.z-1)
if is_solid(lvm:get_node_at(cp)) then
cp = vector.new(xi, pos.y-2, pos.z-1)
make_solid(lvm, cp, surface_mat, platform_mat)
cp.z = pos.z-2
make_solid(lvm, cp, surface_mat, platform_mat)
2024-07-19 14:56:06 +02:00
end
2024-07-20 02:10:25 +02:00
local cp = vector.new(xi, pos.y-3, pos.z+fdepth)
if is_solid(lvm:get_node_at(cp)) then
cp = vector.new(xi, pos.y-2, pos.z+fdepth)
make_solid(lvm, cp, surface_mat, platform_mat)
cp.z = pos.z + fdepth + 1
make_solid(lvm, cp, surface_mat, platform_mat)
2024-07-19 14:56:06 +02:00
end
2024-07-20 02:10:25 +02:00
end
-- make some additional steps, along both z sides
for zi = pos.z,pos.z+fdepth-1 do
local cp = vector.new(pos.x-1, pos.y-3, zi)
if is_solid(lvm:get_node_at(cp)) then
cp = vector.new(pos.x-1, pos.y-2, zi)
make_solid(lvm, cp, surface_mat, platform_mat)
cp.x = pos.x-2
make_solid(lvm, cp, surface_mat, platform_mat)
2024-07-19 14:56:06 +02:00
end
2024-07-20 02:10:25 +02:00
local cp = vector.new(pos.x+fwidth, pos.y-3, zi)
if is_solid(lvm:get_node_at(cp)) then
cp = vector.new(pos.x+fwidth, pos.y-2, zi)
make_solid(lvm, cp, surface_mat, platform_mat)
cp.x = pos.x+fwidth+1
make_solid(lvm, cp, surface_mat, platform_mat)
2024-07-19 14:56:06 +02:00
end
2024-07-20 02:10:25 +02:00
end
-- cave some additional area overhead, try to make it interesting though
for yi = pos.y+3,pos.y+fheight*3 do
local active = false
for xi = pos.x-2,pos.x+fwidth+1 do
for zi = pos.z-2,pos.z+fdepth+1 do
if excavate(lvm,xi,yi,zi,pr) then active = true end
2024-07-19 14:56:06 +02:00
end
end
2024-07-20 02:10:25 +02:00
if not active and yi > pos.y+fheight+5 then break end
end
-- construct additional baseplate below, also try to make it interesting
for yi = pos.y-2,pos.y-20,-1 do
local active = false
for xi = pos.x-1,pos.x+fwidth do
for zi = pos.z-1,pos.z+fdepth do
if grow_foundation(lvm,xi,yi,zi,pr,surface_mat,platform_mat) then active = true end
2021-01-29 19:49:33 +01:00
end
end
2024-07-20 02:10:25 +02:00
if not active and yi < pos.y-5 then break end
2021-01-29 19:49:33 +01:00
end
end