Merge remote-tracking branch 'origin/villages' into testing

This commit is contained in:
kay27 2022-02-16 06:13:59 +04:00
commit 7de4b56cf6
25 changed files with 552 additions and 874 deletions

View File

@ -480,7 +480,6 @@ function mcl_mapgen.get_voxel_manip(vm_context)
return vm_context.vm
end
local CS_NODES = mcl_mapgen.CS_NODES
function mcl_mapgen.clamp_to_chunk(x, size)
if not size then
minetest.log("warning", "[mcl_mapgen] Couldn't clamp " .. tostring(x) .. " - missing size")
@ -504,6 +503,33 @@ function mcl_mapgen.clamp_to_chunk(x, size)
end
return x - overflow
end
function mcl_mapgen.get_chunk_beginning(x)
if tonumber(x) then
return x - ((x + central_chunk_min_pos) % CS_NODES)
end
if x.x then
return {
x = mcl_mapgen.get_chunk_beginning(x.x),
y = mcl_mapgen.get_chunk_beginning(x.y),
z = mcl_mapgen.get_chunk_beginning(x.z)
}
end
end
function mcl_mapgen.get_chunk_ending(x)
if tonumber(x) then
return mcl_mapgen.get_chunk_beginning(x) + LAST_NODE_IN_CHUNK
end
if x.x then
return {
x = mcl_mapgen.get_chunk_beginning(x.x) + LAST_NODE_IN_CHUNK,
y = mcl_mapgen.get_chunk_beginning(x.y) + LAST_NODE_IN_CHUNK,
z = mcl_mapgen.get_chunk_beginning(x.z) + 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

View File

@ -68,7 +68,7 @@ mobs:register_mob("mobs_mc:blaze", {
light_damage = 0,
view_range = 16,
attack_type = "projectile",
arrow = "mobs_mc:blaze_fireball",
arrow = "mobs_mc:blaze_fireball_entity",
shoot_interval = 3.5,
shoot_offset = 1.0,
passive = false,
@ -85,7 +85,7 @@ mobs:register_mob("mobs_mc:blaze", {
shoot_arrow = function(self, pos, dir)
-- 2-4 damage per arrow
local dmg = math.random(2,4)
mobs.shoot_projectile_handling("mobs_mc:blaze_fireball", pos, dir, self.object:get_yaw(), self.object, 7, dmg,nil,nil,nil,-0.4)
mobs.shoot_projectile_handling("mobs_mc:blaze_fireball_entity", pos, dir, self.object:get_yaw(), self.object, 7, dmg,nil,nil,nil,-0.4)
end,
do_custom = function(self)

View File

@ -47,7 +47,7 @@ minetest.register_craftitem("mcl_fire:fire_charge", {
_on_dispense = function(stack, pos, droppos, dropnode, dropdir)
-- Throw fire charge
local shootpos = vector.add(pos, vector.multiply(dropdir, 0.51))
local fireball = add_entity(shootpos, "mobs_mc:blaze_fireball")
local fireball = add_entity(shootpos, "mobs_mc:blaze_fireball_entity")
local ent = fireball:get_luaentity()
if ent then
ent._shot_from_dispenser = true

View File

@ -0,0 +1,22 @@
# MCL_Villages version 1.0
--------------------------
Originally a fork of Rochambeau's "Settlements", fully rewritten for MineClone 5.
## Using the mod
----------------
This mod adds villages on world generation.
## Credits
----------
* This mod is originally based on "ruins" by BlockMen
* Completely new schematics for MineClone2:
* MysticTempest - CC-BY-SA 4.0
* Basic conversion of Settlements mod for compatibility with MineClone2: MysticTempest
* Reimplemention: kay27
## License
----------
* License of source code: WTFPL

View File

@ -1,45 +0,0 @@
MCL_Villages:
============================
A fork of Rochambeau's "Settlements" mod converted for use in MineClone5.
--------------
Using the mod:
--------------
This mod adds settlements on world generation.
And, in Creative Mode; also comes with a debug tool for spawning in villages.
-------------
MCL2 Credits:
-------------
Code forked from: https://github.com/MysticTempest/settlements/tree/mcl_villages
Commit: e24b4be
================================================================================
Basic conversion of Settlements mod for compatibility with MineClone2, plus new schematics: MysticTempest
Seed-based Village Generation, multi-threading, bugfixes: kay27
=========================
version: 0.1 alpha
License of source code: WTFPL
-----------------------------
(c) Copyright Rochambeau (2018)
This program is free software. It comes without any warranty, to
the extent permitted by applicable law. You can redistribute it
and/or modify it under the terms of the Do What The Fuck You Want
To Public License, Version 2, as published by Sam Hocevar. See
http://sam.zoy.org/wtfpl/COPYING for more details.
Credits:
--------------
This mod is based on "ruins" by BlockMen
Completely new schematics for MineClone2:
MysticTempest - CC-BY-SA 4.0

View File

@ -1,280 +0,0 @@
--[[
-------------------------------------------------------------------------------
-- build schematic, replace material, rotation
-------------------------------------------------------------------------------
function settlements.build_schematic(vm, data, va, pos, building, replace_wall, name)
-- get building node material for better integration to surrounding
local platform_material = mcl_vars.get_node(pos)
if not platform_material or (platform_material.name == "air" or platform_material.name == "ignore") then
return
end
platform_material = platform_material.name
-- pick random material
local material = wallmaterial[math.random(1,#wallmaterial)]
-- schematic conversion to lua
local schem_lua = minetest.serialize_schematic(building,
"lua",
{lua_use_comments = false, lua_num_indent_spaces = 0}).." return schematic"
-- replace material
if replace_wall == "y" then
schem_lua = schem_lua:gsub("mcl_core:cobble", material)
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")
--
-- format schematic string
local schematic = loadstring(schem_lua)()
-- build foundation for the building an make room above
local width = schematic["size"]["x"]
local depth = schematic["size"]["z"]
local height = schematic["size"]["y"]
local possible_rotations = {"0", "90", "180", "270"}
local rotation = possible_rotations[ math.random( #possible_rotations ) ]
settlements.foundation(
pos,
width,
depth,
height,
rotation)
vm:set_data(data)
-- place schematic
minetest.place_schematic_on_vmanip(
vm,
pos,
schematic,
rotation,
nil,
true)
vm:write_to_map(true)
end]]
-------------------------------------------------------------------------------
-- initialize settlement_info
-------------------------------------------------------------------------------
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
--------------------------------------------------------------------------------
function settlements.create_site_plan(maxp, minp, pr)
local settlement_info = {}
local building_all_info
local possible_rotations = {"0", "90", "180", "270"}
-- find center of chunk
local center = {
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_mapgen.get_chunk_number(center)] = true
-- 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+50, z=ptz}
local chunk_number = mcl_mapgen.get_chunk_number(pos1)
local pos_surface, surface_material
if chunks[chunk_number] then
pos_surface, surface_material = settlements.find_surface(pos1)
else
chunks[chunk_number] = true
pos_surface, surface_material = settlements.find_surface(pos1, true)
end
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

View File

@ -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

View File

@ -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

View File

@ -1,26 +1,380 @@
settlements = {}
settlements.modpath = minetest.get_modpath(minetest.get_current_modname())
mcl_villages = {}
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
local noise_params = {
offset = 0,
scale = 2,
spread = {
x = mcl_mapgen.CS_NODES * chance_per_chunk,
y = mcl_mapgen.CS_NODES * chance_per_chunk,
z = mcl_mapgen.CS_NODES * chance_per_chunk,
},
seed = 842458,
octaves = 2,
persistence = 0.5,
}
local perlin_noise
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", max_num = 0.08 , rplc = basic_pseudobiome_villages },
{name = "blacksmith", mts = schem_path.."blacksmith.mts", max_num = 0.055, rplc = basic_pseudobiome_villages },
{name = "butcher", mts = schem_path.."butcher.mts", max_num = 0.03 , rplc = basic_pseudobiome_villages },
{name = "church", mts = schem_path.."church.mts", max_num = 0.04 , rplc = basic_pseudobiome_villages },
{name = "farm", mts = schem_path.."farm.mts", max_num = 0.1 , rplc = basic_pseudobiome_villages },
{name = "lamp", mts = schem_path.."lamp.mts", max_num = 0.1 , rplc = false },
{name = "library", mts = schem_path.."library.mts", max_num = 0.04 , rplc = basic_pseudobiome_villages },
{name = "medium_house", mts = schem_path.."medium_house.mts", max_num = 0.08 , rplc = basic_pseudobiome_villages },
{name = "small_house", mts = schem_path.."small_house.mts", max_num = 0.7 , rplc = basic_pseudobiome_villages },
{name = "tavern", mts = schem_path.."tavern.mts", max_num = 0.050, rplc = basic_pseudobiome_villages },
{name = "well", mts = schem_path.."well.mts", max_num = 0.045, rplc = basic_pseudobiome_villages },
}
local surface_mat = {
["mcl_core:dirt_with_dry_grass"] = { top = "mcl_core:dirt", bottom = "mcl_core:stone" },
["mcl_core:dirt_with_grass"] = { top = "mcl_core:dirt", bottom = "mcl_core:stone" },
["mcl_core:dirt_with_grass_snow"] = { top = "mcl_core:dirt", bottom = "mcl_core:stone" },
["mcl_core:podzol"] = { top = "mcl_core:podzol", bottom = "mcl_core:stone" },
["mcl_core:redsand"] = { top = "mcl_core:redsand", bottom = "mcl_core:redsandstone" },
["mcl_core:sand"] = { top = "mcl_core:sand", bottom = "mcl_core:sandstone" },
["mcl_core:snow"] = { top = "mcl_core:dirt", bottom = "mcl_core:stone" },
}
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 minetest_get_perlin = minetest.get_perlin
local math_pi = math.pi
local math_cos = math.cos
local math_sin = math.sin
local math_min = math.min
local math_max = math.max
local math_floor = math.floor
local math_ceil = math.ceil
local string_find = string.find
local minetest_swap_node = minetest.swap_node
local minetest_registered_nodes = minetest.registered_nodes
local minetest_bulk_set_node = minetest.bulk_set_node
local air_offset = chunk_offset_top - 1
local ground_offset = chunk_offset_bottom + 1
local surface_search_list = {}
for k, _ in pairs(surface_mat) do
table.insert(surface_search_list, k)
end
dofile(settlements.modpath.."/const.lua")
dofile(settlements.modpath.."/utils.lua")
dofile(settlements.modpath.."/foundation.lua")
dofile(settlements.modpath.."/buildings.lua")
dofile(settlements.modpath.."/paths.lua")
--dofile(settlements.modpath.."/convert_lua_mts.lua")
--
-- load settlements on server
--
settlements_in_world = settlements.load()
settlements.grundstellungen()
local function math_round(x)
return (x < 0) and math_ceil(x - 0.5) or math_floor(x + 0.5)
end
local function find_surface(pos, minp, maxp)
local x, z = pos.x, pos.z
local y_top = maxp.y
local y_max = y_top - air_offset
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, minetest_get_node(surface_pos).name
end
end
end
local function get_treasures(pr)
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, 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 distance2 < 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_buildings[schematic_index] = count_buildings[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(pos1, pos2, minp, maxp, pr, mat)
local pos1, pos2 = pos1, pos2
local x1, x2, z1, z2, y = pos1.x, pos2.x, pos1.z, pos2.z, pos1.y - 1
local pos_list_dirt = {}
local pos_list_stone = {}
for x0 = x1, x2 do
for z0 = z1, z2 do
local finish = false
local y1 = y - pr:next(2, 4)
for y0 = y, y1, -1 do
local p0 = {x = x0, y = y0, z = z0}
local node = minetest_get_node(p0)
local node_name = node.name
if node_name ~= "air" and not string_find(node_name, "water") and not string_find(node_name, "flower") then
finish = true
break
end
pos_list_dirt[#pos_list_dirt + 1] = p0
end
if not finish then
for y0 = y1 - 1, math_max(minp.y, y - pr:next(17, 27)), -1 do
local p0 = {x = x0, y = y0, z = z0}
local node = minetest_get_node(p0)
local node_name = node.name
if node_name ~= "air" and not string_find(node_name, "water") and not string_find(node_name, "flower") then
break
end
pos_list_stone[#pos_list_stone + 1] = p0
end
end
end
end
minetest_bulk_set_node(pos_list_dirt, {name = surface_mat[mat].top})
minetest_bulk_set_node(pos_list_stone, {name = surface_mat[mat].bottom})
end
local function terraform(plan, minp, maxp, pr)
local fheight, fwidth, fdepth, schematic_data, pos, rotation, swap_wd, build_material
for _, built_house in pairs(plan) do
schematic_data = built_house.building
pos = built_house.pos
rotation = built_house.rotation
build_material = built_house.surface_mat
swap_wd = rotation == "90" or rotation == "270"
fwidth = swap_wd and schematic_data.hdepth or schematic_data.hwidth
fdepth = swap_wd and schematic_data.hwidth or schematic_data.hdepth
fheight = schematic_data.hheight
local pos2 = {
x = pos.x + fwidth - 1,
y = math_min(pos.y + fheight + 4, maxp.y),
z = pos.z + fdepth - 1
}
ground(pos, {x = pos2.x, y = pos.y + 1, z = pos2.z}, minp, maxp, pr, build_material)
local node_list = {}
for xi = pos.x, pos2.x do
for zi = pos.z, pos2.z do
for yi = pos.y + 1, pos2.y do
node_list[#node_list + 1] = {x = xi, y = yi, z = zi}
end
end
end
minetest_bulk_set_node(node_list, {name = "air"})
end
end
local function paths(plan, minp, maxp)
local starting_point = find_surface({x = plan[1].pos.x + 2, z = plan[1].pos.z + 2}, minp, maxp)
if not starting_point then return end
starting_point.y = starting_point.y + 1
for i = 2, #plan do
local p = plan[i]
local end_point = p.pos
end_point.y = end_point.y + 1
local path = minetest.find_path(starting_point, end_point, mcl_mapgen.CS_NODES, 2, 2, "A*_noprefetch")
if path then
for _, pos in pairs(path) do
pos.y = pos.y - 1
local surface_mat = minetest.get_node(pos).name
if surface_mat == "mcl_core:sand" or surface_mat == "mcl_core:redsand" then
minetest.swap_node(pos, {name = "mcl_core:sandstonesmooth2"})
else
minetest.swap_node(pos, {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", "mcl_chests:chest", "mcl_villages:stonebrickcarved"})
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
minetest_swap_node(pos, {name = "mcl_chests:chest_small"})
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 replace_wall = built_house.building.rplc
local schem_lua = built_house.building.preloaded_schematic
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
--
local function spawn_villager(pos)
minetest.add_entity({x = pos.x, y = pos.y + 1, z = pos.z}, "mobs_mc:villager")
end
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,
tiles = {"mcl_core_stonebrick_carved.png"},
stack_max = 64,
@ -30,93 +384,142 @@ minetest.register_node("mcl_villages:stonebrickcarved", {
is_ground_content = false,
_mcl_blast_resistance = 6,
_mcl_hardness = 1.5,
on_construct = spawn_villager,
})
minetest.register_abm({
label = "Spawn villagers",
nodenames = {"mcl_villages:stonebrickcarved"},
interval = 60,
chance = 3,
action = function(pos, node)
-- check the space above
local p = table.copy(pos)
p.y = p.y + 1
if minetest_get_node(p).name ~= "air" then return end
p.y = p.y + 1
if minetest_get_node(p).name ~= "air" then return end
p.y = p.y - 1
local villagers_counter = 0
for _, obj in pairs(minetest.get_objects_inside_radius(p, 40)) do
local lua_entity = obj:get_luaentity()
if luaentity and luaentity.name == "mobs_mc:villager" then
villagers_counter = villagers_counter + 1
if villagers_counter > 7 then return end
end
end
spawn_villager(pos)
end
})
--[[ Enable for testing, but use MineClone2's own spawn code if/when merging.
--
-- register inhabitants
--
if minetest.get_modpath("mobs_mc") then
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
--
local function build_a_settlement(minp, maxp, blockseed)
minetest.log("action","[mcl_villages] Building village at mapchunk " .. minetest.pos_to_string(minp) .. "..." .. minetest.pos_to_string(maxp) .. ", blockseed = " .. tostring(blockseed))
local pr = PseudoRandom(blockseed)
-- fill settlement_info with buildings and their data
local settlement_info = settlements.create_site_plan(maxp, minp, pr)
if not settlement_info then return end
-- evaluate settlement_info and prepair terrain
settlements.terraform(settlement_info, pr)
-- evaluate settlement_info and build paths between buildings
settlements.paths(settlement_info)
-- evaluate settlement_info and place schematics
settlements.place_schematics(settlement_info, pr)
local function build_a_village(minp, maxp, pr, placer)
minetest.log("action","[mcl_villages] Building village at mapchunk " .. minetest.pos_to_string(minp) .. "..." .. minetest.pos_to_string(maxp))
local pr = pr or PseudoRandom(mcl_mapgen.get_block_seed3(minp))
local plan = create_site_plan(minp, maxp, pr)
if not plan then
if placer then
if placer:is_player() then
minetest.chat_send_player(placer:get_player_name(), S("Map chunk @1 to @2 is not suitable for placing villages.", minetest.pos_to_string(minp), minetest.pos_to_string(maxp)))
end
end
return
end
paths(plan, minp, maxp)
terraform(plan, minp, maxp, pr)
place_schematics(plan, pr)
villages[#villages + 1] = minp
storage:set_string("villages", minetest.serialize(villages))
end
-- Disable natural generation in singlenode.
local mg_name = minetest.get_mapgen_setting("mg_name")
if mg_name ~= "singlenode" then
mcl_mapgen.register_mapgen(function(minp, maxp, blockseed)
-- local str1 = (maxp.y >= 0 and blockseed % 77 == 17) and "YES" or "no"
-- minetest.log("action","[mcl_villages] " .. str1 .. ": minp=" .. minetest.pos_to_string(minp) .. ", maxp=" .. minetest.pos_to_string(maxp) .. ", blockseed=" .. tostring(blockseed))
-- don't build settlement underground
if maxp.y < 0 then return end
-- randomly try to build settlements
if blockseed % 77 ~= 17 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 height_difference, min, max
local pr1=PseudoRandom(blockseed)
for i=1,pr1:next(5,10) do
local x = pr1:next(0, 40) + minp.x + 19
local z = pr1:next(0, 40) + minp.z + 19
local y = minetest_get_spawn_level(x, z)
if not y then return end
if y < (min or y+1) then min = y end
if y > (max or y-1) then max = y end
local mg_name = minetest.get_mapgen_setting("mg_name")
local scan_last_node = mcl_mapgen.LAST_BLOCK * mcl_mapgen.BS - 1
local scan_offset = mcl_mapgen.BS
mcl_mapgen.register_mapgen(function(minp, maxp, chunkseed)
if minp.y < minp_min then return end
local pr = PseudoRandom(chunkseed * random_multiply + random_offset)
local random_number = pr:next(1, chance_per_chunk)
perlin_noise = perlin_noise or minetest_get_perlin(noise_params)
local noise = perlin_noise:get_3d(minp) * noise_multiplier
if (random_number + noise) < struct_threshold then return end
local min, max = 9999999, -9999999
for i = 1, pr:next(5,10) do
local surface_point = find_surface(
vector.add(
vector.new(
pr:next(scan_offset, scan_last_node),
0,
pr:next(scan_offset, scan_last_node)
),
minp
),
minp,
maxp
)
if not surface_point then return end
local y = surface_point.y
min = math_min(y, min)
max = math_max(y, max)
end
height_difference = max - min + 1
--------------------------------------------------------------------------
local height_difference = max - min
if height_difference > max_height_difference then return end
build_a_settlement(minp, maxp, blockseed)
build_a_village(minp, maxp, chunkkseed)
end, mcl_mapgen.order.VILLAGES)
end
-- manually place villages
if minetest.is_creative_enabled("") then
minetest.register_craftitem("mcl_villages:tool", {
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))
for k, v in pairs(schematic_table) do
local schem_lua = minetest.serialize_schematic(
v.mts,
"lua",
{
lua_use_comments = false,
lua_num_indent_spaces = 0,
}
):gsub("mcl_core:stonebrickcarved", "mcl_villages:stonebrickcarved") .. " return schematic"
v.preloaded_schematic = schem_lua
local loaded_schematic = loadstring(schem_lua)()
local size = loaded_schematic.size
v.hwidth = size.x
v.hheight = size.y
v.hdepth = size.z
v.hsize = math.ceil(math.sqrt((size.x/2)^2 + (size.y/2)^2) * 2 + 1)
mcl_structures.register_structure({
name = v.name,
place_function = function(pos, rotation, pr, placer)
local minp = mcl_mapgen.get_chunk_beginning(pos)
local maxp = mcl_mapgen.get_chunk_ending(pos)
local surface_pos, surface_material = find_surface(pos, minp, maxp)
local plan = {
[1] = {
pos = pos,
building = schematic_table[k],
rotation = rotation,
surface_mat = surface_material or "mcl_core:snow",
}
}
if surface_material then
terraform(plan, minp, maxp, pr)
end
place_schematics(plan, pr)
end
})
mcl_wip.register_experimental_item("mcl_villages:tool")
end
mcl_structures.register_structure({
name = "village",
place_function = function(pos, rotation, pr, placer)
local minp = mcl_mapgen.get_chunk_beginning(pos)
local maxp = mcl_mapgen.get_chunk_ending(pos)
build_a_village(minp, maxp, pr, placer)
end
})
function mcl_villages.get_villages()
return villages
end

View File

@ -0,0 +1,3 @@
# textdomain: mcl_villages
Chiseled Stone Village Bricks=Точёный каменный блок из деревни
Map chunk @1 to @2 is not suitable for placing villages.=Чанк с @1 по @2 непригоден для размещения деревень.

View File

@ -0,0 +1,3 @@
# textdomain: mcl_villages
Chiseled Stone Village Bricks=
Map chunk @1 to @2 is not suitable for placing villages.=

View File

@ -1,5 +1,5 @@
name = mcl_villages
author = Rochambeau
description = This mod adds settlements on world generation.
depends = mcl_util, mcl_mapgen_core, mcl_structures, mcl_core, mcl_loot
author = Rochambeau, MysticTempest, kay27
description = This mod adds villages on world generation.
depends = mcl_util, mcl_structures, mcl_core, mcl_loot, mcl_mapgen
optional_depends = mcl_farming, mobs_mc

View File

@ -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

View File

@ -1,217 +0,0 @@
local get_node = mcl_mapgen.get_far_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, wait)
local p6 = vector.new(pos)
local cnt = 0
local itter = 1 -- count up or down
local cnt_max = 200
-- check, in which direction to look for surface
local surface_node
if wait then
surface_node = get_node(p6, true, 10000000)
else
surface_node = get_node(p6)
end
if surface_node.name=="air" or surface_node.name=="ignore" then
itter = -1
end
-- go through nodes an find surface
while cnt < cnt_max do
-- Check Surface_node and Node above
--
if 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 and surface_node and
(string.find(surface_node_plus_1.name,"air") or
string.find(surface_node_plus_1.name,"snow") 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"))
then
settlements.debug("find_surface7: " ..surface_node.name.. " " .. surface_node_plus_1.name)
return p6, surface_node.name
else
settlements.debug("find_surface2: wrong surface+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
-------------------------------------------------------------------------------
-- 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