forked from MineClone5/MineClone5
Merge remote-tracking branch 'origin/villages' into testing
This commit is contained in:
commit
7de4b56cf6
|
@ -480,7 +480,6 @@ function mcl_mapgen.get_voxel_manip(vm_context)
|
||||||
return vm_context.vm
|
return vm_context.vm
|
||||||
end
|
end
|
||||||
|
|
||||||
local CS_NODES = mcl_mapgen.CS_NODES
|
|
||||||
function mcl_mapgen.clamp_to_chunk(x, size)
|
function mcl_mapgen.clamp_to_chunk(x, size)
|
||||||
if not size then
|
if not size then
|
||||||
minetest.log("warning", "[mcl_mapgen] Couldn't clamp " .. tostring(x) .. " - missing size")
|
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
|
end
|
||||||
return x - overflow
|
return x - overflow
|
||||||
end
|
end
|
||||||
|
|
||||||
function mcl_mapgen.get_chunk_beginning(x)
|
function mcl_mapgen.get_chunk_beginning(x)
|
||||||
return x - ((x + central_chunk_min_pos) % CS_NODES)
|
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
|
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
|
||||||
|
|
|
@ -68,7 +68,7 @@ mobs:register_mob("mobs_mc:blaze", {
|
||||||
light_damage = 0,
|
light_damage = 0,
|
||||||
view_range = 16,
|
view_range = 16,
|
||||||
attack_type = "projectile",
|
attack_type = "projectile",
|
||||||
arrow = "mobs_mc:blaze_fireball",
|
arrow = "mobs_mc:blaze_fireball_entity",
|
||||||
shoot_interval = 3.5,
|
shoot_interval = 3.5,
|
||||||
shoot_offset = 1.0,
|
shoot_offset = 1.0,
|
||||||
passive = false,
|
passive = false,
|
||||||
|
@ -85,7 +85,7 @@ mobs:register_mob("mobs_mc:blaze", {
|
||||||
shoot_arrow = function(self, pos, dir)
|
shoot_arrow = function(self, pos, dir)
|
||||||
-- 2-4 damage per arrow
|
-- 2-4 damage per arrow
|
||||||
local dmg = math.random(2,4)
|
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,
|
end,
|
||||||
|
|
||||||
do_custom = function(self)
|
do_custom = function(self)
|
||||||
|
|
|
@ -47,7 +47,7 @@ minetest.register_craftitem("mcl_fire:fire_charge", {
|
||||||
_on_dispense = function(stack, pos, droppos, dropnode, dropdir)
|
_on_dispense = function(stack, pos, droppos, dropnode, dropdir)
|
||||||
-- Throw fire charge
|
-- Throw fire charge
|
||||||
local shootpos = vector.add(pos, vector.multiply(dropdir, 0.51))
|
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()
|
local ent = fireball:get_luaentity()
|
||||||
if ent then
|
if ent then
|
||||||
ent._shot_from_dispenser = true
|
ent._shot_from_dispenser = true
|
||||||
|
|
|
@ -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
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
|
@ -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,380 @@
|
||||||
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
|
||||||
|
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
|
||||||
|
|
||||||
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
|
||||||
--dofile(settlements.modpath.."/convert_lua_mts.lua")
|
y_max = y_max - 1
|
||||||
--
|
local y_bottom = minp.y
|
||||||
-- load settlements on server
|
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)
|
||||||
settlements_in_world = settlements.load()
|
for _, surface_pos in pairs(nodes) do
|
||||||
settlements.grundstellungen()
|
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
|
-- 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", {
|
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,
|
||||||
|
@ -30,93 +384,142 @@ minetest.register_node("mcl_villages:stonebrickcarved", {
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
_mcl_blast_resistance = 6,
|
_mcl_blast_resistance = 6,
|
||||||
_mcl_hardness = 1.5,
|
_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
|
-- on map generation, try to build a settlement
|
||||||
--
|
--
|
||||||
local function build_a_settlement(minp, maxp, blockseed)
|
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) .. ", 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)
|
||||||
-- fill settlement_info with buildings and their data
|
if not plan then
|
||||||
local settlement_info = settlements.create_site_plan(maxp, minp, pr)
|
if placer then
|
||||||
if not settlement_info then return end
|
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)))
|
||||||
-- evaluate settlement_info and prepair terrain
|
end
|
||||||
settlements.terraform(settlement_info, pr)
|
end
|
||||||
|
return
|
||||||
-- evaluate settlement_info and build paths between buildings
|
end
|
||||||
settlements.paths(settlement_info)
|
paths(plan, minp, maxp)
|
||||||
|
terraform(plan, minp, maxp, pr)
|
||||||
-- evaluate settlement_info and place schematics
|
place_schematics(plan, pr)
|
||||||
settlements.place_schematics(settlement_info, pr)
|
villages[#villages + 1] = minp
|
||||||
|
storage:set_string("villages", minetest.serialize(villages))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Disable natural generation in singlenode.
|
-- Disable natural generation in singlenode.
|
||||||
local mg_name = minetest.get_mapgen_setting("mg_name")
|
|
||||||
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)
|
||||||
if maxp.y < 0 then return end
|
if minp.y < minp_min then return end
|
||||||
-- randomly try to build settlements
|
local pr = PseudoRandom(chunkseed * random_multiply + random_offset)
|
||||||
if blockseed % 77 ~= 17 then return end
|
local random_number = pr:next(1, chance_per_chunk)
|
||||||
|
perlin_noise = perlin_noise or minetest_get_perlin(noise_params)
|
||||||
-- don't build settlements on (too) uneven terrain
|
local noise = perlin_noise:get_3d(minp) * noise_multiplier
|
||||||
|
if (random_number + noise) < struct_threshold then return end
|
||||||
-- 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
|
||||||
--------------------------------------------------------------------------
|
for i = 1, pr:next(5,10) do
|
||||||
local height_difference, min, max
|
local surface_point = find_surface(
|
||||||
local pr1=PseudoRandom(blockseed)
|
vector.add(
|
||||||
for i=1,pr1:next(5,10) do
|
vector.new(
|
||||||
local x = pr1:next(0, 40) + minp.x + 19
|
pr:next(scan_offset, scan_last_node),
|
||||||
local z = pr1:next(0, 40) + minp.z + 19
|
0,
|
||||||
local y = minetest_get_spawn_level(x, z)
|
pr:next(scan_offset, scan_last_node)
|
||||||
if not y then return end
|
),
|
||||||
if y < (min or y+1) then min = y end
|
minp
|
||||||
if y > (max or y-1) then max = y end
|
),
|
||||||
|
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
|
end
|
||||||
height_difference = max - min + 1
|
local height_difference = max - min
|
||||||
--------------------------------------------------------------------------
|
|
||||||
|
|
||||||
if height_difference > max_height_difference then return end
|
if height_difference > max_height_difference then return end
|
||||||
|
build_a_village(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
|
for k, v in pairs(schematic_table) do
|
||||||
minetest.register_craftitem("mcl_villages:tool", {
|
local schem_lua = minetest.serialize_schematic(
|
||||||
description = "mcl_villages build tool",
|
v.mts,
|
||||||
inventory_image = "default_tool_woodshovel.png",
|
"lua",
|
||||||
-- build ssettlement
|
{
|
||||||
on_place = function(itemstack, placer, pointed_thing)
|
lua_use_comments = false,
|
||||||
if not pointed_thing.under then return end
|
lua_num_indent_spaces = 0,
|
||||||
local minp = vector.subtract( pointed_thing.under, half_map_chunk_size)
|
}
|
||||||
local maxp = vector.add( pointed_thing.under, half_map_chunk_size)
|
):gsub("mcl_core:stonebrickcarved", "mcl_villages:stonebrickcarved") .. " return schematic"
|
||||||
build_a_settlement(minp, maxp, math.random(0,32767))
|
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
|
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
|
end
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
# textdomain: mcl_villages
|
||||||
|
Chiseled Stone Village Bricks=Точёный каменный блок из деревни
|
||||||
|
Map chunk @1 to @2 is not suitable for placing villages.=Чанк с @1 по @2 непригоден для размещения деревень.
|
|
@ -0,0 +1,3 @@
|
||||||
|
# textdomain: mcl_villages
|
||||||
|
Chiseled Stone Village Bricks=
|
||||||
|
Map chunk @1 to @2 is not suitable for placing villages.=
|
|
@ -1,5 +1,5 @@
|
||||||
name = mcl_villages
|
name = mcl_villages
|
||||||
author = Rochambeau
|
author = Rochambeau, MysticTempest, kay27
|
||||||
description = This mod adds settlements on world generation.
|
description = This mod adds villages on world generation.
|
||||||
depends = mcl_util, mcl_mapgen_core, mcl_structures, mcl_core, mcl_loot
|
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
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -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
|
|
Loading…
Reference in New Issue