2024-07-23 01:09:17 +02:00
|
|
|
local min_jobs = tonumber(minetest.settings:get("mcl_villages_min_jobs")) or 1
|
|
|
|
local max_jobs = tonumber(minetest.settings:get("mcl_villages_max_jobs")) or 12
|
|
|
|
local placement_priority = minetest.settings:get("mcl_villages_placement_priority") or "random"
|
|
|
|
|
|
|
|
local S = minetest.get_translator(minetest.get_current_modname())
|
|
|
|
|
|
|
|
local function add_building(settlement, building, count_buildings)
|
|
|
|
table.insert(settlement, building)
|
2024-08-23 10:55:30 +02:00
|
|
|
count_buildings[building.name] = (count_buildings[building.name] or 0) + 1
|
|
|
|
count_buildings.num_jobs = count_buildings.num_jobs + (building.num_jobs or 0)
|
|
|
|
count_buildings.num_beds = count_buildings.num_beds + (building.num_beds or 0)
|
|
|
|
if building.group then
|
|
|
|
count_buildings[building.group] = (count_buildings[building.group] or 0) + 1
|
|
|
|
end
|
2024-07-23 01:09:17 +02:00
|
|
|
end
|
|
|
|
|
2024-08-23 10:55:30 +02:00
|
|
|
local function layout_town(vm, minp, maxp, pr, input_settlement)
|
2024-07-23 01:09:17 +02:00
|
|
|
local center = vector.new(pr:next(minp.x + 24, maxp.x - 24), maxp.y, pr:next(minp.z + 24, maxp.z - 24))
|
2024-07-24 17:29:40 +02:00
|
|
|
minetest.log("action", "[mcl_villages] sudo make me a village at: " .. minetest.pos_to_string(minp).." - "..minetest.pos_to_string(maxp))
|
2021-01-27 09:56:53 +01:00
|
|
|
local possible_rotations = {"0", "90", "180", "270"}
|
2024-07-19 14:56:06 +02:00
|
|
|
local center_surface
|
2023-01-03 19:32:52 +01:00
|
|
|
|
2024-07-23 01:09:17 +02:00
|
|
|
local settlement = {}
|
2021-01-27 09:56:53 +01:00
|
|
|
-- now some buildings around in a circle, radius = size of town center
|
2024-07-24 17:29:40 +02:00
|
|
|
local x, y, z, r, lastr = center.x, center.y, center.z, 0, 99
|
2024-08-23 10:55:30 +02:00
|
|
|
local mindist = 3
|
|
|
|
if #input_settlement >= 12 then mindist = 2 end
|
2024-07-23 01:09:17 +02:00
|
|
|
-- draw j circles around center and increase radius by math.random(2,4)
|
|
|
|
for j = 1,20 do
|
|
|
|
local steps = math.min(math.floor(math.pi * 2 * r / 2), 30) -- try up to 30 angles
|
|
|
|
for a = 0, steps - 1 do
|
|
|
|
if #settlement == #input_settlement then break end -- everything placed
|
|
|
|
local angle = a * 71 / steps * math.pi * 2 -- prime to increase randomness
|
|
|
|
local cpos = vector.new(math.floor(x + r * math.cos(angle) + 0.5), y, math.floor(z - r * math.sin(angle) + 0.5))
|
|
|
|
local building = table.copy(input_settlement[#settlement + 1])
|
|
|
|
local size = vector.copy(building.size)
|
|
|
|
--local rotation = possible_rotations[pr:next(1, #possible_rotations)]
|
2024-08-06 20:37:44 +02:00
|
|
|
local rotation = math.floor(math.atan2(center.z-cpos.z, center.x-cpos.x) / math.pi * 2+6.5)%4
|
|
|
|
rotation = possible_rotations[1+rotation]
|
2024-07-23 01:09:17 +02:00
|
|
|
if rotation == "90" or rotation == "270" then size.x, size.z = size.z, size.x end
|
2024-08-06 20:37:44 +02:00
|
|
|
local tlpos = vector.offset(cpos, -math.floor((size.x-1)/2), 0, -math.floor((size.z-1)/2))
|
2024-07-23 01:09:17 +02:00
|
|
|
|
|
|
|
-- ensure we have 3 space for terraforming, and avoid problems with VoxelManip
|
|
|
|
if tlpos.x - 3 >= minp.x and tlpos.x + size.x + 3 <= maxp.x
|
|
|
|
and tlpos.z + 3 >= minp.z and tlpos.z + size.y + 3 <= maxp.z then
|
2024-08-23 10:55:30 +02:00
|
|
|
local pos, surface_material = vl_terraforming.find_level_vm(vm, cpos, size)
|
2024-07-23 01:09:17 +02:00
|
|
|
-- check distance to other buildings. Note that we still want to add baseplates etc.
|
2024-08-23 10:55:30 +02:00
|
|
|
if pos and mcl_villages.surface_mat[surface_material.name] and mcl_villages.check_distance(settlement, cpos, size.x, size.z, mindist) then
|
2024-07-23 01:09:17 +02:00
|
|
|
-- use town bell as new reference point for placement height
|
|
|
|
if #settlement == 0 then
|
2024-07-24 17:29:40 +02:00
|
|
|
center_surface, y = cpos, math.min(maxp.y, pos.y + mcl_villages.max_height_difference * 0.5 + 1)
|
2024-07-23 01:09:17 +02:00
|
|
|
end
|
2024-07-24 17:29:40 +02:00
|
|
|
-- limit height differences to town center, but gradually allow more
|
2024-08-06 20:37:44 +02:00
|
|
|
if math.abs(pos.y - center_surface.y) <= mcl_villages.max_height_difference * (0.25 + math.min(r/40,0.5)) then
|
|
|
|
local minp = vector.offset(pos, -math.floor((size.x-1)/2), building.yadjust, -math.floor((size.z-1)/2))
|
2024-07-23 01:09:17 +02:00
|
|
|
building.minp = minp
|
|
|
|
building.maxp = vector.offset(minp, size.x, size.y, size.z)
|
|
|
|
building.pos = pos
|
|
|
|
building.size = size
|
|
|
|
building.rotation = rotation
|
|
|
|
building.surface_mat = surface_material
|
|
|
|
table.insert(settlement, building)
|
2024-07-24 17:29:40 +02:00
|
|
|
-- minetest.log("verbose", "[mcl_villages] Planning "..schema["name"].." at "..minetest.pos_to_string(pos))
|
2024-07-23 01:09:17 +02:00
|
|
|
lastr = r
|
2024-07-24 17:29:40 +02:00
|
|
|
else
|
|
|
|
minetest.log("verbose", "Too large height difference "..math.abs(pos.y - center_surface.y).." at distance "..r)
|
2021-01-27 09:56:53 +01:00
|
|
|
end
|
2024-07-19 14:56:06 +02:00
|
|
|
end
|
2021-01-27 09:56:53 +01:00
|
|
|
end
|
2021-02-22 00:15:32 +01:00
|
|
|
end
|
2024-07-23 01:09:17 +02:00
|
|
|
r = r + pr:next(2,4)
|
2024-07-24 17:29:40 +02:00
|
|
|
if r > lastr + 20 then -- too disconnected
|
|
|
|
minetest.log("verbose", "Disconnected village "..r.." > "..lastr)
|
2021-02-22 00:15:32 +01:00
|
|
|
break
|
2021-01-27 09:56:53 +01:00
|
|
|
end
|
2024-07-19 14:56:06 +02:00
|
|
|
end
|
2024-07-23 01:09:17 +02:00
|
|
|
-- minetest.log("verbose", "Planned "..#input_settlement.." buildings, placed "..#settlement)
|
|
|
|
if #settlement < #input_settlement and #settlement < 6 then
|
2024-07-24 17:29:40 +02:00
|
|
|
minetest.log("action", "[mcl_villages] Bad village location, could only place "..#settlement.." buildings at "..minetest.pos_to_string(center))
|
2024-07-19 14:56:06 +02:00
|
|
|
return
|
2021-01-27 09:56:53 +01:00
|
|
|
end
|
2024-07-20 13:57:01 +02:00
|
|
|
minetest.log("action", "[mcl_villages] village plan completed at " .. minetest.pos_to_string(center))
|
2024-07-23 01:09:17 +02:00
|
|
|
return settlement
|
2021-02-27 00:33:51 +01:00
|
|
|
end
|
2022-05-20 23:44:58 +02:00
|
|
|
|
2024-08-23 10:55:30 +02:00
|
|
|
function mcl_villages.create_site_plan(vm, minp, maxp, pr)
|
2024-07-23 01:09:17 +02:00
|
|
|
local settlement = {}
|
|
|
|
|
|
|
|
-- initialize all settlement_info table
|
2024-09-03 17:16:36 +02:00
|
|
|
local count_buildings = { num_jobs = 0, num_beds = 0, target_jobs = pr:next(min_jobs, max_jobs) }
|
2024-07-23 01:09:17 +02:00
|
|
|
|
|
|
|
-- first building is townhall in the center
|
|
|
|
local bindex = pr:next(1, #mcl_villages.schematic_bells)
|
|
|
|
local bell_info = table.copy(mcl_villages.schematic_bells[bindex])
|
|
|
|
|
|
|
|
if mcl_villages.mandatory_buildings['jobs'] then
|
|
|
|
for _, bld_name in pairs(mcl_villages.mandatory_buildings['jobs']) do
|
|
|
|
local building_info = info_for_building(bld_name, mcl_villages.schematic_jobs)
|
|
|
|
add_building(settlement, building_info, count_buildings)
|
2022-05-20 23:44:58 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-09-03 17:16:36 +02:00
|
|
|
while count_buildings.num_jobs < count_buildings.target_jobs do
|
2024-07-23 01:09:17 +02:00
|
|
|
local rindex = pr:next(1, #mcl_villages.schematic_jobs)
|
|
|
|
local building_info = mcl_villages.schematic_jobs[rindex]
|
|
|
|
|
|
|
|
if
|
2024-09-03 17:16:36 +02:00
|
|
|
(building_info.min_jobs == nil or count_buildings.target_jobs >= building_info.min_jobs)
|
|
|
|
and (building_info.max_jobs == nil or count_buildings.target_jobs <= building_info.max_jobs)
|
2024-07-23 01:09:17 +02:00
|
|
|
and (
|
2024-08-23 10:55:30 +02:00
|
|
|
building_info.num_others == nil
|
|
|
|
or (count_buildings[building_info.group or building_info.name] or 0) == 0
|
|
|
|
or building_info.num_others * (count_buildings[building_info.group or building_info.name] or 0) < count_buildings.num_jobs
|
2024-07-23 01:09:17 +02:00
|
|
|
)
|
|
|
|
then
|
|
|
|
add_building(settlement, building_info, count_buildings)
|
2022-05-20 23:44:58 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2024-07-23 01:09:17 +02:00
|
|
|
if mcl_villages.mandatory_buildings['houses'] then
|
|
|
|
for _, bld_name in pairs(mcl_villages.mandatory_buildings['houses']) do
|
|
|
|
local building_info = info_for_building(bld_name, mcl_villages.schematic_houses)
|
|
|
|
add_building(settlement, building_info, count_buildings)
|
|
|
|
end
|
2023-02-18 14:51:31 +01:00
|
|
|
end
|
|
|
|
|
2024-07-23 01:09:17 +02:00
|
|
|
while count_buildings.num_beds <= count_buildings.num_jobs do
|
|
|
|
local rindex = pr:next(1, #mcl_villages.schematic_houses)
|
|
|
|
local building_info = mcl_villages.schematic_houses[rindex]
|
2021-02-27 00:33:51 +01:00
|
|
|
|
2024-07-23 01:09:17 +02:00
|
|
|
if
|
2024-09-03 17:16:36 +02:00
|
|
|
(building_info.min_jobs == nil or count_buildings.target_jobs >= building_info.min_jobs)
|
|
|
|
and (building_info.max_jobs == nil or count_buildings.target_jobs <= building_info.max_jobs)
|
2024-07-23 01:09:17 +02:00
|
|
|
and (
|
2024-08-23 10:55:30 +02:00
|
|
|
building_info.num_others == nil
|
|
|
|
or (count_buildings[building_info.group or building_info.name] or 0) == 0
|
|
|
|
or building_info.num_others * (count_buildings[building_info.group or building_info.name] or 0) < count_buildings.num_jobs
|
2024-07-23 01:09:17 +02:00
|
|
|
)
|
|
|
|
then
|
|
|
|
add_building(settlement, building_info, count_buildings)
|
2021-02-27 00:33:51 +01:00
|
|
|
end
|
|
|
|
end
|
2024-07-23 01:09:17 +02:00
|
|
|
|
|
|
|
-- Based on number of villagers
|
|
|
|
local num_wells = pr:next(1, math.ceil(count_buildings.num_beds / 10))
|
2024-08-23 10:55:30 +02:00
|
|
|
for _ = 1, num_wells do
|
2024-07-23 01:09:17 +02:00
|
|
|
local windex = pr:next(1, #mcl_villages.schematic_wells)
|
|
|
|
local cur_schem = table.copy(mcl_villages.schematic_wells[windex])
|
|
|
|
table.insert(settlement, pr:next(1, #settlement), cur_schem)
|
2024-07-20 13:57:01 +02:00
|
|
|
end
|
2024-07-23 01:09:17 +02:00
|
|
|
|
|
|
|
if placement_priority == "jobs" then
|
|
|
|
-- keep ordered as is
|
|
|
|
elseif placement_priority == "houses" then
|
|
|
|
table.reverse(settlement)
|
|
|
|
else
|
|
|
|
settlement = mcl_villages.shuffle(settlement, pr)
|
|
|
|
end
|
|
|
|
|
|
|
|
table.insert(settlement, 1, bell_info)
|
2024-08-23 10:55:30 +02:00
|
|
|
return layout_town(vm, minp, maxp, pr, settlement)
|
2021-02-27 00:33:51 +01:00
|
|
|
end
|
2022-05-20 23:44:58 +02:00
|
|
|
|
2024-09-03 17:16:36 +02:00
|
|
|
local function init_nodes(p1, p2, pr)
|
|
|
|
vl_structures.construct_nodes(p1, p2, {
|
|
|
|
"mcl_itemframes:item_frame",
|
|
|
|
"mcl_itemframes:glow_item_frame",
|
|
|
|
"mcl_furnaces:furnace",
|
|
|
|
"mcl_anvils:anvil",
|
|
|
|
"mcl_books:bookshelf",
|
|
|
|
"mcl_armor_stand:armor_stand",
|
|
|
|
-- jobsite: "mcl_smoker:smoker",
|
|
|
|
-- jobsite: "mcl_barrels:barrel_closed",
|
|
|
|
-- jobsite: "mcl_blast_furnace:blast_furnace",
|
|
|
|
-- jobsite: "mcl_brewing:stand_000",
|
|
|
|
})
|
2022-05-26 07:29:28 +02:00
|
|
|
|
2024-09-03 17:16:36 +02:00
|
|
|
-- Support mods with custom job sites
|
|
|
|
local job_sites = minetest.find_nodes_in_area(p1, p2, mobs_mc.jobsites)
|
|
|
|
for _, v in pairs(job_sites) do vl_structures.init_node_construct(v) end
|
|
|
|
|
|
|
|
local nodes = vl_structures.construct_nodes(p1, p2, {"mcl_chests:chest_small", "mcl_chests:chest" })
|
|
|
|
for _, n in pairs(nodes) do mcl_villages.fill_chest(n, pr) end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- important: the vm will be written and then is outdated!
|
2024-08-23 10:55:30 +02:00
|
|
|
function mcl_villages.place_schematics(vm, settlement, blockseed, pr)
|
2024-09-03 17:16:36 +02:00
|
|
|
-- first building is always the bell
|
2024-07-23 01:09:17 +02:00
|
|
|
local bell_pos = vector.offset(settlement[1].minp, math.floor(settlement[1].size.x/2), 0, math.floor(settlement[1].size.z/2))
|
2022-05-26 07:29:28 +02:00
|
|
|
|
2024-07-23 01:09:17 +02:00
|
|
|
for i, building in ipairs(settlement) do
|
|
|
|
local minp, cpos, maxp, size, rotation = building.minp, building.pos, building.maxp, building.size, building.rotation
|
2021-01-27 09:56:53 +01:00
|
|
|
|
2024-07-23 01:09:17 +02:00
|
|
|
-- adjust the schema to match location and biome
|
|
|
|
local surface_material = building.surface_mat or {name = "mcl_core:dirt" }
|
|
|
|
local platform_material = building.platform_mat or building.surface_mat or {name = "mcl_core:stone" }
|
|
|
|
local schem_lua = building.schem_lua
|
2024-08-06 20:37:44 +02:00
|
|
|
schem_lua = schem_lua:gsub('"mcl_core:dirt"', '"'..platform_material.name..'"')
|
|
|
|
schem_lua = schem_lua:gsub('"mcl_core:dirt_with_grass"', '"'..surface_material.name..'"') -- also keeping param2 would be nicer, grass color
|
2024-07-23 01:09:17 +02:00
|
|
|
schem_lua = mcl_villages.substitute_materials(cpos, schem_lua, pr)
|
|
|
|
local schematic = loadstring(schem_lua)()
|
|
|
|
|
|
|
|
-- the foundation and air space for the building was already built before
|
|
|
|
-- minetest.log("debug", "placing schematics for "..building.name.." at "..minetest.pos_to_string(minp).." on "..surface_material)
|
2024-09-03 17:16:36 +02:00
|
|
|
minetest.place_schematic_on_vmanip(vm, minp, schematic, rotation, nil, true, { place_center_x = false, place_center_y = false, place_center_z = false })
|
2024-08-23 10:55:30 +02:00
|
|
|
mcl_villages.store_path_ends(vm, minp, maxp, cpos, blockseed, bell_pos)
|
2024-09-03 17:16:36 +02:00
|
|
|
mcl_villages.increase_no_paths(vm, minp, maxp) -- help the path finder
|
2024-07-23 01:09:17 +02:00
|
|
|
end
|
2024-07-19 14:56:06 +02:00
|
|
|
|
2024-08-23 10:55:30 +02:00
|
|
|
vm:write_to_map(true) -- for path finder and light
|
2024-07-23 01:09:17 +02:00
|
|
|
|
2024-09-03 17:16:36 +02:00
|
|
|
-- Path planning and placement
|
|
|
|
mcl_villages.paths(blockseed, minetest.get_biome_name(minetest.get_biome_data(bell_pos).biome))
|
|
|
|
-- Clean up paths and initialize nodes
|
2024-08-26 00:00:11 +02:00
|
|
|
for i, building in ipairs(settlement) do
|
2024-09-03 17:16:36 +02:00
|
|
|
mcl_villages.clean_no_paths(building.minp, building.maxp)
|
2024-08-26 00:00:11 +02:00
|
|
|
init_nodes(building.minp, building.maxp, pr)
|
|
|
|
end
|
|
|
|
|
2024-09-03 17:16:36 +02:00
|
|
|
-- Replace center block with a temporary block, which will be used run delayed actions
|
|
|
|
local block_name = minetest.get_node(bell_pos).name -- to restore the node afterwards
|
|
|
|
minetest.swap_node(bell_pos, { name = "mcl_villages:village_block" })
|
|
|
|
local meta = minetest.get_meta(bell_pos)
|
|
|
|
meta:set_string("node_type", block_name)
|
2024-07-23 01:09:17 +02:00
|
|
|
meta:set_string("blockseed", blockseed)
|
2024-09-03 17:16:36 +02:00
|
|
|
meta:set_string("infotext", S("The timer for this village has not run yet!"))
|
|
|
|
minetest.get_node_timer(bell_pos):start(1.0)
|
2024-07-23 01:09:17 +02:00
|
|
|
end
|
|
|
|
|
2024-09-03 17:16:36 +02:00
|
|
|
minetest.register_node("mcl_villages:village_block", {
|
|
|
|
drawtype = "glasslike",
|
|
|
|
groups = { not_in_creative_inventory = 1 },
|
|
|
|
light_source = 14, -- This is a light source so that lamps don't get placed near it
|
|
|
|
-- Somethings don't work reliably when done in the map building
|
|
|
|
-- so we use a timer to run them later when they work more reliably
|
|
|
|
-- e.g. spawning mobs, running minetest.find_path
|
|
|
|
on_timer = function(pos, _)
|
|
|
|
local meta = minetest.get_meta(pos)
|
|
|
|
minetest.swap_node(pos, { name = meta:get_string("node_type") })
|
|
|
|
mcl_villages.post_process_village(meta:get_string("blockseed"))
|
|
|
|
return false
|
|
|
|
end,
|
|
|
|
})
|
|
|
|
|
2024-07-23 01:09:17 +02:00
|
|
|
function mcl_villages.post_process_village(blockseed)
|
|
|
|
local village_info = mcl_villages.get_village(blockseed)
|
2024-09-03 17:16:36 +02:00
|
|
|
if not village_info then return end
|
2024-07-23 01:09:17 +02:00
|
|
|
-- minetest.log("Postprocessing village")
|
|
|
|
|
|
|
|
local settlement_info = village_info.data
|
2024-09-03 17:16:36 +02:00
|
|
|
local jobs, beds = {}, {}
|
2024-07-23 01:09:17 +02:00
|
|
|
|
2024-09-03 17:16:36 +02:00
|
|
|
local bell_pos = vector.copy(settlement_info[1].pos)
|
2024-09-05 01:03:33 +02:00
|
|
|
local bell = vector.offset(bell_pos, 0, 2, 0)
|
2024-09-03 17:16:36 +02:00
|
|
|
local biome_name = minetest.get_biome_name(minetest.get_biome_data(bell_pos).biome)
|
2024-07-23 01:09:17 +02:00
|
|
|
|
2024-09-03 17:16:36 +02:00
|
|
|
-- Spawn Golem
|
2024-07-23 01:09:17 +02:00
|
|
|
local l = minetest.add_entity(bell, "mobs_mc:iron_golem"):get_luaentity()
|
|
|
|
if l then
|
|
|
|
l._home = bell
|
|
|
|
else
|
|
|
|
minetest.log("info", "Could not create a golem!")
|
|
|
|
end
|
2024-08-23 10:55:30 +02:00
|
|
|
|
2024-09-03 17:16:36 +02:00
|
|
|
-- Spawn cats
|
|
|
|
local sp = minetest.find_nodes_in_area_under_air(vector.offset(bell, -20, -10, -20),vector.offset(bell, 20, 10, 20), { "group:opaque" })
|
|
|
|
for _ = 1, math.random(3) do
|
|
|
|
local v = minetest.add_entity(vector.offset(sp[math.random(#sp)], 0, 1, 0), "mobs_mc:cat")
|
|
|
|
if v and v:get_luaentity() then
|
|
|
|
v:get_luaentity()._home = bell_pos -- help them stay local
|
|
|
|
else
|
|
|
|
minetest.log("info", "Could not spawn a cat")
|
|
|
|
break
|
|
|
|
end
|
|
|
|
end
|
2024-07-23 01:09:17 +02:00
|
|
|
|
2024-09-03 17:16:36 +02:00
|
|
|
-- collect beds and job sites
|
2024-07-23 01:09:17 +02:00
|
|
|
for _, building in pairs(settlement_info) do
|
2024-09-03 17:16:36 +02:00
|
|
|
local minp, maxp = building.minp, building.maxp
|
|
|
|
if building.num_jobs then
|
2024-07-23 01:09:17 +02:00
|
|
|
local jobsites = minetest.find_nodes_in_area(minp, maxp, mobs_mc.jobsites)
|
2024-09-03 17:16:36 +02:00
|
|
|
for _, job_pos in pairs(jobsites) do table.insert(jobs, job_pos) end
|
2024-07-23 01:09:17 +02:00
|
|
|
end
|
|
|
|
|
2024-09-03 17:16:36 +02:00
|
|
|
if building.num_beds then
|
2024-07-23 01:09:17 +02:00
|
|
|
local bld_beds = minetest.find_nodes_in_area(minp, maxp, { "group:bed" })
|
|
|
|
for _, bed_pos in pairs(bld_beds) do
|
2024-09-03 17:16:36 +02:00
|
|
|
local bed_group = minetest.get_item_group(minetest.get_node(bed_pos).name, "bed")
|
|
|
|
-- We only spawn at bed bottoms, 1 is bottom, 2 is top
|
|
|
|
if bed_group == 1 then table.insert(beds, bed_pos) end
|
2024-07-23 01:09:17 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2024-09-03 17:16:36 +02:00
|
|
|
-- TODO: shuffle jobs?
|
2024-07-23 01:09:17 +02:00
|
|
|
|
|
|
|
-- minetest.log("beds: "..#beds.." jobsites: "..#jobs)
|
|
|
|
if beds then
|
|
|
|
for _, bed_pos in pairs(beds) do
|
2024-09-03 17:16:36 +02:00
|
|
|
minetest.forceload_block(bed_pos, true)
|
2024-07-23 01:09:17 +02:00
|
|
|
local m = minetest.get_meta(bed_pos)
|
|
|
|
m:set_string("bell_pos", minetest.pos_to_string(bell_pos))
|
|
|
|
if m:get_string("villager") == "" then
|
2024-08-23 10:55:30 +02:00
|
|
|
local v = minetest.add_entity(vector.offset(bed_pos, 0, 0.06, 0), "mobs_mc:villager")
|
2024-07-23 01:09:17 +02:00
|
|
|
if v then
|
|
|
|
local l = v:get_luaentity()
|
|
|
|
l._bed = bed_pos
|
|
|
|
l._bell = bell_pos
|
|
|
|
m:set_string("villager", l._id)
|
|
|
|
m:set_string("infotext", S("A villager sleeps here"))
|
|
|
|
|
|
|
|
local job_pos = table.remove(jobs, 1)
|
2024-09-03 17:16:36 +02:00
|
|
|
if job_pos then villager_employ(l, job_pos) end -- HACK: merge more MCLA villager job code?
|
|
|
|
for _, callback in pairs(mcl_villages.on_villager_placed) do callback(v, blockseed) end
|
2024-07-23 01:09:17 +02:00
|
|
|
else
|
|
|
|
minetest.log("info", "Could not create a villager!")
|
|
|
|
end
|
|
|
|
else
|
2024-09-03 17:16:36 +02:00
|
|
|
minetest.log("info", "bed already owned by " .. m:get_string("villager")) -- should not happen unless villages overlap
|
2024-07-23 01:09:17 +02:00
|
|
|
end
|
2024-07-19 14:56:06 +02:00
|
|
|
end
|
2021-01-27 09:56:53 +01:00
|
|
|
end
|
|
|
|
end
|
2024-08-06 20:37:44 +02:00
|
|
|
|
|
|
|
-- Terraform for an entire village
|
2024-08-23 10:55:30 +02:00
|
|
|
function mcl_villages.terraform(vm, settlement, pr)
|
|
|
|
-- TODO: sort top-down, then bottom-up, or opposite?
|
|
|
|
-- we make the foundations 2 node wider than necessary, to have one node for path laying
|
2024-08-06 20:37:44 +02:00
|
|
|
for i, building in ipairs(settlement) do
|
|
|
|
if not building.no_clearance then
|
|
|
|
local pos, size = building.pos, building.size
|
2024-09-03 17:16:36 +02:00
|
|
|
pos = vector.offset(pos, -math.floor((size.x-1)/2), 0, -math.floor((size.z-1)/2))
|
|
|
|
-- TODO: allow different clearance for different buildings?
|
2024-08-23 10:55:30 +02:00
|
|
|
vl_terraforming.clearance_vm(vm, pos.x-1, pos.y, pos.z-1, size.x+2, size.y, size.z+2, 2, building.surface_mat, building.dust_mat, pr)
|
2024-08-06 20:37:44 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
for i, building in ipairs(settlement) do
|
|
|
|
if not building.no_ground_turnip then
|
|
|
|
local pos, size = building.pos, building.size
|
|
|
|
local surface_mat = building.surface_mat
|
2024-09-03 17:16:36 +02:00
|
|
|
local platform_mat = building.platform_mat or { name = mcl_villages.foundation_materials[surface_mat.name] or "mcl_core:dirt" }
|
|
|
|
local stone_mat = building.stone_mat or { name = mcl_villages.stone_materials[surface_mat.name] or "mcl_core:stone" }
|
2024-08-23 10:55:30 +02:00
|
|
|
local dust_mat = building.dust_mat
|
2024-08-06 20:37:44 +02:00
|
|
|
building.platform_mat = platform_mat -- remember for use in schematic placement
|
|
|
|
building.stone_mat = stone_mat
|
|
|
|
pos = vector.offset(pos, -math.floor((size.x-1)/2), 0, -math.floor((size.z-1)/2))
|
2024-08-23 10:55:30 +02:00
|
|
|
vl_terraforming.foundation_vm(vm, pos.x-2, pos.y, pos.z-2, size.x+4, -5, size.z+4, 2, surface_mat, platform_mat, stone_mat, dust_mat, pr)
|
2024-08-06 20:37:44 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|