forked from MineClone5/MineClone5
Slightly rewrite villages at all
This commit is contained in:
parent
7e7c0c3a37
commit
4b4e29b3c1
|
@ -511,3 +511,7 @@ end
|
||||||
function mcl_mapgen.get_chunk_ending(x)
|
function mcl_mapgen.get_chunk_ending(x)
|
||||||
return mcl_mapgen.get_chunk_beginning(x) + LAST_NODE_IN_CHUNK
|
return mcl_mapgen.get_chunk_beginning(x) + LAST_NODE_IN_CHUNK
|
||||||
end
|
end
|
||||||
|
|
||||||
|
mcl_mapgen.get_block_seed = get_block_seed
|
||||||
|
mcl_mapgen.get_block_seed2 = get_block_seed2
|
||||||
|
mcl_mapgen.get_block_seed3 = get_block_seed3
|
||||||
|
|
|
@ -1,208 +0,0 @@
|
||||||
function settlements.initialize_settlement_info(pr)
|
|
||||||
local count_buildings = {}
|
|
||||||
|
|
||||||
-- count_buildings table reset
|
|
||||||
for k,v in pairs(settlements.schematic_table) do
|
|
||||||
count_buildings[v["name"]] = 0
|
|
||||||
end
|
|
||||||
|
|
||||||
-- randomize number of buildings
|
|
||||||
local number_of_buildings = pr:next(10, 25)
|
|
||||||
local number_built = 1
|
|
||||||
settlements.debug("Village ".. number_of_buildings)
|
|
||||||
|
|
||||||
return count_buildings, number_of_buildings, number_built
|
|
||||||
end
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- fill settlement_info
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
local possible_rotations = {"0", "90", "180", "270"}
|
|
||||||
function settlements.create_site_plan(minp, maxp, pr)
|
|
||||||
local settlement_info = {}
|
|
||||||
local building_all_info
|
|
||||||
-- find center of chunk
|
|
||||||
local center = vector.add(minp, mcl_mapgen.HALF_CS_NODES)
|
|
||||||
-- find center_surface of chunk
|
|
||||||
local center_surface, surface_material = settlements.find_surface(center)
|
|
||||||
|
|
||||||
-- go build settlement around center
|
|
||||||
if not center_surface then return false end
|
|
||||||
|
|
||||||
-- add settlement to list
|
|
||||||
table.insert(settlements_in_world, center_surface)
|
|
||||||
-- save list to file
|
|
||||||
settlements.save()
|
|
||||||
-- 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
|
|
||||||
local x, z, r = center_surface.x, center_surface.z, building_all_info["hsize"]
|
|
||||||
-- draw j circles around center and increase radius by math.random(2,5)
|
|
||||||
for j = 1,20 do
|
|
||||||
-- set position on imaginary circle
|
|
||||||
for j = 0, 360, 15 do
|
|
||||||
local angle = j * math.pi / 180
|
|
||||||
local ptx, ptz = x + r * math.cos( angle ), z + r * math.sin( angle )
|
|
||||||
ptx = settlements.round(ptx, 0)
|
|
||||||
ptz = settlements.round(ptz, 0)
|
|
||||||
local pos1 = { x=ptx, y=center_surface.y, z=ptz}
|
|
||||||
local pos_surface, surface_material = settlements.find_surface(pos1)
|
|
||||||
if not pos_surface then break end
|
|
||||||
|
|
||||||
local randomized_schematic_table = shuffle(settlements.schematic_table, pr)
|
|
||||||
-- pick schematic
|
|
||||||
local size = #randomized_schematic_table
|
|
||||||
for i = size, 1, -1 do
|
|
||||||
-- already enough buildings of that type?
|
|
||||||
if count_buildings[randomized_schematic_table[i]["name"]] < randomized_schematic_table[i]["max_num"]*number_of_buildings then
|
|
||||||
building_all_info = randomized_schematic_table[i]
|
|
||||||
-- check distance to other buildings
|
|
||||||
local distance_to_other_buildings_ok = settlements.check_distance(settlement_info, pos_surface, building_all_info["hsize"])
|
|
||||||
if distance_to_other_buildings_ok then
|
|
||||||
-- count built houses
|
|
||||||
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
|
|
||||||
if number_of_buildings == number_built then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if number_built >= number_of_buildings then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
r = r + pr:next(2,5)
|
|
||||||
end
|
|
||||||
settlements.debug("really ".. number_built)
|
|
||||||
return settlement_info
|
|
||||||
end
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- evaluate settlement_info and place schematics
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- Initialize node
|
|
||||||
local function construct_node(p1, p2, name)
|
|
||||||
local r = minetest.registered_nodes[name]
|
|
||||||
if r then
|
|
||||||
if r.on_construct then
|
|
||||||
local nodes = minetest.find_nodes_in_area(p1, p2, name)
|
|
||||||
for p=1, #nodes do
|
|
||||||
local pos = nodes[p]
|
|
||||||
r.on_construct(pos)
|
|
||||||
end
|
|
||||||
return nodes
|
|
||||||
end
|
|
||||||
minetest.log("warning", "[mcl_villages] No on_construct defined for node name " .. name)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
minetest.log("warning", "[mcl_villages] Attempt to 'construct' inexistant nodes: " .. name)
|
|
||||||
end
|
|
||||||
local function init_nodes(p1, rotation, pr, size)
|
|
||||||
local p2 = vector.subtract(vector.add(p1, size), 1)
|
|
||||||
construct_node(p1, p2, "mcl_itemframes:item_frame")
|
|
||||||
construct_node(p1, p2, "mcl_furnaces:furnace")
|
|
||||||
construct_node(p1, p2, "mcl_anvils:anvil")
|
|
||||||
|
|
||||||
local nodes = construct_node(p1, p2, "mcl_chests:chest")
|
|
||||||
if nodes and #nodes > 0 then
|
|
||||||
for p=1, #nodes do
|
|
||||||
local pos = nodes[p]
|
|
||||||
settlements.fill_chest(pos, pr)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
function settlements.place_schematics(settlement_info, pr)
|
|
||||||
local building_all_info
|
|
||||||
for i, built_house in ipairs(settlement_info) do
|
|
||||||
for j, schem in ipairs(settlements.schematic_table) do
|
|
||||||
if settlement_info[i]["name"] == schem["name"] then
|
|
||||||
building_all_info = schem
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local pos = settlement_info[i]["pos"]
|
|
||||||
local rotation = settlement_info[i]["rotat"]
|
|
||||||
-- get building node material for better integration to surrounding
|
|
||||||
local platform_material = settlement_info[i]["surface_mat"]
|
|
||||||
--platform_material_name = minetest.get_name_from_content_id(platform_material)
|
|
||||||
-- pick random material
|
|
||||||
--local material = wallmaterial[pr:next(1,#wallmaterial)]
|
|
||||||
--
|
|
||||||
local building = building_all_info["mts"]
|
|
||||||
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
|
|
||||||
schem_lua = schem_lua:gsub("mcl_core:dirt_with_grass", platform_material)
|
|
||||||
|
|
||||||
--[[ Disable special junglewood for now.
|
|
||||||
-- 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)()
|
|
||||||
-- build foundation for the building an make room above
|
|
||||||
-- place schematic
|
|
||||||
mcl_structures.place_schematic({
|
|
||||||
pos = pos,
|
|
||||||
schematic = schematic,
|
|
||||||
rotation = rotation,
|
|
||||||
on_placed = init_nodes,
|
|
||||||
pr = pr,
|
|
||||||
})
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,81 +0,0 @@
|
||||||
-- switch for debugging
|
|
||||||
function settlements.debug(message)
|
|
||||||
-- minetest.chat_send_all(message)
|
|
||||||
-- minetest.log("warning", "[mcl_villages] "..message)
|
|
||||||
minetest.log("verbose", "[mcl_villages] "..message)
|
|
||||||
end
|
|
||||||
|
|
||||||
--[[ Manually set in 'buildings.lua'
|
|
||||||
-- material to replace cobblestone with
|
|
||||||
local wallmaterial = {
|
|
||||||
"mcl_core:junglewood",
|
|
||||||
"mcl_core:sprucewood",
|
|
||||||
"mcl_core:wood",
|
|
||||||
"mcl_core:birchwood",
|
|
||||||
"mcl_core:acaciawood",
|
|
||||||
"mcl_core:stonebrick",
|
|
||||||
"mcl_core:cobble",
|
|
||||||
"mcl_core:sandstonecarved",
|
|
||||||
"mcl_core:sandstone",
|
|
||||||
"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
|
|
||||||
--
|
|
||||||
|
|
||||||
--
|
|
||||||
-- path to schematics
|
|
||||||
--
|
|
||||||
schem_path = settlements.modpath.."/schematics/"
|
|
||||||
--
|
|
||||||
-- list of schematics
|
|
||||||
--
|
|
||||||
local basic_pseudobiome_villages = minetest.settings:get_bool("basic_pseudobiome_villages", true)
|
|
||||||
|
|
||||||
settlements.schematic_table = {
|
|
||||||
{name = "large_house", mts = schem_path.."large_house.mts", hwidth = 11, hdepth = 12, hheight = 9, hsize = 14, max_num = 0.08 , rplc = basic_pseudobiome_villages },
|
|
||||||
{name = "blacksmith", mts = schem_path.."blacksmith.mts", hwidth = 7, hdepth = 7, hheight = 13, hsize = 13, max_num = 0.055, rplc = basic_pseudobiome_villages },
|
|
||||||
{name = "butcher", mts = schem_path.."butcher.mts", hwidth = 11, 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 = "farm", mts = schem_path.."farm.mts", hwidth = 7, hdepth = 7, hheight = 13, hsize = 13, max_num = 0.1 , rplc = basic_pseudobiome_villages },
|
|
||||||
{name = "lamp", mts = schem_path.."lamp.mts", hwidth = 3, hdepth = 3, 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 = "medium_house", mts = schem_path.."medium_house.mts", hwidth = 8, hdepth = 12, hheight = 8, hsize = 14, max_num = 0.08 , rplc = basic_pseudobiome_villages },
|
|
||||||
{name = "small_house", mts = schem_path.."small_house.mts", hwidth = 9, hdepth = 7, hheight = 8, hsize = 13, max_num = 0.7 , rplc = basic_pseudobiome_villages },
|
|
||||||
{name = "tavern", mts = schem_path.."tavern.mts", hwidth = 11, hdepth = 10, hheight = 10, hsize = 13, max_num = 0.050, rplc = basic_pseudobiome_villages },
|
|
||||||
{name = "well", mts = schem_path.."well.mts", hwidth = 6, hdepth = 8, hheight = 6, hsize = 10, max_num = 0.045, rplc = basic_pseudobiome_villages },
|
|
||||||
}
|
|
||||||
|
|
||||||
--
|
|
||||||
-- list of settlements, load on server start up
|
|
||||||
--
|
|
||||||
settlements_in_world = {}
|
|
||||||
--
|
|
||||||
--
|
|
||||||
-- maximum allowed difference in height for building a sttlement
|
|
||||||
--
|
|
||||||
max_height_difference = 56
|
|
||||||
--
|
|
||||||
--
|
|
||||||
--
|
|
||||||
half_map_chunk_size = 40
|
|
||||||
--quarter_map_chunk_size = 20
|
|
|
@ -1,65 +0,0 @@
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- function to fill empty space below baseplate when building on a hill
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
function settlements.ground(pos, pr) -- role model: Wendelsteinkircherl, Brannenburg
|
|
||||||
local p2 = vector.new(pos)
|
|
||||||
local cnt = 0
|
|
||||||
local mat = "mcl_core:dirt"
|
|
||||||
p2.y = p2.y-1
|
|
||||||
while true do
|
|
||||||
cnt = cnt+1
|
|
||||||
if cnt > 20 then break end
|
|
||||||
if cnt>pr:next(2,4) then
|
|
||||||
mat = "mcl_core:stone"
|
|
||||||
end
|
|
||||||
minetest.swap_node(p2, {name=mat})
|
|
||||||
p2.y = p2.y-1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- function clear space above baseplate
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
function settlements.terraform(settlement_info, pr)
|
|
||||||
local fheight, fwidth, fdepth, schematic_data
|
|
||||||
|
|
||||||
for i, built_house in ipairs(settlement_info) do
|
|
||||||
-- pick right schematic_info to current built_house
|
|
||||||
for j, schem in ipairs(settlements.schematic_table) do
|
|
||||||
if settlement_info[i]["name"] == schem["name"] then
|
|
||||||
schematic_data = schem
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
local pos = settlement_info[i]["pos"]
|
|
||||||
if settlement_info[i]["rotat"] == "0" or settlement_info[i]["rotat"] == "180" then
|
|
||||||
fwidth = schematic_data["hwidth"]
|
|
||||||
fdepth = schematic_data["hdepth"]
|
|
||||||
else
|
|
||||||
fwidth = schematic_data["hdepth"]
|
|
||||||
fdepth = schematic_data["hwidth"]
|
|
||||||
end
|
|
||||||
--fheight = schematic_data["hheight"] * 3 -- remove trees and leaves above
|
|
||||||
fheight = schematic_data["hheight"] -- remove trees and leaves above
|
|
||||||
--
|
|
||||||
-- now that every info is available -> create platform and clear space above
|
|
||||||
--
|
|
||||||
for xi = 0,fwidth-1 do
|
|
||||||
for zi = 0,fdepth-1 do
|
|
||||||
for yi = 0,fheight *3 do
|
|
||||||
if yi == 0 then
|
|
||||||
local p = {x=pos.x+xi, y=pos.y, z=pos.z+zi}
|
|
||||||
settlements.ground(p, pr)
|
|
||||||
else
|
|
||||||
-- write ground
|
|
||||||
-- local p = {x=pos.x+xi, y=pos.y+yi, z=pos.z+zi}
|
|
||||||
-- local node = mcl_vars.get_node(p)
|
|
||||||
-- if node and node.name ~= "air" then
|
|
||||||
-- minetest.swap_node(p,{name="air"})
|
|
||||||
-- end
|
|
||||||
minetest.swap_node({x=pos.x+xi, y=pos.y+yi, z=pos.z+zi},{name="air"})
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,26 +1,338 @@
|
||||||
settlements = {}
|
mcl_villages = {}
|
||||||
settlements.modpath = minetest.get_modpath(minetest.get_current_modname())
|
local chunk_offset_top = 16
|
||||||
|
local chunk_offset_bottom = 3
|
||||||
|
local max_height_difference = 12
|
||||||
|
local minp_min = -64
|
||||||
|
local chance_per_chunk = 1
|
||||||
|
local noise_multiplier = 1
|
||||||
|
local random_offset = 1
|
||||||
|
local random_multiply = 19
|
||||||
|
local struct_threshold = chance_per_chunk - 1
|
||||||
|
local modname = minetest.get_current_modname()
|
||||||
|
local modpath = minetest.get_modpath(modname)
|
||||||
|
local S = minetest.get_translator(modname)
|
||||||
|
local basic_pseudobiome_villages = minetest.settings:get_bool("basic_pseudobiome_villages", true)
|
||||||
|
local schem_path = modpath .. "/schematics/"
|
||||||
|
local schematic_table = {
|
||||||
|
{name = "large_house", mts = schem_path.."large_house.mts", hwidth = 11, hdepth = 12, hheight = 9, hsize = 14, max_num = 0.08 , rplc = basic_pseudobiome_villages },
|
||||||
|
{name = "blacksmith", mts = schem_path.."blacksmith.mts", hwidth = 7, hdepth = 7, hheight = 13, hsize = 13, max_num = 0.055, rplc = basic_pseudobiome_villages },
|
||||||
|
{name = "butcher", mts = schem_path.."butcher.mts", hwidth = 11, 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 = "farm", mts = schem_path.."farm.mts", hwidth = 7, hdepth = 7, hheight = 13, hsize = 13, max_num = 0.1 , rplc = basic_pseudobiome_villages },
|
||||||
|
{name = "lamp", mts = schem_path.."lamp.mts", hwidth = 3, hdepth = 3, 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 = "medium_house", mts = schem_path.."medium_house.mts", hwidth = 8, hdepth = 12, hheight = 8, hsize = 14, max_num = 0.08 , rplc = basic_pseudobiome_villages },
|
||||||
|
{name = "small_house", mts = schem_path.."small_house.mts", hwidth = 9, hdepth = 7, hheight = 8, hsize = 13, max_num = 0.7 , rplc = basic_pseudobiome_villages },
|
||||||
|
{name = "tavern", mts = schem_path.."tavern.mts", hwidth = 11, hdepth = 10, hheight = 10, hsize = 13, max_num = 0.050, rplc = basic_pseudobiome_villages },
|
||||||
|
{name = "well", mts = schem_path.."well.mts", hwidth = 6, hdepth = 8, hheight = 6, hsize = 10, max_num = 0.045, rplc = basic_pseudobiome_villages },
|
||||||
|
}
|
||||||
|
local surface_mat = {
|
||||||
|
["mcl_core:dirt_with_dry_grass"] = true,
|
||||||
|
["mcl_core:dirt_with_grass"] = true,
|
||||||
|
["mcl_core:dirt_with_grass_snow"] = true,
|
||||||
|
["mcl_core:podzol"] = true,
|
||||||
|
["mcl_core:redsand"] = true,
|
||||||
|
["mcl_core:sand"] = true,
|
||||||
|
["mcl_core:snow"] = true,
|
||||||
|
}
|
||||||
|
local storage = minetest.get_mod_storage()
|
||||||
|
local villages = minetest.deserialize(storage:get_string("villages") or "return {}") or {}
|
||||||
|
local minetest_get_spawn_level = minetest.get_spawn_level
|
||||||
|
local minetest_get_node = minetest.get_node
|
||||||
|
local minetest_find_nodes_in_area = minetest.find_nodes_in_area
|
||||||
|
local mcl_structures_get_perlin_noise_level = mcl_structures.get_perlin_noise_level
|
||||||
|
local math_pi = math.pi
|
||||||
|
local math_cos = math.cos
|
||||||
|
local math_sin = math.sin
|
||||||
|
local math_floor = math.floor
|
||||||
|
local math_ceil = math.ceil
|
||||||
|
local minetest_swap_node = minetest.swap_node
|
||||||
|
local minetest_registered_nodes = minetest.registered_nodes
|
||||||
|
local air_offset = chunk_offset_top - 1
|
||||||
|
local ground_offset = chunk_offset_bottom + 1
|
||||||
|
local surface_search_list = {}
|
||||||
|
for k, _ in surface_mat do
|
||||||
|
table.insert(surface_search_list, k)
|
||||||
|
end
|
||||||
|
|
||||||
local minetest_get_spawn_level = minetest.get_spawn_level
|
local function math_round(x)
|
||||||
|
return (x < 0) and math_ceil(x - 0.5) or math_floor(x + 0.5)
|
||||||
|
end
|
||||||
|
|
||||||
dofile(settlements.modpath.."/const.lua")
|
local function find_surface(pos, minp, maxp)
|
||||||
dofile(settlements.modpath.."/utils.lua")
|
local x, z = pos.x, pos.z
|
||||||
dofile(settlements.modpath.."/foundation.lua")
|
local y_top = maxp.y
|
||||||
dofile(settlements.modpath.."/buildings.lua")
|
local y_max = y_top - air_offset
|
||||||
dofile(settlements.modpath.."/paths.lua")
|
if #minetest_find_nodes_in_area({x=x, y=y_max, z=z}, {x=x, y=y_top, z=z}, "air") < chunk_offset_top then return end
|
||||||
|
y_max = y_max - 1
|
||||||
|
local y_bottom = minp.y
|
||||||
|
local y_min = y_bottom + chunk_offset_bottom
|
||||||
|
local nodes = minetest_find_nodes_in_area({x=x, y=y_min, z=z}, {x=x, y=y_max, z=z}, surface_search_list)
|
||||||
|
for _, surface_pos in pairs(nodes) do
|
||||||
|
local node_name_from_above = minetest_get_node({x=surface_pos.x, y=surface_pos.y+1, z=surface_pos.z}).name
|
||||||
|
if string.find(node_name_from_above, "air" )
|
||||||
|
or string.find(node_name_from_above, "snow" )
|
||||||
|
or string.find(node_name_from_above, "fern" )
|
||||||
|
or string.find(node_name_from_above, "flower")
|
||||||
|
or string.find(node_name_from_above, "bush" )
|
||||||
|
or string.find(node_name_from_above, "tree" )
|
||||||
|
or string.find(node_name_from_above, "grass" )
|
||||||
|
then return surface_pos, minetese_get_node(surface_pos).name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--
|
local function get_treasures(pr)
|
||||||
-- load settlements on server
|
local loottable = {{
|
||||||
--
|
stacks_min = 3,
|
||||||
settlements_in_world = settlements.load()
|
stacks_max = 8,
|
||||||
settlements.grundstellungen()
|
items = {
|
||||||
|
{ itemstring = "mcl_core:diamond" , weight = 3, amount_min = 1, amount_max = 3 },
|
||||||
|
{ itemstring = "mcl_core:iron_ingot" , weight = 10, amount_min = 1, amount_max = 5 },
|
||||||
|
{ itemstring = "mcl_core:gold_ingot" , weight = 5, amount_min = 1, amount_max = 3 },
|
||||||
|
{ itemstring = "mcl_farming:bread" , weight = 15, amount_min = 1, amount_max = 3 },
|
||||||
|
{ itemstring = "mcl_core:apple" , weight = 15, amount_min = 1, amount_max = 3 },
|
||||||
|
{ itemstring = "mcl_tools:pick_iron" , weight = 5, },
|
||||||
|
{ itemstring = "mcl_tools:sword_iron" , weight = 5, },
|
||||||
|
{ itemstring = "mcl_armor:chestplate_iron" , weight = 5, },
|
||||||
|
{ itemstring = "mcl_armor:helmet_iron" , weight = 5, },
|
||||||
|
{ itemstring = "mcl_armor:leggings_iron" , weight = 5, },
|
||||||
|
{ itemstring = "mcl_armor:boots_iron" , weight = 5, },
|
||||||
|
{ itemstring = "mcl_core:obsidian" , weight = 5, amount_min = 3, amount_max = 7 },
|
||||||
|
{ itemstring = "mcl_core:sapling" , weight = 5, amount_min = 3, amount_max = 7 },
|
||||||
|
{ itemstring = "mcl_mobitems:saddle" , weight = 3, },
|
||||||
|
{ itemstring = "mobs_mc:iron_horse_armor" , weight = 1, },
|
||||||
|
{ itemstring = "mobs_mc:gold_horse_armor" , weight = 1, },
|
||||||
|
{ itemstring = "mobs_mc:diamond_horse_armor", weight = 1, },
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
local items = mcl_loot.get_multi_loot(loottable, pr)
|
||||||
|
return items
|
||||||
|
end
|
||||||
|
|
||||||
|
local function fill_chest(pos, pr)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
minetest.registered_nodes["mcl_chests:chest_small"].on_construct(pos)
|
||||||
|
local inv = minetest.get_inventory( {type="node", pos=pos} )
|
||||||
|
local items = get_treasures(pr)
|
||||||
|
mcl_loot.fill_inventory(inv, "main", items, pr)
|
||||||
|
end
|
||||||
|
|
||||||
|
local possible_rotations = {"0", "90", "180", "270"}
|
||||||
|
|
||||||
|
local function get_random_rotation(pr)
|
||||||
|
return possible_rotations[pr:next(1, #possible_rotations)]
|
||||||
|
end
|
||||||
|
|
||||||
|
local function create_site_plan(minp, maxp, pr)
|
||||||
|
local plan = {}
|
||||||
|
local building_all_info
|
||||||
|
local center = vector.add(minp, mcl_mapgen.HALF_CS_NODES)
|
||||||
|
local center_surface, surface_material = find_surface(center, minp, maxp)
|
||||||
|
if not center_surface then return end
|
||||||
|
|
||||||
|
local number_of_buildings = pr:next(10, 25)
|
||||||
|
local shuffle = {}
|
||||||
|
local count_buildings = {}
|
||||||
|
for i = 1, #schematic_table do
|
||||||
|
shuffle[i] = i
|
||||||
|
count_buildings[i] = 0
|
||||||
|
end
|
||||||
|
for i = #shuffle, 2, -1 do
|
||||||
|
local j = pr:next(1, i)
|
||||||
|
shuffle[i], shuffle[j] = shuffle[j], shuffle[i]
|
||||||
|
end
|
||||||
|
local number_built = 1
|
||||||
|
local shuffle_index = pr:next(1, #schematic_table)
|
||||||
|
|
||||||
|
-- first building is townhall in the center
|
||||||
|
plan[#plan + 1] = {
|
||||||
|
pos = center_surface,
|
||||||
|
building = schematic_table[shuffle_index],
|
||||||
|
rotation = get_random_rotation(pr),
|
||||||
|
surface_mat = surface_material,
|
||||||
|
}
|
||||||
|
count_buildings[1] = count_buildings[1] + 1
|
||||||
|
-- now some buildings around in a circle, radius = size of town center
|
||||||
|
local x, z, r = center_surface.x, center_surface.z, schematic_table[1].hsize
|
||||||
|
-- draw j circles around center and increase radius by random(2, 5)
|
||||||
|
for k = 1, 20 do
|
||||||
|
-- set position on imaginary circle
|
||||||
|
for j = 0, 360, 15 do
|
||||||
|
local angle = j * math_pi / 180
|
||||||
|
local pos_surface, surface_material = find_surface(
|
||||||
|
{
|
||||||
|
x = math_round(x + r * math_cos(angle)),
|
||||||
|
z = math_round(z + r * math_sin(angle))
|
||||||
|
},
|
||||||
|
minp,
|
||||||
|
maxp,
|
||||||
|
)
|
||||||
|
if pos_surface then
|
||||||
|
shuffle_index = (shuffle_index % (#schematic_table)) + 1
|
||||||
|
local schematic_index = shuffle[shuffle_index]
|
||||||
|
local schematic = schematic_table[schematic_index]
|
||||||
|
if count_buildings[schematic_index] < schematic.max_num * number_of_buildings then
|
||||||
|
local hsize2 = schematic.hsize^2
|
||||||
|
local is_distance_ok = true
|
||||||
|
for _, built_house in pairs(plan) do
|
||||||
|
local pos = built_house.pos
|
||||||
|
local building = built_house.building
|
||||||
|
local distance2 = (pos_surface.x - pos.x)^2 + (pos_surface.z - pos.z)^2
|
||||||
|
if distance2 < building.hsize^2 or distance < hsize2 then
|
||||||
|
is_distance_ok = false
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if is_distance_ok then
|
||||||
|
plan[#plan + 1] = {
|
||||||
|
pos = pos_surface,
|
||||||
|
building = schematic,
|
||||||
|
rotation = get_random_rotation(pr),
|
||||||
|
surface_mat = surface_material,
|
||||||
|
}
|
||||||
|
count_buildinigs[schematic_index] = count_buildinigs[schematic_index] + 1
|
||||||
|
number_built = number_built + 1
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if number_built >= number_of_buildings then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if number_built >= number_of_buildings then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
r = r + pr:next(2, 5)
|
||||||
|
end
|
||||||
|
return plan
|
||||||
|
end
|
||||||
|
|
||||||
|
local function ground(pos, minp, maxp, pr)
|
||||||
|
local p2 = vector.new(pos)
|
||||||
|
local cnt = 0
|
||||||
|
local mat = "mcl_core:dirt"
|
||||||
|
p2.y = p2.y - 1
|
||||||
|
local min_y = math_max(minp.y, p2.y - pr:next(17,27))
|
||||||
|
local stone_level = p2.y - pr:next(2, 4)
|
||||||
|
while p2.y >= min_y do
|
||||||
|
if p2.y == stone_level then
|
||||||
|
mat = "mcl_core:stone"
|
||||||
|
end
|
||||||
|
minetest.swap_node(p2, {name=mat})
|
||||||
|
p2.y = p2.y - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function terraform(plan, minp, maxp, pr)
|
||||||
|
local fheight, fwidth, fdepth, schematic_data, pos, rotation
|
||||||
|
for _, built_house in pairs(plan) do
|
||||||
|
schematic_data = plan[i].building
|
||||||
|
pos = plan[i].pos
|
||||||
|
rotation = plan[i].rotation
|
||||||
|
if rotation == "0" or rotation = "180" then
|
||||||
|
fwidth = schematic_data.hwidth
|
||||||
|
fdepth = schematic_data.hdepth
|
||||||
|
else
|
||||||
|
fwidth = schematic_data.hdepth
|
||||||
|
fdepth = schematic_data.hwidth
|
||||||
|
end
|
||||||
|
fheight = schematic_data.hheight
|
||||||
|
for xi = pos.x, pos.x + fwidth - 1 do
|
||||||
|
for zi = pos.z, pos.z + fdepth - 1 do
|
||||||
|
for yi = pos.y, math_min(pos.y + fheight * 3, maxp.y) do
|
||||||
|
local p = {x = xi, y = yi, z = zi}
|
||||||
|
if yi == pos.y then
|
||||||
|
ground(p, pr)
|
||||||
|
else
|
||||||
|
minetest_swap_node(p, {name = "air"})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function paths(plan)
|
||||||
|
local starting_point
|
||||||
|
local end_point
|
||||||
|
local distance
|
||||||
|
starting_point = plan[1].pos
|
||||||
|
for o, p in pairs(plan) do
|
||||||
|
end_point = settlement_info[o].pos
|
||||||
|
local path = minetest.find_path(starting_point, end_point, mcl_mapgen.CS_NODES, 2, 2)
|
||||||
|
if path then
|
||||||
|
for _, pos in pairs(path) do
|
||||||
|
local surface_mat = minetest.get_node(pos).name
|
||||||
|
if surface_mat == "mcl_core:sand" or surface_mat == "mcl_core:redsand" then
|
||||||
|
minetest.swap_node(surface_point, {name = "mcl_core:sandstonesmooth2"})
|
||||||
|
else
|
||||||
|
minetest.swap_node(surface_point, {name = "mcl_core:grass_path"})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function init_nodes(p1, rotation, pr, size)
|
||||||
|
local p2 = vector.subtract(vector.add(p1, size), 1)
|
||||||
|
local nodes = minetest.find_nodes_in_area(p1, p2, {"mcl_itemframes:item_frame", "mcl_furnaces:furnace", "mcl_anvils:anvil"})
|
||||||
|
for _, pos in pairs(nodes) do
|
||||||
|
local name = minetest_get_node(pos).name
|
||||||
|
local def = minetest_registered_nodes[minetest_get_node(pos).name]
|
||||||
|
def.on_construct(pos)
|
||||||
|
if name == "mcl_chests:chest" then
|
||||||
|
fill_chest(pos, pr)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function place_schematics(plan, pr)
|
||||||
|
for _, built_house in pairs(plan) do
|
||||||
|
local pos = built_house.pos
|
||||||
|
local rotation = built_house.rotation
|
||||||
|
local platform_material = built_house.surface_mat
|
||||||
|
local building = built_house.building.mts
|
||||||
|
local replace_wall = built_house.building.rplc
|
||||||
|
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")
|
||||||
|
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")
|
||||||
|
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_core:brick_block", "mcl_core:redsandstone")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
schem_lua = schem_lua:gsub("mcl_core:dirt_with_grass", platform_material)
|
||||||
|
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")
|
||||||
|
|
||||||
|
local schematic = loadstring(schem_lua)()
|
||||||
|
-- build foundation for the building an make room above
|
||||||
|
-- place schematic
|
||||||
|
mcl_structures.place_schematic({
|
||||||
|
pos = pos,
|
||||||
|
schematic = schematic,
|
||||||
|
rotation = rotation,
|
||||||
|
on_placed = init_nodes,
|
||||||
|
pr = pr,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
--
|
--
|
||||||
-- register block for npc spawn
|
-- register block for npc spawn
|
||||||
--
|
--
|
||||||
minetest.register_node("mcl_villages:stonebrickcarved", {
|
minetest.register_node("mcl_villages:stonebrickcarved", {
|
||||||
description = ("Chiseled Stone Village Bricks"),
|
description = S("Chiseled Stone Village Bricks"),
|
||||||
_doc_items_longdesc = doc.sub.items.temp.build,
|
_doc_items_longdesc = doc.sub.items.temp.build,
|
||||||
tiles = {"mcl_core_stonebrick_carved.png"},
|
tiles = {"mcl_core_stonebrick_carved.png"},
|
||||||
stack_max = 64,
|
stack_max = 64,
|
||||||
|
@ -36,73 +348,59 @@ minetest.register_node("mcl_villages:stonebrickcarved", {
|
||||||
--
|
--
|
||||||
-- 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, pr)
|
||||||
minetest.log("action","[mcl_villages] Building village at mapchunk " .. minetest.pos_to_string(minp) .. "..." .. minetest.pos_to_string(maxp) .. ", blockseed = " .. tostring(blockseed))
|
minetest.log("action","[mcl_villages] Building village at mapchunk " .. minetest.pos_to_string(minp) .. "..." .. minetest.pos_to_string(maxp))
|
||||||
local pr = PseudoRandom(blockseed)
|
local pr = pr or PseudoRandom(mcl_mapgen.get_block_seed3(minp))
|
||||||
|
local plan = create_site_plan(minp, maxp, pr)
|
||||||
|
if not plan then return end
|
||||||
|
terraform(plan, minp, maxp, pr)
|
||||||
|
paths(plan)
|
||||||
|
place_schematics(plan, pr)
|
||||||
|
|
||||||
-- fill settlement_info with buildings and their data
|
local center = vector.add(minp, mcl_mapgen.HALF_CS_NODES)
|
||||||
local settlement_info = settlements.create_site_plan(minp, maxp, pr)
|
local center_surface = settlements.find_surface(center)
|
||||||
if not settlement_info then return end
|
table.insert(villages, center_surface)
|
||||||
|
storage:set_string("villages", minetest.serialize(villages))
|
||||||
|
|
||||||
-- evaluate settlement_info and prepair terrain
|
-- save list to file
|
||||||
settlements.terraform(settlement_info, pr)
|
settlements.save()
|
||||||
|
|
||||||
-- evaluate settlement_info and build paths between buildings
|
|
||||||
settlements.paths(settlement_info)
|
|
||||||
|
|
||||||
-- evaluate settlement_info and place schematics
|
|
||||||
settlements.place_schematics(settlement_info, pr)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Disable natural generation in singlenode.
|
-- Disable natural generation in singlenode.
|
||||||
local mg_name = minetest.get_mapgen_setting("mg_name")
|
|
||||||
local scan_last_node = (mcl_mapgen.CS - 2) * mcl_mapgen.BS - 1
|
|
||||||
local scan_offset = mcl_mapgen.BS
|
|
||||||
if mg_name ~= "singlenode" then
|
if mg_name ~= "singlenode" then
|
||||||
mcl_mapgen.register_mapgen(function(minp, maxp, blockseed)
|
local mg_name = minetest.get_mapgen_setting("mg_name")
|
||||||
-- local str1 = (maxp.y >= 0 and blockseed % 77 == 17) and "YES" or "no"
|
local scan_last_node = mcl_mapgen.LAST_BLOCK * mcl_mapgen.BS - 1
|
||||||
-- minetest.log("action","[mcl_villages] " .. str1 .. ": minp=" .. minetest.pos_to_string(minp) .. ", maxp=" .. minetest.pos_to_string(maxp) .. ", blockseed=" .. tostring(blockseed))
|
local scan_offset = mcl_mapgen.BS
|
||||||
-- don't build settlement underground
|
mcl_mapgen.register_mapgen(function(minp, maxp, chunkseed)
|
||||||
local y_max = maxp.y
|
if minp.y < minp_min then return end
|
||||||
if y_max < -30 then return end
|
local pr = PseudoRandom(chunkseed * random_multiply + random_offset)
|
||||||
-- randomly try to build settlements
|
local noise = mcl_structures_get_perlin_noise_level(minp) * noise_multiplier
|
||||||
-- if blockseed % 77 ~= 17 then return end
|
if (random_number + noise) < struct_threshold then return end
|
||||||
|
|
||||||
-- don't build settlements on (too) uneven terrain
|
|
||||||
|
|
||||||
-- lame and quick replacement of `heightmap` by kay27 - we maybe need to restore `heightmap` analysis if there will be a way for the engine to avoid cavegen conflicts:
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
local min, max = 9999999, -9999999
|
local min, max = 9999999, -9999999
|
||||||
local pr = PseudoRandom(blockseed)
|
|
||||||
for i = 1, pr:next(5,10) do
|
for i = 1, pr:next(5,10) do
|
||||||
local pos = vector.add(vector.new(pr:next(0, scan_last_node) + scan_offset, 0, pr:next(0, scan_last_node) + scan_offset), minp)
|
local surface_point = settlements.find_surface(
|
||||||
local surface_point = settlements.find_surface(pos)
|
vector.add(
|
||||||
|
vector.new(
|
||||||
|
pr:next(scan_offset, scan_last_node) + ,
|
||||||
|
0,
|
||||||
|
pr:next(0, scan_last_node) + scan_offset
|
||||||
|
),
|
||||||
|
minp
|
||||||
|
)
|
||||||
|
)
|
||||||
if not surface_point then return end
|
if not surface_point then return end
|
||||||
local y = surface_point.y
|
local y = surface_point.y
|
||||||
min = math.min(y, min)
|
min = math.min(y, min)
|
||||||
max = math.max(y, max)
|
max = math.max(y, max)
|
||||||
end
|
end
|
||||||
local height_difference = max - min
|
local height_difference = max - min
|
||||||
--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
minetest.chat_send_all("height diff="..height_difference)
|
minetest.chat_send_all("height diff="..height_difference)
|
||||||
if height_difference > 10 then return end
|
if height_difference > max_height_difference then return end
|
||||||
|
build_a_settlement(minp, maxp, chunkkseed)
|
||||||
build_a_settlement(minp, maxp, blockseed)
|
|
||||||
end, mcl_mapgen.order.VILLAGES)
|
end, mcl_mapgen.order.VILLAGES)
|
||||||
end
|
end
|
||||||
-- manually place villages
|
|
||||||
if minetest.is_creative_enabled("") then
|
function mcl_villages.get_villages()
|
||||||
minetest.register_craftitem("mcl_villages:tool", {
|
return villages
|
||||||
description = "mcl_villages build tool",
|
|
||||||
inventory_image = "default_tool_woodshovel.png",
|
|
||||||
-- build ssettlement
|
|
||||||
on_place = function(itemstack, placer, pointed_thing)
|
|
||||||
if not pointed_thing.under then return end
|
|
||||||
local minp = vector.subtract( pointed_thing.under, half_map_chunk_size)
|
|
||||||
local maxp = vector.add( pointed_thing.under, half_map_chunk_size)
|
|
||||||
build_a_settlement(minp, maxp, math.random(0,32767))
|
|
||||||
end
|
|
||||||
})
|
|
||||||
mcl_wip.register_experimental_item("mcl_villages:tool")
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
# textdomain: mcl_villages
|
||||||
|
Chiseled Stone Village Bricks=
|
|
@ -1,5 +1,5 @@
|
||||||
name = mcl_villages
|
name = mcl_villages
|
||||||
author = Rochambeau, MysticTempest, kay27
|
author = Rochambeau, MysticTempest, kay27
|
||||||
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, mcl_mapgen
|
depends = mcl_util, mcl_structures, mcl_core, mcl_loot, mcl_mapgen
|
||||||
optional_depends = mcl_farming, mobs_mc
|
optional_depends = mcl_farming, mobs_mc
|
||||||
|
|
|
@ -1,91 +0,0 @@
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- generate paths between buildings
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
function settlements.paths(settlement_info)
|
|
||||||
local starting_point
|
|
||||||
local end_point
|
|
||||||
local distance
|
|
||||||
--for k,v in pairs(settlement_info) do
|
|
||||||
starting_point = settlement_info[1]["pos"]
|
|
||||||
for o,p in pairs(settlement_info) do
|
|
||||||
|
|
||||||
end_point = settlement_info[o]["pos"]
|
|
||||||
if starting_point ~= end_point
|
|
||||||
then
|
|
||||||
-- loop until end_point is reched (distance == 0)
|
|
||||||
while true do
|
|
||||||
|
|
||||||
-- define surrounding pos to starting_point
|
|
||||||
local north_p = {x=starting_point.x+1, y=starting_point.y, z=starting_point.z}
|
|
||||||
local south_p = {x=starting_point.x-1, y=starting_point.y, z=starting_point.z}
|
|
||||||
local west_p = {x=starting_point.x, y=starting_point.y, z=starting_point.z+1}
|
|
||||||
local east_p = {x=starting_point.x, y=starting_point.y, z=starting_point.z-1}
|
|
||||||
-- measure distance to end_point
|
|
||||||
local dist_north_p_to_end = math.sqrt(
|
|
||||||
((north_p.x - end_point.x)*(north_p.x - end_point.x))+
|
|
||||||
((north_p.z - end_point.z)*(north_p.z - end_point.z))
|
|
||||||
)
|
|
||||||
local dist_south_p_to_end = math.sqrt(
|
|
||||||
((south_p.x - end_point.x)*(south_p.x - end_point.x))+
|
|
||||||
((south_p.z - end_point.z)*(south_p.z - end_point.z))
|
|
||||||
)
|
|
||||||
local dist_west_p_to_end = math.sqrt(
|
|
||||||
((west_p.x - end_point.x)*(west_p.x - end_point.x))+
|
|
||||||
((west_p.z - end_point.z)*(west_p.z - end_point.z))
|
|
||||||
)
|
|
||||||
local dist_east_p_to_end = math.sqrt(
|
|
||||||
((east_p.x - end_point.x)*(east_p.x - end_point.x))+
|
|
||||||
((east_p.z - end_point.z)*(east_p.z - end_point.z))
|
|
||||||
)
|
|
||||||
-- evaluate which pos is closer to the end_point
|
|
||||||
if dist_north_p_to_end <= dist_south_p_to_end and
|
|
||||||
dist_north_p_to_end <= dist_west_p_to_end and
|
|
||||||
dist_north_p_to_end <= dist_east_p_to_end
|
|
||||||
then
|
|
||||||
starting_point = north_p
|
|
||||||
distance = dist_north_p_to_end
|
|
||||||
|
|
||||||
elseif dist_south_p_to_end <= dist_north_p_to_end and
|
|
||||||
dist_south_p_to_end <= dist_west_p_to_end and
|
|
||||||
dist_south_p_to_end <= dist_east_p_to_end
|
|
||||||
then
|
|
||||||
starting_point = south_p
|
|
||||||
distance = dist_south_p_to_end
|
|
||||||
|
|
||||||
elseif dist_west_p_to_end <= dist_north_p_to_end and
|
|
||||||
dist_west_p_to_end <= dist_south_p_to_end and
|
|
||||||
dist_west_p_to_end <= dist_east_p_to_end
|
|
||||||
then
|
|
||||||
starting_point = west_p
|
|
||||||
distance = dist_west_p_to_end
|
|
||||||
|
|
||||||
elseif dist_east_p_to_end <= dist_north_p_to_end and
|
|
||||||
dist_east_p_to_end <= dist_south_p_to_end and
|
|
||||||
dist_east_p_to_end <= dist_west_p_to_end
|
|
||||||
then
|
|
||||||
starting_point = east_p
|
|
||||||
distance = dist_east_p_to_end
|
|
||||||
end
|
|
||||||
-- find surface of new starting point
|
|
||||||
local surface_point, surface_mat = settlements.find_surface(starting_point)
|
|
||||||
-- replace surface node with mcl_core:grass_path
|
|
||||||
if surface_point
|
|
||||||
then
|
|
||||||
if surface_mat == "mcl_core:sand" or surface_mat == "mcl_core:redsand" then
|
|
||||||
minetest.swap_node(surface_point,{name="mcl_core:sandstonesmooth2"})
|
|
||||||
else
|
|
||||||
minetest.swap_node(surface_point,{name="mcl_core:grass_path"})
|
|
||||||
end
|
|
||||||
-- don't set y coordinate, surface might be too low or high
|
|
||||||
starting_point.x = surface_point.x
|
|
||||||
starting_point.z = surface_point.z
|
|
||||||
end
|
|
||||||
if distance <= 1 or
|
|
||||||
starting_point == end_point
|
|
||||||
then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
|
@ -1,198 +0,0 @@
|
||||||
local get_node = minetest.get_node
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- function to copy tables
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
function settlements.shallowCopy(original)
|
|
||||||
local copy = {}
|
|
||||||
for key, value in pairs(original) do
|
|
||||||
copy[key] = value
|
|
||||||
end
|
|
||||||
return copy
|
|
||||||
end
|
|
||||||
--
|
|
||||||
--
|
|
||||||
--
|
|
||||||
function settlements.round(num, numDecimalPlaces)
|
|
||||||
local mult = 10^(numDecimalPlaces or 0)
|
|
||||||
return math.floor(num * mult + 0.5) / mult
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- function to find surface block y coordinate
|
|
||||||
-- returns surface postion
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
function settlements.find_surface(pos)
|
|
||||||
local p6 = vector.new(pos)
|
|
||||||
p6.y = mcl_mapgen.get_chunk_ending(p6.y)
|
|
||||||
local ymin = mcl_mapgen.get_chunk_beginning(p6.y)
|
|
||||||
local node = get_node(p6)
|
|
||||||
minetest.chat_send_all(node.name)
|
|
||||||
if node.name ~= "air" then return end
|
|
||||||
while true do
|
|
||||||
p6.y = p6.y - 1
|
|
||||||
if p6.y < ymin then return end
|
|
||||||
node = get_node(p6)
|
|
||||||
if settlements.surface_mat[node.name] then
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
minetest.chat_send_all(node.name)
|
|
||||||
|
|
||||||
local prev_node = minetest.get_node(vector.new(p6.x, p6.y + 1, p6.z))
|
|
||||||
local name = prev_node.name
|
|
||||||
if (string.find(name, "air")
|
|
||||||
or string.find(name, "snow")
|
|
||||||
or string.find(name, "fern")
|
|
||||||
or string.find(name, "flower")
|
|
||||||
or string.find(name, "bush")
|
|
||||||
or string.find(name, "tree")
|
|
||||||
or string.find(name, "grass")
|
|
||||||
) then
|
|
||||||
minetest.chat_send_all("found! "..node.name..", "..minetest.pos_to_string(p6))
|
|
||||||
return p6, node.name
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- check distance for new building
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
function settlements.check_distance(settlement_info, building_pos, building_size)
|
|
||||||
local distance
|
|
||||||
for i, built_house in ipairs(settlement_info) do
|
|
||||||
distance = math.sqrt(
|
|
||||||
((building_pos.x - built_house["pos"].x)*(building_pos.x - built_house["pos"].x))+
|
|
||||||
((building_pos.z - built_house["pos"].z)*(building_pos.z - built_house["pos"].z)))
|
|
||||||
if distance < building_size or distance < built_house["hsize"] then
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return true
|
|
||||||
end
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- save list of generated settlements
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
function settlements.save()
|
|
||||||
local file = io.open(minetest.get_worldpath().."/settlements.txt", "w")
|
|
||||||
if file then
|
|
||||||
file:write(minetest.serialize(settlements_in_world))
|
|
||||||
file:close()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- load list of generated settlements
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
function settlements.load()
|
|
||||||
local file = io.open(minetest.get_worldpath().."/settlements.txt", "r")
|
|
||||||
if file then
|
|
||||||
local table = minetest.deserialize(file:read("*all"))
|
|
||||||
if type(table) == "table" then
|
|
||||||
return table
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return {}
|
|
||||||
end
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- fill chests
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
function settlements.fill_chest(pos, pr)
|
|
||||||
-- initialize chest (mts chests don't have meta)
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
if meta:get_string("infotext") ~= "Chest" then
|
|
||||||
-- For MineClone2 0.70 or before
|
|
||||||
-- minetest.registered_nodes["mcl_chests:chest"].on_construct(pos)
|
|
||||||
--
|
|
||||||
-- For MineClone2 after commit 09ab1482b5 (the new entity chests)
|
|
||||||
minetest.registered_nodes["mcl_chests:chest_small"].on_construct(pos)
|
|
||||||
end
|
|
||||||
-- fill chest
|
|
||||||
local inv = minetest.get_inventory( {type="node", pos=pos} )
|
|
||||||
|
|
||||||
local function get_treasures(prand)
|
|
||||||
local loottable = {{
|
|
||||||
stacks_min = 3,
|
|
||||||
stacks_max = 8,
|
|
||||||
items = {
|
|
||||||
{ itemstring = "mcl_core:diamond", weight = 3, amount_min = 1, amount_max = 3 },
|
|
||||||
{ itemstring = "mcl_core:iron_ingot", weight = 10, amount_min = 1, amount_max = 5 },
|
|
||||||
{ itemstring = "mcl_core:gold_ingot", weight = 5, amount_min = 1, amount_max = 3 },
|
|
||||||
{ itemstring = "mcl_farming:bread", weight = 15, amount_min = 1, amount_max = 3 },
|
|
||||||
{ itemstring = "mcl_core:apple", weight = 15, amount_min = 1, amount_max = 3 },
|
|
||||||
{ itemstring = "mcl_tools:pick_iron", weight = 5 },
|
|
||||||
{ itemstring = "mcl_tools:sword_iron", weight = 5 },
|
|
||||||
{ itemstring = "mcl_armor:chestplate_iron", weight = 5 },
|
|
||||||
{ itemstring = "mcl_armor:helmet_iron", weight = 5 },
|
|
||||||
{ itemstring = "mcl_armor:leggings_iron", weight = 5 },
|
|
||||||
{ itemstring = "mcl_armor:boots_iron", weight = 5 },
|
|
||||||
{ itemstring = "mcl_core:obsidian", weight = 5, amount_min = 3, amount_max = 7 },
|
|
||||||
{ itemstring = "mcl_core:sapling", weight = 5, amount_min = 3, amount_max = 7 },
|
|
||||||
{ itemstring = "mcl_mobitems:saddle", weight = 3 },
|
|
||||||
{ itemstring = "mobs_mc:iron_horse_armor", weight = 1 },
|
|
||||||
{ itemstring = "mobs_mc:gold_horse_armor", weight = 1 },
|
|
||||||
{ itemstring = "mobs_mc:diamond_horse_armor", weight = 1 },
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
local items = mcl_loot.get_multi_loot(loottable, prand)
|
|
||||||
return items
|
|
||||||
end
|
|
||||||
|
|
||||||
local items = get_treasures(pr)
|
|
||||||
mcl_loot.fill_inventory(inv, "main", items, pr)
|
|
||||||
end
|
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- initialize furnace
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
function settlements.initialize_furnace(pos)
|
|
||||||
-- find chests within radius
|
|
||||||
local furnacepos = minetest.find_node_near(pos,
|
|
||||||
7, --radius
|
|
||||||
{"mcl_furnaces:furnace"})
|
|
||||||
-- initialize furnacepos (mts furnacepos don't have meta)
|
|
||||||
if furnacepos
|
|
||||||
then
|
|
||||||
local meta = minetest.get_meta(furnacepos)
|
|
||||||
if meta:get_string("infotext") ~= "furnace"
|
|
||||||
then
|
|
||||||
minetest.registered_nodes["mcl_furnaces:furnace"].on_construct(furnacepos)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- initialize anvil
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
function settlements.initialize_anvil(pos)
|
|
||||||
-- find chests within radius
|
|
||||||
local anvilpos = minetest.find_node_near(pos,
|
|
||||||
7, --radius
|
|
||||||
{"mcl_anvils:anvil"})
|
|
||||||
-- initialize anvilpos (mts anvilpos don't have meta)
|
|
||||||
if anvilpos
|
|
||||||
then
|
|
||||||
local meta = minetest.get_meta(anvilpos)
|
|
||||||
if meta:get_string("infotext") ~= "anvil"
|
|
||||||
then
|
|
||||||
minetest.registered_nodes["mcl_anvils:anvil"].on_construct(anvilpos)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- randomize table
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
function shuffle(tbl, pr)
|
|
||||||
local table = settlements.shallowCopy(tbl)
|
|
||||||
local size = #table
|
|
||||||
for i = size, 1, -1 do
|
|
||||||
local rand = pr:next(1, size)
|
|
||||||
table[i], table[rand] = table[rand], table[i]
|
|
||||||
end
|
|
||||||
return table
|
|
||||||
end
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
-- Set array to list
|
|
||||||
-- https://stackoverflow.com/questions/656199/search-for-an-item-in-a-lua-list
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
function settlements.Set (list)
|
|
||||||
local set = {}
|
|
||||||
for _, l in ipairs(list) do set[l] = true end
|
|
||||||
return set
|
|
||||||
end
|
|
Loading…
Reference in New Issue