mirror of
https://git.minetest.land/MineClone2/MineClone2.git
synced 2025-01-10 18:47:31 +01:00
Big villages overhaul
This commit is contained in:
parent
ad6a3792f3
commit
2ec440132a
@ -2,7 +2,7 @@
|
|||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- build schematic, replace material, rotation
|
-- build schematic, replace material, rotation
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
function settlements.build_schematic(vm, data, va, pos, building, replace_wall, name)
|
function mcl_villages.build_schematic(vm, data, va, pos, building, replace_wall, name)
|
||||||
-- get building node material for better integration to surrounding
|
-- get building node material for better integration to surrounding
|
||||||
local platform_material = mcl_vars.get_node(pos)
|
local platform_material = mcl_vars.get_node(pos)
|
||||||
if not platform_material or (platform_material.name == "air" or platform_material.name == "ignore") then
|
if not platform_material or (platform_material.name == "air" or platform_material.name == "ignore") then
|
||||||
@ -36,7 +36,7 @@ function settlements.build_schematic(vm, data, va, pos, building, replace_wall,
|
|||||||
local height = schematic["size"]["y"]
|
local height = schematic["size"]["y"]
|
||||||
local possible_rotations = {"0", "90", "180", "270"}
|
local possible_rotations = {"0", "90", "180", "270"}
|
||||||
local rotation = possible_rotations[ math.random( #possible_rotations ) ]
|
local rotation = possible_rotations[ math.random( #possible_rotations ) ]
|
||||||
settlements.foundation(
|
mcl_villages.foundation(
|
||||||
pos,
|
pos,
|
||||||
width,
|
width,
|
||||||
depth,
|
depth,
|
||||||
@ -57,123 +57,125 @@ end]]
|
|||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- initialize settlement_info
|
-- initialize settlement_info
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
function settlements.initialize_settlement_info(pr)
|
function mcl_villages.initialize_settlement_info(pr)
|
||||||
local count_buildings = {}
|
local count_buildings = {}
|
||||||
|
|
||||||
-- count_buildings table reset
|
-- count_buildings table reset
|
||||||
for k,v in pairs(settlements.schematic_table) do
|
for k,v in pairs(mcl_villages.schematic_table) do
|
||||||
count_buildings[v["name"]] = 0
|
count_buildings[v["name"]] = 0
|
||||||
end
|
end
|
||||||
|
|
||||||
-- randomize number of buildings
|
-- randomize number of buildings
|
||||||
local number_of_buildings = pr:next(10, 25)
|
local number_of_buildings = pr:next(10, 25)
|
||||||
local number_built = 1
|
local number_built = 0
|
||||||
settlements.debug("Village ".. number_of_buildings)
|
mcl_villages.debug("Village ".. number_of_buildings)
|
||||||
|
|
||||||
return count_buildings, number_of_buildings, number_built
|
return count_buildings, number_of_buildings, number_built
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
-- check ground for a single building
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
local function try_place_building(pos_surface, building_all_info, rotation, settlement_info, pr)
|
||||||
|
local fwidth, fdepth = building_all_info["hwidth"], building_all_info["hdepth"]
|
||||||
|
if rotation == "90" or rotation == "270" then fwidth, fdepth = fdepth, fwidth end
|
||||||
|
local fheight = building_all_info["hheight"]
|
||||||
|
-- use building centers for better placement
|
||||||
|
pos_surface.x = pos_surface.x - math.ceil(fwidth / 2)
|
||||||
|
pos_surface.z = pos_surface.z - math.ceil(fdepth / 2)
|
||||||
|
-- to find the y position, also check the corners
|
||||||
|
local ys = {pos_surface.y}
|
||||||
|
local pos_c
|
||||||
|
pos_c = mcl_villages.find_surface_down(vector.new(pos_surface.x-1, pos_surface.y+fheight, pos_surface.z-1))
|
||||||
|
if pos_c then table.insert(ys, pos_c.y) end
|
||||||
|
pos_c = mcl_villages.find_surface_down(vector.new(pos_surface.x+fwidth+2, pos_surface.y+fheight, pos_surface.z-1))
|
||||||
|
if pos_c then table.insert(ys, pos_c.y) end
|
||||||
|
pos_c = mcl_villages.find_surface_down(vector.new(pos_surface.x-1, pos_surface.y+fheight, pos_surface.z+fdepth+2))
|
||||||
|
if pos_c then table.insert(ys, pos_c.y) end
|
||||||
|
pos_c = mcl_villages.find_surface_down(vector.new(pos_surface.x+fwidth+2, pos_surface.y+fheight, pos_surface.z+fdepth+2))
|
||||||
|
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] > fheight + 3 then return nil end
|
||||||
|
pos_surface.y = ys[math.ceil(#ys/2)]
|
||||||
|
-- check distance to other buildings
|
||||||
|
if mcl_villages.check_distance(settlement_info, pos_surface, building_all_info["hsize"]) then
|
||||||
|
return pos_surface
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- fill settlement_info
|
-- fill settlement_info
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
function settlements.create_site_plan(maxp, minp, pr)
|
function mcl_villages.create_site_plan(minp, maxp, pr)
|
||||||
local settlement_info = {}
|
local center = vector.new(math.floor((minp.x+maxp.x)/2),maxp.y,math.floor((minp.z+maxp.z)/2))
|
||||||
local building_all_info
|
minetest.log("action", "sudo make me a village at: " .. minetest.pos_to_string(center))
|
||||||
local possible_rotations = {"0", "90", "180", "270"}
|
local possible_rotations = {"0", "90", "180", "270"}
|
||||||
|
local center_surface
|
||||||
|
|
||||||
-- find center of chunk
|
local count_buildings, number_of_buildings, number_built = mcl_villages.initialize_settlement_info(pr)
|
||||||
local center = {
|
local settlement_info = {}
|
||||||
x=math.floor((minp.x+maxp.x)/2),
|
|
||||||
y=maxp.y,
|
|
||||||
z=math.floor((minp.z+maxp.z)/2)
|
|
||||||
}
|
|
||||||
|
|
||||||
-- find center_surface of chunk
|
|
||||||
local center_surface , surface_material = settlements.find_surface(center, true)
|
|
||||||
local chunks = {}
|
|
||||||
chunks[mcl_vars.get_chunk_number(center)] = true
|
|
||||||
|
|
||||||
-- go build settlement around center
|
|
||||||
if not center_surface then
|
|
||||||
minetest.log("action", "Cannot build village at: " .. minetest.pos_to_string(center))
|
|
||||||
return false
|
|
||||||
else
|
|
||||||
minetest.log("action", "Village built.")
|
|
||||||
--minetest.log("action", "Build village at: " .. minetest.pos_to_string(center) .. " with surface material: " .. surface_material)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- initialize all settlement_info table
|
|
||||||
local count_buildings, number_of_buildings, number_built = settlements.initialize_settlement_info(pr)
|
|
||||||
-- first building is townhall in the center
|
|
||||||
building_all_info = settlements.schematic_table[1]
|
|
||||||
local rotation = possible_rotations[ pr:next(1, #possible_rotations ) ]
|
|
||||||
-- add to settlement info table
|
|
||||||
local index = 1
|
|
||||||
settlement_info[index] = {
|
|
||||||
pos = center_surface,
|
|
||||||
name = building_all_info["name"],
|
|
||||||
hsize = building_all_info["hsize"],
|
|
||||||
rotat = rotation,
|
|
||||||
surface_mat = surface_material
|
|
||||||
}
|
|
||||||
--increase index for following buildings
|
|
||||||
index = index + 1
|
|
||||||
-- now some buildings around in a circle, radius = size of town center
|
-- now some buildings around in a circle, radius = size of town center
|
||||||
local x, z, r = center_surface.x, center_surface.z, building_all_info["hsize"]
|
local x, y, z, r = center.x, maxp.y, center.z, 0
|
||||||
-- draw j circles around center and increase radius by math.random(2,5)
|
-- draw j circles around center and increase radius by math.random(2,5)
|
||||||
for j = 1,20 do
|
for j = 1,10 do
|
||||||
-- set position on imaginary circle
|
for angle = 0, math.pi*2, 0.262 do -- 24 attempts on a circle
|
||||||
for j = 0, 360, 15 do
|
local pos1 = vector.new(math.floor(x + r * math.cos(angle) + 0.5), y, math.floor(z - r * math.sin(angle) + 0.5))
|
||||||
local angle = j * math.pi / 180
|
local pos_surface, surface_material = mcl_villages.find_surface(pos1, false)
|
||||||
local ptx, ptz = x + r * math.cos( angle ), z + r * math.sin( angle )
|
if pos_surface then
|
||||||
ptx = settlements.round(ptx, 0)
|
local randomized_schematic_table = mcl_villages.shuffle(mcl_villages.schematic_table, pr)
|
||||||
ptz = settlements.round(ptz, 0)
|
if #settlement_info == 0 then randomized_schematic_table = { mcl_villages.schematic_table[1] } end -- place town bell first
|
||||||
local pos1 = { x=ptx, y=center_surface.y+50, z=ptz}
|
-- pick schematic
|
||||||
local chunk_number = mcl_vars.get_chunk_number(pos1)
|
local size = #randomized_schematic_table
|
||||||
local pos_surface, surface_material
|
for i = 1, #randomized_schematic_table do
|
||||||
if chunks[chunk_number] then
|
local building_all_info = randomized_schematic_table[i]
|
||||||
pos_surface, surface_material = settlements.find_surface(pos1)
|
-- already enough buildings of that type?
|
||||||
else
|
if count_buildings[building_all_info["name"]] < building_all_info["max_num"]*number_of_buildings then
|
||||||
chunks[chunk_number] = true
|
local rotation = possible_rotations[pr:next(1, #possible_rotations)]
|
||||||
pos_surface, surface_material = settlements.find_surface(pos1, true)
|
local pos = try_place_building(pos_surface, building_all_info, rotation, settlement_info, pr)
|
||||||
end
|
if pos then
|
||||||
if not pos_surface then break end
|
if #settlement_info == 0 then -- town bell
|
||||||
|
center_surface, y = pos, pos.y + max_height_difference
|
||||||
|
end
|
||||||
|
-- limit height differences to town center
|
||||||
|
if math.abs(pos.y - center_surface.y) > max_height_difference * 0.7 then
|
||||||
|
break -- other buildings likely will not fit either
|
||||||
|
end
|
||||||
|
count_buildings[building_all_info["name"]] = count_buildings[building_all_info["name"]] +1
|
||||||
|
number_built = number_built + 1
|
||||||
|
|
||||||
local randomized_schematic_table = shuffle(settlements.schematic_table, pr)
|
pos.y = pos.y + (building_all_info["yadjust"] or 0)
|
||||||
-- pick schematic
|
table.insert(settlement_info, {
|
||||||
local size = #randomized_schematic_table
|
pos = pos,
|
||||||
for i = size, 1, -1 do
|
name = building_all_info["name"],
|
||||||
-- already enough buildings of that type?
|
hsize = building_all_info["hsize"],
|
||||||
if count_buildings[randomized_schematic_table[i]["name"]] < randomized_schematic_table[i]["max_num"]*number_of_buildings then
|
rotat = rotation,
|
||||||
building_all_info = randomized_schematic_table[i]
|
surface_mat = surface_material
|
||||||
-- check distance to other buildings
|
})
|
||||||
local distance_to_other_buildings_ok = settlements.check_distance(settlement_info, pos_surface, building_all_info["hsize"])
|
-- minetest.log("action", "Placing "..building_all_info["name"].." at "..minetest.pos_to_string(pos))
|
||||||
if distance_to_other_buildings_ok then
|
break
|
||||||
-- count built houses
|
end
|
||||||
count_buildings[building_all_info["name"]] = count_buildings[building_all_info["name"]] +1
|
|
||||||
rotation = possible_rotations[ pr:next(1, #possible_rotations ) ]
|
|
||||||
number_built = number_built + 1
|
|
||||||
settlement_info[index] = {
|
|
||||||
pos = pos_surface,
|
|
||||||
name = building_all_info["name"],
|
|
||||||
hsize = building_all_info["hsize"],
|
|
||||||
rotat = rotation,
|
|
||||||
surface_mat = surface_material
|
|
||||||
}
|
|
||||||
index = index + 1
|
|
||||||
break
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if number_of_buildings == number_built then
|
||||||
|
break
|
||||||
|
end
|
||||||
end
|
end
|
||||||
if number_of_buildings == number_built then
|
if r == 0 then break end -- no angles in the very center
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
if number_built >= number_of_buildings then
|
if number_built >= number_of_buildings then
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
r = r + pr:next(2,5)
|
r = r + pr:next(2,5)
|
||||||
|
if r > 35 then break end -- avoid touching neighboring blocks
|
||||||
end
|
end
|
||||||
settlements.debug("really ".. number_built)
|
mcl_villages.debug("really ".. number_built)
|
||||||
|
if number_built <= 8 then
|
||||||
|
minetest.log("action", "Bad village location, could only place "..number_built.." buildings.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
minetest.log("action", "Village completed at " .. minetest.pos_to_string(center))
|
||||||
|
minetest.log("Village completed at " .. minetest.pos_to_string(center)) -- for debugging only
|
||||||
return settlement_info
|
return settlement_info
|
||||||
end
|
end
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
@ -201,6 +203,7 @@ local function spawn_iron_golem(pos)
|
|||||||
--minetest.log("action", "Attempt to spawn iron golem.")
|
--minetest.log("action", "Attempt to spawn iron golem.")
|
||||||
local p = minetest.find_node_near(pos,50,"mcl_core:grass_path")
|
local p = minetest.find_node_near(pos,50,"mcl_core:grass_path")
|
||||||
if p then
|
if p then
|
||||||
|
p.y = p.y + 1
|
||||||
local l=minetest.add_entity(p,"mobs_mc:iron_golem"):get_luaentity()
|
local l=minetest.add_entity(p,"mobs_mc:iron_golem"):get_luaentity()
|
||||||
if l then
|
if l then
|
||||||
l._home = p
|
l._home = p
|
||||||
@ -245,100 +248,63 @@ local function init_nodes(p1, p2, size, rotation, pr)
|
|||||||
if nodes and #nodes > 0 then
|
if nodes and #nodes > 0 then
|
||||||
for p=1, #nodes do
|
for p=1, #nodes do
|
||||||
local pos = nodes[p]
|
local pos = nodes[p]
|
||||||
settlements.fill_chest(pos, pr)
|
mcl_villages.fill_chest(pos, pr)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function settlements.place_schematics(settlement_info, pr)
|
function mcl_villages.place_schematics(settlement_info, pr)
|
||||||
local building_all_info
|
local building_all_info
|
||||||
|
local lvm = VoxelManip()
|
||||||
|
|
||||||
for i, built_house in ipairs(settlement_info) do
|
for i, built_house in ipairs(settlement_info) do
|
||||||
local is_last = i == #settlement_info
|
local is_last = i == #settlement_info
|
||||||
|
|
||||||
for j, schem in ipairs(settlements.schematic_table) do
|
for j, schem in ipairs(mcl_villages.schematic_table) do
|
||||||
if settlement_info[i]["name"] == schem["name"] then
|
if settlement_info[i]["name"] == schem["name"] then
|
||||||
building_all_info = schem
|
building_all_info = schem
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local pos = settlement_info[i]["pos"]
|
local pos = settlement_info[i]["pos"]
|
||||||
local rotation = settlement_info[i]["rotat"]
|
local rotation = settlement_info[i]["rotat"]
|
||||||
-- get building node material for better integration to surrounding
|
-- get building node material for better integration to surrounding
|
||||||
local platform_material = settlement_info[i]["surface_mat"]
|
local surface_material = settlement_info[i]["surface_mat"] or "mcl_core:stone"
|
||||||
--platform_material_name = minetest.get_name_from_content_id(platform_material)
|
local platform_material = surface_material
|
||||||
-- pick random material
|
local schem_lua = building_all_info["schem_lua"]
|
||||||
--local material = wallmaterial[pr:next(1,#wallmaterial)]
|
if not schem_lua then
|
||||||
--
|
schem_lua = minetest.serialize_schematic(building_all_info["mts"], "lua", { lua_use_comments = false, lua_num_indent_spaces = 0 }) .. " return schematic"
|
||||||
local building = building_all_info["mts"]
|
building_all_info["schem_lua"] = schem_lua
|
||||||
local replace_wall = building_all_info["rplc"]
|
|
||||||
-- schematic conversion to lua
|
|
||||||
local schem_lua = minetest.serialize_schematic(building,
|
|
||||||
"lua",
|
|
||||||
{lua_use_comments = false, lua_num_indent_spaces = 0}).." return schematic"
|
|
||||||
schem_lua = schem_lua:gsub("mcl_core:stonebrickcarved", "mcl_villages:stonebrickcarved")
|
|
||||||
-- replace material
|
|
||||||
if replace_wall then
|
|
||||||
--Note, block substitution isn't matching node names exactly; so nodes that are to be substituted that have the same prefixes cause bugs.
|
|
||||||
-- Example: Attempting to swap out 'mcl_core:stonebrick'; which has multiple, additional sub-variants: (carved, cracked, mossy). Will currently cause issues, so leaving disabled.
|
|
||||||
if platform_material == "mcl_core:snow" or platform_material == "mcl_core:dirt_with_grass_snow" or platform_material == "mcl_core:podzol" then
|
|
||||||
schem_lua = schem_lua:gsub("mcl_core:tree", "mcl_core:sprucetree")
|
|
||||||
schem_lua = schem_lua:gsub("mcl_core:wood", "mcl_core:sprucewood")
|
|
||||||
--schem_lua = schem_lua:gsub("mcl_fences:fence", "mcl_fences:spruce_fence")
|
|
||||||
--schem_lua = schem_lua:gsub("mcl_stairs:slab_wood_top", "mcl_stairs:slab_sprucewood_top")
|
|
||||||
--schem_lua = schem_lua:gsub("mcl_stairs:stair_wood", "mcl_stairs:stair_sprucewood")
|
|
||||||
--schem_lua = schem_lua:gsub("mesecons_pressureplates:pressure_plate_wood_off", "mesecons_pressureplates:pressure_plate_sprucewood_off")
|
|
||||||
elseif platform_material == "mcl_core:sand" or platform_material == "mcl_core:redsand" then
|
|
||||||
schem_lua = schem_lua:gsub("mcl_core:tree", "mcl_core:sandstonecarved")
|
|
||||||
schem_lua = schem_lua:gsub("mcl_core:cobble", "mcl_core:sandstone")
|
|
||||||
schem_lua = schem_lua:gsub("mcl_core:wood", "mcl_core:sandstonesmooth")
|
|
||||||
--schem_lua = schem_lua:gsub("mcl_fences:fence", "mcl_fences:birch_fence")
|
|
||||||
--schem_lua = schem_lua:gsub("mcl_stairs:slab_wood_top", "mcl_stairs:slab_birchwood_top")
|
|
||||||
--schem_lua = schem_lua:gsub("mcl_stairs:stair_wood", "mcl_stairs:stair_birchwood")
|
|
||||||
--schem_lua = schem_lua:gsub("mesecons_pressureplates:pressure_plate_wood_off", "mesecons_pressureplates:pressure_plate_birchwood_off")
|
|
||||||
--schem_lua = schem_lua:gsub("mcl_stairs:stair_stonebrick", "mcl_stairs:stair_redsandstone")
|
|
||||||
--schem_lua = schem_lua:gsub("mcl_core:stonebrick", "mcl_core:redsandstonesmooth")
|
|
||||||
schem_lua = schem_lua:gsub("mcl_core:brick_block", "mcl_core:redsandstone")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
schem_lua = schem_lua:gsub("mcl_core:dirt_with_grass", platform_material)
|
schem_lua = schem_lua:gsub('"mcl_core:dirt"', '"'..platform_material..'"')
|
||||||
|
schem_lua = schem_lua:gsub('"mcl_core:dirt_with_grass"', '"'..surface_material..'"')
|
||||||
--[[ Disable special junglewood for now.
|
local schematic = loadstring(mcl_villages.substitute_materials(pos, schem_lua, pr))()
|
||||||
-- special material for spawning npcs
|
|
||||||
schem_lua = schem_lua:gsub("mcl_core:junglewood", "settlements:junglewood")
|
|
||||||
--]]
|
|
||||||
|
|
||||||
schem_lua = schem_lua:gsub("mcl_stairs:stair_wood_outer", "mcl_stairs:slab_wood")
|
|
||||||
schem_lua = schem_lua:gsub("mcl_stairs:stair_stone_rough_outer", "air")
|
|
||||||
|
|
||||||
-- format schematic string
|
|
||||||
local schematic = loadstring(schem_lua)()
|
|
||||||
|
|
||||||
local is_belltower = building_all_info["name"] == "belltower"
|
local is_belltower = building_all_info["name"] == "belltower"
|
||||||
|
|
||||||
-- build foundation for the building an make room above
|
-- already built the foundation for the building and made room above
|
||||||
|
local sx, sy, sz = schematic.size.x, schematic.size.y, schematic.size.z
|
||||||
mcl_structures.place_schematic(
|
local p2 = vector.new(pos.x+sx-1,pos.y+sy-1,pos.z+sz-1)
|
||||||
|
lvm:read_from_map(pos, p2)
|
||||||
|
minetest.place_schematic_on_vmanip(
|
||||||
|
lvm,
|
||||||
pos,
|
pos,
|
||||||
schematic,
|
schematic,
|
||||||
rotation,
|
rotation,
|
||||||
nil,
|
nil,
|
||||||
true,
|
true,
|
||||||
nil,
|
{ place_center_x = false, place_center_y = false, place_center_z = false }
|
||||||
function(p1, p2, size, rotation, pr)
|
|
||||||
if is_belltower then
|
|
||||||
spawn_iron_golem(p1)
|
|
||||||
else
|
|
||||||
init_nodes(p1, p2, size, rotation, pr)
|
|
||||||
spawn_villagers(p1,p2)
|
|
||||||
fix_village_water(p1,p2)
|
|
||||||
end
|
|
||||||
end,
|
|
||||||
pr
|
|
||||||
)
|
)
|
||||||
|
lvm:write_to_map(true) -- FIXME: postpone
|
||||||
|
if rotation == "90" or rotation == "270" then sx, sz = sz, sx end
|
||||||
|
init_nodes(pos, p2, schematic.size, rotation, pr)
|
||||||
|
|
||||||
|
if is_belltower then
|
||||||
|
spawn_iron_golem(pos)
|
||||||
|
else
|
||||||
|
spawn_villagers(pos,p2)
|
||||||
|
fix_village_water(pos,p2)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
-- switch for debugging
|
-- switch for debugging
|
||||||
function settlements.debug(message)
|
function mcl_villages.debug(message)
|
||||||
-- minetest.chat_send_all(message)
|
-- minetest.chat_send_all(message)
|
||||||
-- minetest.log("warning", "[mcl_villages] "..message)
|
-- minetest.log("warning", "[mcl_villages] "..message)
|
||||||
minetest.log("verbose", "[mcl_villages] "..message)
|
minetest.log("verbose", "[mcl_villages] "..message)
|
||||||
@ -20,44 +20,51 @@ local wallmaterial = {
|
|||||||
"mcl_core:sandstonesmooth2"
|
"mcl_core:sandstonesmooth2"
|
||||||
}
|
}
|
||||||
--]]
|
--]]
|
||||||
settlements.surface_mat = {}
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- Set array to list
|
|
||||||
-- https://stackoverflow.com/questions/656199/search-for-an-item-in-a-lua-list
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
function settlements.grundstellungen()
|
|
||||||
settlements.surface_mat = settlements.Set {
|
|
||||||
"mcl_core:dirt_with_grass",
|
|
||||||
--"mcl_core:dry_dirt_with_grass",
|
|
||||||
"mcl_core:dirt_with_grass_snow",
|
|
||||||
--"mcl_core:dirt_with_dry_grass",
|
|
||||||
"mcl_core:podzol",
|
|
||||||
"mcl_core:sand",
|
|
||||||
"mcl_core:redsand",
|
|
||||||
--"mcl_core:silver_sand",
|
|
||||||
"mcl_core:snow"
|
|
||||||
}
|
|
||||||
end
|
|
||||||
--
|
--
|
||||||
-- possible surfaces where buildings can be built
|
-- possible surfaces where buildings can be built
|
||||||
--
|
--
|
||||||
|
mcl_villages.surface_mat = {}
|
||||||
|
mcl_villages.surface_mat["mcl_core:andesite"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_core:diorite"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_core:dirt"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_core:dirt_with_grass"] = true
|
||||||
|
--mcl_villages.surface_mat["mcl_core:dirt_with_dry_grass"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_core:dirt_with_grass_snow"] = true
|
||||||
|
--mcl_villages.surface_mat["mcl_core:dry_dirt_with_grass"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_core:grass_path"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_core:granite"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_core:podzol"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_core:redsand"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_core:sand"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_core:sandstone"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_core:sandstonesmooth"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_core:sandstonesmooth2"] = true
|
||||||
|
--mcl_villages.surface_mat["mcl_core:silver_sand"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_core:snow"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_core:stone"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_core:stone_with_coal"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_core:stone_with_iron"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_colorblocks:hardened_clay"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_colorblocks:hardened_clay_orange"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_colorblocks:hardened_clay_red"] = true
|
||||||
|
mcl_villages.surface_mat["mcl_colorblocks:hardened_clay_white"] = true
|
||||||
|
|
||||||
--
|
--
|
||||||
-- path to schematics
|
-- path to schematics
|
||||||
--
|
--
|
||||||
schem_path = settlements.modpath.."/schematics/"
|
schem_path = mcl_villages.modpath.."/schematics/"
|
||||||
--
|
--
|
||||||
-- list of schematics
|
-- list of schematics
|
||||||
--
|
--
|
||||||
local basic_pseudobiome_villages = minetest.settings:get_bool("basic_pseudobiome_villages", true)
|
local basic_pseudobiome_villages = minetest.settings:get_bool("basic_pseudobiome_villages", true)
|
||||||
|
|
||||||
settlements.schematic_table = {
|
mcl_villages.schematic_table = {
|
||||||
{name = "belltower", mts = schem_path.."belltower.mts", hwidth = 5, hdepth = 5, hheight = 9, hsize = 14, max_num = 0 , rplc = basic_pseudobiome_villages },
|
{name = "belltower", mts = schem_path.."belltower.mts", hwidth = 5, hdepth = 5, hheight = 9, hsize = 14, max_num = 0.0001 , rplc = basic_pseudobiome_villages, yadjust = 1 },
|
||||||
{name = "large_house", mts = schem_path.."large_house.mts", hwidth = 12, hdepth = 12, hheight = 9, hsize = 14, max_num = 0.08 , rplc = basic_pseudobiome_villages },
|
{name = "large_house", mts = schem_path.."large_house.mts", hwidth = 12, hdepth = 12, hheight = 9, hsize = 14, max_num = 0.08 , rplc = basic_pseudobiome_villages },
|
||||||
{name = "blacksmith", mts = schem_path.."blacksmith.mts", hwidth = 8, hdepth = 11, hheight = 13, hsize = 13, max_num = 0.055, rplc = basic_pseudobiome_villages },
|
{name = "blacksmith", mts = schem_path.."blacksmith.mts", hwidth = 8, hdepth = 11, hheight = 13, hsize = 13, max_num = 0.055 , rplc = basic_pseudobiome_villages },
|
||||||
{name = "butcher", mts = schem_path.."butcher.mts", hwidth = 12, hdepth = 8, hheight = 10, hsize = 14, max_num = 0.03 , rplc = basic_pseudobiome_villages },
|
{name = "butcher", mts = schem_path.."butcher.mts", hwidth = 12, hdepth = 8, hheight = 10, hsize = 14, max_num = 0.03 , rplc = basic_pseudobiome_villages },
|
||||||
{name = "church", mts = schem_path.."church.mts", hwidth = 13, hdepth = 13, hheight = 14, hsize = 15, max_num = 0.04 , rplc = basic_pseudobiome_villages },
|
{name = "church", mts = schem_path.."church.mts", hwidth = 13, hdepth = 13, hheight = 14, hsize = 15, max_num = 0.04 , rplc = basic_pseudobiome_villages },
|
||||||
{name = "farm", mts = schem_path.."farm.mts", hwidth = 9, hdepth = 7, hheight = 13, hsize = 13, max_num = 0.1 , rplc = basic_pseudobiome_villages },
|
{name = "farm", mts = schem_path.."farm.mts", hwidth = 9, hdepth = 7, hheight = 13, hsize = 13, max_num = 0.1 , rplc = basic_pseudobiome_villages, yadjust = 1 },
|
||||||
{name = "lamp", mts = schem_path.."lamp.mts", hwidth = 3, hdepth = 4, hheight = 13, hsize = 10, max_num = 0.1 , rplc = false },
|
{name = "lamp", mts = schem_path.."lamp.mts", hwidth = 3, hdepth = 4, hheight = 13, hsize = 10, max_num = 0.1 , rplc = false },
|
||||||
{name = "library", mts = schem_path.."library.mts", hwidth = 12, hdepth = 12, hheight = 8, hsize = 13, max_num = 0.04 , rplc = basic_pseudobiome_villages },
|
{name = "library", mts = schem_path.."library.mts", hwidth = 12, hdepth = 12, hheight = 8, hsize = 13, max_num = 0.04 , rplc = basic_pseudobiome_villages },
|
||||||
{name = "medium_house", mts = schem_path.."medium_house.mts", hwidth = 9, hdepth = 12, hheight = 8, hsize = 14, max_num = 0.08 , rplc = basic_pseudobiome_villages },
|
{name = "medium_house", mts = schem_path.."medium_house.mts", hwidth = 9, hdepth = 12, hheight = 8, hsize = 14, max_num = 0.08 , rplc = basic_pseudobiome_villages },
|
||||||
@ -67,7 +74,7 @@ settlements.schematic_table = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
--
|
--
|
||||||
-- maximum allowed difference in height for building a sttlement
|
-- maximum allowed difference in height for building a settlement
|
||||||
--
|
--
|
||||||
max_height_difference = 56
|
max_height_difference = 56
|
||||||
--
|
--
|
||||||
@ -75,3 +82,185 @@ max_height_difference = 56
|
|||||||
--
|
--
|
||||||
half_map_chunk_size = 40
|
half_map_chunk_size = 40
|
||||||
--quarter_map_chunk_size = 20
|
--quarter_map_chunk_size = 20
|
||||||
|
|
||||||
|
--
|
||||||
|
-- Biome based block substitutions
|
||||||
|
--
|
||||||
|
-- TODO maybe this should be in the biomes?
|
||||||
|
mcl_villages.biome_map = {
|
||||||
|
BambooJungle = "bamboo",
|
||||||
|
BambooJungleEdge = "bamboo",
|
||||||
|
BambooJungleEdgeM = "bamboo",
|
||||||
|
BambooJungleM = "bamboo",
|
||||||
|
|
||||||
|
Jungle = "jungle",
|
||||||
|
JungleEdge = "jungle",
|
||||||
|
JungleEdgeM = "jungle",
|
||||||
|
JungleM = "jungle",
|
||||||
|
|
||||||
|
Desert = "desert",
|
||||||
|
|
||||||
|
Savanna = "acacia",
|
||||||
|
SavannaM = "acacia",
|
||||||
|
|
||||||
|
Mesa = "hardened_clay",
|
||||||
|
MesaBryce = "hardened_clay ",
|
||||||
|
MesaPlateauF = "hardened_clay",
|
||||||
|
MesaPlateauFM = "hardened_clay",
|
||||||
|
|
||||||
|
MangroveSwamp = "mangrove",
|
||||||
|
|
||||||
|
RoofedForest = "dark_oak",
|
||||||
|
|
||||||
|
BirchForest = "birch",
|
||||||
|
BirchForestM = "birch",
|
||||||
|
|
||||||
|
ColdTaiga = "spruce",
|
||||||
|
ExtremeHills = "spruce",
|
||||||
|
ExtremeHillsM = "spruce",
|
||||||
|
IcePlains = "spruce",
|
||||||
|
IcePlainsSpikes = "spruce",
|
||||||
|
MegaSpruceTaiga = "spruce",
|
||||||
|
MegaTaiga = "spruce",
|
||||||
|
Taiga = "spruce",
|
||||||
|
["ExtremeHills+"] = "spruce",
|
||||||
|
|
||||||
|
CherryGrove = "cherry",
|
||||||
|
|
||||||
|
-- no change
|
||||||
|
--FlowerForest = "oak",
|
||||||
|
--Forest = "oak",
|
||||||
|
--MushroomIsland = "",
|
||||||
|
--Plains = "oak",
|
||||||
|
--StoneBeach = "",
|
||||||
|
--SunflowerPlains = "oak",
|
||||||
|
--Swampland = "oak",
|
||||||
|
}
|
||||||
|
|
||||||
|
mcl_villages.material_substitions = {
|
||||||
|
desert = {
|
||||||
|
{ '"mcl_stairs:slab_oak([^"]*)"', '"mcl_stairs:slab_sandstonesmooth%1"' },
|
||||||
|
{
|
||||||
|
'"mesecons_pressureplates:pressure_plate_oak_([^"]+)"',
|
||||||
|
'"mesecons_pressureplates:pressure_plate_birchwood_%1"',
|
||||||
|
},
|
||||||
|
{ '"mcl_doors:trapdoor_oak([^"]*)"', '"mcl_doors:birch_trapdoor%1"' },
|
||||||
|
{ '"mcl_doors:door_oak([^"]*)"', '"mcl_doors:birch_door%1"' },
|
||||||
|
|
||||||
|
{ "mcl_core:cobble", "mcl_core:sandstone" },
|
||||||
|
{ '"mcl_stairs:stair_cobble([^"]*)"', '"mcl_stairs:stair_sandstone%1"' },
|
||||||
|
{ '"mcl_walls:cobble([^"]*)"', '"mcl_walls:sandstone%1"' },
|
||||||
|
{ '"mcl_stairs:slab_cobble([^"]*)"', '"mcl_stairs:slab_sandstone%1"' },
|
||||||
|
|
||||||
|
{ '"mcl_core:stonebrick"', '"mcl_core:redsandstone"' },
|
||||||
|
{ '"mcl_core:stonebrick_([^"]+)"', '"mcl_core:redsandstone_%1"' },
|
||||||
|
{ '"mcl_walls:stonebrick([^"]*)"', '"mcl_walls:redsandstone%1"' },
|
||||||
|
{ '"mcl_stairs:stair_stonebrick"', '"mcl_stairs:stair_redsandstone"' },
|
||||||
|
{ '"mcl_stairs:stair_stonebrick_([^"]+)"', '"mcl_stairs:stair_redsandstone_%1"' },
|
||||||
|
|
||||||
|
{ '"mcl_stairs:slab_brick_block([^"]*)"', '"mcl_core:redsandstonesmooth2%1"' },
|
||||||
|
{ '"mcl_core:brick_block"', '"mcl_core:redsandstonesmooth2"' },
|
||||||
|
|
||||||
|
{ "mcl_trees:tree_oak", "mcl_core:redsandstonecarved" },
|
||||||
|
{ "mcl_trees:wood_oak", "mcl_core:redsandstonesmooth" },
|
||||||
|
{ '"mcl_fences:oak_fence([^"]*)"', '"mcl_fences:birch_fence%1"' },
|
||||||
|
{ '"mcl_stairs:stair_oak_bark([^"]*)"', '"mcl_stairs:stair_sandstonesmooth2%1"' },
|
||||||
|
{ '"mcl_stairs:stair_oak([^"]*)"', '"mcl_stairs:stair_sandstonesmooth%1"' },
|
||||||
|
},
|
||||||
|
spruce = {
|
||||||
|
{ '"mcl_stairs:slab_oak([^"]*)"', '"mcl_stairs:slab_sprucewood%1"' },
|
||||||
|
{
|
||||||
|
'"mesecons_pressureplates:pressure_plate_oak_([^"]+)"',
|
||||||
|
'"mesecons_pressureplates:pressure_plate_sprucewood_%1"',
|
||||||
|
},
|
||||||
|
{ '"mcl_doors:trapdoor_oak([^"]*)"', '"mcl_doors:spruce_trapdoor%1"' },
|
||||||
|
{ '"mcl_doors:door_oak([^"]*)"', '"mcl_doors:spruce_door%1"' },
|
||||||
|
{ "mcl_trees:tree_oak", "mcl_trees:tree_spruce" },
|
||||||
|
{ "mcl_trees:wood_oak", "mcl_trees:wood_spruce" },
|
||||||
|
{ '"mcl_fences:oak_fence([^"]*)"', '"mcl_fences:spruce_fence%1"' },
|
||||||
|
{ '"mcl_stairs:stair_oak([^"]*)"', '"mcl_stairs:stair_spruce%1"' },
|
||||||
|
},
|
||||||
|
birch = {
|
||||||
|
{ '"mcl_stairs:slab_oak([^"]*)"', '"mcl_stairs:slab_birchwood%1"' },
|
||||||
|
{
|
||||||
|
'"mesecons_pressureplates:pressure_plate_oak_([^"]+)"',
|
||||||
|
'"mesecons_pressureplates:pressure_plate_birchwood_%1"',
|
||||||
|
},
|
||||||
|
{ '"mcl_doors:trapdoor_oak([^"]*)"', '"mcl_doors:birch_trapdoor%1"' },
|
||||||
|
{ '"mcl_doors:door_oak([^"]*)"', '"mcl_doors:birch_door%1"' },
|
||||||
|
{ "mcl_trees:tree_oak", "mcl_trees:tree_birch" },
|
||||||
|
{ "mcl_trees:wood_oak", "mcl_trees:wood_birch" },
|
||||||
|
{ '"mcl_fences:oak_fence([^"]*)"', '"mcl_fences:birch_fence%1"' },
|
||||||
|
{ '"mcl_stairs:stair_oak([^"]*)"', '"mcl_stairs:stair_birch%1"' },
|
||||||
|
},
|
||||||
|
acacia = {
|
||||||
|
{ '"mcl_stairs:slab_oak([^"]*)"', '"mcl_stairs:slab_acaciawood%1"' },
|
||||||
|
{
|
||||||
|
'"mesecons_pressureplates:pressure_plate_oak_([^"]+)"',
|
||||||
|
'"mesecons_pressureplates:pressure_plate_acaciawood_%1"',
|
||||||
|
},
|
||||||
|
{ '"mcl_doors:trapdoor_oak([^"]*)"', '"mcl_doors:acacia_trapdoor%1"' },
|
||||||
|
{ '"mcl_doors:door_oak([^"]*)"', '"mcl_doors:acacia_door%1"' },
|
||||||
|
{ "mcl_trees:tree_oak", "mcl_trees:tree_acacia" },
|
||||||
|
{ "mcl_trees:wood_oak", "mcl_trees:wood_acacia" },
|
||||||
|
{ '"mcl_fences:oak_fence([^"]*)"', '"mcl_fences:acacia_fence%1"' },
|
||||||
|
{ '"mcl_stairs:stair_oak([^"]*)"', '"mcl_stairs:stair_acacia%1"' },
|
||||||
|
},
|
||||||
|
dark_oak = {
|
||||||
|
{ '"mcl_stairs:slab_oak([^"]*)"', '"mcl_stairs:slab_darkwood%1"' },
|
||||||
|
{
|
||||||
|
'"mesecons_pressureplates:pressure_plate_oak_([^"]+)"',
|
||||||
|
'"mesecons_pressureplates:pressure_plate_darkwood_%1"',
|
||||||
|
},
|
||||||
|
{ '"mcl_doors:trapdoor_oak([^"]*)"', '"mcl_doors:dark_oak_trapdoor%1"' },
|
||||||
|
{ '"mcl_doors:door_oak([^"]*)"', '"mcl_doors:dark_oak_door%1"' },
|
||||||
|
{ "mcl_trees:tree_oak", "mcl_trees:tree_dark_oak" },
|
||||||
|
{ "mcl_trees:wood_oak", "mcl_trees:wood_dark_oak" },
|
||||||
|
{ '"mcl_fences:oak_fence([^"]*)"', '"mcl_fences:dark_oak_fence%1"' },
|
||||||
|
{ '"mcl_stairs:stair_oak([^"]*)"', '"mcl_stairs:stair_dark_oak%1"' },
|
||||||
|
},
|
||||||
|
jungle = {
|
||||||
|
{ '"mcl_stairs:slab_oak([^"]*)"', '"mcl_stairs:slab_junglewood%1"' },
|
||||||
|
{
|
||||||
|
'"mesecons_pressureplates:pressure_plate_oak_([^"]+)"',
|
||||||
|
'"mesecons_pressureplates:pressure_plate_junglewood_%1"',
|
||||||
|
},
|
||||||
|
{ '"mcl_doors:trapdoor_oak([^"]*)"', '"mcl_doors:jungle_trapdoor%1"' },
|
||||||
|
{ '"mcl_doors:door_oak([^"]*)"', '"mcl_doors:jungle_door%1"' },
|
||||||
|
{ "mcl_trees:tree_oak", "mcl_trees:tree_jungle" },
|
||||||
|
{ "mcl_trees:wood_oak", "mcl_trees:wood_jungle" },
|
||||||
|
{ '"mcl_fences:oak_fence([^"]*)"', '"mcl_fences:jungle_fence%1"' },
|
||||||
|
{ '"mcl_stairs:stair_oak([^"]*)"', '"mcl_stairs:stair_jungle%1"' },
|
||||||
|
},
|
||||||
|
bamboo = {
|
||||||
|
{ '"mcl_stairs:slab_oak([^"]*)"', '"mcl_stairs:slab_bamboo_block%1"' },
|
||||||
|
{
|
||||||
|
'"mesecons_pressureplates:pressure_plate_oak_([^"]+)"',
|
||||||
|
'"mesecons_pressureplates:pressure_plate_bamboo_%1"',
|
||||||
|
},
|
||||||
|
{ '"mcl_doors:trapdoor_oak([^"]*)"', '"mcl_doors:trapdoor_bamboo%1"' },
|
||||||
|
{ '"mcl_doors:door_oak([^"]*)"', '"mcl_doors:door_bamboo%1"' },
|
||||||
|
|
||||||
|
{ "mcl_core:cobble", "mcl_core:andesite" },
|
||||||
|
{ '"mcl_stairs:stair_cobble([^"]*)"', '"mcl_stairs:stair_andesite%1"' },
|
||||||
|
{ '"mcl_walls:cobble([^"]*)"', '"mcl_walls:andesite%1"' },
|
||||||
|
{ '"mcl_stairs:slab_cobble([^"]*)"', '"mcl_stairs:slab_andesite%1"' },
|
||||||
|
{ "mcl_trees:tree_oak", "mcl_trees:tree_bamboo" },
|
||||||
|
{ "mcl_trees:wood_oak", "mcl_trees:wood_bamboo" },
|
||||||
|
{ '"mcl_fences:oak_fence([^"]*)"', '"mcl_fences:bamboo_fence%1"' },
|
||||||
|
{ '"mcl_stairs:stair_oak([^"]*)"', '"mcl_stairs:stair_bamboo%1"' },
|
||||||
|
},
|
||||||
|
cherry = {
|
||||||
|
{ '"mcl_stairs:slab_oak([^"]*)"', '"mcl_stairs:slab_cherry_blossom%1"' },
|
||||||
|
{
|
||||||
|
'"mesecons_pressureplates:pressure_plate_oak_([^"]+)"',
|
||||||
|
'"mesecons_pressureplates:pressure_plate_cherry_blossom_%1"',
|
||||||
|
},
|
||||||
|
{ '"mcl_doors:trapdoor_oak([^"]*)"', '"mcl_doors:trapdoor_cherry_blossom%1"' },
|
||||||
|
{ '"mcl_doors:door_oak([^"]*)"', '"mcl_doors:door_cherry_blossom%1"' },
|
||||||
|
{ "mcl_trees:tree_oak", "mcl_trees:tree_cherry_blossom" },
|
||||||
|
{ "mcl_trees:wood_oak", "mcl_trees:wood_cherry_blossom" },
|
||||||
|
{ '"mcl_fences:oak_fence([^"]*)"', '"mcl_fences:cherry_blossom_fence%1"' },
|
||||||
|
{ '"mcl_stairs:stair_oak([^"]*)"', '"mcl_stairs:stair_cherry_blossom%1"' },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
@ -1,48 +1,71 @@
|
|||||||
local function mcl_log (message)
|
|
||||||
mcl_util.mcl_log (message, "[Village - Foundation]")
|
|
||||||
end
|
|
||||||
|
|
||||||
local foundation_materials = {}
|
local foundation_materials = {}
|
||||||
|
|
||||||
foundation_materials["mcl_core:sand"] = "mcl_core:sandstone"
|
foundation_materials["mcl_core:sand"] = "mcl_core:sandstone"
|
||||||
--"mcl_core:sandstonecarved"
|
--"mcl_core:sandstonecarved"
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
local function is_air(node)
|
||||||
-- function to fill empty space below baseplate when building on a hill
|
return not node or node.name == "air" or node.name == "ignore"
|
||||||
-------------------------------------------------------------------------------
|
end
|
||||||
function settlements.ground(pos, pr, platform_material) -- role model: Wendelsteinkircherl, Brannenburg
|
local function is_solid(node)
|
||||||
local p2 = vector.new(pos)
|
if not node or node.name == "air" or node.name == "ignore" then return false end
|
||||||
local cnt = 0
|
--if string.find(node.name,"leaf") then return false end
|
||||||
|
--if string.find(node.name,"tree") then return false end
|
||||||
local mat = "mcl_core:dirt"
|
local ndef = minetest.registered_nodes[node.name]
|
||||||
if not platform_material then
|
return ndef and ndef.walkable
|
||||||
mat = "mcl_core:dirt"
|
end
|
||||||
else
|
local function excavate(lvm,xi,yi,zi,pr)
|
||||||
mat = platform_material
|
local pos, n, c = vector.new(xi,yi,zi), nil, 0
|
||||||
end
|
local node = lvm:get_node_at(pos)
|
||||||
|
if is_air(node) then return false end -- already empty, nothing to do
|
||||||
p2.y = p2.y-1
|
pos.y = pos.y-1
|
||||||
while true do
|
if not is_air(lvm:get_node_at(pos)) then return false end -- below is solid, do not clear above anymore
|
||||||
cnt = cnt+1
|
-- count empty nodes below otherwise
|
||||||
if cnt > 20 then break end
|
for x = xi-1,xi+1 do
|
||||||
if cnt>pr:next(2,4) then
|
for z = zi-1,zi+1 do
|
||||||
if not platform_material then
|
pos.x, pos.z = x, z
|
||||||
mat = "mcl_core:stone"
|
if is_air(lvm:get_node_at(pos)) then c = c + 1 end
|
||||||
end
|
|
||||||
end
|
end
|
||||||
minetest.swap_node(p2, {name=mat})
|
|
||||||
p2.y = p2.y-1
|
|
||||||
end
|
end
|
||||||
|
-- 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
|
||||||
|
if pr:next(0,905) > c * 100 then return false end
|
||||||
|
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
|
||||||
|
-- stop randomly depending on fill, to narrow down the foundation
|
||||||
|
if pr:next(0,905) > c * 100 then return false end
|
||||||
|
lvm:set_node_at(vector.new(xi, yi, zi),{name=platform_mat})
|
||||||
|
return true -- modified
|
||||||
end
|
end
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- function clear space above baseplate
|
-- function clear space above baseplate
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
function settlements.terraform(settlement_info, pr)
|
function mcl_villages.terraform(settlement_info, pr)
|
||||||
local fheight, fwidth, fdepth, schematic_data
|
local fheight, fwidth, fdepth, schematic_data
|
||||||
|
--local lvm, emin, emax = minetest.get_mapgen_object("voxelmanip")
|
||||||
|
local lvm = VoxelManip()
|
||||||
|
|
||||||
for i, built_house in ipairs(settlement_info) do
|
for i, built_house in ipairs(settlement_info) do
|
||||||
-- pick right schematic_info to current built_house
|
-- pick right schematic_info to current built_house
|
||||||
for j, schem in ipairs(settlements.schematic_table) do
|
for j, schem in ipairs(mcl_villages.schematic_table) do
|
||||||
if settlement_info[i]["name"] == schem["name"] then
|
if settlement_info[i]["name"] == schem["name"] then
|
||||||
schematic_data = schem
|
schematic_data = schem
|
||||||
break
|
break
|
||||||
@ -50,41 +73,187 @@ function settlements.terraform(settlement_info, pr)
|
|||||||
end
|
end
|
||||||
local pos = settlement_info[i]["pos"]
|
local pos = settlement_info[i]["pos"]
|
||||||
if settlement_info[i]["rotat"] == "0" or settlement_info[i]["rotat"] == "180" then
|
if settlement_info[i]["rotat"] == "0" or settlement_info[i]["rotat"] == "180" then
|
||||||
fwidth = schematic_data["hwidth"]
|
fwidth, fdepth = schematic_data["hwidth"], schematic_data["hdepth"]
|
||||||
fdepth = schematic_data["hdepth"]
|
|
||||||
else
|
else
|
||||||
fwidth = schematic_data["hdepth"]
|
fwidth, fdepth = schematic_data["hdepth"], schematic_data["hwidth"]
|
||||||
fdepth = schematic_data["hwidth"]
|
|
||||||
end
|
end
|
||||||
--fheight = schematic_data["hheight"] * 3 -- remove trees and leaves above
|
|
||||||
fheight = schematic_data["hheight"] -- remove trees and leaves above
|
fheight = schematic_data["hheight"] -- remove trees and leaves above
|
||||||
|
|
||||||
|
-- use biome-specific materials
|
||||||
local surface_mat = settlement_info[i]["surface_mat"]
|
local surface_mat = settlement_info[i]["surface_mat"]
|
||||||
mcl_log("Surface material: " .. tostring(surface_mat))
|
mcl_villages.debug("Surface material: " .. tostring(surface_mat))
|
||||||
local platform_mat = foundation_materials[surface_mat]
|
local platform_mat = foundation_materials[surface_mat] or "mcl_core:dirt"
|
||||||
mcl_log("Foundation material: " .. tostring(platform_mat))
|
mcl_villages.debug("Foundation material: " .. tostring(platform_mat))
|
||||||
|
|
||||||
--
|
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))
|
||||||
-- now that every info is available -> create platform and clear space above
|
-- TODO: further optimize by using raw data arrays instead of set_node_at. But OK for a first draft.
|
||||||
--
|
lvm:get_data()
|
||||||
for xi = 0,fwidth-1 do
|
-- excavate the needed volume, some headroom, and add a baseplate
|
||||||
for zi = 0,fdepth-1 do
|
local p2 = vector.new(pos)
|
||||||
for yi = 0,fheight *3 do
|
for xi = pos.x,pos.x+fwidth-1 do
|
||||||
if yi == 0 then
|
for zi = pos.z,pos.z+fdepth-1 do
|
||||||
local p = {x=pos.x+xi, y=pos.y, z=pos.z+zi}
|
lvm:set_node_at(vector.new(xi, pos.y+1, zi),{name="air"})
|
||||||
-- Pass in biome info and make foundations of same material (seed: apple for desert)
|
-- pos.y+2 to pos.y+5 are filled larger below!
|
||||||
settlements.ground(p, pr, platform_mat)
|
for yi = pos.y+6,pos.y+fheight do
|
||||||
else
|
lvm:set_node_at(vector.new(xi, yi, zi),{name="air"})
|
||||||
-- write ground
|
end
|
||||||
-- local p = {x=pos.x+xi, y=pos.y+yi, z=pos.z+zi}
|
local cp = vector.new(xi, pos.y, zi)
|
||||||
-- local node = mcl_vars.get_node(p)
|
local cur = lvm:get_node_at(cp)
|
||||||
-- if node and node.name ~= "air" then
|
if not is_solid(cur) or cur.name == platform_mat then
|
||||||
-- minetest.swap_node(p,{name="air"})
|
lvm:set_node_at(cp, {name=surface_mat})
|
||||||
-- end
|
end
|
||||||
minetest.swap_node({x=pos.x+xi, y=pos.y+yi, z=pos.z+zi},{name="air"})
|
local cp = vector.new(xi, pos.y - 1, zi)
|
||||||
|
local cur = lvm:get_node_at(cp)
|
||||||
|
if not is_solid(cur) then
|
||||||
|
lvm:set_node_at(cp, {name=platform_mat})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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"})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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"})
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
-- slightly widen the baseplate, to make easier to enter for mobs
|
||||||
|
for xi = pos.x,pos.x+fwidth-1 do
|
||||||
|
local cp = vector.new(xi, pos.y-1, pos.z)
|
||||||
|
local cur = lvm:get_node_at(cp)
|
||||||
|
if not is_solid(cur) then
|
||||||
|
lvm:set_node_at(cp, {name=platform_mat})
|
||||||
|
end
|
||||||
|
local cp = vector.new(xi, pos.y-1, pos.z-1)
|
||||||
|
local cur = lvm:get_node_at(cp)
|
||||||
|
if not is_solid(cur) or cur.name == platform_mat then
|
||||||
|
lvm:set_node_at(cp, {name=surface_mat})
|
||||||
|
end
|
||||||
|
local cp = vector.new(xi, pos.y-1, pos.z+fdepth-1)
|
||||||
|
local cur = lvm:get_node_at(cp)
|
||||||
|
if not is_solid(cur) then
|
||||||
|
lvm:set_node_at(cp, {name=platform_mat})
|
||||||
|
end
|
||||||
|
local cp = vector.new(xi, pos.y-1, pos.z+fdepth)
|
||||||
|
local cur = lvm:get_node_at(cp)
|
||||||
|
if not is_solid(cur) or cur.name == platform_mat then
|
||||||
|
lvm:set_node_at(cp, {name=surface_mat})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for zi = pos.z,pos.z+fdepth-1 do
|
||||||
|
local cp = vector.new(pos.x, pos.y-1, zi)
|
||||||
|
local cur = lvm:get_node_at(cp)
|
||||||
|
if not is_solid(cur) then
|
||||||
|
lvm:set_node_at(cp, {name=platform_mat})
|
||||||
|
end
|
||||||
|
local cp = vector.new(pos.x-1, pos.y-1, zi)
|
||||||
|
local cur = lvm:get_node_at(cp)
|
||||||
|
if not is_solid(cur) or cur.name == platform_mat then
|
||||||
|
lvm:set_node_at(cp, {name=surface_mat})
|
||||||
|
end
|
||||||
|
local cp = vector.new(pos.x+fwidth-1, pos.y-1, zi)
|
||||||
|
local cur = lvm:get_node_at(cp)
|
||||||
|
if not is_solid(cur) then
|
||||||
|
lvm:set_node_at(cp, {name=platform_mat})
|
||||||
|
end
|
||||||
|
local cp = vector.new(pos.x+fwidth, pos.y-1, zi)
|
||||||
|
local cur = lvm:get_node_at(cp)
|
||||||
|
if not is_solid(cur) or cur.name == platform_mat then
|
||||||
|
lvm:set_node_at(cp, {name=surface_mat})
|
||||||
|
end
|
||||||
|
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)
|
||||||
|
local cur = lvm:get_node_at(cp)
|
||||||
|
if not is_solid(cur) or cur.name == platform_mat then
|
||||||
|
lvm:set_node_at(cp, {name=surface_mat})
|
||||||
|
end
|
||||||
|
cp.z = pos.z-2
|
||||||
|
cur = lvm:get_node_at(cp)
|
||||||
|
if not is_solid(cur) or cur.name == platform_mat then
|
||||||
|
lvm:set_node_at(cp, {name=surface_mat})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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)
|
||||||
|
local cur = lvm:get_node_at(cp)
|
||||||
|
if not is_solid(cur) or cur.name == platform_mat then
|
||||||
|
lvm:set_node_at(cp, {name=surface_mat})
|
||||||
|
end
|
||||||
|
cp.z = pos.z + fdepth + 1
|
||||||
|
cur = lvm:get_node_at(cp)
|
||||||
|
if not is_solid(cur) or cur.name == platform_mat then
|
||||||
|
lvm:set_node_at(cp, {name=surface_mat})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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)
|
||||||
|
local cur = lvm:get_node_at(cp)
|
||||||
|
if not is_solid(cur) or cur.name == platform_mat then
|
||||||
|
lvm:set_node_at(cp, {name=surface_mat})
|
||||||
|
end
|
||||||
|
cp.x = pos.x-2
|
||||||
|
cur = lvm:get_node_at(cp)
|
||||||
|
if not is_solid(cur) or cur.name == platform_mat then
|
||||||
|
lvm:set_node_at(cp, {name=surface_mat})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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)
|
||||||
|
local cur = lvm:get_node_at(cp)
|
||||||
|
if not is_solid(cur) or cur.name == platform_mat then
|
||||||
|
lvm:set_node_at(cp, {name=surface_mat})
|
||||||
|
end
|
||||||
|
cp.x = pos.x+fwidth+1
|
||||||
|
cur = lvm:get_node_at(cp)
|
||||||
|
if not is_solid(cur) or cur.name == platform_mat then
|
||||||
|
lvm:set_node_at(cp, {name=surface_mat})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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
|
||||||
|
end
|
||||||
|
end
|
||||||
|
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
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not active and yi < pos.y-5 then break end
|
||||||
|
end
|
||||||
|
lvm:write_to_map(false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,20 +1,16 @@
|
|||||||
settlements = {}
|
mcl_villages = {}
|
||||||
settlements.modpath = minetest.get_modpath(minetest.get_current_modname())
|
mcl_villages.modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||||
|
|
||||||
dofile(settlements.modpath.."/const.lua")
|
local village_chance = tonumber(minetest.settings:get("mcl_villages_village_chance")) or 5
|
||||||
dofile(settlements.modpath.."/utils.lua")
|
|
||||||
dofile(settlements.modpath.."/foundation.lua")
|
dofile(mcl_villages.modpath.."/const.lua")
|
||||||
dofile(settlements.modpath.."/buildings.lua")
|
dofile(mcl_villages.modpath.."/utils.lua")
|
||||||
dofile(settlements.modpath.."/paths.lua")
|
dofile(mcl_villages.modpath.."/foundation.lua")
|
||||||
--dofile(settlements.modpath.."/convert_lua_mts.lua")
|
dofile(mcl_villages.modpath.."/buildings.lua")
|
||||||
--
|
dofile(mcl_villages.modpath.."/paths.lua")
|
||||||
-- load settlements on server
|
|
||||||
--
|
|
||||||
settlements.grundstellungen()
|
|
||||||
|
|
||||||
local S = minetest.get_translator(minetest.get_current_modname())
|
local S = minetest.get_translator(minetest.get_current_modname())
|
||||||
|
|
||||||
local villagegen={}
|
|
||||||
--
|
--
|
||||||
-- register block for npc spawn
|
-- register block for npc spawn
|
||||||
--
|
--
|
||||||
@ -32,42 +28,20 @@ minetest.register_node("mcl_villages:stonebrickcarved", {
|
|||||||
|
|
||||||
minetest.register_node("mcl_villages:structblock", {drawtype="airlike",groups = {not_in_creative_inventory=1},})
|
minetest.register_node("mcl_villages:structblock", {drawtype="airlike",groups = {not_in_creative_inventory=1},})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--[[ Enable for testing, but use MineClone2's own spawn code if/when merging.
|
|
||||||
--
|
|
||||||
-- register inhabitants
|
|
||||||
--
|
|
||||||
if minetest.get_modpath("mobs_mc") then
|
|
||||||
mcl_mobs:register_spawn("mobs_mc:villager", --name
|
|
||||||
{"mcl_core:stonebrickcarved"}, --nodes
|
|
||||||
15, --max_light
|
|
||||||
0, --min_light
|
|
||||||
20, --chance
|
|
||||||
7, --active_object_count
|
|
||||||
31000, --max_height
|
|
||||||
nil) --day_toggle
|
|
||||||
end
|
|
||||||
--]]
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- on map generation, try to build a settlement
|
-- on map generation, try to build a settlement
|
||||||
--
|
--
|
||||||
local function build_a_settlement(minp, maxp, blockseed)
|
local function build_a_settlement(minp, maxp, blockseed)
|
||||||
local pr = PseudoRandom(blockseed)
|
if mcl_villages.village_exists(blockseed) then return end
|
||||||
|
|
||||||
-- fill settlement_info with buildings and their data
|
local pr = PseudoRandom(blockseed)
|
||||||
local settlement_info = settlements.create_site_plan(maxp, minp, pr)
|
local settlement_info = mcl_villages.create_site_plan(minp, maxp, pr)
|
||||||
if not settlement_info then return end
|
if not settlement_info then return end
|
||||||
|
|
||||||
-- evaluate settlement_info and prepair terrain
|
mcl_villages.terraform(settlement_info, pr)
|
||||||
settlements.terraform(settlement_info, pr)
|
mcl_villages.place_schematics(settlement_info, pr)
|
||||||
|
mcl_villages.paths(settlement_info)
|
||||||
-- evaluate settlement_info and build paths between buildings
|
mcl_villages.add_village(blockseed, settlement_info)
|
||||||
settlements.paths(settlement_info)
|
|
||||||
|
|
||||||
-- evaluate settlement_info and place schematics
|
|
||||||
settlements.place_schematics(settlement_info, pr)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local function ecb_village(blockpos, action, calls_remaining, param)
|
local function ecb_village(blockpos, action, calls_remaining, param)
|
||||||
@ -76,33 +50,24 @@ local function ecb_village(blockpos, action, calls_remaining, param)
|
|||||||
build_a_settlement(minp, maxp, blockseed)
|
build_a_settlement(minp, maxp, blockseed)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local villagegen={}
|
||||||
-- Disable natural generation in singlenode.
|
-- Disable natural generation in singlenode.
|
||||||
local mg_name = minetest.get_mapgen_setting("mg_name")
|
local mg_name = minetest.get_mapgen_setting("mg_name")
|
||||||
if mg_name ~= "singlenode" then
|
if mg_name ~= "singlenode" then
|
||||||
mcl_mapgen_core.register_generator("villages", nil, function(minp, maxp, blockseed)
|
mcl_mapgen_core.register_generator("villages", nil, function(minp, maxp, blockseed)
|
||||||
if maxp.y < 0 then return end
|
if maxp.y < 0 or village_chance == 0 then return end
|
||||||
|
local pr = PseudoRandom(blockseed)
|
||||||
-- randomly try to build settlements
|
if pr:next(0, 100) > village_chance then return end
|
||||||
if blockseed % 77 ~= 17 then return end
|
|
||||||
--minetest.log("Rng good. Generate attempt")
|
|
||||||
|
|
||||||
-- needed for manual and automated settlement building
|
|
||||||
-- don't build settlements on (too) uneven terrain
|
|
||||||
local n=minetest.get_node_or_nil(minp)
|
local n=minetest.get_node_or_nil(minp)
|
||||||
if n and n.name == "mcl_villages:structblock" then return end
|
--if n and n.name == "mcl_villages:structblock" then return end
|
||||||
--minetest.log("No existing village attempt here")
|
if n and n.name ~= "air" then return end
|
||||||
|
|
||||||
if villagegen[minetest.pos_to_string(minp)] ~= nil then return end
|
|
||||||
|
|
||||||
--minetest.log("Not in village gen. Put down placeholder: " .. minetest.pos_to_string(minp) .. " || " .. minetest.pos_to_string(maxp))
|
|
||||||
minetest.set_node(minp,{name="mcl_villages:structblock"})
|
minetest.set_node(minp,{name="mcl_villages:structblock"})
|
||||||
|
|
||||||
local height_difference = settlements.evaluate_heightmap()
|
--[[minetest.emerge_area(
|
||||||
if not height_difference or height_difference > max_height_difference then
|
minp, maxp, --vector.offset(minp, -16, -16, -16), vector.offset(maxp, 16, 16, 16),
|
||||||
minetest.log("action", "Do not spawn village here as heightmap not good")
|
ecb_village,
|
||||||
return
|
{ minp = vector.copy(minp), maxp = vector.copy(maxp), blockseed = blockseed }
|
||||||
end
|
)]]--
|
||||||
--minetest.log("Build me a village: " .. minetest.pos_to_string(minp) .. " || " .. minetest.pos_to_string(maxp))
|
|
||||||
villagegen[minetest.pos_to_string(minp)]={minp=vector.new(minp), maxp=vector.new(maxp), blockseed=blockseed}
|
villagegen[minetest.pos_to_string(minp)]={minp=vector.new(minp), maxp=vector.new(maxp), blockseed=blockseed}
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
@ -125,15 +90,15 @@ if minetest.is_creative_enabled("") then
|
|||||||
minetest.register_craftitem("mcl_villages:tool", {
|
minetest.register_craftitem("mcl_villages:tool", {
|
||||||
description = S("mcl_villages build tool"),
|
description = S("mcl_villages build tool"),
|
||||||
inventory_image = "default_tool_woodshovel.png",
|
inventory_image = "default_tool_woodshovel.png",
|
||||||
-- build ssettlement
|
-- build settlement
|
||||||
on_place = function(itemstack, placer, pointed_thing)
|
on_place = function(itemstack, placer, pointed_thing)
|
||||||
if not pointed_thing.under then return end
|
if not pointed_thing.under then return end
|
||||||
if not minetest.check_player_privs(placer, "server") then
|
if not minetest.check_player_privs(placer, "server") then
|
||||||
minetest.chat_send_player(placer:get_player_name(), S("Placement denied. You need the “server” privilege to place villages."))
|
minetest.chat_send_player(placer:get_player_name(), S("Placement denied. You need the “server” privilege to place villages."))
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local minp = vector.subtract( pointed_thing.under, half_map_chunk_size)
|
local minp = vector.subtract(pointed_thing.under, half_map_chunk_size)
|
||||||
local maxp = vector.add( 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))
|
build_a_settlement(minp, maxp, math.random(0,32767))
|
||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
name = mcl_villages
|
name = mcl_villages
|
||||||
author = Rochambeau
|
author = Rochambeau
|
||||||
description = This mod adds settlements on world generation.
|
description = This mod adds settlements on world generation.
|
||||||
depends = mcl_util, mcl_mapgen_core, mcl_structures, mcl_core, mcl_loot
|
depends = mcl_util, mcl_mapgen_core, mcl_structures, mcl_core, mcl_loot, mobs_mc
|
||||||
optional_depends = mcl_farming, mobs_mc
|
optional_depends = mcl_farming
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- generate paths between buildings
|
-- generate paths between buildings
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
function settlements.paths(settlement_info)
|
function mcl_villages.paths(settlement_info)
|
||||||
local starting_point
|
local starting_point
|
||||||
local end_point
|
local end_point
|
||||||
local distance
|
local distance
|
||||||
@ -67,7 +67,7 @@ function settlements.paths(settlement_info)
|
|||||||
distance = dist_east_p_to_end
|
distance = dist_east_p_to_end
|
||||||
end
|
end
|
||||||
-- find surface of new starting point
|
-- find surface of new starting point
|
||||||
local surface_point, surface_mat = settlements.find_surface(starting_point)
|
local surface_point, surface_mat = mcl_villages.find_surface(starting_point)
|
||||||
-- replace surface node with mcl_core:grass_path
|
-- replace surface node with mcl_core:grass_path
|
||||||
if surface_point
|
if surface_point
|
||||||
then
|
then
|
||||||
|
@ -1,106 +1,105 @@
|
|||||||
local get_node = mcl_vars.get_node
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- function to copy tables
|
-- function to copy tables
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
function settlements.shallowCopy(original)
|
function mcl_villages.shallowCopy(original)
|
||||||
local copy = {}
|
local copy = {}
|
||||||
for key, value in pairs(original) do
|
for key, value in pairs(original) do
|
||||||
copy[key] = value
|
copy[key] = value
|
||||||
end
|
end
|
||||||
return copy
|
return copy
|
||||||
end
|
end
|
||||||
--
|
|
||||||
--
|
|
||||||
--
|
|
||||||
function settlements.round(num, numDecimalPlaces)
|
|
||||||
local mult = 10^(numDecimalPlaces or 0)
|
|
||||||
return math.floor(num * mult + 0.5) / mult
|
|
||||||
end
|
|
||||||
|
|
||||||
|
local function is_above_surface(name)
|
||||||
|
return name == "air" or
|
||||||
|
string.find(name,"grass") or
|
||||||
|
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,"bush")
|
||||||
|
end
|
||||||
|
local get_node = mcl_vars.get_node
|
||||||
|
function mcl_villages.find_surface_down(pos, surface_node)
|
||||||
|
local p6 = vector.new(pos)
|
||||||
|
surface_node = surface_node or get_node(p6) --, true, 1000000)
|
||||||
|
if not surface_node then return end
|
||||||
|
for y = p6.y - 1, math.max(0,p6.y - 120), -1 do
|
||||||
|
p6.y = y
|
||||||
|
local top_node = surface_node
|
||||||
|
surface_node = get_node(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.name
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local ndef = minetest.registered_nodes[surface_node.name]
|
||||||
|
if ndef and ndef.walkable then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
function mcl_villages.find_surface_up(pos, surface_node)
|
||||||
|
local p6 = vector.new(pos)
|
||||||
|
surface_node = surface_node or get_node(p6) --, true, 1000000)
|
||||||
|
if not surface_node then return end
|
||||||
|
for y = p6.y + 1, p6.y + 50 do
|
||||||
|
p6.y = y
|
||||||
|
local top_node = get_node(p6)
|
||||||
|
if not top_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)
|
||||||
|
p6.y = p6.y - 1
|
||||||
|
return p6, surface_node.name
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local ndef = minetest.registered_nodes[surface_node.name]
|
||||||
|
if ndef and ndef.walkable then
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
surface_node = top_node
|
||||||
|
end
|
||||||
|
end
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- function to find surface block y coordinate
|
-- function to find surface block y coordinate
|
||||||
-- returns surface postion
|
-- returns surface postion
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
function settlements.find_surface(pos, wait)
|
function mcl_villages.find_surface(pos, wait)
|
||||||
local p6 = vector.new(pos)
|
local p6 = vector.new(pos)
|
||||||
local cnt = 0
|
if p6.y < 0 then p6.y = 0 end -- start at water level
|
||||||
local itter = 1 -- count up or down
|
|
||||||
local cnt_max = 200
|
|
||||||
-- check, in which direction to look for surface
|
|
||||||
local surface_node
|
local surface_node
|
||||||
if wait then
|
if wait then
|
||||||
surface_node = get_node(p6, true, 10000000)
|
surface_node = get_node(p6, true, 10000000)
|
||||||
else
|
else
|
||||||
surface_node = get_node(p6)
|
surface_node = get_node(p6)
|
||||||
end
|
end
|
||||||
if surface_node.name=="air" or surface_node.name=="ignore" then
|
-- downward, if starting position is empty
|
||||||
itter = -1
|
if is_above_surface(surface_node.name) then
|
||||||
|
return mcl_villages.find_surface_down(p6, surface_node)
|
||||||
|
else
|
||||||
|
return mcl_villages.find_surface_up(p6, surface_node)
|
||||||
end
|
end
|
||||||
-- go through nodes an find surface
|
|
||||||
while cnt < cnt_max do
|
|
||||||
-- Check Surface_node and Node above
|
|
||||||
if surface_node and settlements.surface_mat[surface_node.name] then
|
|
||||||
local surface_node_plus_1 = get_node({ x=p6.x, y=p6.y+1, z=p6.z})
|
|
||||||
|
|
||||||
if surface_node_plus_1 then
|
|
||||||
|
|
||||||
local surface_node_minus_1 = get_node({ x=p6.x, y=p6.y-1, z=p6.z})
|
|
||||||
local is_leaf_below = minetest.get_item_group(surface_node_minus_1, "leaves") ~= 0 or
|
|
||||||
string.find(surface_node_minus_1.name,"leaves")
|
|
||||||
|
|
||||||
if not is_leaf_below and ((string.find(surface_node_plus_1.name,"air") or
|
|
||||||
string.find(surface_node_plus_1.name,"fern") or
|
|
||||||
string.find(surface_node_plus_1.name,"flower") or
|
|
||||||
string.find(surface_node_plus_1.name,"bush") or
|
|
||||||
string.find(surface_node_plus_1.name,"tree") or
|
|
||||||
string.find(surface_node_plus_1.name,"grass")) or
|
|
||||||
string.find(surface_node_plus_1.name,"snow"))
|
|
||||||
then
|
|
||||||
settlements.debug("find_surface success: " ..surface_node.name.. " " .. surface_node_plus_1.name)
|
|
||||||
settlements.debug("node below: " .. tostring(surface_node_minus_1.name))
|
|
||||||
settlements.debug("node below leaves group: " .. tostring(minetest.get_item_group(surface_node_minus_1, "leaves")))
|
|
||||||
return p6, surface_node.name
|
|
||||||
else
|
|
||||||
settlements.debug("find_surface2: wrong surface+1")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
settlements.debug("find_surface8: missing node or plus_1")
|
|
||||||
end
|
|
||||||
else
|
|
||||||
settlements.debug("find_surface3: wrong surface "..surface_node.name.." at pos "..minetest.pos_to_string(p6))
|
|
||||||
end
|
|
||||||
|
|
||||||
p6.y = p6.y + itter
|
|
||||||
if p6.y < 0 then
|
|
||||||
settlements.debug("find_surface4: y<0")
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
cnt = cnt+1
|
|
||||||
surface_node = get_node(p6)
|
|
||||||
end
|
|
||||||
settlements.debug("find_surface5: cnt_max overflow")
|
|
||||||
return nil
|
|
||||||
end
|
end
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- check distance for new building
|
-- check distance for new building
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
function settlements.check_distance(settlement_info, building_pos, building_size)
|
function mcl_villages.check_distance(settlement_info, building_pos, building_size)
|
||||||
local distance
|
|
||||||
for i, built_house in ipairs(settlement_info) do
|
for i, built_house in ipairs(settlement_info) do
|
||||||
distance = math.sqrt(
|
local dx, dz = building_pos.x - built_house["pos"].x, building_pos.z - built_house["pos"].z
|
||||||
((building_pos.x - built_house["pos"].x)*(building_pos.x - built_house["pos"].x))+
|
local dsq = dx*dx+dz*dz
|
||||||
((building_pos.z - built_house["pos"].z)*(building_pos.z - built_house["pos"].z)))
|
if dsq < building_size^2 or dsq < built_house["hsize"]^2 then return false end
|
||||||
if distance < building_size or distance < built_house["hsize"] then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- fill chests
|
-- fill chests
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
function settlements.fill_chest(pos, pr)
|
function mcl_villages.fill_chest(pos, pr)
|
||||||
-- initialize chest (mts chests don't have meta)
|
-- initialize chest (mts chests don't have meta)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
if meta:get_string("infotext") ~= "Chest" then
|
if meta:get_string("infotext") ~= "Chest" then
|
||||||
@ -148,123 +147,93 @@ end
|
|||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- initialize furnace
|
-- initialize furnace
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
function settlements.initialize_furnace(pos)
|
function mcl_villages.initialize_furnace(pos)
|
||||||
-- find chests within radius
|
-- find chests within radius
|
||||||
local furnacepos = minetest.find_node_near(pos,
|
local furnacepos = minetest.find_node_near(pos,
|
||||||
7, --radius
|
7, --radius
|
||||||
{"mcl_furnaces:furnace"})
|
{"mcl_furnaces:furnace"})
|
||||||
-- initialize furnacepos (mts furnacepos don't have meta)
|
-- initialize furnacepos (mts furnacepos don't have meta)
|
||||||
if furnacepos
|
if furnacepos then
|
||||||
then
|
local meta = minetest.get_meta(furnacepos)
|
||||||
local meta = minetest.get_meta(furnacepos)
|
if meta:get_string("infotext") ~= "furnace" then
|
||||||
if meta:get_string("infotext") ~= "furnace"
|
minetest.registered_nodes["mcl_furnaces:furnace"].on_construct(furnacepos)
|
||||||
then
|
end
|
||||||
minetest.registered_nodes["mcl_furnaces:furnace"].on_construct(furnacepos)
|
end
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- initialize anvil
|
-- initialize anvil
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
function settlements.initialize_anvil(pos)
|
function mcl_villages.initialize_anvil(pos)
|
||||||
-- find chests within radius
|
-- find chests within radius
|
||||||
local anvilpos = minetest.find_node_near(pos,
|
local anvilpos = minetest.find_node_near(pos,
|
||||||
7, --radius
|
7, --radius
|
||||||
{"mcl_anvils:anvil"})
|
{"mcl_anvils:anvil"})
|
||||||
-- initialize anvilpos (mts anvilpos don't have meta)
|
-- initialize anvilpos (mts anvilpos don't have meta)
|
||||||
if anvilpos
|
if anvilpos then
|
||||||
then
|
local meta = minetest.get_meta(anvilpos)
|
||||||
local meta = minetest.get_meta(anvilpos)
|
if meta:get_string("infotext") ~= "anvil" then
|
||||||
if meta:get_string("infotext") ~= "anvil"
|
minetest.registered_nodes["mcl_anvils:anvil"].on_construct(anvilpos)
|
||||||
then
|
end
|
||||||
minetest.registered_nodes["mcl_anvils:anvil"].on_construct(anvilpos)
|
end
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
-- randomize table
|
-- randomize table
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
function shuffle(tbl, pr)
|
function mcl_villages.shuffle(tbl, pr)
|
||||||
local table = settlements.shallowCopy(tbl)
|
local copy = {}
|
||||||
local size = #table
|
for key, value in ipairs(tbl) do
|
||||||
for i = size, 1, -1 do
|
table.insert(copy, pr:next(1, #copy + 1), value)
|
||||||
local rand = pr:next(1, size)
|
|
||||||
table[i], table[rand] = table[rand], table[i]
|
|
||||||
end
|
end
|
||||||
return table
|
return copy
|
||||||
end
|
end
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- evaluate heightmap
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
function settlements.evaluate_heightmap()
|
|
||||||
local heightmap = minetest.get_mapgen_object("heightmap")
|
|
||||||
|
|
||||||
if not heightmap then
|
-- Load a schema and replace nodes in it based on biome
|
||||||
minetest.log("action", "No heightmap. That should not happen")
|
function mcl_villages.substitute_materials(pos, schem_lua, pr)
|
||||||
return max_height_difference + 1
|
local modified_schem_lua = schem_lua
|
||||||
end
|
local biome_data = minetest.get_biome_data(pos)
|
||||||
|
local biome_name = minetest.get_biome_name(biome_data.biome)
|
||||||
|
|
||||||
--minetest.log("action", "heightmap size: " .. tostring(#heightmap))
|
if mcl_villages.biome_map[biome_name] and mcl_villages.material_substitions[mcl_villages.biome_map[biome_name]] then
|
||||||
|
for _, sub in pairs(mcl_villages.material_substitions[mcl_villages.biome_map[biome_name]]) do
|
||||||
-- max height and min height, initialize with impossible values for easier first time setting
|
modified_schem_lua = modified_schem_lua:gsub(sub[1], sub[2])
|
||||||
local max_y = -50000
|
|
||||||
local min_y = 50000
|
|
||||||
-- only evaluate the center square of heightmap 40 x 40
|
|
||||||
local square_start = 1621
|
|
||||||
local square_end = 1661
|
|
||||||
for j = 1 , 40, 1 do
|
|
||||||
if square_start >= #heightmap then
|
|
||||||
--minetest.log("action", "Heightmap size reached. Go no further outside")
|
|
||||||
break
|
|
||||||
end
|
end
|
||||||
for i = square_start, square_end, 1 do
|
end
|
||||||
--minetest.log("action", "current hm index: " .. tostring(i) .. "current hm entry: " .. tostring(heightmap[i]))
|
|
||||||
|
|
||||||
if i >= #heightmap then
|
return modified_schem_lua
|
||||||
--minetest.log("action", "Heightmap size reached. Go no further")
|
end
|
||||||
break
|
|
||||||
end
|
local villages = {}
|
||||||
local current_hm_entry = heightmap[i]
|
local mod_storage = minetest.get_mod_storage()
|
||||||
if current_hm_entry then
|
|
||||||
-- skip buggy heightmaps, return high value. Converted mcl5 maps can be -31007
|
local function lazy_load_village(name)
|
||||||
if current_hm_entry == -31000 or heightmap[i] == 31000 then
|
if not villages[name] then
|
||||||
--minetest.log("action", "incorrect heighmap values. abandon")
|
local data = mod_storage:get("mcl_villages." .. name)
|
||||||
return max_height_difference + 1
|
if data then
|
||||||
end
|
villages[name] = minetest.deserialize(data)
|
||||||
if current_hm_entry < min_y then
|
|
||||||
min_y = current_hm_entry
|
|
||||||
end
|
|
||||||
if current_hm_entry > max_y then
|
|
||||||
max_y = current_hm_entry
|
|
||||||
end
|
|
||||||
else
|
|
||||||
--minetest.log("action", "Failed to get hm index: " .. tostring(i) .. "and ... " .. tostring(#heightmap))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
-- set next line
|
|
||||||
square_start = square_start + 80
|
|
||||||
square_end = square_end + 80
|
|
||||||
end
|
end
|
||||||
-- return the difference between highest and lowest pos in chunk
|
end
|
||||||
local height_diff = max_y - min_y
|
|
||||||
|
|
||||||
--minetest.log("action", "height_diff = " .. tostring(height_diff))
|
function mcl_villages.get_village(name)
|
||||||
|
lazy_load_village(name)
|
||||||
-- filter buggy heightmaps
|
if villages[name] then
|
||||||
if height_diff <= 1 then
|
return table.copy(villages[name])
|
||||||
return max_height_difference + 1
|
|
||||||
end
|
end
|
||||||
--minetest.log("action", "return heigh diff = " .. tostring(height_diff))
|
|
||||||
-- debug info
|
|
||||||
settlements.debug("heightdiff ".. height_diff)
|
|
||||||
return height_diff
|
|
||||||
end
|
end
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- Set array to list
|
function mcl_villages.village_exists(name)
|
||||||
-- https://stackoverflow.com/questions/656199/search-for-an-item-in-a-lua-list
|
lazy_load_village(name)
|
||||||
-------------------------------------------------------------------------------
|
return villages[name] ~= nil
|
||||||
function settlements.Set (list)
|
end
|
||||||
local set = {}
|
|
||||||
for _, l in ipairs(list) do set[l] = true end
|
function mcl_villages.add_village(name, data)
|
||||||
return set
|
lazy_load_village(name)
|
||||||
|
if villages[name] then
|
||||||
|
minetest.log("info","Village already exists: " .. name )
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
local new_village = {name = name, data = data}
|
||||||
|
mod_storage:set_string("mcl_villages." .. name, minetest.serialize(new_village))
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user