diff --git a/mods/MAPGEN/mcl_villages/buildings.lua b/mods/MAPGEN/mcl_villages/buildings.lua index 030c3a7c9..bf378d9f5 100644 --- a/mods/MAPGEN/mcl_villages/buildings.lua +++ b/mods/MAPGEN/mcl_villages/buildings.lua @@ -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)) diff --git a/mods/MAPGEN/mcl_villages/init.lua b/mods/MAPGEN/mcl_villages/init.lua index af8617edd..7513c01f8 100644 --- a/mods/MAPGEN/mcl_villages/init.lua +++ b/mods/MAPGEN/mcl_villages/init.lua @@ -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") diff --git a/mods/MAPGEN/mcl_villages/utils.lua b/mods/MAPGEN/mcl_villages/utils.lua index e0ca75422..fc6868110 100644 --- a/mods/MAPGEN/mcl_villages/utils.lua +++ b/mods/MAPGEN/mcl_villages/utils.lua @@ -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