fixes and parameter tuning

This commit is contained in:
kno10 2024-07-24 17:29:40 +02:00
parent 5b520d8713
commit eb2b1f8704
3 changed files with 53 additions and 60 deletions

View file

@ -106,7 +106,7 @@ local function check_ground(lvm, cpos, size)
if pos_c then table.insert(ys, pos_c.y) end
table.sort(ys)
-- well supported base, not too uneven?
if #ys < 5 or ys[#ys]-ys[1] > 6 then return nil, nil end
if #ys < 5 or ys[#ys]-ys[1] > 8 then return nil, nil end
cpos.y = math.floor(0.5 * (ys[math.floor(#ys/2)] + ys[math.ceil(#ys/2)]) + 0.5) -- median, rounded
return cpos, surface_material
end
@ -120,13 +120,13 @@ end
local function layout_town(lvm, minp, maxp, pr, input_settlement)
local center = vector.new(pr:next(minp.x + 24, maxp.x - 24), maxp.y, pr:next(minp.z + 24, maxp.z - 24))
minetest.log("action", "[mcl_villages] sudo make me a village at: " .. minetest.pos_to_string(center))
minetest.log("action", "[mcl_villages] sudo make me a village at: " .. minetest.pos_to_string(minp).." - "..minetest.pos_to_string(maxp))
local possible_rotations = {"0", "90", "180", "270"}
local center_surface
local settlement = {}
-- now some buildings around in a circle, radius = size of town center
local x, y, z, r, lastr = center.x, maxp.y, center.z, 0, 99
local x, y, z, r, lastr = center.x, center.y, center.z, 0, 99
local mindist = 4
if #input_settlement >= 12 then mindist = 3 end
-- draw j circles around center and increase radius by math.random(2,4)
@ -152,10 +152,10 @@ local function layout_town(lvm, minp, maxp, pr, input_settlement)
if pos and mcl_villages.check_distance(settlement, cpos, size.x, size.z, mindist) then
-- use town bell as new reference point for placement height
if #settlement == 0 then
center_surface, y = cpos, pos.y + mcl_villages.max_height_difference * 0.5 + 1
center_surface, y = cpos, math.min(maxp.y, pos.y + mcl_villages.max_height_difference * 0.5 + 1)
end
-- limit height differences to town center, but gradually
if math.abs(pos.y - center_surface.y) <= mcl_villages.max_height_difference * (0.3 + math.min(r/30,0.5)) then
-- limit height differences to town center, but gradually allow more
if math.abs(pos.y - center_surface.y) <= mcl_villages.max_height_difference * (0.25 + math.min(r/30,0.5)) then
local minp = vector.offset(pos, -math.floor(size.x/2), building.yadjust, -math.floor(size.z/2))
building.minp = minp
building.maxp = vector.offset(minp, size.x, size.y, size.z)
@ -164,22 +164,23 @@ local function layout_town(lvm, minp, maxp, pr, input_settlement)
building.rotation = rotation
building.surface_mat = surface_material
table.insert(settlement, building)
-- minetest.log("verbose", "[mcl_villages] Placing "..schema["name"].." at "..minetest.pos_to_string(pos))
-- minetest.log("verbose", "[mcl_villages] Planning "..schema["name"].." at "..minetest.pos_to_string(pos))
lastr = r
--else
-- minetest.log("Height difference "..math.abs(pos.y - center_surface.y))
else
minetest.log("verbose", "Too large height difference "..math.abs(pos.y - center_surface.y).." at distance "..r)
end
end
end
end
r = r + pr:next(2,4)
if r > lastr + 25 then -- too disconnected
if r > lastr + 20 then -- too disconnected
minetest.log("verbose", "Disconnected village "..r.." > "..lastr)
break
end
end
-- minetest.log("verbose", "Planned "..#input_settlement.." buildings, placed "..#settlement)
if #settlement < #input_settlement and #settlement < 6 then
minetest.log("action", "[mcl_villages] Bad village location, could only place "..#settlement.." buildings.")
minetest.log("action", "[mcl_villages] Bad village location, could only place "..#settlement.." buildings at "..minetest.pos_to_string(center))
return
end
minetest.log("action", "[mcl_villages] village plan completed at " .. minetest.pos_to_string(center))

View file

@ -1,7 +1,7 @@
mcl_villages = {}
mcl_villages.modpath = minetest.get_modpath(minetest.get_current_modname())
local village_chance = tonumber(minetest.settings:get("mcl_villages_village_probability")) or 5
local village_chance = tonumber(minetest.settings:get("mcl_villages_village_probability")) or 1
dofile(mcl_villages.modpath.."/const.lua")
dofile(mcl_villages.modpath.."/utils.lua")
@ -25,21 +25,16 @@ minetest.register_node("mcl_villages:structblock", {drawtype="airlike",groups =
--
local function build_a_settlement(minp, maxp, blockseed)
if mcl_villages.village_exists(blockseed) then return end
local pr = PseudoRandom(blockseed)
local settlement = mcl_villages.create_site_plan(minp, maxp, pr)
if not settlement then return end
local lvm, emin, emax = minetest.get_mapgen_object("voxelmanip")
lvm:get_data()
-- all foundations first, then all buildings, to avoid damaging very close buildings
--mcl_villages.terraform(lvm, settlement, pr)
--mcl_villages.place_schematics(lvm, settlement, pr)
lvm:write_to_map(false)
-- TODO: replace with MCLA code: mcl_villages.paths(settlement)
local pr = PcgRandom(blockseed)
local lvm = VoxelManip()
lvm:read_from_map(minp, maxp)
local settlement = mcl_villages.create_site_plan(lvm, minp, maxp, pr)
if not settlement then return false, false end
-- all foundations first, then all buildings, to avoid damaging very close buildings
mcl_villages.terraform(lvm, settlement, pr)
mcl_villages.place_schematics(lvm, settlement, blockseed, pr)
mcl_villages.add_village(blockseed, settlement)
--lvm:write_to_map(false)
for _, on_village_placed_callback in pairs(mcl_villages.on_village_placed) do
on_village_placed_callback(settlement, blockseed)
end
@ -144,9 +139,9 @@ if minetest.is_creative_enabled("") then
minetest.chat_send_player(placer:get_player_name(), S("Placement denied. You need the “server” privilege to place villages."))
return
end
local minp = vector.subtract(pointed_thing.under, half_map_chunk_size)
local maxp = vector.add(pointed_thing.under, half_map_chunk_size)
--build_a_settlement(minp, maxp, math.random(0,32767))
local minp = vector.subtract(pointed_thing.under, mcl_villages.half_map_chunk_size)
local maxp = vector.add(pointed_thing.under, mcl_villages.half_map_chunk_size)
build_a_settlement(minp, maxp, math.random(0,32767))
end
})
mcl_wip.register_experimental_item("mcl_villages:tool")

View file

@ -1,43 +1,39 @@
-------------------------------------------------------------------------------
-- function to copy tables
-------------------------------------------------------------------------------
function mcl_villages.shallowCopy(original)
local copy = {}
for key, value in pairs(original) do
copy[key] = value
end
return copy
end
local function is_above_surface(name)
return name == "air" or
string.find(name,"grass") or
-- note: not dirt_with_grass!
string.find(name,"tree") or
string.find(name,"leaves") or
string.find(name,"snow") or
string.find(name,"fern") or
string.find(name,"flower") or
string.find(name,"flower") or -- includes grass decorations
string.find(name,"bush")
end
function mcl_villages.find_surface_down(lvm, pos, surface_node)
local p6 = vector.new(pos)
surface_node = surface_node or lvm:get_node_at(p6)
if not surface_node then return end
for y = p6.y - 1, math.max(0,p6.y - 120), -1 do
local has_air = is_above_surface(surface_node.name)
for y = p6.y - 1, math.max(0,p6.y - 80), -1 do
p6.y = y
local top_node = surface_node
surface_node = lvm:get_node_at(p6)
if not surface_node then return nil end
if is_above_surface(top_node.name) then
if mcl_villages.surface_mat[surface_node.name] then
-- minetest.log("verbose", "Found "..surface_node.name.." below "..top_node.name)
return p6, surface_node
end
if not surface_node or surface_node.name == "ignore" then return nil end
if is_above_surface(surface_node.name) then
has_air = true
else
local ndef = minetest.registered_nodes[surface_node.name]
if ndef and ndef.walkable then
return nil
if has_air then
if mcl_villages.surface_mat[surface_node.name] then
--minetest.log("Found "..surface_node.name.." below "..top_node.name)
return p6, surface_node
else
local ndef = minetest.registered_nodes[surface_node.name]
if ndef and ndef.walkable then
--minetest.log("Found non-suitable "..surface_node.name.." below "..top_node.name)
return nil
end
end
end
has_air = false
end
end
end
@ -45,20 +41,21 @@ function mcl_villages.find_surface_up(lvm, pos, surface_node)
local p6 = vector.new(pos)
surface_node = surface_node or lvm:get_node_at(p6) --, true, 1000000)
if not surface_node then return end
for y = p6.y + 1, p6.y + 50 do
for y = p6.y + 1, p6.y + 80 do
p6.y = y
local top_node = lvm:get_node_at(p6)
if not top_node then return nil end
if not top_node or top_node.name == "ignore" then return nil end
if is_above_surface(top_node.name) then
if mcl_villages.surface_mat[surface_node.name] then
-- minetest.log("verbose","Found "..surface_node.name.." below "..top_node.name)
-- minetest.log("Found "..surface_node.name.." below "..top_node.name)
p6.y = p6.y - 1
return p6, surface_node
end
else
local ndef = minetest.registered_nodes[surface_node.name]
if ndef and ndef.walkable then
return nil
else
local ndef = minetest.registered_nodes[surface_node.name]
if ndef and ndef.walkable then
-- minetest.log("Found non-suitable "..surface_node.name.." below "..top_node.name)
return nil
end
end
end
surface_node = top_node