forked from VoxeLibre/VoxeLibre
Compare commits
28 Commits
master
...
mapgen-tes
Author | SHA1 | Date |
---|---|---|
kno10 | edaf158686 | |
kno10 | 162749decc | |
kno10 | 1435867673 | |
kno10 | 4496f7adfc | |
kno10 | 465b4162e7 | |
kno10 | e746ef46a9 | |
kno10 | d7ac288ba1 | |
kno10 | 27b6963d20 | |
kno10 | 0c4a120191 | |
kno10 | 1b5598f527 | |
kno10 | 7cde4976de | |
kno10 | 201ba616fe | |
kno10 | e8aeb34b93 | |
kno10 | 9411e60b8c | |
kno10 | b3efd6f681 | |
kno10 | a22dadf412 | |
kno10 | 73268386ec | |
kno10 | eb2b1f8704 | |
kno10 | 5b520d8713 | |
kno10 | 8e94eca3be | |
kno10 | 79d96e9ea0 | |
kno10 | d89eec9d98 | |
kno10 | 238c5a650e | |
kno10 | 2564fdcf5b | |
kno10 | f9a8033410 | |
kno10 | b42f883131 | |
kno10 | f73580bf3f | |
kno10 | e7fa2b8fb5 |
|
@ -1131,3 +1131,16 @@ if not vector.in_area then
|
|||
(pos.z >= min.z) and (pos.z <= max.z)
|
||||
end
|
||||
end
|
||||
|
||||
if not minetest.bulk_swap_node then -- maybe in 5.10 https://github.com/minetest/minetest/pull/15043
|
||||
minetest.bulk_swap_node = function(pos_list, node)
|
||||
-- for dense and large sets, we could also try a VManip, but often this enough for now
|
||||
local swap_node = minetest.swap_node
|
||||
for _, pos in ipairs(pos_list) do
|
||||
swap_node(pos, node)
|
||||
end
|
||||
end
|
||||
-- async emerge environment, untested:
|
||||
if minetest.set_node == minetest.swap_node then minetest.bulk_swap_node = minetest.bulk_set_node end
|
||||
end
|
||||
|
||||
|
|
|
@ -388,7 +388,7 @@ end
|
|||
|
||||
|
||||
|
||||
local function on_step_work (self, dtime)
|
||||
local function on_step_work(self, dtime, moveresult)
|
||||
local pos = self.object:get_pos()
|
||||
if not pos then return end
|
||||
|
||||
|
@ -402,7 +402,7 @@ local function on_step_work (self, dtime)
|
|||
-- Do we abandon out of here now?
|
||||
end
|
||||
|
||||
if self:falling(pos) then return end
|
||||
if self:falling(pos, moveresult) then return end
|
||||
if self:step_damage (dtime, pos) then return end
|
||||
|
||||
if self.state == "die" then return end
|
||||
|
@ -502,11 +502,11 @@ end
|
|||
|
||||
|
||||
-- main mob function
|
||||
function mob_class:on_step(dtime)
|
||||
function mob_class:on_step(dtime, moveresult)
|
||||
if not DEVELOPMENT then
|
||||
-- Removed as bundled Lua (5.1 doesn't support xpcall)
|
||||
--local status, retVal = xpcall(on_step_work, on_step_error_handler, self, dtime)
|
||||
local status, retVal = pcall(on_step_work, self, dtime)
|
||||
local status, retVal = pcall(on_step_work, self, dtime, moveresult)
|
||||
if status then
|
||||
return retVal
|
||||
else
|
||||
|
@ -521,7 +521,7 @@ function mob_class:on_step(dtime)
|
|||
log_error (dump(retVal), dump(pos), dump(self))
|
||||
end
|
||||
else
|
||||
return on_step_work (self, dtime)
|
||||
return on_step_work (self, dtime, moveresult)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -927,7 +927,8 @@ end
|
|||
|
||||
-- falling and fall damage
|
||||
-- returns true if mob died
|
||||
function mob_class:falling(pos)
|
||||
function mob_class:falling(pos, moveresult)
|
||||
if moveresult and moveresult.touching_ground then return false end
|
||||
|
||||
if self.fly and self.state ~= "die" then
|
||||
return
|
||||
|
|
|
@ -128,7 +128,7 @@ mcl_mobs.register_mob("mobs_mc:enderdragon", {
|
|||
on_die = function(self, pos, cmi_cause)
|
||||
if self._portal_pos then
|
||||
mcl_portals.spawn_gateway_portal()
|
||||
mcl_structures.place_structure(self._portal_pos,mcl_structures.registered_structures["end_exit_portal_open"],PseudoRandom(minetest.get_mapgen_setting("seed")),-1)
|
||||
mcl_structures.spawn_end_exit_portal(self._portal_pos)
|
||||
if self._initial then
|
||||
mcl_experience.throw_xp(pos, 11500) -- 500 + 11500 = 12000
|
||||
minetest.set_node(vector.add(self._portal_pos, vector.new(0, 5, 0)), {name = "mcl_end:dragon_egg"})
|
||||
|
|
|
@ -114,10 +114,9 @@ mcl_mobs.register_mob("mobs_mc:shulker", {
|
|||
for n=1, math.min(64, #nodes) do
|
||||
local r = pr:next(1, #nodes)
|
||||
local nodepos = nodes[r]
|
||||
local tg = vector.offset(nodepos,0,1,0)
|
||||
local tg = vector.offset(nodepos,0,0.5,0)
|
||||
if check_spot(tg) then
|
||||
telepos = tg
|
||||
node_ok = true
|
||||
end
|
||||
end
|
||||
if telepos then
|
||||
|
|
|
@ -2328,6 +2328,16 @@ mcl_mobs.register_mob("mobs_mc:villager", {
|
|||
end,
|
||||
})
|
||||
|
||||
-- HACK: for compatibility with the new mcl_villages code, but will not allow easy modding yet
|
||||
mobs_mc.jobsites = {}
|
||||
for _,p in pairs(professions) do
|
||||
if p.jobsite then
|
||||
table.insert(mobs_mc.jobsites, p.jobsite)
|
||||
end
|
||||
end
|
||||
function villager_employ(v, jobsite_pos)
|
||||
if jobsite_pos then employ(v, jobsite_pos) end
|
||||
end
|
||||
|
||||
--[[
|
||||
Villager spawning in mcl_villages
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,5 +1,4 @@
|
|||
-- Cactus and Sugar Cane
|
||||
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
minetest.register_node("mcl_core:cactus", {
|
||||
|
@ -42,9 +41,8 @@ minetest.register_node("mcl_core:cactus", {
|
|||
},
|
||||
-- Only allow to place cactus on sand or cactus
|
||||
on_place = mcl_util.generate_on_place_plant_function(function(pos, node)
|
||||
local node_below = minetest.get_node_or_nil({x=pos.x,y=pos.y-1,z=pos.z})
|
||||
if not node_below then return false end
|
||||
return (node_below.name == "mcl_core:cactus" or minetest.get_item_group(node_below.name, "sand") == 1)
|
||||
local node_below = minetest.get_node_or_nil(vector.offset(pos, 0, -1, 0))
|
||||
return node_below and (node_below.name == "mcl_core:cactus" or minetest.get_item_group(node_below.name, "sand") == 1)
|
||||
end),
|
||||
_mcl_blast_resistance = 0.4,
|
||||
_mcl_hardness = 0.4,
|
||||
|
@ -90,7 +88,7 @@ minetest.register_node("mcl_core:reeds", {
|
|||
node_placement_prediction = "",
|
||||
drop = "mcl_core:reeds", -- to prevent color inheritation
|
||||
on_place = mcl_util.generate_on_place_plant_function(function(place_pos, place_node)
|
||||
local soil_pos = {x=place_pos.x, y=place_pos.y-1, z=place_pos.z}
|
||||
local soil_pos = vector.new(place_pos.x, place_pos.y-1, place_pos.z)
|
||||
local soil_node = minetest.get_node_or_nil(soil_pos)
|
||||
if not soil_node then return false end
|
||||
local snn = soil_node.name -- soil node name
|
||||
|
@ -113,16 +111,12 @@ minetest.register_node("mcl_core:reeds", {
|
|||
-- Legal water position rules are the same as for decoration spawn_by rules.
|
||||
-- This differs from MC, which does not allow diagonal neighbors
|
||||
-- and neighbors 1 layer above.
|
||||
local np1 = {x=soil_pos.x-1, y=soil_pos.y, z=soil_pos.z-1}
|
||||
local np2 = {x=soil_pos.x+1, y=soil_pos.y+1, z=soil_pos.z+1}
|
||||
if #minetest.find_nodes_in_area(np1, np2, {"group:water", "group:frosted_ice"}) > 0 then
|
||||
if #minetest.find_nodes_in_area(vector.offset(soil_pos, -1, 0, -1), vector.offset(soil_pos, 1, 1, 1), {"group:water", "group:frosted_ice"}) > 0 then
|
||||
-- Water found! Sugar canes are happy! :-)
|
||||
return true
|
||||
end
|
||||
|
||||
-- No water found! Sugar canes are not amuzed and refuses to be placed. :-(
|
||||
return false
|
||||
|
||||
end),
|
||||
on_construct = function(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
|
|
|
@ -9,11 +9,11 @@ local wood_slab_groups = {handy = 1, axey = 1, material_wood = 1, wood_slab = 1}
|
|||
local wood_stair_groups = {handy = 1, axey = 1, material_wood = 1, wood_stairs = 1}
|
||||
|
||||
local function generate_warped_tree(pos)
|
||||
minetest.place_schematic(pos,modpath.."/schematics/warped_fungus_1.mts","random",nil,false,"place_center_x,place_center_z")
|
||||
minetest.place_schematic(pos,modpath.."/schematics/warped_fungus_"..math.random(1,3)..".mts","random",nil,false,"place_center_x,place_center_z")
|
||||
end
|
||||
|
||||
function generate_crimson_tree(pos)
|
||||
minetest.place_schematic(pos,modpath.."/schematics/crimson_fungus_1.mts","random",nil,false,"place_center_x,place_center_z")
|
||||
minetest.place_schematic(pos,modpath.."/schematics/crimson_fungus_"..math.random(1,3)..".mts","random",nil,false,"place_center_x,place_center_z")
|
||||
end
|
||||
|
||||
function grow_vines(pos, moreontop ,vine, dir)
|
||||
|
|
|
@ -80,7 +80,7 @@ local function spawn_crystal(pos)
|
|||
crystal_explode(crystal)
|
||||
end
|
||||
local portal_pos = vector.add(portal_center, vector.new(0, -1, 0))
|
||||
mcl_structures.place_structure(portal_pos,mcl_structures.registered_structures["end_exit_portal"],PseudoRandom(minetest.get_mapgen_setting("seed")),-1)
|
||||
vl_structures.place_structure(portal_pos,vl_structures.registered_structures["end_exit_portal"],PseudoRandom(minetest.get_mapgen_setting("seed")),-1)
|
||||
end
|
||||
|
||||
minetest.register_entity("mcl_end:crystal", {
|
||||
|
|
|
@ -89,7 +89,7 @@ minetest.register_craftitem("mcl_end:ender_eye", {
|
|||
local player_name = user:get_player_name()
|
||||
local origin = user:get_pos()
|
||||
origin.y = origin.y + 1.5
|
||||
local strongholds = mcl_structures.registered_structures["end_shrine"].static_pos
|
||||
local strongholds = vl_structures.registered_structures["end_shrine"].static_pos
|
||||
local dim = mcl_worlds.pos_to_dimension(origin)
|
||||
local is_creative = minetest.is_creative_enabled(player_name)
|
||||
|
||||
|
|
|
@ -4,34 +4,38 @@ local storage = mcl_portals.storage
|
|||
local vector = vector
|
||||
|
||||
local gateway_positions = {
|
||||
{x = 96, y = -26925, z = 0},
|
||||
{x = 91, y = -26925, z = 29},
|
||||
{x = 77, y = -26925, z = 56},
|
||||
{x = 56, y = -26925, z = 77},
|
||||
{x = 29, y = -26925, z = 91},
|
||||
{x = 0, y = -26925, z = 96},
|
||||
{x = -29, y = -26925, z = 91},
|
||||
{x = -56, y = -26925, z = 77},
|
||||
{x = -77, y = -26925, z = 56},
|
||||
{x = -91, y = -26925, z = 29},
|
||||
{x = -96, y = -26925, z = 0},
|
||||
{x = -91, y = -26925, z = -29},
|
||||
{x = -77, y = -26925, z = -56},
|
||||
{x = -56, y = -26925, z = -77},
|
||||
{x = -29, y = -26925, z = -91},
|
||||
{x = 0, y = -26925, z = -96},
|
||||
{x = 29, y = -26925, z = -91},
|
||||
{x = 56, y = -26925, z = -77},
|
||||
{x = 77, y = -26925, z = -56},
|
||||
{x = 91, y = -26925, z = -29},
|
||||
vector.new(96, -26925, 0),
|
||||
vector.new(91, -26925, 29),
|
||||
vector.new(77, -26925, 56),
|
||||
vector.new(56, -26925, 77),
|
||||
vector.new(29, -26925, 91),
|
||||
vector.new(0, -26925, 96),
|
||||
vector.new(-29, -26925, 91),
|
||||
vector.new(-56, -26925, 77),
|
||||
vector.new(-77, -26925, 56),
|
||||
vector.new(-91, -26925, 29),
|
||||
vector.new(-96, -26925, 0),
|
||||
vector.new(-91, -26925, -29),
|
||||
vector.new(-77, -26925, -56),
|
||||
vector.new(-56, -26925, -77),
|
||||
vector.new(-29, -26925, -91),
|
||||
vector.new(0, -26925, -96),
|
||||
vector.new(29, -26925, -91),
|
||||
vector.new(56, -26925, -77),
|
||||
vector.new(77, -26925, -56),
|
||||
vector.new(91, -26925, -29),
|
||||
}
|
||||
|
||||
local path_gateway_portal = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_end_gateway_portal.mts"
|
||||
|
||||
local function spawn_gateway_portal(pos, dest_str)
|
||||
return mcl_structures.place_schematic(vector.add(pos, vector.new(-1, -2, -1)), path_gateway_portal, "0", nil, true, nil, dest_str and function()
|
||||
return vl_structures.place_schematic(vector.offset(pos, -1, -2, -1), 0, path_gateway_portal, "0", {
|
||||
force_placement = true,
|
||||
prepare = false,
|
||||
after_place = dest_str and function()
|
||||
minetest.get_meta(pos):set_string("mcl_portals:gateway_destination", dest_str)
|
||||
end)
|
||||
end
|
||||
}, nil)
|
||||
end
|
||||
|
||||
function mcl_portals.spawn_gateway_portal()
|
||||
|
|
|
@ -183,12 +183,12 @@ local dimension_to_teleport = { nether = "overworld", overworld = "nether" }
|
|||
|
||||
local limits = {
|
||||
nether = {
|
||||
pmin = {x=LIM_MIN, y = N_Y_MIN, z = LIM_MIN},
|
||||
pmax = {x=LIM_MAX, y = N_Y_MAX, z = LIM_MAX},
|
||||
pmin = vector.new(LIM_MIN, N_Y_MIN, LIM_MIN),
|
||||
pmax = vector.new(LIM_MAX, N_Y_MAX, LIM_MAX),
|
||||
},
|
||||
overworld = {
|
||||
pmin = {x=LIM_MIN, y = O_Y_MIN, z = LIM_MIN},
|
||||
pmax = {x=LIM_MAX, y = O_Y_MAX, z = LIM_MAX},
|
||||
pmin = vector.new(LIM_MIN, O_Y_MIN, LIM_MIN),
|
||||
pmax = vector.new(LIM_MAX, O_Y_MAX, LIM_MAX),
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -206,12 +206,10 @@ end
|
|||
-- for old portals, so that players don't get surprises. New portals, or portals that lost
|
||||
-- node storage due to destruction should use the lookup table.
|
||||
local function get_portal_pos(pos)
|
||||
local p1 = vector.offset(pos,-5,-1,-5)
|
||||
local p2 = vector.offset(pos,5,5,5)
|
||||
local nn = find_nodes_in_area(p1,p2,{"mcl_portals:portal"})
|
||||
local nn = find_nodes_in_area(vector.offset(pos,-5,-1,-5), vector.offset(pos,5,5,5), {"mcl_portals:portal"})
|
||||
for _,p in pairs(nn) do
|
||||
local m = minetest.get_meta(p):get_string("target_portal")
|
||||
if m and m ~= "" and mcl_vars.get_node(p).name == "mcl_portals:portal" then
|
||||
if m and m ~= "" and minetest.get_node(p).name == "mcl_portals:portal" then
|
||||
return minetest.get_position_from_hash(m)
|
||||
end
|
||||
end
|
||||
|
@ -229,15 +227,13 @@ end
|
|||
local function add_exit(p)
|
||||
local retval = {key=false, new=false}
|
||||
|
||||
if not p or not p.y or not p.z or not p.x then
|
||||
return retval
|
||||
end
|
||||
if not p or not p.y or not p.z or not p.x then return retval end
|
||||
local x, y, z = floor(p.x), floor(p.y), floor(p.z)
|
||||
local p = {x = x, y = y, z = z}
|
||||
local p = vector.new(x, y, z)
|
||||
|
||||
if get_node({x=x,y=y-1,z=z}).name ~= OBSIDIAN
|
||||
if get_node(vector.new(x, y-1, z)).name ~= OBSIDIAN
|
||||
or get_node(p).name ~= PORTAL
|
||||
or get_node({x=x,y=y+1,z=z}).name ~= PORTAL
|
||||
or get_node(vector.new(x, y+1, z)).name ~= PORTAL
|
||||
then
|
||||
return retval
|
||||
end
|
||||
|
@ -301,7 +297,7 @@ local function remove_exit(p)
|
|||
end
|
||||
|
||||
local x, y, z = floor(p.x), floor(p.y), floor(p.z)
|
||||
local p = {x = x, y = y, z = z}
|
||||
local p = vector.new(x, y, z)
|
||||
|
||||
local k = get_exit_key(p)
|
||||
if not exits[k] then
|
||||
|
@ -529,14 +525,14 @@ local function destroy_nether_portal(pos, node)
|
|||
while i <= #nodes do
|
||||
pos = nodes[i]
|
||||
if orientation == 0 then
|
||||
check_remove({x = pos.x - 1, y = pos.y, z = pos.z})
|
||||
check_remove({x = pos.x + 1, y = pos.y, z = pos.z})
|
||||
check_remove(vector.offset(pos, -1, 0, 0))
|
||||
check_remove(vector.offset(pos, 1, 0, 0))
|
||||
else
|
||||
check_remove({x = pos.x, y = pos.y, z = pos.z - 1})
|
||||
check_remove({x = pos.x, y = pos.y, z = pos.z + 1})
|
||||
check_remove(vector.offset(pos, 0, 0, -1))
|
||||
check_remove(vector.offset(pos, 0, 0, 1))
|
||||
end
|
||||
check_remove({x = pos.x, y = pos.y - 1, z = pos.z})
|
||||
check_remove({x = pos.x, y = pos.y + 1, z = pos.z})
|
||||
check_remove(vector.offset(pos, 0, -1, 0))
|
||||
check_remove(vector.offset(pos, 0, 1, 0))
|
||||
remove_exits({pos})
|
||||
i = i + 1
|
||||
end
|
||||
|
@ -624,7 +620,7 @@ local function build_and_light_frame(x1, y1, z1, x2, y2, z2, name)
|
|||
else
|
||||
set_node(pos, {name = PORTAL, param2 = orientation})
|
||||
add_exits({
|
||||
{x=pos.x, y=pos.y-1, z=pos.z}
|
||||
vector.new(pos.x, pos.y-1, pos.z)
|
||||
})
|
||||
end
|
||||
end
|
||||
|
@ -701,8 +697,8 @@ function build_nether_portal(cube_pos1, width, height, orientation, name, clear_
|
|||
-- Build obsidian platform:
|
||||
for x = pos.x - orientation, pos.x + orientation + (width_inner - 1) * (1 - orientation), 1 + orientation do
|
||||
for z = pos.z - 1 + orientation, pos.z + 1 - orientation + (width_inner - 1) * orientation, 2 - orientation do
|
||||
local pp = {x = x, y = pos.y - 1, z = z}
|
||||
local pp_1 = {x = x, y = pos.y - 2, z = z}
|
||||
local pp = vector.new(x, pos.y - 1, z)
|
||||
local pp_1 = vector.new(x, pos.y - 2, z)
|
||||
local nn = get_node(pp).name
|
||||
local nn_1 = get_node(pp_1).name
|
||||
if ((nn=="air" and nn_1 == "air") or not registered_nodes[nn].is_ground_content) and not is_protected(pp, name) then
|
||||
|
@ -823,7 +819,7 @@ local function finalize_teleport(obj, exit)
|
|||
local _, dim = mcl_worlds.y_to_layer(exit.y)
|
||||
|
||||
-- If player stands, player is at ca. something+0.5 which might cause precision problems, so we used ceil for objpos.y
|
||||
objpos = {x = floor(objpos.x+0.5), y = ceil(objpos.y), z = floor(objpos.z+0.5)}
|
||||
objpos = vector.new(floor(objpos.x+0.5), ceil(objpos.y), floor(objpos.z+0.5))
|
||||
if get_node(objpos).name ~= PORTAL then
|
||||
log("action", "Entity no longer standing in portal")
|
||||
return
|
||||
|
@ -1085,19 +1081,19 @@ local function search_for_build_location(blockpos, action, calls_remaining, para
|
|||
if nc2 >= (W_MIN*(H_MIN-1)*W_MIN) - ACCEPTABLE_PORTAL_REPLACES then
|
||||
-- We have sorted the candidates by distance, this is the best location.
|
||||
distance = distance0
|
||||
pos0 = {x=node.x, y=node.y, z=node.z}
|
||||
pos0 = vector.new(node.x, node.y, node.z)
|
||||
log("verbose", "Found acceptable location at "..pos_to_string(pos0)..", distance "..distance0..", air nodes "..nc2)
|
||||
break
|
||||
elseif not most_airy_pos or nc2>most_airy_count then
|
||||
-- Remember the cube with the most amount of air as a fallback.
|
||||
most_airy_count = nc2
|
||||
most_airy_distance = distance0
|
||||
most_airy_pos = {x=node.x, y=node.y, z=node.z}
|
||||
most_airy_pos = vector.new(node.x, node.y, node.z)
|
||||
log("verbose", "Found fallback location at "..pos_to_string(most_airy_pos)..", distance "..distance0..", air nodes "..nc2)
|
||||
elseif most_airy_pos and nc2==most_airy_count and distance0<most_airy_distance then
|
||||
-- Use distance as a tiebreaker.
|
||||
most_airy_distance = distance0
|
||||
most_airy_pos = {x=node.x, y=node.y, z=node.z}
|
||||
most_airy_pos = vector.new(node.x, node.y, node.z)
|
||||
log("verbose", "Found fallback location at "..pos_to_string(most_airy_pos)..", distance "..distance0..", air nodes "..nc2)
|
||||
end
|
||||
|
||||
|
@ -1128,7 +1124,7 @@ local function search_for_build_location(blockpos, action, calls_remaining, para
|
|||
log("verbose", "No space found, emerging one chunk below")
|
||||
end
|
||||
|
||||
local new_target = {x=target.x, y=target.y + direction * mcl_vars.chunk_size_in_nodes, z=target.z}
|
||||
local new_target = vector.new(target.x, target.y + direction * mcl_vars.chunk_size_in_nodes, target.z)
|
||||
pos1, pos2 = find_build_limits(new_target, param.target_dim)
|
||||
local diff = add(pos2, mul(pos1, -1))
|
||||
|
||||
|
@ -1202,7 +1198,7 @@ local function create_portal(origin, target, target_dim, name, obj)
|
|||
origin = origin,
|
||||
target = target,
|
||||
target_dim = target_dim,
|
||||
ideal_target = vector.new(target.x, target.y, target.z), -- copy
|
||||
ideal_target = vector.copy(target),
|
||||
pos1 = pos1,
|
||||
pos2 = pos2,
|
||||
name=name,
|
||||
|
@ -1223,13 +1219,12 @@ local function available_for_nether_portal(p)
|
|||
end
|
||||
|
||||
local function check_and_light_shape(pos, orientation)
|
||||
local stack = {{x = pos.x, y = pos.y, z = pos.z}}
|
||||
local stack = {vector.copy(pos)}
|
||||
local node_list = {}
|
||||
local index_list = {}
|
||||
local node_counter = 0
|
||||
-- Search most low node from the left (pos1) and most right node from the top (pos2)
|
||||
local pos1 = {x = pos.x, y = pos.y, z = pos.z}
|
||||
local pos2 = {x = pos.x, y = pos.y, z = pos.z}
|
||||
local pos1, pos2 = vector.copy(pos), vector.copy(pos)
|
||||
|
||||
local kx, ky, kz = pos.x - 1999, pos.y - 1999, pos.z - 1999
|
||||
while #stack > 0 do
|
||||
|
@ -1247,22 +1242,22 @@ local function check_and_light_shape(pos, orientation)
|
|||
return false
|
||||
end
|
||||
node_counter = node_counter + 1
|
||||
node_list[node_counter] = {x = x, y = y, z = z}
|
||||
node_list[node_counter] = vector.new(x, y, z)
|
||||
index_list[k] = true
|
||||
stack[i].y = y - 1
|
||||
stack[i + 1] = {x = x, y = y + 1, z = z}
|
||||
stack[i + 1] = vector.new(x, y + 1, z)
|
||||
if orientation == 0 then
|
||||
stack[i + 2] = {x = x - 1, y = y, z = z}
|
||||
stack[i + 3] = {x = x + 1, y = y, z = z}
|
||||
stack[i + 2] = vector.new(x - 1, y, z)
|
||||
stack[i + 3] = vector.new(x + 1, y, z)
|
||||
else
|
||||
stack[i + 2] = {x = x, y = y, z = z - 1}
|
||||
stack[i + 3] = {x = x, y = y, z = z + 1}
|
||||
stack[i + 2] = vector.new(x, y, z - 1)
|
||||
stack[i + 3] = vector.new(x, y, z + 1)
|
||||
end
|
||||
if (y < pos1.y) or (y == pos1.y and (x < pos1.x or z < pos1.z)) then
|
||||
pos1 = {x = x, y = y, z = z}
|
||||
pos1 = vector.new(x, y, z)
|
||||
end
|
||||
if (x > pos2.x or z > pos2.z) or (x == pos2.x and z == pos2.z and y > pos2.y) then
|
||||
pos2 = {x = x, y = y, z = z}
|
||||
pos2 = vector.new(x, y, z)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -1344,7 +1339,7 @@ local function check_portal_then_teleport(obj, origin, exit)
|
|||
remove_exits({exit})
|
||||
-- Also remove from structure storage, otherwise ABM will try the same bad exit again.
|
||||
local objpos = obj:get_pos()
|
||||
delete_portal_pos({x = floor(objpos.x+0.5), y = ceil(objpos.y), z = floor(objpos.z+0.5)})
|
||||
delete_portal_pos(vector.new(floor(objpos.x+0.5), ceil(objpos.y), floor(objpos.z+0.5)))
|
||||
|
||||
origin_flush(origin, nil)
|
||||
return
|
||||
|
@ -1367,7 +1362,7 @@ local function teleport_no_delay(obj, portal_pos)
|
|||
local target_dim = dimension_to_teleport[current_dim]
|
||||
|
||||
-- If player stands, player is at ca. something+0.5 which might cause precision problems, so we used ceil for objpos.y
|
||||
origin = {x = floor(objpos.x+0.5), y = ceil(objpos.y), z = floor(objpos.z+0.5)}
|
||||
origin = vector.new(floor(objpos.x+0.5), ceil(objpos.y), floor(objpos.z+0.5))
|
||||
if get_node(origin).name ~= PORTAL then return end
|
||||
|
||||
local target = get_target(origin)
|
||||
|
@ -1450,8 +1445,8 @@ local function animation(player, playername)
|
|||
end
|
||||
minetest.add_particlespawner({
|
||||
amount = 1,
|
||||
minpos = {x = pos.x - 0.1, y = pos.y + 1.4, z = pos.z - 0.1},
|
||||
maxpos = {x = pos.x + 0.1, y = pos.y + 1.6, z = pos.z + 0.1},
|
||||
minpos = vector.offset(pos, -0.1, 1.4, -0.1),
|
||||
maxpos = vector.offset(pos, 0.1, 1.6, 0.1),
|
||||
minvel = 0,
|
||||
maxvel = 0,
|
||||
minacc = 0,
|
||||
|
@ -1496,11 +1491,11 @@ minetest.register_abm({
|
|||
local time = random() * 1.9 + 0.5
|
||||
local velocity, acceleration
|
||||
if o == 1 then
|
||||
velocity = {x = random() * 0.7 + 0.3, y = random() - 0.5, z = random() - 0.5}
|
||||
acceleration = {x = random() * 1.1 + 0.3, y = random() - 0.5, z = random() - 0.5}
|
||||
velocity = vector.new(random() * 0.7 + 0.3, random() - 0.5, random() - 0.5)
|
||||
acceleration = vector.new(random() * 1.1 + 0.3, random() - 0.5, random() - 0.5)
|
||||
else
|
||||
velocity = {x = random() - 0.5, y = random() - 0.5, z = random() * 0.7 + 0.3}
|
||||
acceleration = {x = random() - 0.5, y = random() - 0.5, z = random() * 1.1 + 0.3}
|
||||
velocity = vector.new(random() - 0.5, random() - 0.5, random() * 0.7 + 0.3)
|
||||
acceleration = vector.new(random() - 0.5, random() - 0.5, random() * 1.1 + 0.3)
|
||||
end
|
||||
local distance = add(mul(velocity, time), mul(acceleration, time * time / 2))
|
||||
if d == 1 then
|
||||
|
@ -1566,12 +1561,12 @@ minetest.override_item(OBSIDIAN, {
|
|||
end
|
||||
|
||||
-- check each of 6 sides of it and destroy every portal
|
||||
check_remove({x = pos.x - 1, y = pos.y, z = pos.z})
|
||||
check_remove({x = pos.x + 1, y = pos.y, z = pos.z})
|
||||
check_remove({x = pos.x, y = pos.y, z = pos.z - 1})
|
||||
check_remove({x = pos.x, y = pos.y, z = pos.z + 1})
|
||||
check_remove({x = pos.x, y = pos.y - 1, z = pos.z})
|
||||
check_remove({x = pos.x, y = pos.y + 1, z = pos.z})
|
||||
check_remove(vector.offset(pos, -1, 0, 0))
|
||||
check_remove(vector.offset(pos, 1, 0, 0))
|
||||
check_remove(vector.offset(pos, 0, 0, -1))
|
||||
check_remove(vector.offset(pos, 0, 0, 1))
|
||||
check_remove(vector.offset(pos, 0, -1, 0))
|
||||
check_remove(vector.offset(pos, 0, 1, 0))
|
||||
end,
|
||||
|
||||
_on_ignite = function(user, pointed_thing)
|
||||
|
@ -1579,16 +1574,16 @@ minetest.override_item(OBSIDIAN, {
|
|||
-- Check empty spaces around obsidian and light all frames found.
|
||||
-- Permit igniting of portals that are partly protected to maintain integrity.
|
||||
local portals_placed =
|
||||
mcl_portals.light_nether_portal({x = x - 1, y = y, z = z}) or mcl_portals.light_nether_portal({x = x + 1, y = y, z = z}) or
|
||||
mcl_portals.light_nether_portal({x = x, y = y - 1, z = z}) or mcl_portals.light_nether_portal({x = x, y = y + 1, z = z}) or
|
||||
mcl_portals.light_nether_portal({x = x, y = y, z = z - 1}) or mcl_portals.light_nether_portal({x = x, y = y, z = z + 1})
|
||||
mcl_portals.light_nether_portal(vector.new(x - 1, y, z)) or mcl_portals.light_nether_portal(vector.new(x + 1, y, z)) or
|
||||
mcl_portals.light_nether_portal(vector.new(x, y - 1, z)) or mcl_portals.light_nether_portal(vector.new(x, y + 1, z)) or
|
||||
mcl_portals.light_nether_portal(vector.new(x, y, z - 1)) or mcl_portals.light_nether_portal(vector.new(x, y, z + 1))
|
||||
if portals_placed then
|
||||
log("verbose", "Nether portal activated at "..pos_to_string({x=x,y=y,z=z})..".")
|
||||
log("verbose", "Nether portal activated at "..pos_to_string(vector.new(x, y, z))..".")
|
||||
if minetest.get_modpath("doc") then
|
||||
doc.mark_entry_as_revealed(user:get_player_name(), "nodes", PORTAL)
|
||||
|
||||
-- Achievement for finishing a Nether portal TO the Nether
|
||||
local dim = mcl_worlds.pos_to_dimension({x=x, y=y, z=z})
|
||||
local dim = mcl_worlds.pos_to_dimension(vector.new(x, y, z))
|
||||
if minetest.get_modpath("awards") and dim ~= "nether" and user:is_player() then
|
||||
awards.unlock(user:get_player_name(), "mcl:buildNetherPortal")
|
||||
end
|
||||
|
@ -1600,13 +1595,13 @@ minetest.override_item(OBSIDIAN, {
|
|||
end,
|
||||
})
|
||||
|
||||
mcl_structures.register_structure("nether_portal",{
|
||||
vl_structures.register_structure("nether_portal",{
|
||||
nospawn = true,
|
||||
filenames = {
|
||||
modpath.."/schematics/mcl_portals_nether_portal.mts"
|
||||
}
|
||||
})
|
||||
mcl_structures.register_structure("nether_portal_open",{
|
||||
vl_structures.register_structure("nether_portal_open",{
|
||||
nospawn = true,
|
||||
filenames = {
|
||||
modpath.."/schematics/mcl_portals_nether_portal_open.mts"
|
||||
|
|
|
@ -20,7 +20,7 @@ local function connectable(itemstring)
|
|||
return (minetest.get_item_group(itemstring, "wall") == 1) or (minetest.get_item_group(itemstring, "solid") == 1)
|
||||
end
|
||||
|
||||
local function update_wall(pos)
|
||||
function mcl_walls.update_wall(pos)
|
||||
local thisnode = minetest.get_node(pos)
|
||||
|
||||
if minetest.get_item_group(thisnode.name, "wall") == 0 then
|
||||
|
@ -67,11 +67,12 @@ local function update_wall(pos)
|
|||
|
||||
minetest.add_node(pos, {name = basename..sum})
|
||||
end
|
||||
local update_wall = mcl_walls.update_wall
|
||||
|
||||
local function update_wall_global(pos)
|
||||
for i = 1,5 do
|
||||
local dir = directions[i]
|
||||
update_wall({x = pos.x + dir.x, y = pos.y + dir.y, z = pos.z + dir.z})
|
||||
update_wall(vector.offset(pos, dir.x, dir.y, dir.z))
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -269,7 +270,7 @@ function mcl_walls.register_wall(nodename, description, source, tiles, inventory
|
|||
fixed = {-4/16, -0.5, -4/16, 4/16, 1, 4/16}
|
||||
},
|
||||
collisionbox = {-0.2, 0, -0.2, 0.2, 1.4, 0.2},
|
||||
on_construct = update_wall,
|
||||
on_construct = mcl_walls.update_wall,
|
||||
sounds = sounds,
|
||||
_mcl_blast_resistance = blast_resistance,
|
||||
_mcl_hardness = hardness,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,6 +2,7 @@
|
|||
|
||||
mcl_dungeons = {}
|
||||
|
||||
local logging = minetest.settings:get_bool("mcl_logging_dungeons", false)
|
||||
local mg_name = minetest.get_mapgen_setting("mg_name")
|
||||
-- Are dungeons disabled?
|
||||
if mcl_vars.mg_dungeons == false or mg_name == "singlenode" then return end
|
||||
|
@ -234,7 +235,9 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
|
|||
-- Check conditions. If okay, start generating
|
||||
if check and (openings_counter < 1 or openings_counter > 5) then return end
|
||||
|
||||
if logging then
|
||||
minetest.log("action","[mcl_dungeons] Placing new dungeon at "..minetest.pos_to_string(vector_new(x, y, z)))
|
||||
end
|
||||
-- Okay! Spawning starts!
|
||||
|
||||
-- Remember spawner chest positions to set metadata later
|
||||
|
@ -253,7 +256,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
|
|||
-- If it failed again, tough luck! We stick with only 1 chest spawned.
|
||||
local lastRandom
|
||||
local secondChance = true -- second chance is still available
|
||||
for i=1, totalChests do
|
||||
for _ = 1, totalChests do
|
||||
local r = pr:next(1, totalChestSlots)
|
||||
if r == lastRandom and secondChance then
|
||||
-- Oops! Same slot selected. Try again.
|
||||
|
@ -368,8 +371,11 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param)
|
|||
end
|
||||
|
||||
set_node(pos, {name="mcl_chests:chest", param2=facedir})
|
||||
vl_structures.construct_nodes(pos, pos, {"mcl_chests:chest"})
|
||||
local meta = get_meta(pos)
|
||||
if logging then
|
||||
minetest.log("action", "[mcl_dungeons] Filling chest " .. tostring(c) .. " at " .. minetest.pos_to_string(pos))
|
||||
end
|
||||
mcl_loot.fill_inventory(meta:get_inventory(), "main", mcl_loot.get_multi_loot(loottable, pr), pr)
|
||||
end
|
||||
|
||||
|
@ -404,7 +410,9 @@ local function dungeons_nodes(minp, maxp, blockseed)
|
|||
local z = pr:next(minp.z, maxp.z-dim.z-1)
|
||||
local p1 = vector_new(x, y, z)
|
||||
local p2 = vector_new(x+dim.x+1, y+dim.y+1, z+dim.z+1)
|
||||
if logging then
|
||||
minetest.log("verbose","[mcl_dungeons] size=" ..minetest.pos_to_string(dim) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2))
|
||||
end
|
||||
emerge_area(p1, p2, ecb_spawn_dungeon, {p1=p1, p2=p2, dim=dim, pr=pr})
|
||||
end
|
||||
end
|
||||
|
@ -414,7 +422,9 @@ function mcl_dungeons.spawn_dungeon(p1, _, pr)
|
|||
if not p1 or not pr or not p1.x or not p1.y or not p1.z then return end
|
||||
local dim = dungeonsizes[pr:next(1, #dungeonsizes)]
|
||||
local p2 = vector_new(p1.x+dim.x+1, p1.y+dim.y+1, p1.z+dim.z+1)
|
||||
if logging then
|
||||
minetest.log("verbose","[mcl_dungeons] size=" ..minetest.pos_to_string(dim) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2))
|
||||
end
|
||||
emerge_area(p1, p2, ecb_spawn_dungeon, {p1=p1, p2=p2, dim=dim, pr=pr, dontcheck=true})
|
||||
end
|
||||
|
||||
|
|
|
@ -1,77 +1,31 @@
|
|||
local logging = minetest.settings:get_bool("mcl_logging_mapgen", false)
|
||||
local log_timing = minetest.settings:get_bool("mcl_logging_mapgen_timing", false) -- detailed, for performance debugging
|
||||
|
||||
local registered_generators = {}
|
||||
|
||||
local lvm, nodes, param2 = 0, 0, 0
|
||||
local lvm_buffer = {}
|
||||
|
||||
local logging = minetest.settings:get_bool("mcl_logging_mapgen",false)
|
||||
|
||||
local function roundN(n, d)
|
||||
if type(n) ~= "number" then return n end
|
||||
local m = 10^d
|
||||
return math.floor(n * m + 0.5) / m
|
||||
end
|
||||
|
||||
local function run_generators (p1, p2, blockseed)
|
||||
if nodes > 0 then
|
||||
for _, rec in ipairs(registered_generators) do
|
||||
if rec.nf then
|
||||
rec.nf(p1, p2, blockseed)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function update_data (vm, data, data2)
|
||||
-- Write stuff
|
||||
vm:set_data(data)
|
||||
if param2 > 0 then
|
||||
vm:set_param2_data(data2)
|
||||
end
|
||||
end
|
||||
|
||||
local function post_generator_processing(vm, minp, maxp, deco_used, deco_table, ore_used, ore_table)
|
||||
if deco_table then
|
||||
minetest.generate_decorations(vm,vector.new(minp.x,deco_table.min,minp.z),vector.new(maxp.x,deco_table.max,maxp.z))
|
||||
elseif deco_used then
|
||||
minetest.generate_decorations(vm)
|
||||
end
|
||||
if ore_table then
|
||||
minetest.generate_ores(vm,vector.new(minp.x,ore_table.min,minp.z),vector.new(maxp.x,ore_table.max,maxp.z))
|
||||
elseif ore_used then
|
||||
minetest.generate_ores(vm)
|
||||
end
|
||||
end
|
||||
|
||||
local function post_generator_processing_2(vm, p1, p2, shadow)
|
||||
vm:calc_lighting(p1, p2, shadow)
|
||||
vm:write_to_map()
|
||||
vm:update_liquids()
|
||||
end
|
||||
local seed = minetest.get_mapgen_setting("seed")
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp, blockseed)
|
||||
local t1 = os.clock()
|
||||
local p1, p2 = {x=minp.x, y=minp.y, z=minp.z}, {x=maxp.x, y=maxp.y, z=maxp.z}
|
||||
if lvm > 0 then
|
||||
local lvm_used, shadow, deco_used, deco_table, ore_used, ore_table = false, false, false, false, false, false
|
||||
local lb2 = {} -- param2
|
||||
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
|
||||
local e1, e2 = {x=emin.x, y=emin.y, z=emin.z}, {x=emax.x, y=emax.y, z=emax.z}
|
||||
local data2
|
||||
local data = vm:get_data(lvm_buffer)
|
||||
if param2 > 0 then
|
||||
data2 = vm:get_param2_data(lb2)
|
||||
local area = VoxelArea(emin, emax)
|
||||
local data = vm:get_data()
|
||||
local data2 = param2 > 0 and vm:get_param2_data()
|
||||
if log_timing then
|
||||
minetest.log("action", string.format("[mcl_mapgen_core] %-20s %s ... %s %8.2fms", "get_data", minetest.pos_to_string(minp), minetest.pos_to_string(maxp), (os.clock() - t1)*1000))
|
||||
end
|
||||
local area = VoxelArea:new({MinEdge=e1, MaxEdge=e2})
|
||||
|
||||
local lvm_used, shadow, deco_used, deco_table, ore_used, ore_table = false, false, false, false, false, false
|
||||
for _, rec in ipairs(registered_generators) do
|
||||
if rec.vf then
|
||||
local gt1 = os.clock()
|
||||
local p1, p2 = vector.copy(minp), vector.copy(maxp) -- defensive copies
|
||||
local e1, e2 = vector.copy(emin), vector.copy(emax) -- defensive copies
|
||||
local lvm_used0, shadow0, deco, ore = rec.vf(vm, data, data2, e1, e2, area, p1, p2, blockseed)
|
||||
if lvm_used0 then
|
||||
lvm_used = true
|
||||
end
|
||||
if shadow0 then
|
||||
shadow = true
|
||||
end
|
||||
lvm_used = lvm_used or lvm_used0
|
||||
shadow = shadow or shadow0
|
||||
if deco and type(deco) == "table" then
|
||||
deco_table = deco
|
||||
elseif deco then
|
||||
|
@ -82,26 +36,66 @@ minetest.register_on_generated(function(minp, maxp, blockseed)
|
|||
elseif deco then
|
||||
ore_used = true
|
||||
end
|
||||
if log_timing then
|
||||
minetest.log("action", string.format("[mcl_mapgen_core] %-20s %s ... %s %8.2fms", rec.id, minetest.pos_to_string(minp), minetest.pos_to_string(maxp), (os.clock() - gt1)*1000))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if lvm_used then
|
||||
update_data (vm, data, data2)
|
||||
post_generator_processing(vm, minp, maxp, deco_used, deco_table, ore_used, ore_table)
|
||||
post_generator_processing_2(vm, p1, p2, shadow)
|
||||
local gt1 = os.clock()
|
||||
vm:set_data(data)
|
||||
if param2 > 0 then vm:set_param2_data(data2) end
|
||||
if log_timing then
|
||||
minetest.log("action", string.format("[mcl_mapgen_core] %-20s %s ... %s %8.2fms", "set_data", minetest.pos_to_string(minp), minetest.pos_to_string(maxp), (os.clock() - gt1)*1000))
|
||||
end
|
||||
local gt1 = os.clock()
|
||||
if deco_table and #deco_table > 0 then
|
||||
minetest.generate_decorations(vm,vector.new(minp.x,deco_table.min,minp.z),vector.new(maxp.x,deco_table.max,maxp.z))
|
||||
elseif deco_used then
|
||||
minetest.generate_decorations(vm)
|
||||
end
|
||||
if log_timing and (deco_table or deco_used) then
|
||||
minetest.log("action", string.format("[mcl_mapgen_core] %-20s %s ... %s %8.2fms", "decorations", minetest.pos_to_string(minp), minetest.pos_to_string(maxp), (os.clock() - gt1)*1000))
|
||||
end
|
||||
local gt1 = os.clock()
|
||||
if ore_table and #ore_table > 0 then
|
||||
minetest.generate_ores(vm,vector.new(minp.x,ore_table.min,minp.z),vector.new(maxp.x,ore_table.max,maxp.z))
|
||||
elseif ore_used then
|
||||
minetest.generate_ores(vm)
|
||||
end
|
||||
if log_timing and (ore_table or ore_used) then
|
||||
minetest.log("action", string.format("[mcl_mapgen_core] %-20s %s ... %s %8.2fms", "ores", minetest.pos_to_string(minp), minetest.pos_to_string(maxp), (os.clock() - gt1)*1000))
|
||||
end
|
||||
local gt1 = os.clock()
|
||||
vm:calc_lighting(minp, maxp, shadow)
|
||||
vm:write_to_map()
|
||||
vm:update_liquids()
|
||||
if log_timing then
|
||||
minetest.log("action", string.format("[mcl_mapgen_core] %-20s %s ... %s %8.2fms", "light/write/liquids", minetest.pos_to_string(minp), minetest.pos_to_string(maxp), (os.clock() - gt1)*1000))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
run_generators (p1, p2, blockseed)
|
||||
if nodes > 0 then
|
||||
for _, rec in ipairs(registered_generators) do
|
||||
if rec.nf then
|
||||
local gt1 = os.clock()
|
||||
local p1, p2 = vector.copy(minp), vector.copy(maxp) -- defensive copies
|
||||
rec.nf(p1, p2, blockseed)
|
||||
if log_timing then
|
||||
minetest.log("action", string.format("[mcl_mapgen_core] %-20s %s ... %s %8.2fms", rec.id, minetest.pos_to_string(minp), minetest.pos_to_string(maxp), (os.clock() - gt1)*1000))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
mcl_vars.add_chunk(minp)
|
||||
if logging then
|
||||
minetest.log("action", "[mcl_mapgen_core] Generating chunk " .. minetest.pos_to_string(minp) .. " ... " .. minetest.pos_to_string(maxp).."..."..tostring(roundN(((os.clock() - t1)*1000),2)).."ms")
|
||||
minetest.log("action", string.format("[mcl_mapgen_core] %-20s %s ... %s %8.2fms", "Generating chunk", minetest.pos_to_string(minp), minetest.pos_to_string(maxp), (os.clock() - t1)*1000))
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
|
||||
function minetest.register_on_generated(node_function)
|
||||
mcl_mapgen_core.register_generator("mod_"..minetest.get_current_modname().."_"..tostring(#registered_generators+1), nil, node_function)
|
||||
end
|
||||
|
@ -145,3 +139,91 @@ function mcl_mapgen_core.unregister_generator(id)
|
|||
if rec.needs_param2 then param2 = param2 - 1 end
|
||||
--if rec.needs_level0 then level0 = level0 - 1 end
|
||||
end
|
||||
|
||||
-- Try to make decorations more deterministic in order, by sorting by priority and name
|
||||
-- At least for low-priority this should make map seeds more comparable, but
|
||||
-- adding for example a new structure can still change everything that comes
|
||||
-- later, because currently decoration blockseeds are incremented sequentially
|
||||
-- c.f., https://github.com/minetest/minetest/issues/14919
|
||||
local pending_decorations = {}
|
||||
local gennotify_map = {}
|
||||
function mcl_mapgen_core.register_decoration(def, callback)
|
||||
def = table.copy(def) -- defensive deep copy, needed for water lily
|
||||
if def.gen_callback and not def.name then error("gen_callback requires a named decoration.") end
|
||||
if callback then error("Callbacks have been redesigned.") end
|
||||
if pending_decorations == nil then
|
||||
minetest.log("warning", "Decoration registered after mapgen core initialization: "..tostring(def.name))
|
||||
minetest.register_decoration(def)
|
||||
if def.gen_callback then
|
||||
def.deco_id = minetest.get_decoration_id(def.name)
|
||||
if not def.deco_id then
|
||||
error("Failed to get the decoration id for "..tostring(key))
|
||||
else
|
||||
minetest.set_gen_notify({decoration = true}, {def.deco_id})
|
||||
gennotify_map["decoration#" .. def.deco_id] = def
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
table.insert(pending_decorations, def)
|
||||
end
|
||||
local function sort_decorations()
|
||||
local keys, map = {}, {}
|
||||
for i, def in pairs(pending_decorations) do
|
||||
local name = def.name
|
||||
-- we try to generate fallback names to make order more deterministic
|
||||
name = name or (def.decoration and string.format("%s:%04d", def.decoration, i))
|
||||
if not name and type(def.schematic) == "string" then
|
||||
local sc = string.split(def.schematic, "/")
|
||||
name = string.format("%s:%04d", sc[#sc], i)
|
||||
end
|
||||
if not name and type(def.schematic) == "table" and def.schematic.data then
|
||||
name = ""
|
||||
for _, v in ipairs(def.schematic.data) do
|
||||
if v.name then name = name .. v.name .. ":" end
|
||||
end
|
||||
name = name .. string.format("%04d", i)
|
||||
end
|
||||
name = name or string.format("%04d", i)
|
||||
local prio = (def.priority or 1000) + i/1000
|
||||
local key = string.format("%08.3f:%s", prio, name)
|
||||
table.insert(keys, key)
|
||||
map[key] = def
|
||||
end
|
||||
table.sort(keys)
|
||||
for _, key in ipairs(keys) do
|
||||
local def = map[key]
|
||||
local deco_id = minetest.register_decoration(def)
|
||||
if not deco_id then
|
||||
error("Failed to register decoration"..tostring(key))
|
||||
end
|
||||
if def.gen_callback then
|
||||
deco_id = minetest.get_decoration_id(def.name)
|
||||
if not deco_id then
|
||||
error("Failed to get the decoration id for "..tostring(key))
|
||||
else
|
||||
minetest.set_gen_notify({decoration = true}, {deco_id})
|
||||
gennotify_map["decoration#" .. deco_id] = def
|
||||
end
|
||||
end
|
||||
end
|
||||
pending_decorations = nil -- as we will not run again
|
||||
end
|
||||
|
||||
mcl_mapgen_core.register_generator("Gennotify callbacks", nil, function(minp, maxp, blockseed)
|
||||
local pr = PcgRandom(blockseed + seed + 48214) -- constant seed offset
|
||||
local gennotify = minetest.get_mapgen_object("gennotify")
|
||||
for key, def in pairs(gennotify_map) do
|
||||
local t = gennotify[key]
|
||||
if t and #t > 0 then
|
||||
-- Fisher-Yates shuffle, using pr
|
||||
for i = 1, #t-1 do
|
||||
local r = pr:next(i,#t)
|
||||
t[i], t[r] = t[r], t[i]
|
||||
end
|
||||
def.gen_callback(t, minp, maxp, blockseed)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_mods_loaded(sort_decorations)
|
||||
|
|
|
@ -1,10 +1,4 @@
|
|||
mcl_mapgen_core = {}
|
||||
local registered_generators = {}
|
||||
|
||||
local lvm, nodes, param2 = 0, 0, 0
|
||||
local lvm_used = false
|
||||
local lvm_buffer = {}
|
||||
|
||||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
|
||||
|
@ -122,8 +116,6 @@ elseif mg_name == "fractal" then
|
|||
mg_flags.caverns = true
|
||||
end
|
||||
|
||||
|
||||
|
||||
local mg_flags_str = ""
|
||||
for k,v in pairs(mg_flags) do
|
||||
if v == false then
|
||||
|
@ -210,39 +202,42 @@ end
|
|||
-- If function(pos_to_check, content_id_at_this_pos), will set node only if returns true.
|
||||
-- min, max: Minimum and maximum Y levels of the layers to set
|
||||
-- minp, maxp: minp, maxp of the on_generated
|
||||
-- lvm_used: Set to true if any node in this on_generated has been set before.
|
||||
--
|
||||
-- returns true if any node was set and lvm_used otherwise
|
||||
local function set_layers(data, area, content_id, check, min, max, minp, maxp, lvm_used, pr)
|
||||
if (maxp.y >= min and minp.y <= max) then
|
||||
for y = math.max(min, minp.y), math.min(max, maxp.y) do
|
||||
for x = minp.x, maxp.x do
|
||||
for z = minp.z, maxp.z do
|
||||
local p_pos = area:index(x, y, z)
|
||||
if check then
|
||||
if type(check) == "function" and check({x=x,y=y,z=z}, data[p_pos], pr) then
|
||||
-- returns true if any node was set
|
||||
local function set_layers(data, area, content_id, check, min, max, minp, maxp, pr)
|
||||
if maxp.y < min or minp.y > max then return false end
|
||||
local lvm_used = false
|
||||
if not check then
|
||||
for p_pos in area:iter(minp.x, math.max(min, minp.y), minp.z, maxp.x, math.min(max, maxp.y), maxp.z) do
|
||||
data[p_pos] = content_id
|
||||
lvm_used = true
|
||||
elseif check == data[p_pos] then
|
||||
end
|
||||
elseif type(check) == "function" then
|
||||
-- slow path, needs vector coordinates (bedrock uses y only)
|
||||
for p_pos in area:iter(minp.x, math.max(min, minp.y), minp.z, maxp.x, math.min(max, maxp.y), maxp.z) do
|
||||
if check(area:position(p_pos), data[p_pos], pr) then
|
||||
data[p_pos] = content_id
|
||||
lvm_used = true
|
||||
end
|
||||
end
|
||||
else
|
||||
for p_pos in area:iter(minp.x, math.max(min, minp.y), minp.z, maxp.x, math.min(max, maxp.y), maxp.z) do
|
||||
if check == data[p_pos] then
|
||||
data[p_pos] = content_id
|
||||
lvm_used = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return lvm_used
|
||||
end
|
||||
|
||||
local function set_grass_palette(minp,maxp,data2,area,biomemap,nodes)
|
||||
local function set_grass_palette(minp,maxp,data2,area,nodes)
|
||||
-- Flat area at y=0 to read biome 3 times faster than 5.3.0.get_biome_data(pos).biome: 43us vs 125us per iteration:
|
||||
local biomemap = minetest.get_mapgen_object("biomemap")
|
||||
if not biomemap then return end
|
||||
local aream = VoxelArea:new({MinEdge={x=minp.x, y=0, z=minp.z}, MaxEdge={x=maxp.x, y=0, z=maxp.z}})
|
||||
local aream = VoxelArea(vector.new(minp.x, 0, minp.z), vector.new(maxp.x, 0, maxp.z))
|
||||
local nodes = minetest.find_nodes_in_area(minp, maxp, nodes)
|
||||
local lvm_used = false
|
||||
for n=1, #nodes do
|
||||
local n = nodes[n]
|
||||
local p_pos = area:index(n.x, n.y, n.z)
|
||||
|
@ -259,11 +254,13 @@ local function set_grass_palette(minp,maxp,data2,area,biomemap,nodes)
|
|||
return lvm_used
|
||||
end
|
||||
|
||||
local function set_foliage_palette(minp,maxp,data2,area,biomemap,nodes)
|
||||
local function set_foliage_palette(minp,maxp,data2,area,nodes)
|
||||
-- Flat area at y=0 to read biome 3 times faster than 5.3.0.get_biome_data(pos).biome: 43us vs 125us per iteration:
|
||||
local biomemap = minetest.get_mapgen_object("biomemap")
|
||||
if not biomemap then return end
|
||||
local aream = VoxelArea:new({MinEdge={x=minp.x, y=0, z=minp.z}, MaxEdge={x=maxp.x, y=0, z=maxp.z}})
|
||||
local aream = VoxelArea(vector.new(minp.x, 0, minp.z), vector.new(maxp.x, 0, maxp.z))
|
||||
local nodes = minetest.find_nodes_in_area(minp, maxp, nodes)
|
||||
local lvm_used = false
|
||||
for n=1, #nodes do
|
||||
local n = nodes[n]
|
||||
local p_pos = area:index(n.x, n.y, n.z)
|
||||
|
@ -283,11 +280,13 @@ local function set_foliage_palette(minp,maxp,data2,area,biomemap,nodes)
|
|||
return lvm_used
|
||||
end
|
||||
|
||||
local function set_water_palette(minp,maxp,data2,area,biomemap,nodes)
|
||||
local function set_water_palette(minp,maxp,data2,area,nodes)
|
||||
-- Flat area at y=0 to read biome 3 times faster than 5.3.0.get_biome_data(pos).biome: 43us vs 125us per iteration:
|
||||
local biomemap = minetest.get_mapgen_object("biomemap")
|
||||
if not biomemap then return end
|
||||
local aream = VoxelArea:new({MinEdge={x=minp.x, y=0, z=minp.z}, MaxEdge={x=maxp.x, y=0, z=maxp.z}})
|
||||
local aream = VoxelArea(vector.new(minp.x, 0, minp.z), vector.new(maxp.x, 0, maxp.z))
|
||||
local nodes = minetest.find_nodes_in_area(minp, maxp, nodes)
|
||||
local lvm_used = false
|
||||
for n=1, #nodes do
|
||||
local n = nodes[n]
|
||||
local p_pos = area:index(n.x, n.y, n.z)
|
||||
|
@ -305,12 +304,11 @@ local function set_water_palette(minp,maxp,data2,area,biomemap,nodes)
|
|||
end
|
||||
|
||||
local function set_seagrass_param2(minp,maxp,data2,area,nodes)
|
||||
local aream = VoxelArea:new({MinEdge={x=minp.x, y=0, z=minp.z}, MaxEdge={x=maxp.x, y=0, z=maxp.z}})
|
||||
local nodes = minetest.find_nodes_in_area(minp, maxp, nodes)
|
||||
local lvm_used = false
|
||||
for n=1, #nodes do
|
||||
local n = nodes[n]
|
||||
local p_pos = area:index(n.x, n.y, n.z)
|
||||
data2[p_pos] = 3
|
||||
data2[area:index(n.x, n.y, n.z)] = 3
|
||||
lvm_used = true
|
||||
end
|
||||
return lvm_used
|
||||
|
@ -318,49 +316,47 @@ end
|
|||
|
||||
-- Below the bedrock, generate air/void
|
||||
local function world_structure(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
|
||||
local biomemap --ymin, ymax
|
||||
local lvm_used = false
|
||||
local pr = PseudoRandom(blockseed)
|
||||
local lvm_used = false
|
||||
|
||||
-- The Void below the Nether:
|
||||
lvm_used = set_layers(data, area, c_void , nil, mcl_vars.mapgen_edge_min , mcl_vars.mg_nether_min -1, minp, maxp, lvm_used, pr)
|
||||
lvm_used = set_layers(data, area, c_void , nil, mcl_vars.mapgen_edge_min , mcl_vars.mg_nether_min -1, minp, maxp, pr) or lvm_used
|
||||
|
||||
-- [[ THE NETHER: mcl_vars.mg_nether_min mcl_vars.mg_nether_max ]]
|
||||
|
||||
-- The Air on the Nether roof, https://git.minetest.land/VoxeLibre/VoxeLibre/issues/1186
|
||||
lvm_used = set_layers(data, area, c_air , nil, mcl_vars.mg_nether_max +1, mcl_vars.mg_nether_max + 128 , minp, maxp, lvm_used, pr)
|
||||
lvm_used = set_layers(data, area, c_air , nil, mcl_vars.mg_nether_max +1, mcl_vars.mg_nether_max + 128 , minp, maxp, pr) or lvm_used
|
||||
-- The Void above the Nether below the End:
|
||||
lvm_used = set_layers(data, area, c_void , nil, mcl_vars.mg_nether_max + 128 +1, mcl_vars.mg_end_min -1, minp, maxp, lvm_used, pr)
|
||||
lvm_used = set_layers(data, area, c_void , nil, mcl_vars.mg_nether_max + 128 +1, mcl_vars.mg_end_min -1, minp, maxp, pr) or lvm_used
|
||||
|
||||
-- [[ THE END: mcl_vars.mg_end_min mcl_vars.mg_end_max ]]
|
||||
|
||||
-- The Void above the End below the Realm barrier:
|
||||
lvm_used = set_layers(data, area, c_void , nil, mcl_vars.mg_end_max +1, mcl_vars.mg_realm_barrier_overworld_end_min-1, minp, maxp, lvm_used, pr)
|
||||
lvm_used = set_layers(data, area, c_void , nil, mcl_vars.mg_end_max +1, mcl_vars.mg_realm_barrier_overworld_end_min-1, minp, maxp, pr) or lvm_used
|
||||
-- Realm barrier between the Overworld void and the End
|
||||
lvm_used = set_layers(data, area, c_realm_barrier, nil, mcl_vars.mg_realm_barrier_overworld_end_min , mcl_vars.mg_realm_barrier_overworld_end_max , minp, maxp, lvm_used, pr)
|
||||
lvm_used = set_layers(data, area, c_realm_barrier, nil, mcl_vars.mg_realm_barrier_overworld_end_min , mcl_vars.mg_realm_barrier_overworld_end_max , minp, maxp, pr) or lvm_used
|
||||
-- The Void above Realm barrier below the Overworld:
|
||||
lvm_used = set_layers(data, area, c_void , nil, mcl_vars.mg_realm_barrier_overworld_end_max+1, mcl_vars.mg_overworld_min -1, minp, maxp, lvm_used, pr)
|
||||
lvm_used = set_layers(data, area, c_void , nil, mcl_vars.mg_realm_barrier_overworld_end_max+1, mcl_vars.mg_overworld_min -1, minp, maxp, pr) or lvm_used
|
||||
|
||||
|
||||
if mg_name ~= "singlenode" then
|
||||
-- Bedrock
|
||||
lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_vars.mg_bedrock_overworld_min, mcl_vars.mg_bedrock_overworld_max, minp, maxp, lvm_used, pr)
|
||||
lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_vars.mg_bedrock_nether_bottom_min, mcl_vars.mg_bedrock_nether_bottom_max, minp, maxp, lvm_used, pr)
|
||||
lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_vars.mg_bedrock_nether_top_min, mcl_vars.mg_bedrock_nether_top_max, minp, maxp, lvm_used, pr)
|
||||
lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_vars.mg_bedrock_overworld_min, mcl_vars.mg_bedrock_overworld_max, minp, maxp, pr) or lvm_used
|
||||
lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_vars.mg_bedrock_nether_bottom_min, mcl_vars.mg_bedrock_nether_bottom_max, minp, maxp, pr) or lvm_used
|
||||
lvm_used = set_layers(data, area, c_bedrock, bedrock_check, mcl_vars.mg_bedrock_nether_top_min, mcl_vars.mg_bedrock_nether_top_max, minp, maxp, pr) or lvm_used
|
||||
|
||||
-- Flat Nether
|
||||
if mg_name == "flat" then
|
||||
lvm_used = set_layers(data, area, c_air, nil, mcl_vars.mg_flat_nether_floor, mcl_vars.mg_flat_nether_ceiling, minp, maxp, lvm_used, pr)
|
||||
lvm_used = set_layers(data, area, c_air, nil, mcl_vars.mg_flat_nether_floor, mcl_vars.mg_flat_nether_ceiling, minp, maxp, pr) or lvm_used
|
||||
end
|
||||
|
||||
-- Big lava seas by replacing air below a certain height
|
||||
if mcl_vars.mg_lava then
|
||||
lvm_used = set_layers(data, area, c_lava, c_air, mcl_vars.mg_overworld_min, mcl_vars.mg_lava_overworld_max, minp, maxp, lvm_used, pr)
|
||||
lvm_used = set_layers(data, area, c_nether_lava, c_air, mcl_vars.mg_nether_min, mcl_vars.mg_lava_nether_max, minp, maxp, lvm_used, pr)
|
||||
lvm_used = set_layers(data, area, c_lava, c_air, mcl_vars.mg_overworld_min, mcl_vars.mg_lava_overworld_max, minp, maxp, pr) or lvm_used
|
||||
lvm_used = set_layers(data, area, c_nether_lava, c_air, mcl_vars.mg_nether_min, mcl_vars.mg_lava_nether_max, minp, maxp, pr) or lvm_used
|
||||
end
|
||||
end
|
||||
local deco = false
|
||||
local ores = false
|
||||
local deco, ores = false, false
|
||||
if minp.y > mcl_vars.mg_nether_deco_max - 64 and maxp.y < mcl_vars.mg_nether_max + 128 then
|
||||
deco = {min=mcl_vars.mg_nether_deco_max,max=mcl_vars.mg_nether_max}
|
||||
end
|
||||
|
@ -372,57 +368,35 @@ local function world_structure(vm, data, data2, emin, emax, area, minp, maxp, bl
|
|||
end
|
||||
|
||||
local function block_fixes_grass(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
|
||||
local biomemap = minetest.get_mapgen_object("biomemap")
|
||||
local lvm_used = false
|
||||
local pr = PseudoRandom(blockseed)
|
||||
if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then
|
||||
-- Set param2 (=color) of nodes which use the grass colour palette.
|
||||
lvm_used = set_grass_palette(minp,maxp,data2,area,biomemap,{"group:grass_palette"})
|
||||
end
|
||||
return lvm_used
|
||||
return minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min and
|
||||
set_grass_palette(minp,maxp,data2,area,{"group:grass_palette"})
|
||||
end
|
||||
|
||||
local function block_fixes_foliage(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
|
||||
local biomemap = minetest.get_mapgen_object("biomemap")
|
||||
local lvm_used = false
|
||||
local pr = PseudoRandom(blockseed)
|
||||
if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then
|
||||
-- Set param2 (=color) of nodes which use the foliage colour palette.
|
||||
lvm_used = set_foliage_palette(minp,maxp,data2,area,biomemap,{"group:foliage_palette", "group:foliage_palette_wallmounted"})
|
||||
end
|
||||
return lvm_used
|
||||
return minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min and
|
||||
set_foliage_palette(minp,maxp,data2,area,{"group:foliage_palette", "group:foliage_palette_wallmounted"})
|
||||
end
|
||||
|
||||
local function block_fixes_water(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
|
||||
local biomemap = minetest.get_mapgen_object("biomemap")
|
||||
local lvm_used = false
|
||||
local pr = PseudoRandom(blockseed)
|
||||
if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then
|
||||
-- Set param2 (=color) of nodes which use the water colour palette.
|
||||
lvm_used = set_water_palette(minp,maxp,data2,area,biomemap,{"group:water_palette"})
|
||||
end
|
||||
return lvm_used
|
||||
return minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min and
|
||||
set_water_palette(minp,maxp,data2,area,{"group:water_palette"})
|
||||
end
|
||||
|
||||
local function block_fixes_seagrass(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
|
||||
local lvm_used = false
|
||||
local pr = PseudoRandom(blockseed)
|
||||
if minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min then
|
||||
-- Set param2 of seagrass to 3.
|
||||
lvm_used = set_seagrass_param2(minp, maxp, data2, area, {"group:seagrass"})
|
||||
end
|
||||
return lvm_used
|
||||
return minp.y <= mcl_vars.mg_overworld_max and maxp.y >= mcl_vars.mg_overworld_min and
|
||||
set_seagrass_param2(minp, maxp, data2, area, {"group:seagrass"})
|
||||
end
|
||||
|
||||
-- End block fixes:
|
||||
local function end_basic(vm, data, data2, emin, emax, area, minp, maxp, blockseed)
|
||||
if maxp.y < mcl_vars.mg_end_min or minp.y > mcl_vars.mg_end_max then return end
|
||||
local biomemap --ymin, ymax
|
||||
local lvm_used = false
|
||||
local pr = PseudoRandom(blockseed)
|
||||
local nodes
|
||||
if mg_name ~= "v6" then
|
||||
nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source"})
|
||||
local nodes = minetest.find_nodes_in_area(emin, emax, {"mcl_core:water_source"})
|
||||
if #nodes > 0 then
|
||||
lvm_used = true
|
||||
for _,n in pairs(nodes) do
|
||||
|
@ -430,14 +404,12 @@ local function end_basic(vm, data, data2, emin, emax, area, minp, maxp, blocksee
|
|||
end
|
||||
end
|
||||
end
|
||||
return true, false
|
||||
lvm_used = true -- light is broken otherwise
|
||||
return lvm_used, false
|
||||
end
|
||||
|
||||
|
||||
mcl_mapgen_core.register_generator("world_structure", world_structure, nil, 1, true)
|
||||
mcl_mapgen_core.register_generator("end_fixes", end_basic, function(minp,maxp)
|
||||
if maxp.y < mcl_vars.mg_end_min or minp.y > mcl_vars.mg_end_max then return end
|
||||
end, 9999, true)
|
||||
mcl_mapgen_core.register_generator("end_fixes", end_basic, nil, 9999, true)
|
||||
|
||||
if mg_name ~= "v6" and mg_name ~= "singlenode" then
|
||||
mcl_mapgen_core.register_generator("block_fixes_grass", block_fixes_grass, nil, 9999, true)
|
||||
|
@ -450,31 +422,7 @@ if mg_name == "v6" then
|
|||
dofile(modpath.."/v6.lua")
|
||||
end
|
||||
|
||||
-- This should be moved to mcl_structures eventually if the dependencies can be sorted out.
|
||||
mcl_mapgen_core.register_generator("structures",nil, function(minp, maxp, blockseed)
|
||||
local gennotify = minetest.get_mapgen_object("gennotify")
|
||||
local has = false
|
||||
local poshash = minetest.hash_node_position(minp)
|
||||
for _,struct in pairs(mcl_structures.registered_structures) do
|
||||
local pr = PseudoRandom(blockseed + 42)
|
||||
if struct.deco_id then
|
||||
for _, pos in pairs(gennotify["decoration#"..struct.deco_id] or {}) do
|
||||
if struct.chunk_probability == nil or (not has and pr:next(1,struct.chunk_probability) == 1 ) then
|
||||
mcl_structures.place_structure(vector.offset(pos,0,1,0),struct,pr,blockseed)
|
||||
has=true
|
||||
end
|
||||
end
|
||||
elseif struct.static_pos then
|
||||
for _,p in pairs(struct.static_pos) do
|
||||
if vector.in_area(p,minp,maxp) then
|
||||
mcl_structures.place_structure(p,struct,pr,blockseed)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return false, false, false
|
||||
end, 100, true)
|
||||
|
||||
-- still needed?
|
||||
minetest.register_lbm({
|
||||
label = "Fix grass palette indexes", -- This LBM fixes any incorrect grass palette indexes.
|
||||
name = "mcl_mapgen_core:fix_grass_palette_indexes",
|
||||
|
@ -484,7 +432,7 @@ minetest.register_lbm({
|
|||
local grass_palette_index = mcl_util.get_palette_indexes_from_pos(pos).grass_palette_index
|
||||
if node.param2 ~= grass_palette_index then
|
||||
node.param2 = grass_palette_index
|
||||
minetest.set_node(pos, node)
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
@ -503,14 +451,14 @@ minetest.register_lbm({
|
|||
minetest.place_node(vector.offset(pos, 0, 1, 0), node) -- Offset required, since otherwise the leaves sink one node for some reason.
|
||||
elseif node.param2 ~= foliage_palette_index and node.name ~= "mcl_core:vine" then
|
||||
node.param2 = foliage_palette_index
|
||||
minetest.set_node(pos, node)
|
||||
minetest.swap_node(pos, node)
|
||||
elseif node.name == "mcl_core:vine" then
|
||||
local biome_param2 = foliage_palette_index
|
||||
local rotation_param2 = mcl_util.get_colorwallmounted_rotation(pos)
|
||||
local final_param2 = (biome_param2 * 8) + rotation_param2
|
||||
if node.param2 ~= final_param2 then
|
||||
node.param2 = final_param2
|
||||
minetest.set_node(pos, node)
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -525,7 +473,7 @@ minetest.register_lbm({
|
|||
local water_palette_index = mcl_util.get_palette_indexes_from_pos(pos).water_palette_index
|
||||
if node.param2 ~= water_palette_index then
|
||||
node.param2 = water_palette_index
|
||||
minetest.set_node(pos, node)
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
@ -538,15 +486,17 @@ minetest.register_lbm({
|
|||
action = function(pos, node)
|
||||
if node.param2 ~= 3 then
|
||||
node.param2 = 3
|
||||
minetest.set_node(pos, node)
|
||||
minetest.swap_node(pos, node)
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
--[[ No longer necessary? Ugly?
|
||||
-- We go outside x and y for where trees are placed next to a biome that has already been generated.
|
||||
-- We go above maxp.y because trees can often get placed close to the top of a generated area and folliage may not
|
||||
-- be coloured correctly.
|
||||
local function fix_folliage_missed (minp, maxp)
|
||||
local function fix_foliage_missed(minp, maxp, blockseed)
|
||||
if maxp.y < 0 then return end
|
||||
local pos1, pos2 = vector.offset(minp, -6, 0, -6), vector.offset(maxp, 6, 14, 6)
|
||||
local foliage = minetest.find_nodes_in_area(pos1, pos2, {"group:foliage_palette", "group:foliage_palette_wallmounted"})
|
||||
for _, fpos in pairs(foliage) do
|
||||
|
@ -554,22 +504,19 @@ local function fix_folliage_missed (minp, maxp)
|
|||
local foliage_palette_index = mcl_util.get_palette_indexes_from_pos(fpos).foliage_palette_index
|
||||
if fnode.param2 ~= foliage_palette_index and fnode.name ~= "mcl_core:vine" then
|
||||
fnode.param2 = foliage_palette_index
|
||||
minetest.set_node(fpos, fnode)
|
||||
minetest.swap_node(fpos, fnode)
|
||||
elseif fnode.name == "mcl_core:vine" then
|
||||
local biome_param2 = foliage_palette_index
|
||||
local rotation_param2 = mcl_util.get_colorwallmounted_rotation(fpos)
|
||||
local final_param2 = (biome_param2 * 8) + rotation_param2
|
||||
if fnode.param2 ~= final_param2 then
|
||||
fnode.param2 = final_param2
|
||||
minetest.set_node(fpos, fnode)
|
||||
minetest.swap_node(fpos, fnode)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp, blockseed) -- Set correct palette indexes of missed foliage.
|
||||
if maxp.y < 0 then
|
||||
return
|
||||
end
|
||||
fix_folliage_missed (minp, maxp)
|
||||
end)
|
||||
fix_foliage_missed(minp, maxp)
|
||||
end)]]
|
||||
|
|
|
@ -450,7 +450,8 @@ if minetest.settings:get_bool("mcl_generate_ores", true) then
|
|||
ore_type = "scatter",
|
||||
ore = "mcl_nether:ancient_debris",
|
||||
wherein = ancient_debris_wherein,
|
||||
clust_scarcity = 25000, -- 0.004% chance
|
||||
clust_scarcity = 15000,
|
||||
-- in MC it's 0.004% chance (~= scarcity 25000) but reports and experiments show that ancient debris is unreasonably hard to find in survival with that value
|
||||
clust_num_ores = 3,
|
||||
clust_size = 3,
|
||||
y_min = mcl_vars.mg_nether_min + 8,
|
||||
|
|
|
@ -45,6 +45,7 @@ local function register_mgv6_decorations()
|
|||
|
||||
-- Doubletall grass
|
||||
minetest.register_decoration({
|
||||
priority = 1500,
|
||||
deco_type = "schematic",
|
||||
schematic = {
|
||||
size = { x=1, y=3, z=1 },
|
||||
|
@ -81,6 +82,7 @@ local function register_mgv6_decorations()
|
|||
},
|
||||
-- v6 hack: This makes sure large ferns only appear in jungles
|
||||
spawn_by = { "mcl_core:jungletree", "mcl_flowers:fern" },
|
||||
priority = 1510, -- larger than fern
|
||||
num_spawn_by = 1,
|
||||
place_on = {"group:grass_block_no_snow"},
|
||||
|
||||
|
@ -192,6 +194,7 @@ local function register_mgv6_decorations()
|
|||
},
|
||||
-- Small trick to make sure melon spawn in jungles
|
||||
spawn_by = { "mcl_core:jungletree", "mcl_flowers:fern" },
|
||||
priority = 1510, -- larger than fern
|
||||
num_spawn_by = 1,
|
||||
y_min = 1,
|
||||
y_max = 40,
|
||||
|
@ -214,6 +217,7 @@ local function register_mgv6_decorations()
|
|||
y_min = 1,
|
||||
y_max = mcl_vars.overworld_max,
|
||||
decoration = "mcl_flowers:tallgrass",
|
||||
priority = 1500,
|
||||
})
|
||||
minetest.register_decoration({
|
||||
deco_type = "simple",
|
||||
|
@ -230,6 +234,7 @@ local function register_mgv6_decorations()
|
|||
y_min = 1,
|
||||
y_max = mcl_vars.overworld_max,
|
||||
decoration = "mcl_flowers:tallgrass",
|
||||
priority = 1500,
|
||||
})
|
||||
|
||||
-- Seagrass and kelp
|
||||
|
@ -256,6 +261,7 @@ local function register_mgv6_decorations()
|
|||
y_min = mcl_vars.overworld_min,
|
||||
y_max = 0,
|
||||
decoration = "mcl_ocean:seagrass_"..mat,
|
||||
priority = 1500,
|
||||
})
|
||||
minetest.register_decoration({
|
||||
deco_type = "simple",
|
||||
|
@ -276,6 +282,7 @@ local function register_mgv6_decorations()
|
|||
y_min = mcl_vars.overworld_min,
|
||||
y_max = -5,
|
||||
decoration = "mcl_ocean:seagrass_"..mat,
|
||||
priority = 1500,
|
||||
})
|
||||
|
||||
minetest.register_decoration({
|
||||
|
@ -356,6 +363,7 @@ local function register_mgv6_decorations()
|
|||
y_min = 1,
|
||||
y_max = mcl_vars.overworld_max,
|
||||
decoration = "mcl_flowers:tallgrass",
|
||||
priority = 1500,
|
||||
})
|
||||
|
||||
local mushrooms = {"mcl_mushrooms:mushroom_red", "mcl_mushrooms:mushroom_brown"}
|
||||
|
@ -501,7 +509,7 @@ local function generate_mgv6_structures()
|
|||
local surface = minetest.find_nodes_in_area({x=p.x,y=p.y-1,z=p.z}, floor, "mcl_core:snowblock")
|
||||
local surface2 = minetest.find_nodes_in_area({x=p.x,y=p.y-1,z=p.z}, floor, "mcl_core:dirt_with_grass_snow")
|
||||
if #surface + #surface2 >= 63 then
|
||||
mcl_structures.call_struct(p, "igloo", nil, pr)
|
||||
vl_structures.call_struct(p, "igloo", nil, pr)
|
||||
chunk_has_igloo = true
|
||||
end
|
||||
end
|
||||
|
@ -520,7 +528,7 @@ local function generate_mgv6_structures()
|
|||
local nodes = minetest.find_nodes_in_area(p1, p2, {"mcl_core:sandstone", "mcl_core:stone", "mcl_core:diorite", "mcl_core:andesite", "mcl_core:granite", "mcl_core:stone_with_coal", "mcl_core:dirt", "mcl_core:gravel"})
|
||||
|
||||
if #nodes >= 100 then -- >= 80%
|
||||
mcl_structures.call_struct(p1, "fossil", nil, pr)
|
||||
vl_structures.call_struct(p1, "fossil", nil, pr)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -557,15 +565,12 @@ local function generate_mgv6_structures()
|
|||
if #free_nodes >= ((size.x+1)*(size.y+1)*(size.z+1)) then
|
||||
local place = {x=p.x, y=WITCH_HUT_HEIGHT-1, z=p.z}
|
||||
|
||||
-- FIXME: For some mysterious reason (black magic?) this
|
||||
-- function does sometimes NOT spawn the witch hut. One can only see the
|
||||
-- oak wood nodes in the water, but no hut. :-/
|
||||
mcl_structures.place_structure(place,mcl_structures.registered_structures["witch_hut"],pr)
|
||||
vl_structures.place_structure(place,vl_structures.registered_structures["witch_hut"],pr)
|
||||
|
||||
local function place_tree_if_free(pos, prev_result)
|
||||
local nn = minetest.get_node(pos).name
|
||||
if nn == "mcl_flowers:waterlily" or nn == "mcl_core:water_source" or nn == "mcl_core:water_flowing" or nn == "air" then
|
||||
minetest.set_node(pos, {name="mcl_core:tree", param2=0})
|
||||
minetest.swap_node(pos, {name="mcl_core:tree", param2=0})
|
||||
return prev_result
|
||||
else
|
||||
return false
|
||||
|
@ -629,7 +634,7 @@ local function generate_mgv6_structures()
|
|||
local spruce_collisions = minetest.find_nodes_in_area({x=p.x+1,y=p.y+2,z=p.z+1}, {x=p.x+4, y=p.y+6, z=p.z+4}, {"mcl_core:sprucetree", "mcl_core:spruceleaves"})
|
||||
|
||||
if #surface >= 9 and #spruce_collisions == 0 then
|
||||
mcl_structures.place_structure(p,mcl_structures.registered_structures["ice_spike_large"],pr)
|
||||
vl_structures.place_structure(p,vl_structures.registered_structures["ice_spike_large"],pr)
|
||||
end
|
||||
elseif spike < 100 then
|
||||
-- Check surface
|
||||
|
@ -640,7 +645,7 @@ local function generate_mgv6_structures()
|
|||
local spruce_collisions = minetest.find_nodes_in_area({x=p.x+1,y=p.y+1,z=p.z+1}, {x=p.x+6, y=p.y+6, z=p.z+6}, {"mcl_core:sprucetree", "mcl_core:spruceleaves"})
|
||||
|
||||
if #surface >= 25 and #spruce_collisions == 0 then
|
||||
mcl_structures.place_structure(p,mcl_structures.registered_structures["ice_spike_small"],pr)
|
||||
vl_structures.place_structure(p,vl_structures.registered_structures["ice_spike_small"],pr)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -671,9 +676,9 @@ local function generate_underground_mushrooms(minp, maxp, seed)
|
|||
local l = minetest.get_node_light(bpos, 0.5)
|
||||
if bpos.y >= min and bpos.y <= max and l and l <= 12 and pr_shroom:next(1,1000) < 4 then
|
||||
if pr_shroom:next(1,2) == 1 then
|
||||
minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"})
|
||||
minetest.swap_node(bpos, {name = "mcl_mushrooms:mushroom_brown"})
|
||||
else
|
||||
minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"})
|
||||
minetest.swap_node(bpos, {name = "mcl_mushrooms:mushroom_red"})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -710,14 +715,14 @@ local function generate_nether_decorations(minp, maxp, seed)
|
|||
special_deco(rack, function(bpos)
|
||||
-- Eternal fire on netherrack
|
||||
if pr_nether:next(1,100) <= 3 then
|
||||
minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"})
|
||||
minetest.swap_node(bpos, {name = "mcl_fire:eternal_fire"})
|
||||
end
|
||||
end)
|
||||
|
||||
-- Eternal fire on magma cubes
|
||||
special_deco(magma, function(bpos)
|
||||
if pr_nether:next(1,150) == 1 then
|
||||
minetest.set_node(bpos, {name = "mcl_fire:eternal_fire"})
|
||||
minetest.swap_node(bpos, {name = "mcl_fire:eternal_fire"})
|
||||
end
|
||||
end)
|
||||
|
||||
|
@ -728,9 +733,9 @@ local function generate_nether_decorations(minp, maxp, seed)
|
|||
if bpos.y > mcl_vars.mg_lava_nether_max + 6 and l and l <= 12 and pr_nether:next(1,1000) <= 4 then
|
||||
-- TODO: Make mushrooms appear in groups, use Perlin noise
|
||||
if pr_nether:next(1,2) == 1 then
|
||||
minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_brown"})
|
||||
minetest.swap_node(bpos, {name = "mcl_mushrooms:mushroom_brown"})
|
||||
else
|
||||
minetest.set_node(bpos, {name = "mcl_mushrooms:mushroom_red"})
|
||||
minetest.swap_node(bpos, {name = "mcl_mushrooms:mushroom_red"})
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
@ -739,7 +744,7 @@ local function generate_nether_decorations(minp, maxp, seed)
|
|||
-- TODO: Spawn in Nether fortresses
|
||||
special_deco(ssand, function(bpos)
|
||||
if pr_nether:next(1, nether_wart_chance) == 1 then
|
||||
minetest.set_node(bpos, {name = "mcl_nether:nether_wart"})
|
||||
minetest.swap_node(bpos, {name = "mcl_nether:nether_wart"})
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
|
|
@ -1,25 +1,20 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local S = minetest.get_translator(modname)
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local peaceful = minetest.settings:get_bool("only_peaceful_mobs", false)
|
||||
|
||||
local BLAZE_SPAWNER_MAX_LIGHT = 11
|
||||
|
||||
mcl_structures.register_structure("nether_outpost",{
|
||||
vl_structures.register_structure("nether_outpost",{
|
||||
place_on = {"mcl_nether:netherrack","mcl_crimson:crimson_nylium","mcl_crimson:warped_nylium","mcl_blackstone:basalt","mcl_blackstone:soul_soil","mcl_blackstone:blackstone","mcl_nether:soul_sand"},
|
||||
fill_ratio = 0.01,
|
||||
chunk_probability = 900,
|
||||
flags = "all_floors",
|
||||
chunk_probability = 23,
|
||||
flags = "place_center_x, place_center_y, all_floors",
|
||||
biomes = {"Nether","SoulsandValley","WarpedForest","CrimsonForest","BasaltDelta"},
|
||||
sidelen = 24,
|
||||
solid_ground = true,
|
||||
make_foundation = true,
|
||||
prepare = { tolerance = 20, padding = 4, corners = 5, foundation = true, clear = true, clear_top = 4 },
|
||||
y_min = mcl_vars.mg_lava_nether_max - 1,
|
||||
y_max = mcl_vars.mg_nether_max - 30,
|
||||
filenames = { modpath.."/schematics/mcl_nether_fortresses_nether_outpost.mts" },
|
||||
y_offset = 0,
|
||||
after_place = function(pos)
|
||||
local sp = minetest.find_nodes_in_area(pos,vector.offset(pos,0,20,0),{"mcl_mobspawners:spawner"})
|
||||
after_place = function(pos,def,pr,p1,p2)
|
||||
local sp = minetest.find_nodes_in_area(p1,p2,{"mcl_mobspawners:spawner"})
|
||||
if not sp[1] then return end
|
||||
mcl_mobspawners.setup_spawner(sp[1], "mobs_mc:blaze", 0, BLAZE_SPAWNER_MAX_LIGHT, 10, 8, 0)
|
||||
end
|
||||
|
@ -30,80 +25,101 @@ local nbridges = {
|
|||
modpath.."/schematics/mcl_nether_fortresses_nether_bridge_3.mts",
|
||||
modpath.."/schematics/mcl_nether_fortresses_nether_bridge_4.mts",
|
||||
}
|
||||
mcl_structures.register_structure("nether_bridge",{
|
||||
place_on = {"mcl_nether:nether_lava_source","mcl_nether:netherrack","mcl_crimson:crimson_nylium","mcl_crimson:warped_nylium","mcl_blackstone:basalt","mcl_blackstone:soul_soil","mcl_blackstone:blackstone","mcl_nether:soul_sand","mcl_core:bedrock"},
|
||||
fill_ratio = 0.01,
|
||||
chunk_probability = 500,
|
||||
flags = "all_floors",
|
||||
sidelen = 38,
|
||||
solid_ground = false,
|
||||
make_foundation = false,
|
||||
y_min = mcl_vars.mg_nether_min - 4,
|
||||
y_max = mcl_vars.mg_lava_nether_max - 20,
|
||||
vl_structures.register_structure("nether_bridge",{
|
||||
place_on = {"mcl_nether:nether_lava_source","mcl_nether:netherrack","mcl_crimson:crimson_nylium","mcl_crimson:warped_nylium","mcl_blackstone:basalt","mcl_blackstone:soul_soil","mcl_blackstone:blackstone","mcl_nether:soul_sand"},
|
||||
chunk_probability = 8, -- because of the y restriction these are quite rare
|
||||
flags = "place_center_x, place_center_y, all_floors",
|
||||
prepare = { tolerance = 50, padding = -1, corners = 0, clear_bottom = 8, clear_top = 6 }, -- asymmetric padding would be nice to have
|
||||
force_placement = true,
|
||||
y_min = mcl_vars.mg_lava_nether_max,
|
||||
y_max = mcl_vars.mg_lava_nether_max + 25, -- otherwise, we may see some very long legs
|
||||
filenames = nbridges,
|
||||
y_offset = function(pr) return pr:next(15,20) end,
|
||||
after_place = function(pos,def,pr)
|
||||
local p1 = vector.offset(pos,-14,0,-14)
|
||||
local p2 = vector.offset(pos,14,24,14)
|
||||
mcl_structures.spawn_mobs("mobs_mc:witherskeleton",{"mcl_blackstone:blackstone_chiseled_polished"},p1,p2,pr,5)
|
||||
end
|
||||
})
|
||||
|
||||
mcl_structures.register_structure("nether_outpost_with_bridges",{
|
||||
place_on = {"mcl_nether:netherrack","mcl_crimson:crimson_nylium","mcl_crimson:warped_nylium","mcl_blackstone:basalt","mcl_blackstone:soul_soil","mcl_blackstone:blackstone","mcl_nether:soul_sand","mcl_nether:nether_lava_source"},
|
||||
fill_ratio = 0.01,
|
||||
chunk_probability = 1300,
|
||||
flags = "all_floors",
|
||||
biomes = {"Nether","SoulsandValley","WarpedForest","CrimsonForest","BasaltDelta"},
|
||||
sidelen = 24,
|
||||
solid_ground = true,
|
||||
make_foundation = true,
|
||||
y_min = mcl_vars.mg_lava_nether_max - 1,
|
||||
y_max = mcl_vars.mg_nether_max - 30,
|
||||
filenames = { modpath.."/schematics/mcl_nether_fortresses_nether_outpost.mts" },
|
||||
daughters = {{
|
||||
files = { nbridges[1] },
|
||||
pos = vector.new(0,-2,-24),
|
||||
rot = 180,
|
||||
},
|
||||
{
|
||||
files = { nbridges[1] },
|
||||
pos = vector.new(0,-2,24),
|
||||
rot = 0,
|
||||
},
|
||||
{
|
||||
files = { nbridges[1] },
|
||||
pos = vector.new(-24,-2,0),
|
||||
rot = 270,
|
||||
},
|
||||
{
|
||||
files = { nbridges[1] },
|
||||
pos = vector.new(24,-2,0),
|
||||
rot = 90,
|
||||
},
|
||||
},
|
||||
after_place = function(pos,def,pr)
|
||||
local sp = minetest.find_nodes_in_area(pos,vector.offset(pos,0,20,0),{"mcl_mobspawners:spawner"})
|
||||
if not sp[1] then return end
|
||||
mcl_mobspawners.setup_spawner(sp[1], "mobs_mc:blaze", 0, BLAZE_SPAWNER_MAX_LIGHT, 10, 8, 0)
|
||||
|
||||
local legs = minetest.find_nodes_in_area(vector.offset(pos,-45,-2,-45),vector.offset(pos,45,0,45), "mcl_nether:nether_brick")
|
||||
y_offset = function(pr) return pr:next(-8, -5) end,
|
||||
after_place = function(pos,def,pr,p1,p2)
|
||||
vl_structures.spawn_mobs("mobs_mc:witherskeleton",{"mcl_blackstone:blackstone_chiseled_polished"},p1,p2,pr,5)
|
||||
-- p1.y is not a typo, we want to lowest level only
|
||||
local legs = minetest.find_nodes_in_area(vector.new(p1.x,p1.y,p1.z),vector.new(p2.x,p1.y,p2.z), "mcl_nether:nether_brick")
|
||||
local bricks = {}
|
||||
-- TODO: port leg generation to voxel manipulators?
|
||||
for _,leg in pairs(legs) do
|
||||
while minetest.get_item_group(mcl_vars.get_node(vector.offset(leg,0,-1,0), true, 333333).name, "solid") == 0 do
|
||||
while true do
|
||||
leg = vector.offset(leg,0,-1,0)
|
||||
local nodename = minetest.get_node(leg).name
|
||||
if nodename == "ignore" then break end
|
||||
if nodename ~= "air" and nodename ~= "mcl_core:lava_source" and minetest.get_item_group(nodename, "solid") ~= 0 then break end
|
||||
table.insert(bricks,leg)
|
||||
end
|
||||
end
|
||||
minetest.bulk_set_node(bricks, {name = "mcl_nether:nether_brick", param2 = 2})
|
||||
|
||||
local p1 = vector.offset(pos,-45,13,-45)
|
||||
local p2 = vector.offset(pos,45,13,45)
|
||||
mcl_structures.spawn_mobs("mobs_mc:witherskeleton",{"mcl_blackstone:blackstone_chiseled_polished"},p1,p2,pr,5)
|
||||
minetest.bulk_swap_node(bricks, {name = "mcl_nether:nether_brick", param2 = 2})
|
||||
end
|
||||
},true)
|
||||
})
|
||||
|
||||
mcl_structures.register_structure_spawn({
|
||||
vl_structures.register_structure("nether_outpost_with_bridges",{
|
||||
place_on = {"mcl_nether:netherrack","mcl_crimson:crimson_nylium","mcl_crimson:warped_nylium","mcl_blackstone:basalt","mcl_blackstone:soul_soil","mcl_blackstone:blackstone","mcl_nether:soul_sand","mcl_nether:nether_lava_source"},
|
||||
chunk_probability = 10, -- because of the y restriction, it will still be rare
|
||||
flags = "place_center_x, place_center_y, all_floors",
|
||||
biomes = {"Nether","SoulsandValley","WarpedForest","CrimsonForest","BasaltDelta"},
|
||||
prepare = { tolerance = 20, padding = 4, corners = 5, foundation = true, clear_top = 3 },
|
||||
y_min = mcl_vars.mg_lava_nether_max - 1,
|
||||
y_max = mcl_vars.mg_lava_nether_max + 40,
|
||||
-- todo: spawn_by a lot of air?
|
||||
filenames = { modpath.."/schematics/mcl_nether_fortresses_nether_outpost.mts" },
|
||||
emerge_padding = { vector.new(-38,-8,-38), vector.new(38,0,38) },
|
||||
daughters = {
|
||||
{
|
||||
filenames = { nbridges[1], nbridges[2] },
|
||||
pos = vector.new(0,-3,24),
|
||||
rotation= 0,
|
||||
no_level = true,
|
||||
prepare = { tolerance = -1, foundation = false, clear = true, clear_bottom = 16, clear_top = 2, padding = 1, corners = 4 },
|
||||
},
|
||||
{
|
||||
filenames = { nbridges[1], nbridges[2] },
|
||||
pos = vector.new(24,-3,0),
|
||||
rotation = 90,
|
||||
no_level = true,
|
||||
prepare = { tolerance = -1, foundation = false, clear = true, clear_bottom = 16, clear_top = 2, padding = 1, corners = 4 },
|
||||
},
|
||||
{
|
||||
filenames = { nbridges[1], nbridges[2] },
|
||||
pos = vector.new(0,-3,-25),
|
||||
rotation = 180,
|
||||
no_level = true,
|
||||
prepare = { tolerance = -1, foundation = false, clear = true, clear_bottom = 16, clear_top = 2, padding = 1, corners = 4 },
|
||||
},
|
||||
{
|
||||
filenames = { nbridges[1], nbridges[2] },
|
||||
pos = vector.new(-25,-3,0),
|
||||
rotation = 270,
|
||||
no_level = true,
|
||||
prepare = { tolerance = -1, foundation = false, clear = true, clear_bottom = 16, clear_top = 2, padding = 1, corners = 4 },
|
||||
},
|
||||
},
|
||||
after_place = function(pos,def,pr,p1,p2)
|
||||
local sp = minetest.find_nodes_in_area(p1,p2,{"mcl_mobspawners:spawner"})
|
||||
if not sp[1] then return end
|
||||
mcl_mobspawners.setup_spawner(sp[1], "mobs_mc:blaze", 0, BLAZE_SPAWNER_MAX_LIGHT, 10, 8, 0)
|
||||
-- the -3 offset needs to be carefully aligned with the bridges above
|
||||
local legs = minetest.find_nodes_in_area(vector.offset(pos,-45,-3,-45),vector.offset(pos,45,-3,45), "mcl_nether:nether_brick")
|
||||
local bricks = {}
|
||||
-- TODO: port leg generation to voxel manipulators?
|
||||
for _,leg in pairs(legs) do
|
||||
while true do
|
||||
leg = vector.offset(leg,0,-1,0)
|
||||
local nodename = minetest.get_node(leg).name
|
||||
if nodename == "ignore" then break end
|
||||
if nodename ~= "air" and nodename ~= "mcl_core:lava_source" and minetest.get_item_group(nodename, "solid") ~= 0 then break end
|
||||
table.insert(bricks,leg)
|
||||
end
|
||||
end
|
||||
minetest.bulk_swap_node(bricks, {name = "mcl_nether:nether_brick", param2 = 2})
|
||||
|
||||
local p1, p2 = vector.offset(pos,-45,12,-45), vector.offset(pos,45,22,45)
|
||||
vl_structures.spawn_mobs("mobs_mc:witherskeleton",{"mcl_blackstone:blackstone_chiseled_polished"},p1,p2,pr,5)
|
||||
end
|
||||
})
|
||||
|
||||
vl_structures.register_structure_spawn({
|
||||
name = "mobs_mc:witherskeleton",
|
||||
y_min = mcl_vars.mg_lava_nether_max,
|
||||
y_max = mcl_vars.mg_nether_max,
|
||||
|
@ -113,15 +129,12 @@ mcl_structures.register_structure_spawn({
|
|||
spawnon = { "mcl_blackstone:blackstone_chiseled_polished" },
|
||||
})
|
||||
|
||||
mcl_structures.register_structure("nether_bulwark",{
|
||||
vl_structures.register_structure("nether_bulwark",{
|
||||
place_on = {"mcl_nether:netherrack","mcl_crimson:crimson_nylium","mcl_crimson:warped_nylium","mcl_blackstone:basalt","mcl_blackstone:soul_soil","mcl_blackstone:blackstone","mcl_nether:soul_sand"},
|
||||
fill_ratio = 0.01,
|
||||
chunk_probability = 900,
|
||||
flags = "all_floors",
|
||||
chunk_probability = 29,
|
||||
flags = "place_center_x, place_center_y, all_floors",
|
||||
biomes = {"Nether","SoulsandValley","WarpedForest","CrimsonForest"},
|
||||
sidelen = 36,
|
||||
solid_ground = true,
|
||||
make_foundation = true,
|
||||
prepare = { tolerance=10, padding=4, corners=5, foundation=-5, clear_top=0 },
|
||||
y_min = mcl_vars.mg_lava_nether_max - 1,
|
||||
y_max = mcl_vars.mg_nether_max - 30,
|
||||
filenames = {
|
||||
|
@ -131,23 +144,24 @@ mcl_structures.register_structure("nether_bulwark",{
|
|||
modpath.."/schematics/mcl_nether_fortresses_nether_bulwark_4.mts",
|
||||
},
|
||||
daughters = {{
|
||||
files = {
|
||||
filenames = {
|
||||
modpath.."/schematics/mcl_nether_fortresses_nether_bulwark_interior_1.mts",
|
||||
modpath.."/schematics/mcl_nether_fortresses_nether_bulwark_interior_2.mts",
|
||||
modpath.."/schematics/mcl_nether_fortresses_nether_bulwark_interior_3.mts",
|
||||
modpath.."/schematics/mcl_nether_fortresses_nether_bulwark_interior_4.mts",
|
||||
},
|
||||
pos = vector.new(0,0,0),
|
||||
pos = vector.new(0,1,0),
|
||||
rotation = "random",
|
||||
force_placement = true,
|
||||
prepare = { tolerance = -1, foundation = false, clear = false },
|
||||
},
|
||||
},
|
||||
y_offset = 0,
|
||||
construct_nodes = {"group:wall"},
|
||||
after_place = function(pos,def,pr)
|
||||
local p1 = vector.offset(pos,-14,0,-14)
|
||||
local p2 = vector.offset(pos,14,24,14)
|
||||
mcl_structures.spawn_mobs("mobs_mc:piglin",{"mcl_blackstone:blackstone_brick_polished","mcl_stairs:slab_blackstone_polished"},p1,p2,pr,5)
|
||||
mcl_structures.spawn_mobs("mobs_mc:piglin_brute",{"mcl_blackstone:blackstone_brick_polished","mcl_stairs:slab_blackstone_polished"},p1,p2,pr)
|
||||
mcl_structures.spawn_mobs("mobs_mc:hoglin",{"mcl_blackstone:nether_gold"},p1,p2,pr,4)
|
||||
after_place = function(pos,def,pr,p1,p2)
|
||||
vl_structures.spawn_mobs("mobs_mc:piglin",{"mcl_blackstone:blackstone_brick_polished","mcl_stairs:slab_blackstone_polished"},p1,p2,pr,5)
|
||||
vl_structures.spawn_mobs("mobs_mc:piglin_brute",{"mcl_blackstone:blackstone_brick_polished","mcl_stairs:slab_blackstone_polished"},p1,p2,pr)
|
||||
vl_structures.spawn_mobs("mobs_mc:hoglin",{"mcl_blackstone:nether_gold"},p1,p2,pr,4)
|
||||
end,
|
||||
loot = {
|
||||
["mcl_chests:chest_small" ] ={
|
||||
|
@ -194,22 +208,22 @@ mcl_structures.register_structure("nether_bulwark",{
|
|||
},
|
||||
})
|
||||
|
||||
mcl_structures.register_structure_spawn({
|
||||
vl_structures.register_structure_spawn({
|
||||
name = "mobs_mc:piglin",
|
||||
y_min = mcl_vars.mg_nether_min,
|
||||
y_max = mcl_vars.mg_nether_max,
|
||||
chance = 10,
|
||||
interval = 60,
|
||||
limit = 9,
|
||||
spawnon = {"mcl_blackstone:blackstone_brick_polished","mcl_stairs:slab_blackstone_polished"},
|
||||
spawnon = {"mcl_blackstone:blackstone_brick_polished", "mcl_stairs:slab_blackstone_polished"},
|
||||
})
|
||||
|
||||
mcl_structures.register_structure_spawn({
|
||||
vl_structures.register_structure_spawn({
|
||||
name = "mobs_mc:piglin_brute",
|
||||
y_min = mcl_vars.mg_nether_min,
|
||||
y_max = mcl_vars.mg_nether_max,
|
||||
chance = 20,
|
||||
interval = 60,
|
||||
limit = 4,
|
||||
spawnon = {"mcl_blackstone:blackstone_brick_polished","mcl_stairs:slab_blackstone_polished"},
|
||||
spawnon = {"mcl_blackstone:blackstone_brick_polished", "mcl_stairs:slab_blackstone_polished"},
|
||||
})
|
||||
|
|
|
@ -83,21 +83,20 @@ local function generate_strongholds(minp, maxp, blockseed)
|
|||
pos.z = maxp.z - 7
|
||||
end
|
||||
|
||||
--mcl_structures.call_struct(pos, "end_portal_shrine", nil, pr)
|
||||
--vl_structures.call_struct(pos, "end_portal_shrine", nil, pr)
|
||||
strongholds[s].generated = true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
mcl_structures.register_structure("end_shrine",{
|
||||
vl_structures.register_structure("end_shrine",{
|
||||
static_pos = init_strongholds(),
|
||||
prepare = { tolerance = -1, foundation = false, clear = false },
|
||||
filenames = {
|
||||
minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_end_portal_room_simple.mts"
|
||||
},
|
||||
after_place = function(pos,def,pr,blockseed,p1,p2,size,rotation)
|
||||
local p1 = vector.subtract(pos,size)
|
||||
local p2 = vector.add(pos,size)
|
||||
after_place = function(pos, def, pr, p1, p2, size, rotation)
|
||||
local spawners = minetest.find_nodes_in_area(p1, p2, "mcl_mobspawners:spawner")
|
||||
for s=1, #spawners do
|
||||
--local meta = minetest.get_meta(spawners[s])
|
||||
|
|
|
@ -1,38 +1,7 @@
|
|||
# mcl_structures
|
||||
Structure placement API for MCL2.
|
||||
VoxeLibre structures
|
||||
|
||||
## mcl_structures.register_structure(name,structure definition,nospawn)
|
||||
If nospawn is truthy the structure will not be placed by mapgen and the decoration parameters can be omitted. This is intended for secondary structures the placement of which gets triggered by the placement of other structures. It can also be used to register testing structures so they can be used with /spawnstruct.
|
||||
This module contains standard VoxeLibre structures such as nether portals.
|
||||
|
||||
### structure definition
|
||||
{
|
||||
fill_ratio = OR noise = {},
|
||||
biomes = {},
|
||||
y_min =,
|
||||
y_max =,
|
||||
place_on = {},
|
||||
spawn_by = {},
|
||||
num_spawn_by =,
|
||||
flags = (default: "place_center_x, place_center_z, force_placement")
|
||||
(same as decoration def)
|
||||
y_offset =, --can be a number or a function returning a number
|
||||
filenames = {} OR place_func = function(pos,def,pr)
|
||||
-- filenames can be a list of any schematics accepted by mcl_structures.place_schematic / minetest.place_schematic
|
||||
on_place = function(pos,def,pr) end,
|
||||
-- called before placement. denies placement when returning falsy.
|
||||
after_place = function(pos,def,pr)
|
||||
-- executed after successful placement
|
||||
sidelen = int, --length of one side of the structure. used for foundations.
|
||||
solid_ground = bool, -- structure requires solid ground
|
||||
make_foundation = bool, -- a foundation is automatically built for the structure. needs the sidelen param
|
||||
loot = ,
|
||||
--a table of loot tables for mcl_loot indexed by node names
|
||||
-- e.g. { ["mcl_chests:chest_small"] = {loot},... }
|
||||
}
|
||||
## mcl_structures.registered_structures
|
||||
Table of the registered structure defintions indexed by name.
|
||||
The API has been redesigned and moved to the vl_structures module.
|
||||
|
||||
## mcl_structures.place_structure(pos, def, pr)
|
||||
Places a structure using the mapgen placement function
|
||||
|
||||
## mcl_structures.place_schematic(pos, schematic, rotation, replacements, force_placement, flags, after_placement_callback, pr, callback_param)
|
||||
|
|
|
@ -1,393 +0,0 @@
|
|||
mcl_structures.registered_structures = {}
|
||||
|
||||
local disabled_structures = minetest.settings:get("mcl_disabled_structures")
|
||||
if disabled_structures then disabled_structures = disabled_structures:split(",")
|
||||
else disabled_structures = {} end
|
||||
|
||||
local peaceful = minetest.settings:get_bool("only_peaceful_mobs", false)
|
||||
local mob_cap_player = tonumber(minetest.settings:get("mcl_mob_cap_player")) or 75
|
||||
local mob_cap_animal = tonumber(minetest.settings:get("mcl_mob_cap_animal")) or 10
|
||||
|
||||
local logging = minetest.settings:get_bool("mcl_logging_structures",true)
|
||||
|
||||
local mg_name = minetest.get_mapgen_setting("mg_name")
|
||||
|
||||
local rotations = {
|
||||
"0",
|
||||
"90",
|
||||
"180",
|
||||
"270"
|
||||
}
|
||||
|
||||
function mcl_structures.is_disabled(structname)
|
||||
return table.indexof(disabled_structures,structname) ~= -1
|
||||
end
|
||||
|
||||
local function ecb_place(blockpos, action, calls_remaining, param)
|
||||
if calls_remaining >= 1 then return end
|
||||
minetest.place_schematic(param.pos, param.schematic, param.rotation, param.replacements, param.force_placement, param.flags)
|
||||
if param.after_placement_callback and param.p1 and param.p2 then
|
||||
param.after_placement_callback(param.p1, param.p2, param.size, param.rotation, param.pr, param.callback_param)
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_structures.place_schematic(pos, schematic, rotation, replacements, force_placement, flags, after_placement_callback, pr, callback_param)
|
||||
if type(schematic) ~= "table" and not mcl_util.file_exists(schematic) then
|
||||
minetest.log("warning","[mcl_structures] schematic file "..tostring(schematic).." does not exist.")
|
||||
return end
|
||||
local s = loadstring(minetest.serialize_schematic(schematic, "lua", {lua_use_comments = false, lua_num_indent_spaces = 0}) .. " return schematic")()
|
||||
if s and s.size then
|
||||
local x, z = s.size.x, s.size.z
|
||||
if rotation then
|
||||
if rotation == "random" and pr then
|
||||
rotation = rotations[pr:next(1,#rotations)]
|
||||
end
|
||||
if rotation == "random" then
|
||||
x = math.max(x, z)
|
||||
z = x
|
||||
elseif rotation == "90" or rotation == "270" then
|
||||
x, z = z, x
|
||||
end
|
||||
end
|
||||
local p1 = {x=pos.x , y=pos.y , z=pos.z }
|
||||
local p2 = {x=pos.x+x-1, y=pos.y+s.size.y-1, z=pos.z+z-1}
|
||||
minetest.log("verbose", "[mcl_structures] size=" ..minetest.pos_to_string(s.size) .. ", rotation=" .. tostring(rotation) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2))
|
||||
local param = {pos=vector.new(pos), schematic=s, rotation=rotation, replacements=replacements, force_placement=force_placement, flags=flags, p1=p1, p2=p2, after_placement_callback = after_placement_callback, size=vector.new(s.size), pr=pr, callback_param=callback_param}
|
||||
minetest.emerge_area(p1, p2, ecb_place, param)
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_structures.get_struct(file)
|
||||
local localfile = modpath.."/schematics/"..file
|
||||
local file, errorload = io.open(localfile, "rb")
|
||||
if errorload then
|
||||
minetest.log("error", "[mcl_structures] Could not open this struct: "..localfile)
|
||||
return nil
|
||||
end
|
||||
|
||||
local allnode = file:read("*a")
|
||||
file:close()
|
||||
|
||||
return allnode
|
||||
end
|
||||
|
||||
-- Call on_construct on pos.
|
||||
-- Useful to init chests from formspec.
|
||||
local function init_node_construct(pos)
|
||||
local node = minetest.get_node(pos)
|
||||
local def = minetest.registered_nodes[node.name]
|
||||
if def and def.on_construct then
|
||||
def.on_construct(pos)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
mcl_structures.init_node_construct = init_node_construct
|
||||
|
||||
function mcl_structures.fill_chests(p1,p2,loot,pr)
|
||||
for it,lt in pairs(loot) do
|
||||
local nodes = minetest.find_nodes_in_area(p1, p2, it)
|
||||
for _,p in pairs(nodes) do
|
||||
local lootitems = mcl_loot.get_multi_loot(lt, pr)
|
||||
mcl_structures.init_node_construct(p)
|
||||
local meta = minetest.get_meta(p)
|
||||
local inv = meta:get_inventory()
|
||||
mcl_loot.fill_inventory(inv, "main", lootitems, pr)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function generate_loot(pos, def, pr)
|
||||
local hl = def.sidelen
|
||||
local p1 = vector.offset(pos,-hl,-hl,-hl)
|
||||
local p2 = vector.offset(pos,hl,hl,hl)
|
||||
if def.loot then mcl_structures.fill_chests(p1,p2,def.loot,pr) end
|
||||
end
|
||||
|
||||
function mcl_structures.construct_nodes(p1,p2,nodes)
|
||||
local nn=minetest.find_nodes_in_area(p1,p2,nodes)
|
||||
for _,p in pairs(nn) do
|
||||
mcl_structures.init_node_construct(p)
|
||||
end
|
||||
end
|
||||
|
||||
local function construct_nodes(pos,def,pr)
|
||||
return mcl_structures.construct_nodes(vector.offset(pos,-def.sidelen/2,0,-def.sidelen/2),vector.offset(pos,def.sidelen/2,def.sidelen,def.sidelen/2),def.construct_nodes)
|
||||
end
|
||||
|
||||
|
||||
function mcl_structures.find_lowest_y(pp)
|
||||
local y = 31000
|
||||
for _,p in pairs(pp) do
|
||||
if p.y < y then y = p.y end
|
||||
end
|
||||
return y
|
||||
end
|
||||
|
||||
function mcl_structures.find_highest_y(pp)
|
||||
local y = -31000
|
||||
for _,p in pairs(pp) do
|
||||
if p.y > y then y = p.y end
|
||||
end
|
||||
return y
|
||||
end
|
||||
|
||||
local function smooth_cube(nn,pos,plane,amnt)
|
||||
local r = {}
|
||||
local amnt = amnt or 9
|
||||
table.sort(nn,function(a, b)
|
||||
if false or plane then
|
||||
return vector.distance(vector.new(pos.x,0,pos.z), vector.new(a.x,0,a.z)) < vector.distance(vector.new(pos.x,0,pos.z), vector.new(b.x,0,b.z))
|
||||
else
|
||||
return vector.distance(pos, a) < vector.distance(pos, b)
|
||||
end
|
||||
end)
|
||||
for i=1,math.max(1,#nn-amnt) do table.insert(r,nn[i]) end
|
||||
return r
|
||||
end
|
||||
|
||||
local function find_ground(pos,nn,gn)
|
||||
local r = 0
|
||||
for _,v in pairs(nn) do
|
||||
local p=vector.new(v)
|
||||
repeat
|
||||
local n = minetest.get_node(p).name
|
||||
p = vector.offset(p,0,-1,0)
|
||||
until not n or n == "mcl_core:bedrock" or n == "ignore" or n == gn
|
||||
--minetest.log(tostring(pos.y - p.y))
|
||||
if pos.y - p.y > r then r = pos.y - p.y end
|
||||
end
|
||||
return r
|
||||
end
|
||||
|
||||
local function get_foundation_nodes(ground_p1,ground_p2,pos,sidelen,node_stone)
|
||||
local replace = {"air","group:liquid","mcl_core:snow","group:tree","group:leaves","group:plant","grass_block","group:dirt"}
|
||||
local depth = find_ground(pos,minetest.find_nodes_in_area(ground_p1,ground_p2,replace),node_stone)
|
||||
local nn = smooth_cube(minetest.find_nodes_in_area(vector.offset(ground_p1,0,-1,0),vector.offset(ground_p2,0,-depth,0),replace),vector.offset(pos,0,-depth,0),true,sidelen * 64)
|
||||
local stone = {}
|
||||
local filler = {}
|
||||
local top = {}
|
||||
local dust = {}
|
||||
for l,v in pairs(nn) do
|
||||
if v.y == ground_p1.y - 1 then
|
||||
table.insert(filler,v)
|
||||
table.insert(top,vector.offset(v,0,1,0))
|
||||
table.insert(dust,vector.offset(v,0,2,0))
|
||||
elseif v.y < ground_p1.y -1 and v.y > ground_p2.y -4 then table.insert(filler,v)
|
||||
elseif v.y < ground_p2.y - 3 and v.y > ground_p2.y -5 then
|
||||
if math.random(3) == 1 then
|
||||
table.insert(filler,v)
|
||||
else
|
||||
table.insert(stone,v)
|
||||
end
|
||||
else
|
||||
table.insert(stone,v)
|
||||
end
|
||||
end
|
||||
return stone,filler,top,dust
|
||||
end
|
||||
|
||||
local function foundation(ground_p1,ground_p2,pos,sidelen)
|
||||
local node_stone = "mcl_core:stone"
|
||||
local node_filler = "mcl_core:dirt"
|
||||
local node_top = "mcl_core:dirt_with_grass" or minetest.get_node(ground_p1).name
|
||||
local node_dust = nil
|
||||
|
||||
if mg_name ~= "v6" then
|
||||
local b = minetest.registered_biomes[minetest.get_biome_name(minetest.get_biome_data(pos).biome)]
|
||||
--minetest.log(dump(b.node_top))
|
||||
if b then
|
||||
if b.node_top then node_top = b.node_top end
|
||||
if b.node_filler then node_filler = b.node_filler end
|
||||
if b.node_stone then node_stone = b.node_stone end
|
||||
if b.node_dust then node_dust = b.node_dust end
|
||||
end
|
||||
end
|
||||
|
||||
local stone,filler,top,dust = get_foundation_nodes(ground_p1,ground_p2,pos,sidelen,node_stone)
|
||||
minetest.bulk_set_node(top,{name=node_top},node_stone)
|
||||
|
||||
if node_dust then
|
||||
minetest.bulk_set_node(dust,{name=node_dust})
|
||||
end
|
||||
minetest.bulk_set_node(filler,{name=node_filler})
|
||||
minetest.bulk_set_node(stone,{name=node_stone})
|
||||
end
|
||||
|
||||
function mcl_structures.spawn_mobs(mob,spawnon,p1,p2,pr,n,water)
|
||||
n = n or 1
|
||||
local sp = {}
|
||||
if water then
|
||||
local nn = minetest.find_nodes_in_area(p1,p2,spawnon)
|
||||
for k,v in pairs(nn) do
|
||||
if minetest.get_item_group(minetest.get_node(vector.offset(v,0,1,0)).name,"water") > 0 then
|
||||
table.insert(sp,v)
|
||||
end
|
||||
end
|
||||
else
|
||||
sp = minetest.find_nodes_in_area_under_air(p1,p2,spawnon)
|
||||
end
|
||||
table.shuffle(sp)
|
||||
local count = 0
|
||||
local mob_def = minetest.registered_entities[mob]
|
||||
local enabled = (not peaceful) or (mob_def and mob_def.spawn_class ~= "hostile")
|
||||
for _,node in pairs(sp) do
|
||||
if enabled and count < n and minetest.add_entity(vector.offset(node, 0, 1, 0), mob) then
|
||||
count = count + 1
|
||||
end
|
||||
minetest.get_meta(node):set_string("spawnblock", "yes") -- note: also in peaceful mode!
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_structures.place_structure(pos, def, pr, blockseed, rot)
|
||||
if not def then return end
|
||||
if not rot then rot = "random" end
|
||||
local log_enabled = logging and not def.terrain_feature
|
||||
local y_offset = 0
|
||||
if type(def.y_offset) == "function" then
|
||||
y_offset = def.y_offset(pr)
|
||||
elseif def.y_offset then
|
||||
y_offset = def.y_offset
|
||||
end
|
||||
local pp = vector.offset(pos,0,y_offset,0)
|
||||
if def.solid_ground and def.sidelen then
|
||||
local ground_p1 = vector.offset(pos,-def.sidelen/2,-1,-def.sidelen/2)
|
||||
local ground_p2 = vector.offset(pos,def.sidelen/2,-1,def.sidelen/2)
|
||||
|
||||
local solid = minetest.find_nodes_in_area(ground_p1,ground_p2,{"group:solid"})
|
||||
if #solid < ( def.sidelen * def.sidelen ) then
|
||||
if def.make_foundation then
|
||||
foundation(vector.offset(pos,-def.sidelen/2 - 3,-1,-def.sidelen/2 - 3),vector.offset(pos,def.sidelen/2 + 3,-1,def.sidelen/2 + 3),pos,def.sidelen)
|
||||
else
|
||||
if log_enabled then
|
||||
minetest.log("warning","[mcl_structures] "..def.name.." at "..minetest.pos_to_string(pp).." not placed. No solid ground.")
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
if def.on_place and not def.on_place(pos,def,pr,blockseed) then
|
||||
if log_enabled then
|
||||
minetest.log("warning","[mcl_structures] "..def.name.." at "..minetest.pos_to_string(pp).." not placed. Conditions not satisfied.")
|
||||
end
|
||||
return false
|
||||
end
|
||||
if def.filenames then
|
||||
if #def.filenames <= 0 then return false end
|
||||
local r = pr:next(1,#def.filenames)
|
||||
local file = def.filenames[r]
|
||||
if file then
|
||||
local rot = rotations[pr:next(1,#rotations)]
|
||||
local ap = function(pos,def,pr,blockseed) end
|
||||
|
||||
if def.daughters then
|
||||
ap = function(pos,def,pr,blockseed)
|
||||
for _,d in pairs(def.daughters) do
|
||||
local p = vector.add(pos,d.pos)
|
||||
local rot = d.rot or 0
|
||||
mcl_structures.place_schematic(p, d.files[pr:next(1,#d.files)], rot, nil, true, "place_center_x,place_center_z",function()
|
||||
if def.loot then generate_loot(pp,def,pr,blockseed) end
|
||||
if def.construct_nodes then construct_nodes(pp,def,pr,blockseed) end
|
||||
if def.after_place then
|
||||
def.after_place(pos,def,pr)
|
||||
end
|
||||
end,pr)
|
||||
end
|
||||
end
|
||||
elseif def.after_place then
|
||||
ap = def.after_place
|
||||
end
|
||||
mcl_structures.place_schematic(pp, file, rot, def.replacements, true, "place_center_x,place_center_z",function(p1, p2, size, rotation)
|
||||
if not def.daughters then
|
||||
if def.loot then generate_loot(pp,def,pr,blockseed) end
|
||||
if def.construct_nodes then construct_nodes(pp,def,pr,blockseed) end
|
||||
end
|
||||
return ap(pp,def,pr,blockseed,p1,p2,size,rotation)
|
||||
end,pr)
|
||||
if log_enabled then
|
||||
minetest.log("action","[mcl_structures] "..def.name.." placed at "..minetest.pos_to_string(pp))
|
||||
end
|
||||
return true
|
||||
end
|
||||
elseif def.place_func and def.place_func(pp,def,pr,blockseed) then
|
||||
if not def.after_place or ( def.after_place and def.after_place(pp,def,pr,blockseed) ) then
|
||||
if def.loot then generate_loot(pp,def,pr,blockseed) end
|
||||
if def.construct_nodes then construct_nodes(pp,def,pr,blockseed) end
|
||||
if log_enabled then
|
||||
minetest.log("action","[mcl_structures] "..def.name.." placed at "..minetest.pos_to_string(pp))
|
||||
end
|
||||
return true
|
||||
end
|
||||
end
|
||||
if log_enabled then
|
||||
minetest.log("warning","[mcl_structures] placing "..def.name.." failed at "..minetest.pos_to_string(pos))
|
||||
end
|
||||
end
|
||||
|
||||
local EMPTY_SCHEMATIC = { size = {x = 0, y = 0, z = 0}, data = { } }
|
||||
|
||||
function mcl_structures.register_structure(name,def,nospawn) --nospawn means it will not be placed by mapgen decoration mechanism
|
||||
if mcl_structures.is_disabled(name) then return end
|
||||
flags = def.flags or "place_center_x, place_center_z, force_placement"
|
||||
def.name = name
|
||||
if not nospawn and def.place_on then
|
||||
minetest.register_on_mods_loaded(function() --make sure all previous decorations and biomes have been registered
|
||||
def.deco = minetest.register_decoration({
|
||||
name = "mcl_structures:deco_"..name,
|
||||
deco_type = "schematic",
|
||||
schematic = EMPTY_SCHEMATIC,
|
||||
place_on = def.place_on,
|
||||
spawn_by = def.spawn_by,
|
||||
num_spawn_by = def.num_spawn_by,
|
||||
sidelen = 80,
|
||||
fill_ratio = def.fill_ratio,
|
||||
noise_params = def.noise_params,
|
||||
flags = flags,
|
||||
biomes = def.biomes,
|
||||
y_max = def.y_max,
|
||||
y_min = def.y_min
|
||||
})
|
||||
def.deco_id = minetest.get_decoration_id("mcl_structures:deco_"..name)
|
||||
minetest.set_gen_notify({decoration=true}, { def.deco_id })
|
||||
--catching of gennotify happens in mcl_mapgen_core
|
||||
end)
|
||||
end
|
||||
mcl_structures.registered_structures[name] = def
|
||||
end
|
||||
|
||||
local structure_spawns = {}
|
||||
function mcl_structures.register_structure_spawn(def)
|
||||
--name,y_min,y_max,spawnon,biomes,chance,interval,limit
|
||||
minetest.register_abm({
|
||||
label = "Spawn "..def.name,
|
||||
nodenames = def.spawnon,
|
||||
min_y = def.y_min or -31000,
|
||||
max_y = def.y_max or 31000,
|
||||
interval = def.interval or 60,
|
||||
chance = def.chance or 5,
|
||||
action = function(pos, node, active_object_count, active_object_count_wider)
|
||||
local limit = def.limit or 7
|
||||
if active_object_count_wider > limit + mob_cap_animal then return end
|
||||
if active_object_count_wider > mob_cap_player then return end
|
||||
local p = vector.offset(pos,0,1,0)
|
||||
local pname = minetest.get_node(p).name
|
||||
if def.type_of_spawning == "water" then
|
||||
if pname ~= "mcl_core:water_source" and pname ~= "mclx_core:river_water_source" then return end
|
||||
else
|
||||
if pname ~= "air" then return end
|
||||
end
|
||||
if minetest.get_meta(pos):get_string("spawnblock") == "" then return end
|
||||
if mg_name ~= "v6" and mg_name ~= "singlenode" and def.biomes then
|
||||
if table.indexof(def.biomes,minetest.get_biome_name(minetest.get_biome_data(p).biome)) == -1 then
|
||||
return
|
||||
end
|
||||
end
|
||||
local mobdef = minetest.registered_entities[def.name]
|
||||
if mobdef.can_spawn and not mobdef.can_spawn(p) then return end
|
||||
minetest.add_entity(p,def.name)
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
|
||||
vl_structures.register_structure("campsite",{
|
||||
place_on = {"group:grass_block"},
|
||||
flags = "place_center_x, place_center_z",
|
||||
chunk_probability = 50,
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
y_min = 1,
|
||||
prepare = { tolerance = 1, foundation = -2, clear_top = 1, padding = 1, corners = 1 }, -- low tolerance, perform little terraforming
|
||||
filenames = {
|
||||
modpath.."/schematics/campsite_1.mts"
|
||||
},
|
||||
loot = {
|
||||
["mcl_chests:trapped_chest_small"] = {
|
||||
{
|
||||
stacks_min = 1,
|
||||
stacks_max = 3,
|
||||
items = {
|
||||
{ itemstring = "mcl_sus_stew:stew", weight = 10, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_core:paper", weight = 8, amount_min = 1, amount_max = 12 },
|
||||
{ itemstring = "mcl_farming:wheat_item", weight = 7, amount_min = 8, amount_max = 21 },
|
||||
{ itemstring = "mcl_farming:carrot_item", weight = 7, amount_min = 4, amount_max = 8 },
|
||||
{ itemstring = "mcl_farming:potato_item_poison", weight = 7, amount_min = 2, amount_max = 6 },
|
||||
{ itemstring = "mcl_farming:potato_item", weight = 7, amount_min = 2, amount_max = 6 },
|
||||
{ itemstring = "mcl_core:coal_lump", weight = 6, amount_min = 2, amount_max = 8 },
|
||||
{ itemstring = "mcl_mobitems:rotten_flesh", weight = 5, amount_min = 5, amount_max = 24 },
|
||||
{ itemstring = "mcl_farming:potato_item", weight = 3, amount_min = 1, amount_max = 5 },
|
||||
{ itemstring = "mcl_armor:helmet_leather_enchanted", weight = 3, func = function(stack, _)
|
||||
mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}) end },
|
||||
{ itemstring = "mcl_armor:chestplate_leather_enchanted", weight = 3, func = function(stack, _)
|
||||
mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}) end },
|
||||
{ itemstring = "mcl_armor:leggings_leather_enchanted", weight = 3, func = function(stack, _)
|
||||
mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}) end },
|
||||
{ itemstring = "mcl_armor:boots_leather_enchanted", weight = 3, func = function(stack, _)
|
||||
mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}) end },
|
||||
{ itemstring = "mcl_bamboo:bamboo", weight = 2, amount_min = 1, amount_max = 3 },
|
||||
{ itemstring = "mcl_farming:pumpkin", weight = 2, amount_min = 1, amount_max = 3 },
|
||||
{ itemstring = "mcl_tnt:tnt", weight = 1, amount_min = 1, amount_max = 2 },
|
||||
}
|
||||
},
|
||||
{
|
||||
stacks_min = 1,
|
||||
stacks_max = 2,
|
||||
items = {
|
||||
{ itemstring = "mcl_core:iron_ingot", weight = 90, amount_min = 1, amount_max = 2 },
|
||||
{ itemstring = "mcl_core:iron_nugget", weight = 50, amount_min = 1, amount_max = 10 },
|
||||
{ itemstring = "mcl_core:emerald", weight = 40, amount_min = 1, amount_max = 5 },
|
||||
{ itemstring = "mcl_core:lapis", weight = 20, amount_min = 1, amount_max = 10 },
|
||||
{ itemstring = "mcl_core:gold_ingot", weight = 10, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_core:gold_nugget", weight = 10, amount_min = 1, amount_max = 4 },
|
||||
{ itemstring = "mcl_experience:bottle", weight = 5, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_core:diamond", weight = 5, amount_min = 1, amount_max = 1 },
|
||||
}
|
||||
},{
|
||||
stacks_min = 1,
|
||||
stacks_max = 1,
|
||||
items = {
|
||||
--{ itemstring = "FIXME TREASURE MAP", weight = 8, amount_min = 1, amount_max = 5 },
|
||||
{ itemstring = "mcl_core:paper", weight = 20, amount_min = 1, amount_max = 10 },
|
||||
{ itemstring = "mcl_mobitems:feather", weight = 10, amount_min = 1, amount_max = 5 },
|
||||
{ itemstring = "mcl_books:book", weight = 5, amount_min = 1, amount_max = 5 },
|
||||
{ itemstring = "mcl_clock:clock", weight = 1, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_compass:compass", weight = 1, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_maps:empty_map", weight = 1, amount_min = 1, amount_max = 1 },
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -1,16 +1,12 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local S = minetest.get_translator(modname)
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
|
||||
local function temple_placement_callback(pos,def, pr)
|
||||
local hl = def.sidelen / 2
|
||||
local p1 = vector.offset(pos,-hl,-hl,-hl)
|
||||
local p2 = vector.offset(pos,hl,hl,hl)
|
||||
local function temple_placement_callback(pos,def,pr,p1,p2)
|
||||
-- Delete cacti leftovers:
|
||||
local cactus_nodes = minetest.find_nodes_in_area_under_air(p1, p2, "mcl_core:cactus")
|
||||
if cactus_nodes and #cactus_nodes > 0 then
|
||||
for _, pos in pairs(cactus_nodes) do
|
||||
local node_below = minetest.get_node({x=pos.x, y=pos.y-1, z=pos.z})
|
||||
local node_below = minetest.get_node(vector.offset(pos,0,-1,0))
|
||||
if node_below and node_below.name == "mcl_core:sandstone" then
|
||||
minetest.swap_node(pos, {name="air"})
|
||||
end
|
||||
|
@ -32,15 +28,12 @@ local function temple_placement_callback(pos,def, pr)
|
|||
end
|
||||
end
|
||||
|
||||
mcl_structures.register_structure("desert_temple",{
|
||||
vl_structures.register_structure("desert_temple",{
|
||||
place_on = {"group:sand"},
|
||||
fill_ratio = 0.01,
|
||||
flags = "place_center_x, place_center_z",
|
||||
solid_ground = true,
|
||||
make_foundation = true,
|
||||
sidelen = 18,
|
||||
y_offset = -12,
|
||||
chunk_probability = 300,
|
||||
prepare = { tolerance = 10, padding = 3, corners = 3, foundation = true, clear = false },
|
||||
chunk_probability = 18,
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
y_min = 1,
|
||||
biomes = { "Desert" },
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
|
||||
vl_structures.register_structure("desert_well",{
|
||||
place_on = {"group:sand"},
|
||||
flags = "place_center_x, place_center_z",
|
||||
chunk_probability = 15,
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
y_min = 1,
|
||||
y_offset = -2,
|
||||
biomes = { "Desert" },
|
||||
filenames = { modpath.."/schematics/mcl_structures_desert_well.mts" },
|
||||
})
|
||||
|
|
@ -1,42 +1,36 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local S = minetest.get_translator(modname)
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
|
||||
local spawnon = {"mcl_end:purpur_block"}
|
||||
|
||||
local function spawn_shulkers(pos,def,pr)
|
||||
local p1 = vector.offset(pos,-def.sidelen/2,-1,-def.sidelen/2)
|
||||
local p2 = vector.offset(pos,def.sidelen/2,def.sidelen,def.sidelen/2)
|
||||
mcl_structures.spawn_mobs("mobs_mc:shulker",spawnon,p1,p2,pr,1)
|
||||
|
||||
local guard = minetest.find_node_near(pos,def.sidelen,{"mcl_itemframes:item_frame"})
|
||||
if guard then
|
||||
minetest.add_entity(vector.offset(guard,0,-1.5,0),"mobs_mc:shulker")
|
||||
local function spawn_shulkers(pos,def,pr,p1,p2)
|
||||
vl_structures.spawn_mobs("mobs_mc:shulker",spawnon,p1,p2,pr,1)
|
||||
local guard = minetest.find_nodes_in_area(p1,p2,{"mcl_itemframes:item_frame"})
|
||||
if #guard > 0 then
|
||||
minetest.add_entity(vector.offset(guard[1],0,-1.5,0),"mobs_mc:shulker")
|
||||
end
|
||||
end
|
||||
|
||||
mcl_structures.register_structure("end_shipwreck",{
|
||||
vl_structures.register_structure("end_shipwreck",{
|
||||
place_on = {"mcl_end:end_stone"},
|
||||
fill_ratio = 0.001,
|
||||
flags = "place_center_x, place_center_z, all_floors",
|
||||
y_offset = function(pr) return pr:next(-50,-20) end,
|
||||
chunk_probability = 800,
|
||||
y_offset = function(pr) return pr:next(15,40) end,
|
||||
force_placement = false,
|
||||
prepare = { foundation = false, clear = false },
|
||||
chunk_probability = 25,
|
||||
--y_max = mcl_vars.mg_end_max,
|
||||
--y_min = mcl_vars.mg_end_min -100,
|
||||
biomes = { "End", "EndHighlands", "EndMidlands", "EndBarrens", "EndSmallIslands" },
|
||||
sidelen = 32,
|
||||
filenames = {
|
||||
modpath.."/schematics/mcl_structures_end_shipwreck_1.mts",
|
||||
},
|
||||
construct_nodes = {"mcl_chests:ender_chest_small","mcl_chests:ender_chest","mcl_brewing:stand_000","mcl_chests:violet_shulker_box_small"},
|
||||
after_place = function(pos,def,pr)
|
||||
local fr = minetest.find_node_near(pos,def.sidelen,{"mcl_itemframes:item_frame"})
|
||||
if fr then
|
||||
if mcl_itemframes then
|
||||
mcl_itemframes.update_item_entity(fr,minetest.get_node(fr))
|
||||
after_place = function(pos,def,pr,p1,p2)
|
||||
local fr = minetest.find_nodes_in_area(p1,p2,{"mcl_itemframes:item_frame"})
|
||||
if #fr > 0 and mcl_itemframes then
|
||||
mcl_itemframes.update_item_entity(fr[1],minetest.get_node(fr[1]))
|
||||
end
|
||||
end
|
||||
return spawn_shulkers(pos,def,pr)
|
||||
return spawn_shulkers(pos,def,pr,p1,p2)
|
||||
end,
|
||||
loot = {
|
||||
[ "mcl_itemframes:item_frame" ] ={{
|
||||
|
@ -53,7 +47,7 @@ mcl_structures.register_structure("end_shipwreck",{
|
|||
{ itemstring = "mcl_mobitems:bone", weight = 20, amount_min = 4, amount_max=6 },
|
||||
{ itemstring = "mcl_farming:beetroot_seeds", weight = 16, amount_min = 1, amount_max=10 },
|
||||
{ itemstring = "mcl_core:gold_ingot", weight = 15, amount_min = 2, amount_max = 7 },
|
||||
--{ itemstring = "mcl_bamboo:bamboo", weight = 15, amount_min = 1, amount_max=3 }, --FIXME BAMBOO
|
||||
{ itemstring = "mcl_bamboo:bamboo", weight = 15, amount_min = 1, amount_max=3 },
|
||||
{ itemstring = "mcl_core:iron_ingot", weight = 15, amount_min = 4, amount_max = 8 },
|
||||
{ itemstring = "mcl_core:diamond", weight = 3, amount_min = 2, amount_max = 7 },
|
||||
{ itemstring = "mcl_mobitems:saddle", weight = 3, },
|
||||
|
@ -86,16 +80,16 @@ mcl_structures.register_structure("end_shipwreck",{
|
|||
}
|
||||
})
|
||||
|
||||
mcl_structures.register_structure("end_boat",{
|
||||
vl_structures.register_structure("end_boat",{
|
||||
place_on = {"mcl_end:end_stone"},
|
||||
fill_ratio = 0.01,
|
||||
flags = "place_center_x, place_center_z, all_floors",
|
||||
y_offset = function(pr) return pr:next(15,30) end,
|
||||
chunk_probability = 900,
|
||||
y_offset = function(pr) return pr:next(10,20) end,
|
||||
force_placement = false,
|
||||
prepare = { foundation = false, clear = false },
|
||||
chunk_probability = 10,
|
||||
--y_max = mcl_vars.mg_end_max,
|
||||
--y_min = mcl_vars.mg_end_min -100,
|
||||
biomes = { "End", "EndHighlands", "EndMidlands", "EndBarrens", "EndSmallIslands" },
|
||||
sidelen = 20,
|
||||
filenames = {
|
||||
modpath.."/schematics/mcl_structures_end_boat.mts",
|
||||
},
|
||||
|
@ -134,7 +128,7 @@ mcl_structures.register_structure("end_boat",{
|
|||
}
|
||||
})
|
||||
|
||||
mcl_structures.register_structure_spawn({
|
||||
vl_structures.register_structure_spawn({
|
||||
name = "mobs_mc:shulker",
|
||||
y_min = mcl_vars.mg_end_min,
|
||||
y_max = mcl_vars.mg_end_max,
|
||||
|
@ -143,3 +137,52 @@ mcl_structures.register_structure_spawn({
|
|||
limit = 6,
|
||||
spawnon = spawnon,
|
||||
})
|
||||
|
||||
vl_structures.register_structure("small_end_city",{
|
||||
place_on = {"mcl_end:end_stone"},
|
||||
flags = "place_center_x, place_center_z, all_floors",
|
||||
y_offset = 0,
|
||||
chunk_probability = 30,
|
||||
prepare = { foundation = -1, tolerance = 15 },
|
||||
biomes = { "End", "EndHighlands", "EndMidlands", "EndBarrens", "EndSmallIslands" },
|
||||
sidelen = 20,
|
||||
filenames = {
|
||||
modpath.."/schematics/mcl_structures_end_city_simple.mts",
|
||||
},
|
||||
after_place = function(pos,def,pr,p1,p2)
|
||||
-- not on roof
|
||||
vl_structures.spawn_mobs("mobs_mc:shulker",spawnon,p1,vector.offset(p2,0,-2,0),pr,1)
|
||||
end,
|
||||
construct_nodes = {"mcl_chests:ender_chest_small","mcl_chests:ender_chest","mcl_brewing:stand_000","mcl_chests:violet_shulker_box_small"},
|
||||
loot = {
|
||||
[ "mcl_chests:chest_small" ] ={{
|
||||
stacks_min = 2,
|
||||
stacks_max = 6,
|
||||
items = {
|
||||
{ itemstring = "mcl_mobitems:bone", weight = 20, amount_min = 4, amount_max=6 },
|
||||
{ itemstring = "mcl_farming:beetroot_seeds", weight = 16, amount_min = 1, amount_max=10 },
|
||||
{ itemstring = "mcl_core:gold_ingot", weight = 15, amount_min = 2, amount_max = 7 },
|
||||
{ itemstring = "mcl_core:iron_ingot", weight = 15, amount_min = 4, amount_max = 8 },
|
||||
{ itemstring = "mcl_core:diamond", weight = 3, amount_min = 2, amount_max = 7 },
|
||||
{ itemstring = "mcl_mobitems:saddle", weight = 3, },
|
||||
{ itemstring = "mcl_core:emerald", weight = 2, amount_min = 1, amount_max = 3 },
|
||||
{ itemstring = "mcl_tools:pick_iron_enchanted", weight = 3,func = function(stack, pr) mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end },
|
||||
{ itemstring = "mcl_tools:shovel_iron_enchanted", weight = 3,func = function(stack, pr) mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end },
|
||||
{ itemstring = "mcl_tools:sword_iron_enchanted", weight = 3,func = function(stack, pr) mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end },
|
||||
{ itemstring = "mcl_armor:helmet_iron_enchanted", weight = 3,func = function(stack, pr) mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end },
|
||||
{ itemstring = "mcl_armor:chestplate_iron_enchanted", weight = 3,func = function(stack, pr) mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end },
|
||||
{ itemstring = "mcl_armor:leggings_iron_enchanted", weight = 3,func = function(stack, pr) mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end },
|
||||
{ itemstring = "mcl_armor:boots_iron_enchanted", weight = 3,func = function(stack, pr) mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end },
|
||||
{ itemstring = "mcl_tools:pick_diamond_enchanted", weight = 3,func = function(stack, pr) mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end },
|
||||
{ itemstring = "mcl_tools:shovel_diamond_enchanted", weight = 3,func = function(stack, pr) mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end },
|
||||
{ itemstring = "mcl_armor:helmet_diamond_enchanted", weight = 3,func = function(stack, pr) mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end },
|
||||
{ itemstring = "mcl_armor:leggings_diamond_enchanted", weight = 3,func = function(stack, pr) mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end },
|
||||
{ itemstring = "mcl_armor:boots_diamond_enchanted", weight = 3,func = function(stack, pr) mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr) end },
|
||||
{ itemstring = "mcl_core:emerald", weight = 2, amount_min = 1, amount_max = 3 },
|
||||
{ itemstring = "mcl_mobitems:iron_horse_armor", weight = 1, },
|
||||
{ itemstring = "mcl_mobitems:gold_horse_armor", weight = 1, },
|
||||
{ itemstring = "mcl_core:apple_gold_enchanted", weight = 2, },
|
||||
}
|
||||
}}
|
||||
}
|
||||
})
|
||||
|
|
|
@ -1,123 +1,101 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local S = minetest.get_translator(modname)
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local worldseed = minetest.get_mapgen_setting("seed")
|
||||
|
||||
|
||||
mcl_structures.register_structure("end_spawn_obsidian_platform",{
|
||||
static_pos ={mcl_vars.mg_end_platform_pos},
|
||||
place_func = function(pos,def,pr)
|
||||
local obby = minetest.find_nodes_in_area(vector.offset(pos,-2,0,-2),vector.offset(pos,2,0,2),{"air","mcl_end:end_stone"})
|
||||
local air = minetest.find_nodes_in_area(vector.offset(pos,-2,1,-2),vector.offset(pos,2,3,2),{"air","mcl_end:end_stone"})
|
||||
minetest.bulk_set_node(obby,{name="mcl_core:obsidian"})
|
||||
minetest.bulk_set_node(air,{name="air"})
|
||||
return true
|
||||
end,
|
||||
})
|
||||
|
||||
mcl_structures.register_structure("end_exit_portal",{
|
||||
static_pos = { mcl_vars.mg_end_exit_portal_pos },
|
||||
filenames = {
|
||||
modpath.."/schematics/mcl_structures_end_exit_portal.mts"
|
||||
},
|
||||
after_place = function(pos,def,pr,blockseed)
|
||||
if minetest.settings:get_bool("only_peaceful_mobs", false) then
|
||||
return
|
||||
end
|
||||
local p1 = vector.offset(pos,-16,-16,-16)
|
||||
local p2 = vector.offset(pos,16,21,16)
|
||||
minetest.emerge_area(p1,p2,function(blockpos, action, calls_remaining, param)
|
||||
if calls_remaining > 0 then return end
|
||||
minetest.bulk_set_node(minetest.find_nodes_in_area(p1,p2,{"mcl_portals:portal_end"}),{name="air"})
|
||||
local obj = minetest.add_entity(vector.offset(pos,3, 11, 3), "mobs_mc:enderdragon")
|
||||
if obj then
|
||||
local dragon_entity = obj:get_luaentity()
|
||||
dragon_entity._portal_pos = pos
|
||||
if blockseed ~= -1 then
|
||||
dragon_entity._initial = true
|
||||
end
|
||||
else
|
||||
minetest.log("error", "[mcl_mapgen_core] ERROR! Ender dragon doesn't want to spawn")
|
||||
end
|
||||
minetest.fix_light(p1,p2)
|
||||
end)
|
||||
end
|
||||
})
|
||||
mcl_structures.register_structure("end_exit_portal_open",{
|
||||
filenames = {
|
||||
modpath.."/schematics/mcl_structures_end_exit_portal.mts"
|
||||
},
|
||||
after_place = function(pos,def,pr)
|
||||
local p1 = vector.offset(pos,-16,-16,-16)
|
||||
local p2 = vector.offset(pos,16,16,16)
|
||||
minetest.fix_light(p1,p2)
|
||||
end
|
||||
})
|
||||
mcl_structures.register_structure("end_gateway_portal",{
|
||||
filenames = {
|
||||
modpath.."/schematics/mcl_structures_end_gateway_portal.mts"
|
||||
},
|
||||
})
|
||||
|
||||
local function get_tower(p,h,tbl)
|
||||
for i = 1,h do
|
||||
table.insert(tbl,vector.offset(p,0,i,0))
|
||||
end
|
||||
-- mcl_structures_end_exit_portal open is triggered by mods/ENTITIES/mobs_mc/ender_dragon.lua
|
||||
mcl_structures.spawn_end_exit_portal = function(pos)
|
||||
local schematic = vl_structures.load_schematic(modpath.."/schematics/mcl_structures_end_exit_portal.mts")
|
||||
vl_structures.place_schematic(pos, 0, schematic, "0", { name="end_exit_portal_open", prepare = false })
|
||||
end
|
||||
|
||||
local function make_endspike(pos,width,height)
|
||||
local nn = minetest.find_nodes_in_area(vector.offset(pos,-width/2,0,-width/2),vector.offset(pos,width/2,0,width/2),{"air","group:solid"})
|
||||
-- mcl_structures_end_gateway_portal.mts: see mods/ITEMS/mcl_portals/portal_gateway.lua
|
||||
mcl_structures.spawn_end_gateway_portal = function(pos)
|
||||
local schematic = vl_structures.load_schematic(modpath.."/schematics/mcl_structures_end_gateway_portal.mts")
|
||||
vl_structures.place_schematic(pos, 0, schematic, "0", { name="end_gateway_portal", prepare = false })
|
||||
end
|
||||
|
||||
local function make_endspike(pos, rad, height)
|
||||
-- FIXME: why find_nodes, not just use the circle?
|
||||
local nn = minetest.find_nodes_in_area(vector.offset(pos, -rad, 0, -rad), vector.offset(pos, rad, 0, rad), {"air", "group:solid"})
|
||||
table.sort(nn,function(a, b)
|
||||
return vector.distance(pos, a) < vector.distance(pos, b)
|
||||
end)
|
||||
local nodes = {}
|
||||
for i = 1,math.ceil(#nn*0.55) do
|
||||
get_tower(nn[i],height,nodes)
|
||||
for i = 1, math.ceil(#nn * 0.55) do
|
||||
for j = 1, height do
|
||||
table.insert(nodes, vector.offset(nn[i], 0, j, 0))
|
||||
end
|
||||
minetest.bulk_set_node(nodes,{ name="mcl_core:obsidian"} )
|
||||
return vector.offset(pos,0,height,0)
|
||||
end
|
||||
minetest.bulk_swap_node(nodes, {name = "mcl_core:obsidian"})
|
||||
return vector.offset(pos, 0, height, 0)
|
||||
end
|
||||
|
||||
function make_cage(pos,width)
|
||||
function make_cage(pos, rad)
|
||||
if not xpanes then return end
|
||||
local nodes = {}
|
||||
local nodes2 = {}
|
||||
local r = math.max(1,math.floor(width/2) - 2)
|
||||
for x=-r,r do for y = 0,width do for z = -r,r do
|
||||
if x == r or x == -r or z==r or z == -r then
|
||||
table.insert(nodes,vector.add(pos,vector.new(x,y,z)))
|
||||
end
|
||||
end end end
|
||||
if xpanes then
|
||||
minetest.bulk_set_node(nodes,{ name="xpanes:bar_flat"} )
|
||||
for _,p in pairs(nodes) do
|
||||
xpanes.update_pane(p)
|
||||
end
|
||||
end
|
||||
local r = math.max(1, rad - 2)
|
||||
for y = 0, rad * 2 do for xz = -r, r do
|
||||
table.insert(nodes,vector.add(pos,vector.new(xz,y, r)))
|
||||
table.insert(nodes,vector.add(pos,vector.new(xz,y,-r)))
|
||||
table.insert(nodes,vector.add(pos,vector.new( r,y,xz)))
|
||||
table.insert(nodes,vector.add(pos,vector.new(-r,y,xz)))
|
||||
end end
|
||||
minetest.bulk_swap_node(nodes, {name = "xpanes:bar_flat"} )
|
||||
for _,p in pairs(nodes) do xpanes.update_pane(p) end
|
||||
end
|
||||
|
||||
local function get_points_on_circle(pos,r,n)
|
||||
local rt = {}
|
||||
local rt, step = {}, 2 * math.pi / n
|
||||
for i=1, n do
|
||||
table.insert(rt,vector.offset(pos,r * math.cos(((i-1)/n) * (2*math.pi)),0, r* math.sin(((i-1)/n) * (2*math.pi)) ))
|
||||
table.insert(rt, vector.offset(pos, r * math.cos((i-1)*step), 0, r * math.sin((i-1)*step)))
|
||||
end
|
||||
return rt
|
||||
end
|
||||
|
||||
mcl_structures.register_structure("end_spike",{
|
||||
static_pos =get_points_on_circle(vector.offset(mcl_vars.mg_end_exit_portal_pos,0,-20,0),43,10),
|
||||
place_func = function(pos,def,pr)
|
||||
local d = pr:next(6,12)
|
||||
local h = d * pr:next(4,6)
|
||||
local p1 = vector.offset(pos, -d / 2, 0, -d / 2)
|
||||
local p2 = vector.offset(pos, d / 2, h + d, d / 2)
|
||||
minetest.emerge_area(p1, p2, function(blockpos, action, calls_remaining, param)
|
||||
minetest.register_on_mods_loaded(function()
|
||||
-- TODO: use LVM?
|
||||
mcl_mapgen_core.register_generator("end structures", nil, function(minp, maxp, blockseed)
|
||||
if maxp.y < mcl_vars.mg_end_min or minp.y > mcl_vars.mg_end_max then return end
|
||||
-- end spawn obsidian platform
|
||||
local pos = mcl_vars.mg_end_platform_pos
|
||||
if vector.in_area(pos, minp, maxp) then
|
||||
local obby = minetest.find_nodes_in_area(vector.offset(pos,-2,0,-2),vector.offset(pos,2,0,2),{"air","mcl_end:end_stone"})
|
||||
local air = minetest.find_nodes_in_area(vector.offset(pos,-2,1,-2),vector.offset(pos,2,3,2),{"air","mcl_end:end_stone"})
|
||||
minetest.bulk_swap_node(obby,{name="mcl_core:obsidian"})
|
||||
minetest.bulk_swap_node(air,{name="air"})
|
||||
end
|
||||
-- end exit portal and pillars
|
||||
local pos = mcl_vars.mg_end_exit_portal_pos
|
||||
if vector.in_area(pos, minp, maxp) then
|
||||
local pr = PcgRandom(worldseed)
|
||||
-- emerge pillars
|
||||
local p1, p2 = vector.offset(pos, -43-6, -10, -43-6), vector.offset(pos, 43+6, 12*6-10, 43+6)
|
||||
minetest.emerge_area(p1, p2, function(_, _, calls_remaining)
|
||||
if calls_remaining ~= 0 then return end
|
||||
local s = make_endspike(pos,d,h)
|
||||
minetest.set_node(vector.offset(s,0,1,0),{name="mcl_core:bedrock"})
|
||||
minetest.add_entity(vector.offset(s,0,2,0),"mcl_end:crystal")
|
||||
if pr:next(1,3) == 1 then
|
||||
make_cage(vector.offset(s,0,1,0),d)
|
||||
for _, p in ipairs(get_points_on_circle(vector.offset(pos, 0, -10, 0), 43, 10)) do
|
||||
local rad = pr:next(3,6)
|
||||
local top = make_endspike(p, rad, rad * 2 * pr:next(4,6) - 10)
|
||||
minetest.swap_node(vector.offset(top, 0, 1, 0), {name = "mcl_core:bedrock"})
|
||||
minetest.add_entity(vector.offset(top, 0, 2, 0), "mcl_end:crystal")
|
||||
if pr:next(1, 3) == 1 then make_cage(vector.offset(top, 0, 1, 0), rad) end
|
||||
end
|
||||
end)
|
||||
return true
|
||||
end,
|
||||
})
|
||||
-- emerge end portal
|
||||
local schematic = vl_structures.load_schematic(modpath.."/schematics/mcl_structures_end_exit_portal.mts")
|
||||
vl_structures.place_schematic(pos, 0, schematic, "0", { name = "end portal", prepare = false,
|
||||
after_place = function(pos,def,pr,pmin,pmax,size,rot)
|
||||
-- spawn ender dragon
|
||||
if minetest.settings:get_bool("only_peaceful_mobs", false) then return end
|
||||
minetest.bulk_swap_node(minetest.find_nodes_in_area(pmin, pmax, {"mcl_portals:portal_end"}), { name="air" })
|
||||
local obj = minetest.add_entity(vector.offset(pos, 3, 11, 3), "mobs_mc:enderdragon")
|
||||
if obj then
|
||||
local dragon_entity = obj:get_luaentity()
|
||||
dragon_entity._portal_pos = pos
|
||||
dragon_entity._initial = true
|
||||
else
|
||||
minetest.log("error", "[mcl_mapgen_core] ERROR! Ender dragon doesn't want to spawn")
|
||||
end
|
||||
end}, pr)
|
||||
end
|
||||
end, 100)
|
||||
end)
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
|
||||
vl_structures.register_structure("fossil",{
|
||||
place_on = {"group:material_stone","group:sand"},
|
||||
flags = "place_center_x, place_center_z",
|
||||
prepare = false,
|
||||
chunk_probability = 15, -- was 25, FIXME: needs rebalancing
|
||||
y_offset = function(pr) return pr:next(-32,-16) end,
|
||||
y_max = 15,
|
||||
y_min = mcl_vars.mg_overworld_min + 35,
|
||||
biomes = { "Desert" },
|
||||
filenames = {
|
||||
modpath.."/schematics/mcl_structures_fossil_skull_1.mts", -- 4×5×5
|
||||
modpath.."/schematics/mcl_structures_fossil_skull_2.mts", -- 5×5×5
|
||||
modpath.."/schematics/mcl_structures_fossil_skull_3.mts", -- 5×5×7
|
||||
modpath.."/schematics/mcl_structures_fossil_skull_4.mts", -- 7×5×5
|
||||
modpath.."/schematics/mcl_structures_fossil_spine_1.mts", -- 3×3×13
|
||||
modpath.."/schematics/mcl_structures_fossil_spine_2.mts", -- 5×4×13
|
||||
modpath.."/schematics/mcl_structures_fossil_spine_3.mts", -- 7×4×13
|
||||
modpath.."/schematics/mcl_structures_fossil_spine_4.mts", -- 8×5×13
|
||||
},
|
||||
})
|
||||
|
|
@ -14,11 +14,11 @@ local function set_node_no_bedrock(pos, node)
|
|||
return minetest.set_node(pos,node)
|
||||
end
|
||||
|
||||
local function makegeode(pos,def,pr)
|
||||
local function makegeode(pos, _, pr)
|
||||
local size = pr:next(5,7)
|
||||
local p1 = vector.offset(pos,-size,-size,-size)
|
||||
local p2 = vector.offset(pos,size,size,size)
|
||||
minetest.emerge_area(p1, p2, function(blockpos, action, calls_remaining, param)
|
||||
minetest.emerge_area(p1, p2, function(_, _, calls_remaining)
|
||||
if calls_remaining ~= 0 then return end
|
||||
local calcite = {}
|
||||
local nn = minetest.find_nodes_in_area(p1,p2,{"group:material_stone","group:dirt","mcl_core:gravel"})
|
||||
|
@ -37,9 +37,9 @@ local function makegeode(pos,def,pr)
|
|||
set_node_no_bedrock(nn[i],{name="mcl_amethyst:amethyst_block"})
|
||||
end
|
||||
|
||||
for k,v in pairs(minetest.find_nodes_in_area(p1,p2,{"mcl_amethyst:amethyst_block"})) do
|
||||
for _, v in pairs(minetest.find_nodes_in_area(p1,p2,{"mcl_amethyst:amethyst_block"})) do
|
||||
local all_amethyst = true
|
||||
for kk,vv in pairs(adjacents) do
|
||||
for _, vv in pairs(adjacents) do
|
||||
local pp = vector.add(v,vv)
|
||||
local an = minetest.get_node(pp)
|
||||
if an.name ~= "mcl_amethyst:amethyst_block" then
|
||||
|
@ -58,13 +58,13 @@ local function makegeode(pos,def,pr)
|
|||
if all_amethyst then set_node_no_bedrock(v,{name="air"}) end
|
||||
end
|
||||
|
||||
for _,v in pairs(calcite) do
|
||||
for _,vv in pairs(minetest.find_nodes_in_area(vector.offset(v,-1,-1,-1),vector.offset(v,1,1,1),{"group:material_stone"})) do
|
||||
for _, v in pairs(calcite) do
|
||||
for _, vv in pairs(minetest.find_nodes_in_area(vector.offset(v,-1,-1,-1),vector.offset(v,1,1,1),{"group:material_stone"})) do
|
||||
set_node_no_bedrock(vv,{name="mcl_blackstone:basalt_smooth"})
|
||||
end
|
||||
end
|
||||
|
||||
for k,v in pairs(minetest.find_nodes_in_area_under_air(p1,p2,{"mcl_amethyst:amethyst_block","mcl_amethyst:budding_amethyst_block"})) do
|
||||
for _, v in pairs(minetest.find_nodes_in_area_under_air(p1,p2,{"mcl_amethyst:amethyst_block","mcl_amethyst:budding_amethyst_block"})) do
|
||||
local r = pr:next(1,50)
|
||||
if r < 10 then
|
||||
set_node_no_bedrock(vector.offset(v,0,1,0),{name="mcl_amethyst:amethyst_cluster",param2=1})
|
||||
|
@ -75,7 +75,7 @@ local function makegeode(pos,def,pr)
|
|||
return true
|
||||
end
|
||||
|
||||
mcl_structures.register_structure("geode",{
|
||||
vl_structures.register_structure("geode",{
|
||||
place_on = {"group:material_stone"},
|
||||
noise_params = {
|
||||
offset = 0,
|
||||
|
|
|
@ -1,24 +1,11 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local S = minetest.get_translator(modname)
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
|
||||
function mcl_structures.generate_igloo_top(pos, pr)
|
||||
-- Furnace does ot work atm because apparently meta is not set. Need a bit of help with fixing this for furnaces, bookshelves, and brewing stands.
|
||||
local newpos = {x=pos.x,y=pos.y-2,z=pos.z}
|
||||
local path = modpath.."/schematics/mcl_structures_igloo_top.mts"
|
||||
local rotation = tostring(pr:next(0,3)*90)
|
||||
return mcl_structures.place_schematic(newpos, path, rotation, nil, true, nil, function()
|
||||
local p1 = vector.offset(pos,-5,-5,-5)
|
||||
local p2 = vector.offset(pos,5,5,5)
|
||||
mcl_structures.construct_nodes(p1,p2,{"mcl_furnaces:furnace","mcl_books:bookshelf"})
|
||||
end), rotation
|
||||
end
|
||||
local S = minetest.get_translator(modname)
|
||||
|
||||
local function spawn_mobs(p1,p2,vi,zv)
|
||||
local mc = minetest.find_nodes_in_area_under_air(p1,p2,{"mcl_core:stonebrickmossy"})
|
||||
if #mc == 2 then
|
||||
local vp = mc[1]
|
||||
local zp = mc[2]
|
||||
local vp, zp = mc[1], mc[2]
|
||||
if not vi and zv and zv:get_pos() and vector.distance(mc[1],zv:get_pos()) < 2 then
|
||||
vp = mc[2]
|
||||
elseif not zv and vi and vi:get_pos() and vector.distance(mc[2],vi:get_pos()) < 2 then
|
||||
|
@ -26,134 +13,102 @@ local function spawn_mobs(p1,p2,vi,zv)
|
|||
elseif zv and vi then
|
||||
return
|
||||
end
|
||||
vi = minetest.add_entity(vector.offset(mc[1],0,1,0),"mobs_mc:villager")
|
||||
zv = minetest.add_entity(vector.offset(mc[2],0,1,0),"mobs_mc:villager_zombie")
|
||||
vi = minetest.add_entity(vector.offset(vp,0,1,0),"mobs_mc:villager")
|
||||
zv = minetest.add_entity(vector.offset(zp,0,1,0),"mobs_mc:villager_zombie")
|
||||
if vi and vi:get_pos() and zv and zv:get_pos() then
|
||||
minetest.after(1,spawn_mobs,p1,p2,vi,zv)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_structures.generate_igloo_basement(pos, orientation, loot, pr)
|
||||
-- TODO: Add monster eggs
|
||||
local path = modpath.."/schematics/mcl_structures_igloo_basement.mts"
|
||||
mcl_structures.place_schematic(pos, path, orientation, nil, true, nil, function()
|
||||
local p1 = vector.offset(pos,-5,-5,-5)
|
||||
local p2 = vector.offset(pos,5,5,5)
|
||||
mcl_structures.fill_chests(p1,p2,loot,pr)
|
||||
mcl_structures.construct_nodes(p1,p2,{"mcl_brewing:stand_000","mcl_books:bookshelf"})
|
||||
spawn_mobs(p1,p2)
|
||||
end, pr)
|
||||
end
|
||||
|
||||
function mcl_structures.generate_igloo(pos, def, pr)
|
||||
-- Place igloo
|
||||
local success, rotation = mcl_structures.generate_igloo_top(pos, pr)
|
||||
local function igloo_callback(cpos,def,pr,p1,p2,size,rotation)
|
||||
vl_structures.construct_nodes(p1, p2, {"mcl_furnaces:furnace","mcl_books:bookshelf"})
|
||||
-- Place igloo basement with 50% chance
|
||||
local r = pr:next(1,2)
|
||||
if r == 1 then
|
||||
if pr:next(1,2) == 1 then return end
|
||||
local pos = p1 -- we use top left as reference
|
||||
-- Select basement depth
|
||||
local dim = mcl_worlds.pos_to_dimension(pos)
|
||||
--local buffer = pos.y - (mcl_vars.mg_lava_overworld_max + 10)
|
||||
local buffer
|
||||
if dim == "nether" then
|
||||
buffer = pos.y - (mcl_vars.mg_lava_nether_max + 10)
|
||||
elseif dim == "end" then
|
||||
buffer = pos.y - (mcl_vars.mg_end_min + 1)
|
||||
elseif dim == "overworld" then
|
||||
buffer = pos.y - (mcl_vars.mg_lava_overworld_max + 10)
|
||||
else
|
||||
return success
|
||||
end
|
||||
if buffer <= 19 then
|
||||
return success
|
||||
end
|
||||
local depth = pr:next(19, buffer)
|
||||
local bpos = {x=pos.x, y=pos.y-depth, z=pos.z}
|
||||
-- trapdoor position
|
||||
local tpos
|
||||
local dir, tdir
|
||||
local maxdepth = pos.y - (mcl_vars.mg_lava_overworld_max + 10)
|
||||
if maxdepth <= 9 then return true end
|
||||
local depth = pr:next(9, maxdepth)
|
||||
-- trapdoor position and orientation
|
||||
local tpos, dir, tdir
|
||||
if rotation == "0" then
|
||||
dir = {x=-1, y=0, z=0}
|
||||
tdir = {x=1, y=0, z=0}
|
||||
tpos = {x=pos.x+7, y=pos.y-2, z=pos.z+3}
|
||||
dir = vector.new(-1, 0, 0)
|
||||
tdir = vector.new(1, 0, 0)
|
||||
tpos = vector.new(pos.x+7, pos.y, pos.z+3)
|
||||
elseif rotation == "90" then
|
||||
dir = {x=0, y=0, z=-1}
|
||||
tdir = {x=0, y=0, z=-1}
|
||||
tpos = {x=pos.x+3, y=pos.y-2, z=pos.z+1}
|
||||
dir = vector.new(0, 0, -1)
|
||||
tdir = vector.new(0, 0, -1)
|
||||
tpos = vector.new(pos.x+3, pos.y, pos.z+1)
|
||||
elseif rotation == "180" then
|
||||
dir = {x=1, y=0, z=0}
|
||||
tdir = {x=-1, y=0, z=0}
|
||||
tpos = {x=pos.x+1, y=pos.y-2, z=pos.z+3}
|
||||
dir = vector.new(1, 0, 0)
|
||||
tdir = vector.new(-1, 0, 0)
|
||||
tpos = vector.new(pos.x+1, pos.y, pos.z+3)
|
||||
elseif rotation == "270" then
|
||||
dir = {x=0, y=0, z=1}
|
||||
tdir = {x=0, y=0, z=1}
|
||||
tpos = {x=pos.x+3, y=pos.y-2, z=pos.z+7}
|
||||
dir = vector.new(0, 0, 1)
|
||||
tdir = vector.new(0, 0, 1)
|
||||
tpos = vector.new(pos.x+3, pos.y, pos.z+7)
|
||||
else
|
||||
return success
|
||||
minetest.log("bad rotation: "..tostring(rotation))
|
||||
return false
|
||||
end
|
||||
local function set_brick(pos)
|
||||
local c = pr:next(1, 3) -- cracked chance
|
||||
local m = pr:next(1, 10) -- chance for monster egg
|
||||
local brick
|
||||
if m == 1 then
|
||||
if c == 1 then
|
||||
brick = "mcl_monster_eggs:monster_egg_stonebrickcracked"
|
||||
brick = (c == 1 and "mcl_monster_eggs:monster_egg_stonebrickcracked") or "mcl_monster_eggs:monster_egg_stonebrick"
|
||||
else
|
||||
brick = "mcl_monster_eggs:monster_egg_stonebrick"
|
||||
end
|
||||
else
|
||||
if c == 1 then
|
||||
brick = "mcl_core:stonebrickcracked"
|
||||
else
|
||||
brick = "mcl_core:stonebrick"
|
||||
end
|
||||
brick = (c == 1 and "mcl_core:stonebrickcracked") or "mcl_core:stonebrick"
|
||||
end
|
||||
minetest.set_node(pos, {name=brick})
|
||||
end
|
||||
local ladder_param2 = minetest.dir_to_wallmounted(tdir)
|
||||
local real_depth = 0
|
||||
-- Check how deep we can actuall dig
|
||||
for y=1, depth-5 do
|
||||
local real_depth = 2
|
||||
-- Check how deep we can actually dig
|
||||
for y=pos.y-real_depth, pos.y-depth, -1 do
|
||||
real_depth = real_depth + 1
|
||||
local node = minetest.get_node({x=tpos.x,y=tpos.y-y,z=tpos.z})
|
||||
local def = minetest.registered_nodes[node.name]
|
||||
if not (def and def.walkable and def.liquidtype == "none" and def.is_ground_content) then
|
||||
bpos.y = tpos.y-y+1
|
||||
break
|
||||
end
|
||||
local node = minetest.get_node(vector.new(tpos.x, y, tpos.z))
|
||||
local def = node and minetest.registered_nodes[node.name]
|
||||
if not (def and def.walkable and def.liquidtype == "none" and def.is_ground_content) then break end
|
||||
end
|
||||
local bpos = vector.new(cpos.x, pos.y-real_depth+1, cpos.z)
|
||||
if real_depth <= 6 then
|
||||
return success
|
||||
minetest.log("action", "Ground not deep enough for igloo basement: "..real_depth)
|
||||
return false
|
||||
end
|
||||
local path = modpath.."/schematics/mcl_structures_igloo_basement.mts"
|
||||
vl_structures.place_schematic(bpos, -1, path, rotation, {
|
||||
force_placement = true,
|
||||
prepare = { tolerance = -1, foundation = false, clear = false },
|
||||
after_place = function(_, _, pr, p1, p2)
|
||||
-- Generate ladder to basement
|
||||
for y=1, real_depth-1 do
|
||||
set_brick({x=tpos.x-1,y=tpos.y-y,z=tpos.z })
|
||||
set_brick({x=tpos.x+1,y=tpos.y-y,z=tpos.z })
|
||||
set_brick({x=tpos.x ,y=tpos.y-y,z=tpos.z-1})
|
||||
set_brick({x=tpos.x ,y=tpos.y-y,z=tpos.z+1})
|
||||
minetest.set_node({x=tpos.x,y=tpos.y-y,z=tpos.z}, {name="mcl_core:ladder", param2=ladder_param2})
|
||||
end
|
||||
-- Place basement
|
||||
mcl_structures.generate_igloo_basement(bpos, rotation, def.loot, pr)
|
||||
-- Place hidden trapdoor
|
||||
minetest.after(5, function(tpos, dir)
|
||||
local ladder = {name="mcl_core:ladder", param2=minetest.dir_to_wallmounted(tdir)}
|
||||
-- TODO: use voxelmanip?
|
||||
minetest.set_node(tpos, {name="mcl_doors:trapdoor", param2=20+minetest.dir_to_facedir(dir)}) -- TODO: more reliable param2
|
||||
end, tpos, dir)
|
||||
for y = tpos.y-1, bpos.y+4, -1 do
|
||||
set_brick(vector.new(tpos.x-1, y, tpos.z ))
|
||||
set_brick(vector.new(tpos.x+1, y, tpos.z ))
|
||||
set_brick(vector.new(tpos.x , y, tpos.z-1))
|
||||
set_brick(vector.new(tpos.x , y, tpos.z+1))
|
||||
minetest.set_node(vector.new(tpos.x, y, tpos.z), ladder)
|
||||
end
|
||||
return success
|
||||
vl_structures.fill_chests(p1,p2,def.loot,pr)
|
||||
vl_structures.construct_nodes(p1,p2,{"mcl_brewing:stand_000","mcl_books:bookshelf"})
|
||||
spawn_mobs(p1,p2)
|
||||
end
|
||||
}, pr)
|
||||
end
|
||||
|
||||
mcl_structures.register_structure("igloo",{
|
||||
vl_structures.register_structure("igloo",{
|
||||
filenames = { modpath.."/schematics/mcl_structures_igloo_top.mts" },
|
||||
place_on = {"mcl_core:snowblock","mcl_core:snow","group:grass_block_snow"},
|
||||
fill_ratio = 0.01,
|
||||
sidelen = 16,
|
||||
chunk_probability = 250,
|
||||
solid_ground = true,
|
||||
make_foundation = true,
|
||||
chunk_probability = 7,
|
||||
prepare = { padding = 1, corners = 1, foundation = -6, clear_top=-1 },
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
y_min = 0,
|
||||
y_offset = 0,
|
||||
y_offset = -2,
|
||||
biomes = { "ColdTaiga", "IcePlainsSpikes", "IcePlains" },
|
||||
place_func = mcl_structures.generate_igloo,
|
||||
after_place = igloo_callback,
|
||||
loot = {
|
||||
["mcl_chests:chest_small"] = {{
|
||||
stacks_min = 1,
|
||||
|
|
|
@ -1,135 +1,68 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local S = minetest.get_translator(modname)
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
|
||||
mcl_structures = {}
|
||||
|
||||
dofile(modpath.."/api.lua")
|
||||
dofile(modpath.."/shipwrecks.lua")
|
||||
-- some legacy API adapters
|
||||
mcl_structures.is_disabled = vl_structures.is_disabled
|
||||
mcl_structures.init_node_construct = vl_structures.init_node_construct
|
||||
mcl_structures.construct_nodes = vl_structures.construct_nodes
|
||||
mcl_structures.fill_chests = vl_structures.fill_chests
|
||||
mcl_structures.spawn_mobs = vl_structures.spawn_mobs
|
||||
|
||||
-- TODO: provide more legacy adapters that translate parameters?
|
||||
mcl_structures.place_schematic = function(pos, schematic, rotation, replacements, force_placement, flags, after_placement_callback, pr, callback_param)
|
||||
vl_structures.place_schematic(pos, yoffset, schematic, rotation, {
|
||||
replacements = replacements,
|
||||
force_placement = force_placement,
|
||||
flags = flags,
|
||||
after_place = after_placement_callback,
|
||||
callback_param = callback_param
|
||||
}, pr)
|
||||
end
|
||||
mcl_structures.place_structure = vl_structures.place_structure -- still compatible
|
||||
mcl_structures.register_structure = function(name, def, nospawn)
|
||||
-- nospawn: ignored, just pass no place_on!
|
||||
if not def.solid_ground then def.prepare = def.prepare or {} end
|
||||
vl_structures.register_structure(name, def)
|
||||
end
|
||||
|
||||
dofile(modpath.."/campsite.lua")
|
||||
dofile(modpath.."/desert_temple.lua")
|
||||
dofile(modpath.."/desert_well.lua")
|
||||
dofile(modpath.."/end_city.lua")
|
||||
dofile(modpath.."/end_spawn.lua")
|
||||
dofile(modpath.."/fossil.lua")
|
||||
dofile(modpath.."/geode.lua")
|
||||
dofile(modpath.."/igloo.lua")
|
||||
dofile(modpath.."/jungle_temple.lua")
|
||||
dofile(modpath.."/ocean_ruins.lua")
|
||||
dofile(modpath.."/witch_hut.lua")
|
||||
dofile(modpath.."/igloo.lua")
|
||||
dofile(modpath.."/woodland_mansion.lua")
|
||||
dofile(modpath.."/ruined_portal.lua")
|
||||
dofile(modpath.."/geode.lua")
|
||||
dofile(modpath.."/ocean_temple.lua")
|
||||
dofile(modpath.."/pillager_outpost.lua")
|
||||
dofile(modpath.."/end_spawn.lua")
|
||||
dofile(modpath.."/end_city.lua")
|
||||
dofile(modpath.."/ruined_portal.lua")
|
||||
dofile(modpath.."/shipwrecks.lua")
|
||||
dofile(modpath.."/spider_cocoon.lua")
|
||||
dofile(modpath.."/witch_hut.lua")
|
||||
dofile(modpath.."/woodland_mansion.lua")
|
||||
|
||||
|
||||
mcl_structures.register_structure("desert_well",{
|
||||
place_on = {"group:sand"},
|
||||
fill_ratio = 0.01,
|
||||
flags = "place_center_x, place_center_z",
|
||||
not_near = { "desert_temple_new" },
|
||||
solid_ground = true,
|
||||
sidelen = 4,
|
||||
chunk_probability = 600,
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
y_min = 1,
|
||||
y_offset = -2,
|
||||
biomes = { "Desert" },
|
||||
filenames = { modpath.."/schematics/mcl_structures_desert_well.mts" },
|
||||
})
|
||||
|
||||
mcl_structures.register_structure("fossil",{
|
||||
place_on = {"group:material_stone","group:sand"},
|
||||
fill_ratio = 0.01,
|
||||
flags = "place_center_x, place_center_z",
|
||||
solid_ground = true,
|
||||
sidelen = 13,
|
||||
chunk_probability = 1000,
|
||||
y_offset = function(pr) return ( pr:next(1,16) * -1 ) -16 end,
|
||||
y_max = 15,
|
||||
y_min = mcl_vars.mg_overworld_min + 35,
|
||||
biomes = { "Desert" },
|
||||
filenames = {
|
||||
modpath.."/schematics/mcl_structures_fossil_skull_1.mts", -- 4×5×5
|
||||
modpath.."/schematics/mcl_structures_fossil_skull_2.mts", -- 5×5×5
|
||||
modpath.."/schematics/mcl_structures_fossil_skull_3.mts", -- 5×5×7
|
||||
modpath.."/schematics/mcl_structures_fossil_skull_4.mts", -- 7×5×5
|
||||
modpath.."/schematics/mcl_structures_fossil_spine_1.mts", -- 3×3×13
|
||||
modpath.."/schematics/mcl_structures_fossil_spine_2.mts", -- 5×4×13
|
||||
modpath.."/schematics/mcl_structures_fossil_spine_3.mts", -- 7×4×13
|
||||
modpath.."/schematics/mcl_structures_fossil_spine_4.mts", -- 8×5×13
|
||||
},
|
||||
})
|
||||
|
||||
mcl_structures.register_structure("boulder",{
|
||||
vl_structures.register_structure("boulder",{
|
||||
-- as they have no place_on, they will not be spawned by this mechanism. this is just for /spawnstruct
|
||||
filenames = {
|
||||
-- small boulder 3x as likely
|
||||
modpath.."/schematics/mcl_structures_boulder_small.mts",
|
||||
modpath.."/schematics/mcl_structures_boulder_small.mts",
|
||||
modpath.."/schematics/mcl_structures_boulder_small.mts",
|
||||
modpath.."/schematics/mcl_structures_boulder.mts",
|
||||
-- small boulder 3x as likely
|
||||
},
|
||||
},true) --is spawned as a normal decoration. this is just for /spawnstruct
|
||||
|
||||
mcl_structures.register_structure("ice_spike_small",{
|
||||
filenames = { modpath.."/schematics/mcl_structures_ice_spike_small.mts" },
|
||||
},true) --is spawned as a normal decoration. this is just for /spawnstruct
|
||||
mcl_structures.register_structure("ice_spike_large",{
|
||||
sidelen = 6,
|
||||
filenames = { modpath.."/schematics/mcl_structures_ice_spike_large.mts" },
|
||||
},true) --is spawned as a normal decoration. this is just for /spawnstruct
|
||||
|
||||
-- Debug command
|
||||
local function dir_to_rotation(dir)
|
||||
local ax, az = math.abs(dir.x), math.abs(dir.z)
|
||||
if ax > az then
|
||||
if dir.x < 0 then
|
||||
return "270"
|
||||
end
|
||||
return "90"
|
||||
end
|
||||
if dir.z < 0 then
|
||||
return "180"
|
||||
end
|
||||
return "0"
|
||||
end
|
||||
|
||||
minetest.register_chatcommand("spawnstruct", {
|
||||
params = "dungeon",
|
||||
description = S("Generate a pre-defined structure near your position."),
|
||||
privs = {debug = true},
|
||||
func = function(name, param)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if not player then return end
|
||||
local pos = player:get_pos()
|
||||
if not pos then return end
|
||||
pos = vector.round(pos)
|
||||
local dir = minetest.yaw_to_dir(player:get_look_horizontal())
|
||||
local rot = dir_to_rotation(dir)
|
||||
local pr = PseudoRandom(pos.x+pos.y+pos.z)
|
||||
local errord = false
|
||||
local message = S("Structure placed.")
|
||||
if param == "dungeon" and mcl_dungeons and mcl_dungeons.spawn_dungeon then
|
||||
mcl_dungeons.spawn_dungeon(pos, rot, pr)
|
||||
elseif param == "" then
|
||||
message = S("Error: No structure type given. Please use “/spawnstruct <type>”.")
|
||||
errord = true
|
||||
else
|
||||
for n,d in pairs(mcl_structures.registered_structures) do
|
||||
if n == param then
|
||||
mcl_structures.place_structure(pos,d,pr,math.random(),rot)
|
||||
return true,message
|
||||
end
|
||||
end
|
||||
message = S("Error: Unknown structure type. Please use “/spawnstruct <type>”.")
|
||||
errord = true
|
||||
end
|
||||
minetest.chat_send_player(name, message)
|
||||
if errord then
|
||||
minetest.chat_send_player(name, S("Use /help spawnstruct to see a list of avaiable types."))
|
||||
end
|
||||
end
|
||||
})
|
||||
minetest.register_on_mods_loaded(function()
|
||||
local p = ""
|
||||
for n,_ in pairs(mcl_structures.registered_structures) do
|
||||
p = p .. " | "..n
|
||||
end
|
||||
minetest.registered_chatcommands["spawnstruct"].params = minetest.registered_chatcommands["spawnstruct"].params .. p
|
||||
end)
|
||||
|
||||
vl_structures.register_structure("ice_spike_small",{
|
||||
-- as they have no place_on, they will not be spawned by this mechanism. this is just for /spawnstruct
|
||||
filenames = { modpath.."/schematics/mcl_structures_ice_spike_small.mts" },
|
||||
})
|
||||
|
||||
vl_structures.register_structure("ice_spike_large",{
|
||||
-- as they have no place_on, they will not be spawned by this mechanism. this is just for /spawnstruct
|
||||
filenames = { modpath.."/schematics/mcl_structures_ice_spike_large.mts" },
|
||||
})
|
||||
|
||||
|
|
|
@ -2,18 +2,14 @@ local modname = minetest.get_current_modname()
|
|||
local S = minetest.get_translator(modname)
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
|
||||
mcl_structures.register_structure("jungle_temple",{
|
||||
vl_structures.register_structure("jungle_temple",{
|
||||
place_on = {"group:grass_block","group:dirt","mcl_core:dirt_with_grass"},
|
||||
fill_ratio = 0.01,
|
||||
flags = "place_center_x, place_center_z",
|
||||
solid_ground = true,
|
||||
make_foundation = true,
|
||||
y_offset = function(pr) return pr:next(-3,0) -5 end,
|
||||
chunk_probability = 200,
|
||||
chunk_probability = 5,
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
y_min = 1,
|
||||
biomes = { "Jungle" },
|
||||
sidelen = 18,
|
||||
filenames = {
|
||||
modpath.."/schematics/mcl_structures_jungle_temple.mts",
|
||||
modpath.."/schematics/mcl_structures_jungle_temple_nice.mts",
|
||||
|
@ -26,7 +22,7 @@ mcl_structures.register_structure("jungle_temple",{
|
|||
{ itemstring = "mcl_mobitems:bone", weight = 20, amount_min = 4, amount_max=6 },
|
||||
{ itemstring = "mcl_mobitems:rotten_flesh", weight = 16, amount_min = 3, amount_max=7 },
|
||||
{ itemstring = "mcl_core:gold_ingot", weight = 15, amount_min = 2, amount_max = 7 },
|
||||
--{ itemstring = "mcl_bamboo:bamboo", weight = 15, amount_min = 1, amount_max=3 }, --FIXME BAMBOO
|
||||
{ itemstring = "mcl_bamboo:bamboo", weight = 15, amount_min = 1, amount_max=3 },
|
||||
{ itemstring = "mcl_core:iron_ingot", weight = 15, amount_min = 1, amount_max = 5 },
|
||||
{ itemstring = "mcl_core:diamond", weight = 3, amount_min = 1, amount_max = 3 },
|
||||
{ itemstring = "mcl_mobitems:saddle", weight = 3, },
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
name = mcl_structures
|
||||
author = Wuzzy, cora
|
||||
author = Wuzzy, cora, kno10
|
||||
description = Structure placement for MCL2
|
||||
depends = mcl_init, mcl_loot
|
||||
depends = mcl_init, mcl_util, mcl_loot, vl_terraforming, vl_structures
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local S = minetest.get_translator(modname)
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local water_level = minetest.get_mapgen_setting("water_level")
|
||||
|
||||
local cold_oceans = {
|
||||
"RoofedForest_ocean",
|
||||
|
@ -72,18 +72,15 @@ local warm_oceans = {
|
|||
|
||||
local cold = {
|
||||
place_on = {"group:sand","mcl_core:gravel","mcl_core:dirt","mcl_core:clay","group:material_stone"},
|
||||
spawn_by = {"mcl_core:water_source"},
|
||||
spawn_by = {"group:water"},
|
||||
num_spawn_by = 2,
|
||||
fill_ratio = 0.01,
|
||||
flags = "place_center_x, place_center_z, force_placement",
|
||||
solid_ground = true,
|
||||
make_foundation = true,
|
||||
y_offset = -1,
|
||||
y_min = mcl_vars.mg_overworld_min,
|
||||
y_max = -2,
|
||||
chunk_probability = 10, -- todo: 15?
|
||||
biomes = cold_oceans,
|
||||
chunk_probability = 400,
|
||||
sidelen = 20,
|
||||
y_min = mcl_vars.mg_overworld_min,
|
||||
y_max = water_level - 6,
|
||||
y_offset = -1,
|
||||
flags = "place_center_x, place_center_z, force_placement",
|
||||
prepare = { foundation = -2, clear = false, mode="water" },
|
||||
filenames = {
|
||||
modpath.."/schematics/mcl_structures_ocean_ruins_cold_1.mts",
|
||||
modpath.."/schematics/mcl_structures_ocean_ruins_cold_2.mts",
|
||||
|
@ -128,5 +125,5 @@ warm.filenames = {
|
|||
modpath.."/schematics/mcl_structures_ocean_ruins_warm_4.mts",
|
||||
}
|
||||
|
||||
mcl_structures.register_structure("cold_ocean_ruins",cold)
|
||||
mcl_structures.register_structure("warm_ocean_ruins",warm)
|
||||
vl_structures.register_structure("cold_ocean_ruins",cold)
|
||||
vl_structures.register_structure("warm_ocean_ruins",warm)
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local water_level = minetest.get_mapgen_setting("water_level")
|
||||
|
||||
local spawnon = { "mcl_stairs:slab_prismarine_dark" }
|
||||
|
||||
local ocean_biomes = {
|
||||
"RoofedForest_ocean",
|
||||
"JungleEdgeM_ocean",
|
||||
"BirchForestM_ocean",
|
||||
"BirchForest_ocean",
|
||||
"IcePlains_deep_ocean",
|
||||
"Jungle_deep_ocean",
|
||||
"Savanna_ocean",
|
||||
"MesaPlateauF_ocean",
|
||||
"ExtremeHillsM_deep_ocean",
|
||||
"Savanna_deep_ocean",
|
||||
"SunflowerPlains_ocean",
|
||||
"Swampland_deep_ocean",
|
||||
"Swampland_ocean",
|
||||
"MegaSpruceTaiga_deep_ocean",
|
||||
"ExtremeHillsM_ocean",
|
||||
"JungleEdgeM_deep_ocean",
|
||||
"SunflowerPlains_deep_ocean",
|
||||
"BirchForest_deep_ocean",
|
||||
"IcePlainsSpikes_ocean",
|
||||
"Mesa_ocean",
|
||||
"StoneBeach_ocean",
|
||||
"Plains_deep_ocean",
|
||||
"JungleEdge_deep_ocean",
|
||||
"SavannaM_deep_ocean",
|
||||
"Desert_deep_ocean",
|
||||
"Mesa_deep_ocean",
|
||||
"ColdTaiga_deep_ocean",
|
||||
"Plains_ocean",
|
||||
"MesaPlateauFM_ocean",
|
||||
"Forest_deep_ocean",
|
||||
"JungleM_deep_ocean",
|
||||
"FlowerForest_deep_ocean",
|
||||
"MushroomIsland_ocean",
|
||||
"MegaTaiga_ocean",
|
||||
"StoneBeach_deep_ocean",
|
||||
"IcePlainsSpikes_deep_ocean",
|
||||
"ColdTaiga_ocean",
|
||||
"SavannaM_ocean",
|
||||
"MesaPlateauF_deep_ocean",
|
||||
"MesaBryce_deep_ocean",
|
||||
"ExtremeHills+_deep_ocean",
|
||||
"ExtremeHills_ocean",
|
||||
"MushroomIsland_deep_ocean",
|
||||
"Forest_ocean",
|
||||
"MegaTaiga_deep_ocean",
|
||||
"JungleEdge_ocean",
|
||||
"MesaBryce_ocean",
|
||||
"MegaSpruceTaiga_ocean",
|
||||
"ExtremeHills+_ocean",
|
||||
"Jungle_ocean",
|
||||
"RoofedForest_deep_ocean",
|
||||
"IcePlains_ocean",
|
||||
"FlowerForest_ocean",
|
||||
"ExtremeHills_deep_ocean",
|
||||
"MesaPlateauFM_deep_ocean",
|
||||
"Desert_ocean",
|
||||
"Taiga_ocean",
|
||||
"BirchForestM_deep_ocean",
|
||||
"Taiga_deep_ocean",
|
||||
"JungleM_ocean"
|
||||
}
|
||||
|
||||
vl_structures.register_structure("ocean_temple",{
|
||||
place_on = {"group:sand","mcl_core:gravel"},
|
||||
spawn_by = {"group:water"},
|
||||
num_spawn_by = 4,
|
||||
noise_params = {
|
||||
offset = 0,
|
||||
scale = 0.0000122,
|
||||
spread = {x = 250, y = 250, z = 250},
|
||||
seed = 32345,
|
||||
octaves = 3,
|
||||
persist = 0.001,
|
||||
flags = "absvalue",
|
||||
},
|
||||
flags = "force_placement",
|
||||
force_placement = true,
|
||||
prepare = { tolerance = 8, clear = false, foundation = 3, mode="water" },
|
||||
biomes = ocean_biomes,
|
||||
y_max = water_level-4,
|
||||
y_min = mcl_vars.mg_overworld_min,
|
||||
filenames = {
|
||||
modpath .. "/schematics/mcl_structures_ocean_temple.mts",
|
||||
modpath .. "/schematics/mcl_structures_ocean_temple_2.mts",
|
||||
},
|
||||
y_offset = -1, --function(pr) return pr:next(-2,-1) end, -- fewer mobs if buried in sand
|
||||
after_place = function(p, _, pr, p1, p2)
|
||||
vl_structures.spawn_mobs("mobs_mc:guardian",spawnon,p1,p2,pr,5,true)
|
||||
vl_structures.spawn_mobs("mobs_mc:guardian_elder",spawnon,p1,p2,pr,1,true)
|
||||
vl_structures.construct_nodes(p1,p2,{"group:wall"})
|
||||
end,
|
||||
loot = {
|
||||
["mcl_chests:chest_small"] = {
|
||||
{
|
||||
stacks_min = 3,
|
||||
stacks_max = 10,
|
||||
items = {
|
||||
{ itemstring = "mcl_sus_stew:stew", weight = 10, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_core:paper", weight = 8, amount_min = 1, amount_max = 12 },
|
||||
{ itemstring = "mcl_fishing:fish_raw", weight = 5, amount_min = 8, amount_max = 21 },
|
||||
{ itemstring = "mcl_fishing:salmon_raw", weight = 7, amount_min = 4, amount_max = 8 },
|
||||
{ itemstring = "mcl_tnt:tnt", weight = 1, amount_min = 1, amount_max = 2 },
|
||||
}
|
||||
},
|
||||
{
|
||||
stacks_min = 2,
|
||||
stacks_max = 6,
|
||||
items = {
|
||||
{ itemstring = "mcl_core:iron_ingot", weight = 10, amount_min = 1, amount_max = 5 },
|
||||
{ itemstring = "mcl_core:goldblock", weight = 1, amount_min = 1, amount_max = 2 },
|
||||
{ itemstring = "mcl_experience:bottle", weight = 5, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_core:diamond", weight = 5, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_fishing:fishing_rod", weight = 1, amount_min = 1, amount_max = 1 },
|
||||
}
|
||||
},
|
||||
{
|
||||
stacks_min = 4,
|
||||
stacks_max = 4,
|
||||
items = {
|
||||
--{ itemstring = "FIXME TREASURE MAP", weight = 8, amount_min = 1, amount_max = 5 },
|
||||
{ itemstring = "mcl_books:book", weight = 1, amount_min = 1, amount_max = 5 },
|
||||
{ itemstring = "mcl_clock:clock", weight = 1, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_compass:compass", weight = 1, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_maps:empty_map", weight = 1, amount_min = 1, amount_max = 1 },
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
vl_structures.register_structure_spawn({
|
||||
name = "mobs_mc:guardian",
|
||||
y_min = mcl_vars.mg_overworld_min,
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
chance = 10,
|
||||
interval = 60,
|
||||
limit = 9,
|
||||
spawnon = spawnon,
|
||||
})
|
||||
|
||||
vl_structures.register_structure_spawn({
|
||||
name = "mobs_mc:guardian_elder",
|
||||
y_min = mcl_vars.mg_overworld_min,
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
chance = 100,
|
||||
interval = 60,
|
||||
limit = 4,
|
||||
spawnon = spawnon,
|
||||
})
|
||||
|
|
@ -1,19 +1,14 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local S = minetest.get_translator(modname)
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local peaceful = minetest.settings:get_bool("only_peaceful_mobs", false)
|
||||
|
||||
local spawnon = {"mcl_core:stripped_oak","mcl_stairs:slab_birchwood_top"}
|
||||
|
||||
mcl_structures.register_structure("pillager_outpost",{
|
||||
vl_structures.register_structure("pillager_outpost",{
|
||||
place_on = {"group:grass_block","group:dirt","mcl_core:dirt_with_grass","group:sand"},
|
||||
fill_ratio = 0.01,
|
||||
flags = "place_center_x, place_center_z",
|
||||
solid_ground = true,
|
||||
make_foundation = true,
|
||||
sidelen = 32,
|
||||
prepare = { padding = 3, corners = 4, foundation = -8, clear = true },
|
||||
y_offset = 0,
|
||||
chunk_probability = 600,
|
||||
chunk_probability = 15,
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
y_min = 1,
|
||||
biomes = { "Desert", "Plains", "Savanna", "IcePlains", "Taiga" },
|
||||
|
@ -62,22 +57,15 @@ mcl_structures.register_structure("pillager_outpost",{
|
|||
}
|
||||
}}
|
||||
},
|
||||
after_place = function(p,def,pr)
|
||||
local p1 = vector.offset(p,-9,0,-9)
|
||||
local p2 = vector.offset(p,9,32,9)
|
||||
mcl_structures.spawn_mobs("mobs_mc:pillager",spawnon,p1,p2,pr,5)
|
||||
mcl_structures.spawn_mobs("mobs_mc:parrot",{"mesecons_pressureplates:pressure_plate_stone_off"},p1,p2,pr,3)
|
||||
mcl_structures.spawn_mobs("mobs_mc:iron_golem",{"mesecons_button:button_stone_off"},p1,p2,pr,1)
|
||||
for _,n in pairs(minetest.find_nodes_in_area(p1,p2,{"group:wall"})) do
|
||||
local def = minetest.registered_nodes[minetest.get_node(n).name:gsub("_%d+$","")]
|
||||
if def and def.on_construct then
|
||||
def.on_construct(n)
|
||||
end
|
||||
end
|
||||
after_place = function(p,_,pr) -- fixme: use p1, p2 from the callback?
|
||||
local p1, p2 = vector.offset(p,-9,0,-9), vector.offset(p,9,32,9)
|
||||
vl_structures.spawn_mobs("mobs_mc:pillager",spawnon,p1,p2,pr,5)
|
||||
vl_structures.spawn_mobs("mobs_mc:parrot",{"mesecons_pressureplates:pressure_plate_stone_off"},p1,p2,pr,3)
|
||||
vl_structures.spawn_mobs("mobs_mc:iron_golem",{"mesecons_button:button_stone_off"},p1,p2,pr,1)
|
||||
end
|
||||
})
|
||||
|
||||
mcl_structures.register_structure_spawn({
|
||||
vl_structures.register_structure_spawn({
|
||||
name = "mobs_mc:pillager",
|
||||
y_min = mcl_vars.mg_overworld_min,
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
|
|
|
@ -4,7 +4,7 @@ local modpath = minetest.get_modpath(modname)
|
|||
local function get_replacements(b,c,pr)
|
||||
local r = {}
|
||||
if not b then return r end
|
||||
for k,v in pairs(b) do
|
||||
for _, v in pairs(b) do
|
||||
if pr:next(1,100) < c then table.insert(r,v) end
|
||||
end
|
||||
return r
|
||||
|
@ -12,14 +12,11 @@ end
|
|||
|
||||
local def = {
|
||||
place_on = {"group:grass_block","group:dirt","mcl_core:dirt_with_grass","group:grass_block","group:sand","group:grass_block_snow","mcl_core:snow"},
|
||||
fill_ratio = 0.006,
|
||||
flags = "place_center_x, place_center_z, all_floors",
|
||||
solid_ground = true,
|
||||
make_foundation = true,
|
||||
chunk_probability = 800,
|
||||
prepare = { padding = 0, corners = 3, tolerance = 15, foundation = true, clear = true, clear_top = 0 },
|
||||
chunk_probability = 20,
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
y_min = 1,
|
||||
sidelen = 10,
|
||||
y_offset = -5,
|
||||
filenames = {
|
||||
modpath.."/schematics/mcl_structures_ruined_portal_1.mts",
|
||||
|
@ -27,25 +24,23 @@ local def = {
|
|||
modpath.."/schematics/mcl_structures_ruined_portal_3.mts",
|
||||
modpath.."/schematics/mcl_structures_ruined_portal_4.mts",
|
||||
modpath.."/schematics/mcl_structures_ruined_portal_5.mts",
|
||||
modpath.."/schematics/mcl_structures_ruined_portal_6.mts",
|
||||
modpath.."/schematics/mcl_structures_ruined_portal_99.mts",
|
||||
},
|
||||
after_place = function(pos,def,pr)
|
||||
local hl = def.sidelen / 2
|
||||
local p1 = vector.offset(pos,-hl,-hl,-hl)
|
||||
local p2 = vector.offset(pos,hl,hl,hl)
|
||||
after_place = function(pos,def,pr,p1,p2)
|
||||
local gold = minetest.find_nodes_in_area(p1,p2,{"mcl_core:goldblock"})
|
||||
local lava = minetest.find_nodes_in_area(p1,p2,{"mcl_core:lava_source"})
|
||||
local rack = minetest.find_nodes_in_area(p1,p2,{"mcl_nether:netherrack"})
|
||||
local brick = minetest.find_nodes_in_area(p1,p2,{"mcl_core:stonebrick"})
|
||||
local obby = minetest.find_nodes_in_area(p1,p2,{"mcl_core:obsidian"})
|
||||
minetest.bulk_set_node(get_replacements(gold,30,pr),{name="air"})
|
||||
minetest.bulk_set_node(get_replacements(lava,20,pr),{name="mcl_nether:magma"})
|
||||
minetest.bulk_set_node(get_replacements(rack,7,pr),{name="mcl_nether:magma"})
|
||||
minetest.bulk_set_node(get_replacements(obby,30,pr),{name="mcl_core:crying_obsidian"})
|
||||
minetest.bulk_set_node(get_replacements(obby,10,pr),{name="air"})
|
||||
minetest.bulk_set_node(get_replacements(brick,50,pr),{name="mcl_core:stonebrickcracked"})
|
||||
minetest.bulk_swap_node(get_replacements(gold,30,pr),{name="air"})
|
||||
minetest.bulk_swap_node(get_replacements(lava,20,pr),{name="mcl_nether:magma"})
|
||||
minetest.bulk_swap_node(get_replacements(rack,7,pr),{name="mcl_nether:magma"})
|
||||
minetest.bulk_swap_node(get_replacements(obby,30,pr),{name="mcl_core:crying_obsidian"})
|
||||
minetest.bulk_swap_node(get_replacements(obby,10,pr),{name="air"})
|
||||
minetest.bulk_swap_node(get_replacements(brick,50,pr),{name="mcl_core:stonebrickcracked"})
|
||||
brick = minetest.find_nodes_in_area(p1,p2,{"mcl_core:stonebrick"})
|
||||
minetest.bulk_set_node(get_replacements(brick,50,pr),{name="mcl_core:stonebrickmossy"})
|
||||
minetest.bulk_swap_node(get_replacements(brick,50,pr),{name="mcl_core:stonebrickmossy"})
|
||||
end,
|
||||
loot = {
|
||||
["mcl_chests:chest_small" ] ={{
|
||||
|
@ -102,9 +97,10 @@ local def = {
|
|||
}}
|
||||
}
|
||||
}
|
||||
mcl_structures.register_structure("ruined_portal_overworld",def)
|
||||
vl_structures.register_structure("ruined_portal_overworld",def)
|
||||
|
||||
local ndef = table.copy(def)
|
||||
ndef.y_min=mcl_vars.mg_lava_nether_max +10
|
||||
ndef.y_max=mcl_vars.mg_nether_max - 15
|
||||
ndef.place_on = {"mcl_nether:netherrack","group:soul_block","mcl_blackstone:basalt,mcl_blackstone:blackstone","mcl_crimson:crimson_nylium","mcl_crimson:warped_nylium"},
|
||||
mcl_structures.register_structure("ruined_portal_nether",ndef)
|
||||
vl_structures.register_structure("ruined_portal_nether",ndef)
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,19 +1,6 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
--local S = minetest.get_translator(modname)
|
||||
|
||||
local seed = minetest.get_mapgen_setting("seed")
|
||||
local water_level = minetest.get_mapgen_setting("water_level")
|
||||
local pr = PseudoRandom(seed)
|
||||
|
||||
--schematics by chmodsayshello
|
||||
local schems = {
|
||||
modpath.."/schematics/mcl_structures_shipwreck_full_damaged.mts",
|
||||
modpath.."/schematics/mcl_structures_shipwreck_full_normal.mts",
|
||||
modpath.."/schematics/mcl_structures_shipwreck_full_back_damaged.mts",
|
||||
modpath.."/schematics/mcl_structures_shipwreck_half_front.mts",
|
||||
modpath.."/schematics/mcl_structures_shipwreck_half_back.mts",
|
||||
}
|
||||
|
||||
local ocean_biomes = {
|
||||
"RoofedForest_ocean",
|
||||
|
@ -78,42 +65,27 @@ local ocean_biomes = {
|
|||
"JungleM_ocean"
|
||||
}
|
||||
|
||||
local beach_biomes = {
|
||||
"FlowerForest_beach",
|
||||
"Forest_beach",
|
||||
"StoneBeach",
|
||||
"ColdTaiga_beach_water",
|
||||
"Taiga_beach",
|
||||
"Savanna_beach",
|
||||
"Plains_beach",
|
||||
"ExtremeHills_beach",
|
||||
"ColdTaiga_beach",
|
||||
"Swampland_shore",
|
||||
"MushroomIslandShore",
|
||||
"JungleM_shore",
|
||||
"Jungle_shore"
|
||||
}
|
||||
-- FIXME: integrate treasure maps from MCLA
|
||||
|
||||
mcl_structures.register_structure("shipwreck",{
|
||||
vl_structures.register_structure("shipwreck",{
|
||||
place_on = {"group:sand","mcl_core:gravel"},
|
||||
spawn_by = {"group:water"},
|
||||
num_spawn_by = 4,
|
||||
noise_params = {
|
||||
offset = 0,
|
||||
scale = 0.000022,
|
||||
spread = {x = 250, y = 250, z = 250},
|
||||
seed = 3,
|
||||
octaves = 3,
|
||||
persist = 0.001,
|
||||
flags = "absvalue",
|
||||
},
|
||||
sidelen = 16,
|
||||
flags = "force_placement",
|
||||
chunk_probability = 10, -- todo: 15?
|
||||
biomes = ocean_biomes,
|
||||
y_max = water_level-4,
|
||||
y_min = mcl_vars.mg_overworld_min,
|
||||
filenames = schems,
|
||||
y_max = water_level-4,
|
||||
y_offset = function(pr) return pr:next(-4,-2) end,
|
||||
flags = "place_center_x, place_center_z, force_placement",
|
||||
prepare = { tolerance = -1, clear = false, foundation = -2, mode = "water" },
|
||||
filenames = {
|
||||
--schematics by chmodsayshello
|
||||
modpath.."/schematics/mcl_structures_shipwreck_full_damaged.mts",
|
||||
modpath.."/schematics/mcl_structures_shipwreck_full_normal.mts",
|
||||
modpath.."/schematics/mcl_structures_shipwreck_full_back_damaged.mts",
|
||||
modpath.."/schematics/mcl_structures_shipwreck_half_front.mts",
|
||||
modpath.."/schematics/mcl_structures_shipwreck_half_back.mts",
|
||||
},
|
||||
loot = {
|
||||
["mcl_chests:chest_small"] = {
|
||||
{
|
||||
|
@ -130,13 +102,13 @@ mcl_structures.register_structure("shipwreck",{
|
|||
{ itemstring = "mcl_core:coal_lump", weight = 6, amount_min = 2, amount_max = 8 },
|
||||
{ itemstring = "mcl_mobitems:rotten_flesh", weight = 5, amount_min = 5, amount_max = 24 },
|
||||
{ itemstring = "mcl_farming:potato_item", weight = 3, amount_min = 1, amount_max = 5 },
|
||||
{ itemstring = "mcl_armor:helmet_leather_enchanted", weight = 3, func = function(stack, pr)
|
||||
{ itemstring = "mcl_armor:helmet_leather_enchanted", weight = 3, func = function(stack, _)
|
||||
mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}) end },
|
||||
{ itemstring = "mcl_armor:chestplate_leather_enchanted", weight = 3, func = function(stack, pr)
|
||||
{ itemstring = "mcl_armor:chestplate_leather_enchanted", weight = 3, func = function(stack, _)
|
||||
mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}) end },
|
||||
{ itemstring = "mcl_armor:leggings_leather_enchanted", weight = 3, func = function(stack, pr)
|
||||
{ itemstring = "mcl_armor:leggings_leather_enchanted", weight = 3, func = function(stack, _)
|
||||
mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}) end },
|
||||
{ itemstring = "mcl_armor:boots_leather_enchanted", weight = 3, func = function(stack, pr)
|
||||
{ itemstring = "mcl_armor:boots_leather_enchanted", weight = 3, func = function(stack, _)
|
||||
mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}) end },
|
||||
{ itemstring = "mcl_bamboo:bamboo", weight = 2, amount_min = 1, amount_max = 3 },
|
||||
{ itemstring = "mcl_farming:pumpkin", weight = 2, amount_min = 1, amount_max = 3 },
|
||||
|
@ -174,93 +146,3 @@ mcl_structures.register_structure("shipwreck",{
|
|||
}
|
||||
})
|
||||
|
||||
local spawnon = { "mcl_stairs:slab_prismarine_dark"}
|
||||
|
||||
mcl_structures.register_structure("ocean_temple",{
|
||||
place_on = {"group:sand","mcl_core:gravel"},
|
||||
spawn_by = {"group:water"},
|
||||
num_spawn_by = 4,
|
||||
noise_params = {
|
||||
offset = 0,
|
||||
scale = 0.0000122,
|
||||
spread = {x = 250, y = 250, z = 250},
|
||||
seed = 32345,
|
||||
octaves = 3,
|
||||
persist = 0.001,
|
||||
flags = "absvalue",
|
||||
},
|
||||
sidelen = 32,
|
||||
flags = "force_placement",
|
||||
biomes = ocean_biomes,
|
||||
y_max = water_level-4,
|
||||
y_min = mcl_vars.mg_overworld_min,
|
||||
filenames = {
|
||||
modpath .. "/schematics/mcl_structures_ocean_temple.mts",
|
||||
modpath .. "/schematics/mcl_structures_ocean_temple_2.mts",
|
||||
},
|
||||
y_offset = function(pr) return pr:next(-2,0) end,
|
||||
after_place = function(p,def,pr)
|
||||
local p1 = vector.offset(p,-9,0,-9)
|
||||
local p2 = vector.offset(p,9,32,9)
|
||||
mcl_structures.spawn_mobs("mobs_mc:guardian",spawnon,p1,p2,pr,5,true)
|
||||
mcl_structures.spawn_mobs("mobs_mc:guardian_elder",spawnon,p1,p2,pr,1,true)
|
||||
mcl_structures.construct_nodes(p1,p2,{"group:wall"})
|
||||
end,
|
||||
loot = {
|
||||
["mcl_chests:chest_small"] = {
|
||||
{
|
||||
stacks_min = 3,
|
||||
stacks_max = 10,
|
||||
items = {
|
||||
{ itemstring = "mcl_sus_stew:stew", weight = 10, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_core:paper", weight = 8, amount_min = 1, amount_max = 12 },
|
||||
{ itemstring = "mcl_fishing:fish_raw", weight = 5, amount_min = 8, amount_max = 21 },
|
||||
{ itemstring = "mcl_fishing:salmon_raw", weight = 7, amount_min = 4, amount_max = 8 },
|
||||
{ itemstring = "mcl_tnt:tnt", weight = 1, amount_min = 1, amount_max = 2 },
|
||||
}
|
||||
},
|
||||
{
|
||||
stacks_min = 2,
|
||||
stacks_max = 6,
|
||||
items = {
|
||||
{ itemstring = "mcl_core:iron_ingot", weight = 10, amount_min = 1, amount_max = 5 },
|
||||
{ itemstring = "mcl_core:goldblock", weight = 1, amount_min = 1, amount_max = 2 },
|
||||
{ itemstring = "mcl_experience:bottle", weight = 5, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_core:diamond", weight = 5, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_fishing:fishing_rod", weight = 1, amount_min = 1, amount_max = 1 },
|
||||
}
|
||||
},
|
||||
{
|
||||
stacks_min = 4,
|
||||
stacks_max = 4,
|
||||
items = {
|
||||
--{ itemstring = "FIXME TREASURE MAP", weight = 8, amount_min = 1, amount_max = 5 },
|
||||
{ itemstring = "mcl_books:book", weight = 1, amount_min = 1, amount_max = 5 },
|
||||
{ itemstring = "mcl_clock:clock", weight = 1, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_compass:compass", weight = 1, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_maps:empty_map", weight = 1, amount_min = 1, amount_max = 1 },
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
mcl_structures.register_structure_spawn({
|
||||
name = "mobs_mc:guardian",
|
||||
y_min = mcl_vars.mg_overworld_min,
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
chance = 10,
|
||||
interval = 60,
|
||||
limit = 9,
|
||||
spawnon = spawnon,
|
||||
})
|
||||
|
||||
mcl_structures.register_structure_spawn({
|
||||
name = "mobs_mc:guardian_elder",
|
||||
y_min = mcl_vars.mg_overworld_min,
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
chance = 100,
|
||||
interval = 60,
|
||||
limit = 4,
|
||||
spawnon = spawnon,
|
||||
})
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
|
||||
vl_structures.register_structure("cocoon",{
|
||||
place_on = {"group:material_stone"},
|
||||
flags = "place_center_x, place_center_z, all_floors",
|
||||
chunk_probability = 20,
|
||||
y_max = -10,
|
||||
y_min = mcl_vars.mg_overworld_min,
|
||||
y_offset = 2,
|
||||
spawn_by = "air",
|
||||
check_offset = 1,
|
||||
num_spawn_by = 6,
|
||||
force_placement = false,
|
||||
prepare = { foundation = false, clear = false, clear_top = 0, padding = -1, corners = 1 }, -- TODO: make clear/foundation not use grass
|
||||
filenames = {
|
||||
modpath.."/schematics/cocoon_1.mts"
|
||||
},
|
||||
after_place = function(p,def,pr,p1,p2)
|
||||
if mcl_mobspawners then
|
||||
local spawner = minetest.find_nodes_in_area(p1,p2,{"mcl_mobspawners:spawner"})
|
||||
if #spawner > 0 then
|
||||
mcl_mobspawners.setup_spawner(spawner[1], "mobs_mc:cave_spider", 0, 7, 4, 15, -3)
|
||||
end
|
||||
end
|
||||
-- p2.y is the top slice only, not a typo, we look for the rope
|
||||
local cs = minetest.find_nodes_in_area(vector.new(p1.x,p2.y,p1.z), p2, "mcl_wool:white")
|
||||
local rope = {}
|
||||
-- TODO: port to VoxelManip?
|
||||
for _,c in pairs(cs) do
|
||||
while true do
|
||||
c = vector.offset(c,0,1,0)
|
||||
local name = minetest.get_node(c).name
|
||||
if name == "ignore" then break end
|
||||
if name ~= "air" then break end
|
||||
table.insert(rope,c)
|
||||
end
|
||||
end
|
||||
minetest.bulk_swap_node(rope, {name = "mcl_wool:white", param2 = 2})
|
||||
-- remove some of the spiderwebs to add variation
|
||||
local ws = minetest.find_nodes_in_area(p1, p2, "mcl_core:cobweb")
|
||||
local clear = {}
|
||||
for i = 1,math.floor(#ws/4) do
|
||||
if #ws == 0 then break end
|
||||
local idx = pr:next(1,#ws)
|
||||
table.insert(clear, ws[idx])
|
||||
table.remove(ws, idx)
|
||||
end
|
||||
minetest.bulk_swap_node(clear, {name = "air"})
|
||||
end,
|
||||
loot = {
|
||||
["mcl_chests:chest_small"] = {
|
||||
{
|
||||
stacks_min = 2,
|
||||
stacks_max = 4,
|
||||
items = {
|
||||
{ itemstring = "mcl_mobitems:bone", weight = 10, amount_min = 2, amount_max = 4 },
|
||||
{ itemstring = "mcl_farming:potato_item_poison", weight = 7, amount_min = 2, amount_max = 6 },
|
||||
{ itemstring = "mcl_mobitems:rotten_flesh", weight = 5, amount_min = 5, amount_max = 24 },
|
||||
{ itemstring = "mcl_farming:potato_item", weight = 3, amount_min = 1, amount_max = 5 },
|
||||
{ itemstring = "mcl_tnt:tnt", weight = 1, amount_min = 1, amount_max = 2 },
|
||||
}
|
||||
},
|
||||
{
|
||||
stacks_min = 2,
|
||||
stacks_max = 4,
|
||||
items = {
|
||||
{ itemstring = "mcl_core:iron_ingot", weight = 90, amount_min = 1, amount_max = 2 },
|
||||
{ itemstring = "mcl_core:iron_nugget", weight = 50, amount_min = 1, amount_max = 10 },
|
||||
{ itemstring = "mcl_core:emerald", weight = 40, amount_min = 1, amount_max = 5 },
|
||||
{ itemstring = "mcl_core:lapis", weight = 20, amount_min = 1, amount_max = 10 },
|
||||
{ itemstring = "mcl_core:gold_ingot", weight = 10, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_core:gold_nugget", weight = 10, amount_min = 1, amount_max = 4 },
|
||||
{ itemstring = "mcl_experience:bottle", weight = 5, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_core:diamond", weight = 5, amount_min = 1, amount_max = 1 },
|
||||
}
|
||||
},{
|
||||
stacks_min = 1,
|
||||
stacks_max = 1,
|
||||
items = {
|
||||
--{ itemstring = "FIXME TREASURE MAP", weight = 8, amount_min = 1, amount_max = 5 },
|
||||
{ itemstring = "mcl_core:paper", weight = 20, amount_min = 1, amount_max = 10 },
|
||||
{ itemstring = "mcl_mobitems:bone", weight = 10, amount_min = 2, amount_max = 4 },
|
||||
{ itemstring = "mcl_mobitems:rotten_flesh", weight = 5, amount_min = 3, amount_max = 8 },
|
||||
{ itemstring = "mcl_books:book", weight = 5, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_clock:clock", weight = 1, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_compass:compass", weight = 1, amount_min = 1, amount_max = 1 },
|
||||
{ itemstring = "mcl_maps:empty_map", weight = 1, amount_min = 1, amount_max = 1 },
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
})
|
||||
|
|
@ -14,39 +14,46 @@ local function spawn_witch(p1,p2)
|
|||
witch._home = c
|
||||
witch.can_despawn = false
|
||||
end
|
||||
local cat = minetest.add_entity(vector.offset(nn[math.random(#nn)],0,1,0),"mobs_mc:cat"):get_luaentity()
|
||||
local catobject = minetest.add_entity(vector.offset(nn[math.random(#nn)],0,1,0),"mobs_mc:cat")
|
||||
if catobject and catobject:get_pos() then
|
||||
local cat=catobject:get_luaentity()
|
||||
cat.object:set_properties({textures = {"mobs_mc_cat_black.png"}})
|
||||
cat.owner = "!witch!" --so it's not claimable by player
|
||||
cat._home = c
|
||||
cat.can_despawn = false
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local function hut_placement_callback(pos,def,pr)
|
||||
local hl = def.sidelen / 2
|
||||
local p1 = vector.offset(pos,-hl,-hl,-hl)
|
||||
local p2 = vector.offset(pos,hl,hl,hl)
|
||||
local legs = minetest.find_nodes_in_area(vector.offset(pos,-hl,0,-hl),vector.offset(pos,hl,0,hl), "mcl_core:tree")
|
||||
local function hut_placement_callback(pos,def,pr,p1,p2)
|
||||
-- p1.y is the bottom slice only, not a typo, we look for the hut legs
|
||||
local legs = minetest.find_nodes_in_area(p1,vector.new(p2.x,p1.y,p2.z), "mcl_core:tree")
|
||||
local tree = {}
|
||||
-- TODO: port leg generation to VoxelManip?
|
||||
for _,leg in pairs(legs) do
|
||||
while minetest.get_item_group(mcl_vars.get_node(vector.offset(leg,0,-1,0), true, 333333).name, "water") ~= 0 do
|
||||
while true do
|
||||
local name = minetest.get_node(vector.offset(leg,0,-1,0)).name
|
||||
if name == "ignore" then break end
|
||||
if name ~= "air" and minetest.get_item_group(name, "water") == 0 then break end
|
||||
leg = vector.offset(leg,0,-1,0)
|
||||
table.insert(tree,leg)
|
||||
end
|
||||
end
|
||||
minetest.bulk_set_node(tree, {name = "mcl_core:tree", param2 = 2})
|
||||
minetest.bulk_swap_node(tree, {name = "mcl_core:tree", param2 = 2})
|
||||
spawn_witch(p1,p2)
|
||||
end
|
||||
|
||||
mcl_structures.register_structure("witch_hut",{
|
||||
place_on = {"mcl_core:water_source","mclx_core:river_water_source"},
|
||||
fill_ratio = 0.01,
|
||||
flags = "place_center_x, place_center_z, liquid_surface, force_placement",
|
||||
sidelen = 8,
|
||||
chunk_probability = 300,
|
||||
vl_structures.register_structure("witch_hut",{
|
||||
place_on = {"mcl_core:water_source","group:sand","group:grass_block","group:dirt","mclx_core:river_water_source"},
|
||||
spawn_by = {"mcl_core:water_source","mclx_core:river_water_source"},
|
||||
check_offset = -1,
|
||||
num_spawn_by = 3,
|
||||
flags = "place_center_x, place_center_z, all_surfaces",
|
||||
chunk_probability = 8,
|
||||
prepare = { mode="under_air", tolerance=4, clear_bottom=3, padding=0, corners=1, foundation=false },
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
y_min = -4,
|
||||
y_min = -5,
|
||||
y_offset = 0,
|
||||
biomes = { "Swampland", "Swampland_ocean", "Swampland_shore" },
|
||||
filenames = { modpath.."/schematics/mcl_structures_witch_hut.mts" },
|
||||
|
|
|
@ -1,32 +1,26 @@
|
|||
local modname = minetest.get_current_modname()
|
||||
local S = minetest.get_translator(modname)
|
||||
local modpath = minetest.get_modpath(modname)
|
||||
local peaceful = minetest.settings:get_bool("only_peaceful_mobs", false)
|
||||
|
||||
local spawnon = {"mcl_deepslate:deepslate","mcl_core:birchwood","mcl_wool:red_carpet","mcl_wool:brown_carpet"}
|
||||
|
||||
mcl_structures.register_structure("woodland_cabin",{
|
||||
vl_structures.register_structure("woodland_cabin",{
|
||||
place_on = {"group:grass_block","group:dirt","mcl_core:dirt_with_grass"},
|
||||
fill_ratio = 0.01,
|
||||
flags = "place_center_x, place_center_z",
|
||||
solid_ground = true,
|
||||
make_foundation = true,
|
||||
chunk_probability = 800,
|
||||
prepare = { padding = 2, corners = 5, foundation = true, clear = true, clear_top = 2 },
|
||||
force_placement = false,
|
||||
chunk_probability = 20,
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
y_min = 1,
|
||||
biomes = { "RoofedForest" },
|
||||
sidelen = 32,
|
||||
filenames = {
|
||||
modpath.."/schematics/mcl_structures_woodland_cabin.mts",
|
||||
modpath.."/schematics/mcl_structures_woodland_outpost.mts",
|
||||
},
|
||||
construct_nodes = {"mcl_barrels:barrel_closed","mcl_books:bookshelf"},
|
||||
after_place = function(p,def,pr)
|
||||
local p1=vector.offset(p,-def.sidelen,-1,-def.sidelen)
|
||||
local p2=vector.offset(p,def.sidelen,def.sidelen,def.sidelen)
|
||||
mcl_structures.spawn_mobs("mobs_mc:vindicator",spawnon,p1,p2,pr,5)
|
||||
mcl_structures.spawn_mobs("mobs_mc:evoker",spawnon,p1,p2,pr,1)
|
||||
mcl_structures.spawn_mobs("mobs_mc:parrot",{"mcl_heads:wither_skeleton"},p1,p2,pr,1)
|
||||
after_place = function(p,def,pr,p1,p2)
|
||||
vl_structures.spawn_mobs("mobs_mc:vindicator",spawnon,p1,p2,pr,5)
|
||||
vl_structures.spawn_mobs("mobs_mc:evoker",spawnon,p1,p2,pr,1)
|
||||
vl_structures.spawn_mobs("mobs_mc:parrot",{"mcl_heads:wither_skeleton"},p1,p2,pr,1)
|
||||
end,
|
||||
loot = {
|
||||
["mcl_chests:chest_small" ] ={{
|
||||
|
@ -69,7 +63,7 @@ mcl_structures.register_structure("woodland_cabin",{
|
|||
}
|
||||
})
|
||||
|
||||
mcl_structures.register_structure_spawn({
|
||||
vl_structures.register_structure_spawn({
|
||||
name = "mobs_mc:vindicator",
|
||||
y_min = mcl_vars.mg_overworld_min,
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
|
@ -79,7 +73,7 @@ mcl_structures.register_structure_spawn({
|
|||
spawnon = spawnon,
|
||||
})
|
||||
|
||||
mcl_structures.register_structure_spawn({
|
||||
vl_structures.register_structure_spawn({
|
||||
name = "mobs_mc:evoker",
|
||||
y_min = mcl_vars.mg_overworld_min,
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
|
|
|
@ -10,19 +10,6 @@ local adjacents = {
|
|||
vector.new(0,-1,0)
|
||||
}
|
||||
|
||||
local plane_adjacents = {
|
||||
vector.new(1,0,0),
|
||||
vector.new(-1,0,0),
|
||||
vector.new(0,0,1),
|
||||
vector.new(0,0,-1),
|
||||
}
|
||||
|
||||
local function set_node_no_bedrock(pos,node)
|
||||
local n = minetest.get_node(pos)
|
||||
if n.name == "mcl_core:bedrock" then return end
|
||||
return minetest.set_node(pos,node)
|
||||
end
|
||||
|
||||
local function airtower(pos,tbl,h)
|
||||
for i=1,h do
|
||||
table.insert(tbl,vector.offset(pos,0,i,0))
|
||||
|
@ -32,7 +19,7 @@ end
|
|||
local function makelake(pos,size,liquid,placein,border,pr,noair)
|
||||
local p1, p2 = vector.offset(pos,-size,-1,-size), vector.offset(pos,size,-1,size)
|
||||
local e1, e2 = vector.offset(pos,-size,-2,-size), vector.offset(pos,size,15,size)
|
||||
minetest.emerge_area(e1, e2, function(blockpos, action, calls_remaining, param)
|
||||
minetest.emerge_area(e1, e2, function(_, _, calls_remaining)
|
||||
if calls_remaining ~= 0 then return end
|
||||
local nn = minetest.find_nodes_in_area(p1,p2,placein)
|
||||
if not nn[1] then return end
|
||||
|
@ -46,8 +33,8 @@ local function makelake(pos,size,liquid,placein,border,pr,noair)
|
|||
airtower(nn[i],air,20)
|
||||
table.insert(lq,nn[i])
|
||||
end
|
||||
minetest.bulk_set_node(lq,{name=liquid})
|
||||
minetest.bulk_set_node(air,{name="air"})
|
||||
minetest.bulk_swap_node(lq,{name=liquid})
|
||||
minetest.bulk_swap_node(air,{name="air"})
|
||||
air = {}
|
||||
local br = {}
|
||||
for k,v in pairs(lq) do
|
||||
|
@ -74,8 +61,8 @@ local function makelake(pos,size,liquid,placein,border,pr,noair)
|
|||
end
|
||||
end
|
||||
end
|
||||
minetest.bulk_set_node(br,{name=border})
|
||||
minetest.bulk_set_node(air,{name="air"})
|
||||
minetest.bulk_swap_node(br,{name=border})
|
||||
minetest.bulk_swap_node(air,{name="air"})
|
||||
return true
|
||||
end)
|
||||
return true
|
||||
|
@ -83,57 +70,83 @@ end
|
|||
|
||||
local mushrooms = {"mcl_mushrooms:mushroom_brown","mcl_mushrooms:mushroom_red"}
|
||||
|
||||
local function get_fallen_tree_schematic(pos,pr)
|
||||
local function place_fallen_tree(pos,def,pr)
|
||||
local tree = minetest.find_node_near(pos,15,{"group:tree"})
|
||||
if not tree then return end
|
||||
tree = minetest.get_node(tree).name
|
||||
local maxlen = 8
|
||||
local minlen = 2
|
||||
local vprob = 120
|
||||
local mprob = 160
|
||||
local minlen, maxlen = 3, 9
|
||||
local vrate, mrate = 120, 160
|
||||
local len = pr:next(minlen,maxlen)
|
||||
local schem = {
|
||||
size = {x = len + 2, y = 2, z = 3},
|
||||
data = {
|
||||
{name = "air", prob=0},
|
||||
{name = "air", prob=0},
|
||||
}
|
||||
}
|
||||
for i = 1,len do
|
||||
table.insert(schem.data,{name = "mcl_core:vine",param2=4, prob=vprob})
|
||||
local dir = pr:next(0,3)
|
||||
local dx, dy, dz, param2, w1, w2
|
||||
if dir == 0 then
|
||||
dx, dy, dz, param2, w1, w2 = 1, 0, 0, 12, 5, 4
|
||||
elseif dir == 1 then
|
||||
dx, dy, dz, param2, w1, w2 = -1, 0, 0, 12, 4, 5
|
||||
elseif dir == 2 then
|
||||
dx, dy, dz, param2, w1, w2 = 0, 0, 1, 6, 3, 2
|
||||
else -- if dir == 3 then
|
||||
dx, dy, dz, param2, w1, w2 = 0, 0, -1, 6, 2, 3
|
||||
end
|
||||
table.insert(schem.data,{name = "air", prob=0})
|
||||
table.insert(schem.data,{name = "air", prob=0})
|
||||
-- TODO: port this to voxel manipulators
|
||||
-- ensure we have room for the tree
|
||||
local minsupport, maxsupport = 99, 1
|
||||
for i = 1,len do
|
||||
table.insert(schem.data,{name = "air", prob=0})
|
||||
-- check below
|
||||
local n = minetest.get_node(vector.offset(pos, dx * i, -1, dz * i)).name
|
||||
local nd = minetest.registered_nodes[n]
|
||||
if n ~= "air" and nd.groups and nd.groups.solid and i > 2 then
|
||||
if i < minsupport then minsupport = i end
|
||||
maxsupport = i
|
||||
end
|
||||
|
||||
table.insert(schem.data,{name = tree, param2 = 0})
|
||||
table.insert(schem.data,{name = "air", prob=0})
|
||||
for i = 1,len do
|
||||
table.insert(schem.data,{name = tree, param2 = 12})
|
||||
-- check space
|
||||
local n = minetest.get_node(vector.offset(pos, dx * i, 0, dz * i)).name
|
||||
local nd = minetest.registered_nodes[n]
|
||||
if n ~= "air" and nd.groups and not nd.groups.plant then
|
||||
if i < minlen or pr:next(1,maxsupport) == 1 then return end
|
||||
len = i
|
||||
break
|
||||
end
|
||||
table.insert(schem.data,{name = "air", prob=0})
|
||||
table.insert(schem.data,{name = "air", prob=0})
|
||||
for i = 1,len do
|
||||
table.insert(schem.data,{name = mushrooms[pr:next(1,#mushrooms)], param2 = 12, prob=mprob})
|
||||
end
|
||||
|
||||
table.insert(schem.data,{name = "air", prob=0})
|
||||
table.insert(schem.data,{name = "air", prob=0})
|
||||
for i = 1,len do
|
||||
table.insert(schem.data,{name = "mcl_core:vine",param2=5, prob=vprob})
|
||||
if maxsupport - minsupport < minlen then return end
|
||||
len = math.min(len, maxsupport - 1)
|
||||
if len < minlen then return end
|
||||
-- place the tree
|
||||
minetest.swap_node(pos, {name = tree, param2 = 0})
|
||||
-- some are hollow:
|
||||
if vl_hollow_logs.logs and pr:next(1,20) == 1 then
|
||||
local nam = string.sub(tree, string.find(tree, ":") + 1)
|
||||
nam = "vl_hollow_logs:"..nam.."_hollow"
|
||||
if minetest.registered_nodes[nam] then tree = nam end
|
||||
end
|
||||
for i = 2,len do
|
||||
minetest.swap_node(vector.offset(pos, dx * i, 0, dz * i), {name = tree, param2 = param2})
|
||||
if pr:next(0,255) < vrate then
|
||||
local side = vector.offset(pos, dx * i + dz, 0, dz * i + dx)
|
||||
local n = minetest.get_node(side).name
|
||||
if n == "air" then
|
||||
minetest.swap_node(side, {name="mcl_core:vine", param2=w1})
|
||||
end
|
||||
end
|
||||
if pr:next(0,255) < vrate then
|
||||
local side = vector.offset(pos, dx * i - dz, 0, dz * i - dx)
|
||||
local n = minetest.get_node(side).name
|
||||
if n == "air" then
|
||||
minetest.swap_node(side, {name="mcl_core:vine", param2=w2})
|
||||
end
|
||||
end
|
||||
if pr:next(0,255) < mrate then
|
||||
local top = vector.offset(pos, dx * i, 1, dz * i)
|
||||
local n = minetest.get_node(top).name
|
||||
if n == "air" then
|
||||
minetest.swap_node(top, {name = mushrooms[pr:next(1,#mushrooms)], param2 = 12})
|
||||
end
|
||||
end
|
||||
table.insert(schem.data,{name = "air", prob=0})
|
||||
table.insert(schem.data,{name = "air", prob=0})
|
||||
for i = 1,len do
|
||||
table.insert(schem.data,{name = "air", prob=0})
|
||||
end
|
||||
|
||||
return schem
|
||||
end
|
||||
|
||||
mcl_structures.register_structure("fallen_tree",{
|
||||
vl_structures.register_structure("fallen_tree",{
|
||||
priority = 1100, -- after regular trees
|
||||
place_on = {"group:grass_block"},
|
||||
terrain_feature = true,
|
||||
noise_params = {
|
||||
|
@ -145,27 +158,13 @@ mcl_structures.register_structure("fallen_tree",{
|
|||
persist = 0.66
|
||||
},
|
||||
flags = "place_center_x, place_center_z",
|
||||
sidelen = 18,
|
||||
solid_ground = true,
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
y_min = minetest.get_mapgen_setting("water_level"),
|
||||
on_place = function(pos,def,pr)
|
||||
local air_p1 = vector.offset(pos,-def.sidelen/2,1,-def.sidelen/2)
|
||||
local air_p2 = vector.offset(pos,def.sidelen/2,1,def.sidelen/2)
|
||||
local air = minetest.find_nodes_in_area(air_p1,air_p2,{"air"})
|
||||
if #air < ( def.sidelen * def.sidelen ) / 2 then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end,
|
||||
place_func = function(pos,def,pr)
|
||||
local schem=get_fallen_tree_schematic(pos,pr)
|
||||
if not schem then return end
|
||||
return minetest.place_schematic(pos,schem,"random")
|
||||
end
|
||||
place_func = place_fallen_tree
|
||||
})
|
||||
|
||||
mcl_structures.register_structure("lavapool",{
|
||||
vl_structures.register_structure("lavapool",{
|
||||
place_on = {"group:sand", "group:dirt", "group:stone"},
|
||||
terrain_feature = true,
|
||||
noise_params = {
|
||||
|
@ -180,12 +179,12 @@ mcl_structures.register_structure("lavapool",{
|
|||
flags = "place_center_x, place_center_z, all_floors",
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
y_min = minetest.get_mapgen_setting("water_level"),
|
||||
place_func = function(pos,def,pr)
|
||||
place_func = function(pos, _, pr)
|
||||
return makelake(pos,5,"mcl_core:lava_source",{"group:material_stone", "group:sand", "group:dirt"},"mcl_core:stone",pr)
|
||||
end
|
||||
})
|
||||
|
||||
mcl_structures.register_structure("water_lake",{
|
||||
vl_structures.register_structure("water_lake",{
|
||||
place_on = {"group:dirt","group:stone"},
|
||||
terrain_feature = true,
|
||||
noise_params = {
|
||||
|
@ -200,12 +199,12 @@ mcl_structures.register_structure("water_lake",{
|
|||
flags = "place_center_x, place_center_z, all_floors",
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
y_min = minetest.get_mapgen_setting("water_level"),
|
||||
place_func = function(pos,def,pr)
|
||||
place_func = function(pos, _, pr)
|
||||
return makelake(pos,5,"mcl_core:water_source",{"group:material_stone", "group:sand", "group:dirt","group:grass_block"},"mcl_core:dirt_with_grass",pr)
|
||||
end
|
||||
})
|
||||
|
||||
mcl_structures.register_structure("water_lake_mangrove_swamp",{
|
||||
vl_structures.register_structure("water_lake_mangrove_swamp",{
|
||||
place_on = {"mcl_mud:mud"},
|
||||
biomes = { "MangroveSwamp" },
|
||||
terrain_feature = true,
|
||||
|
@ -221,12 +220,12 @@ mcl_structures.register_structure("water_lake_mangrove_swamp",{
|
|||
flags = "place_center_x, place_center_z, all_floors",
|
||||
y_max = mcl_vars.mg_overworld_max,
|
||||
y_min = minetest.get_mapgen_setting("water_level"),
|
||||
place_func = function(pos,def,pr)
|
||||
place_func = function(pos, _, pr)
|
||||
return makelake(pos,3,"mcl_core:water_source",{"group:material_stone", "group:sand", "group:dirt","group:grass_block","mcl_mud:mud"},"mcl_mud:mud",pr,true)
|
||||
end
|
||||
})
|
||||
|
||||
mcl_structures.register_structure("basalt_column",{
|
||||
vl_structures.register_structure("basalt_column",{
|
||||
place_on = {"mcl_blackstone:blackstone","mcl_blackstone:basalt"},
|
||||
terrain_feature = true,
|
||||
spawn_by = {"air"},
|
||||
|
@ -244,7 +243,7 @@ mcl_structures.register_structure("basalt_column",{
|
|||
y_max = mcl_vars.mg_nether_max - 20,
|
||||
y_min = mcl_vars.mg_lava_nether_max + 1,
|
||||
biomes = { "BasaltDelta" },
|
||||
place_func = function(pos,def,pr)
|
||||
place_func = function(pos, _, pr)
|
||||
local nn = minetest.find_nodes_in_area(vector.offset(pos,-5,-1,-5),vector.offset(pos,5,-1,5),{"air","mcl_blackstone:basalt","mcl_blackstone:blackstone"})
|
||||
table.sort(nn,function(a, b)
|
||||
return vector.distance(vector.new(pos.x,0,pos.z), a) < vector.distance(vector.new(pos.x,0,pos.z), b)
|
||||
|
@ -265,12 +264,12 @@ mcl_structures.register_structure("basalt_column",{
|
|||
end
|
||||
end
|
||||
end
|
||||
minetest.bulk_set_node(magma,{name="mcl_nether:magma"})
|
||||
minetest.bulk_set_node(basalt,{name="mcl_blackstone:basalt"})
|
||||
minetest.bulk_swap_node(magma,{name="mcl_nether:magma"})
|
||||
minetest.bulk_swap_node(basalt,{name="mcl_blackstone:basalt"})
|
||||
return true
|
||||
end
|
||||
})
|
||||
mcl_structures.register_structure("basalt_pillar",{
|
||||
vl_structures.register_structure("basalt_pillar",{
|
||||
place_on = {"mcl_blackstone:blackstone","mcl_blackstone:basalt"},
|
||||
terrain_feature = true,
|
||||
noise_params = {
|
||||
|
@ -286,7 +285,7 @@ mcl_structures.register_structure("basalt_pillar",{
|
|||
y_max = mcl_vars.mg_nether_max-40,
|
||||
y_min = mcl_vars.mg_lava_nether_max + 1,
|
||||
biomes = { "BasaltDelta" },
|
||||
place_func = function(pos,def,pr)
|
||||
place_func = function(pos, _, pr)
|
||||
local nn = minetest.find_nodes_in_area(vector.offset(pos,-2,-1,-2),vector.offset(pos,2,-1,2),{"air","mcl_blackstone:basalt","mcl_blackstone:blackstone"})
|
||||
table.sort(nn,function(a, b)
|
||||
return vector.distance(vector.new(pos.x,0,pos.z), a) < vector.distance(vector.new(pos.x,0,pos.z), b)
|
||||
|
@ -306,13 +305,13 @@ mcl_structures.register_structure("basalt_pillar",{
|
|||
end
|
||||
end
|
||||
end
|
||||
minetest.bulk_set_node(basalt,{name="mcl_blackstone:basalt"})
|
||||
minetest.bulk_set_node(magma,{name="mcl_nether:magma"})
|
||||
minetest.bulk_swap_node(basalt,{name="mcl_blackstone:basalt"})
|
||||
minetest.bulk_swap_node(magma,{name="mcl_nether:magma"})
|
||||
return true
|
||||
end
|
||||
})
|
||||
|
||||
mcl_structures.register_structure("lavadelta",{
|
||||
vl_structures.register_structure("lavadelta",{
|
||||
place_on = {"mcl_blackstone:blackstone","mcl_blackstone:basalt"},
|
||||
spawn_by = {"mcl_blackstone:basalt","mcl_blackstone:blackstone"},
|
||||
num_spawn_by = 2,
|
||||
|
@ -330,7 +329,7 @@ mcl_structures.register_structure("lavadelta",{
|
|||
y_max = mcl_vars.mg_nether_max,
|
||||
y_min = mcl_vars.mg_lava_nether_max + 1,
|
||||
biomes = { "BasaltDelta" },
|
||||
place_func = function(pos,def,pr)
|
||||
place_func = function(pos, _, pr)
|
||||
local nn = minetest.find_nodes_in_area_under_air(vector.offset(pos,-10,-1,-10),vector.offset(pos,10,-2,10),{"mcl_blackstone:basalt","mcl_blackstone:blackstone","mcl_nether:netherrack"})
|
||||
table.sort(nn,function(a, b)
|
||||
return vector.distance(vector.new(pos.x,0,pos.z), a) < vector.distance(vector.new(pos.x,0,pos.z), b)
|
||||
|
@ -340,7 +339,7 @@ mcl_structures.register_structure("lavadelta",{
|
|||
for i=1,pr:next(1,#nn) do
|
||||
table.insert(lava,nn[i])
|
||||
end
|
||||
minetest.bulk_set_node(lava,{name="mcl_nether:nether_lava_source"})
|
||||
minetest.bulk_swap_node(lava,{name="mcl_nether:nether_lava_source"})
|
||||
local basalt = {}
|
||||
local magma = {}
|
||||
for _,v in pairs(lava) do
|
||||
|
@ -355,8 +354,8 @@ mcl_structures.register_structure("lavadelta",{
|
|||
table.insert(magma,v)
|
||||
end
|
||||
end
|
||||
minetest.bulk_set_node(basalt,{name="mcl_blackstone:basalt"})
|
||||
minetest.bulk_set_node(magma,{name="mcl_nether:magma"})
|
||||
minetest.bulk_swap_node(basalt,{name="mcl_blackstone:basalt"})
|
||||
minetest.bulk_swap_node(magma,{name="mcl_nether:magma"})
|
||||
return true
|
||||
end
|
||||
})
|
||||
|
|
|
@ -0,0 +1,301 @@
|
|||
# mcl_villages
|
||||
|
||||
When creating buildings or farms for use with this mod, you can prevent paths
|
||||
from crossing areas by using the `mcl_villages:no_paths` block. You may need to
|
||||
stack them 2 high to prevent all paths. After the village paths have be laid
|
||||
this block will be replaced by air.
|
||||
|
||||
## Building Interfaces
|
||||
|
||||
### Parameter
|
||||
|
||||
All of the following functions take a table with the following keys.
|
||||
|
||||
#### Mandatory
|
||||
|
||||
name
|
||||
|
||||
: The name to use for the object.
|
||||
|
||||
mts
|
||||
|
||||
: The path to the mts format schema file.
|
||||
|
||||
#### Optional
|
||||
|
||||
yadjust
|
||||
|
||||
: Y axis adjustment when placing the schema. This can be positive to raise the
|
||||
placement, or negative to lower it.
|
||||
|
||||
If your schema does not contain a ground layer then set this to 1.
|
||||
|
||||
no_ground_turnip
|
||||
|
||||
: If you don't want the foundation under the building modified, you can disable
|
||||
the ground turnip by setting this to true.
|
||||
|
||||
Mainly useful for small thing such as lamps, planters, etc.
|
||||
|
||||
no_clearance
|
||||
|
||||
: If you don't want the area around and above the building modified, you can
|
||||
disable the overground clearance by setting this to true.
|
||||
|
||||
Mainly useful for small thing such as lamps, planters, etc.
|
||||
|
||||
### mcl_villages.register_lamp(table)
|
||||
|
||||
Register a structure to use as a lamp. These will be added to the table used when
|
||||
adding lamps to paths during village creation.
|
||||
|
||||
### mcl_villages.register_bell(table)
|
||||
|
||||
Register a structure to use as a bell. These will be added to the table used when
|
||||
adding the bell during village creation.
|
||||
|
||||
There is 1 bell per village.
|
||||
|
||||
### mcl_villages.register_well(table)
|
||||
|
||||
Register a structure to use as a well. These will be added to the table used when
|
||||
adding the wells during village creation.
|
||||
|
||||
The number of wells is calculated randomly based on the number of beds in the
|
||||
village. Every 10 beds add 1 to the maximum number.
|
||||
|
||||
e.g. 8 beds == 1 well, 15 beds == 1 or 2 wells, 22 beds == 1 to 3 wells, etc.
|
||||
|
||||
### mcl_villages.register_building(table)
|
||||
|
||||
Register a building used for jobs, houses, or other uses.
|
||||
|
||||
The schema is parsed to work out how many jobs and beds are in it.
|
||||
|
||||
If you are adding a job site for a custom profession then ensure you call
|
||||
```mobs_mc.register_villager_profession``` before you register a building using it.
|
||||
|
||||
If a building doesn't have any job sites or beds then it may get added during
|
||||
the house placement phase. This will simply add another building to
|
||||
the village and will not affect the number of jobs or beds.
|
||||
|
||||
#### Additional options
|
||||
|
||||
The ```mcl_villages.register_building``` call accepts the following optional
|
||||
parameters in the table.
|
||||
|
||||
min_jobs
|
||||
|
||||
: A village will need at least this many jobs to have one of these buildings.
|
||||
|
||||
This is used to restrict buildings to bigger villages.
|
||||
|
||||
max_jobs
|
||||
|
||||
: A village will need less that or equal to (<=) this many jobs to have one of
|
||||
these buildings.
|
||||
|
||||
This is used to restrict buildings to smaller villages.
|
||||
|
||||
num_others
|
||||
|
||||
: A village will need this many other job sites before you can have another of
|
||||
these jobs sites.
|
||||
|
||||
This is used to influence the ratio of buildings in a village.
|
||||
|
||||
is_mandatory
|
||||
|
||||
: This ensures that each village will have at least one of these buildings.
|
||||
|
||||
### mobs_mc.register_villager_profession(title, table)
|
||||
|
||||
**TODO** this should be somewhere else.
|
||||
|
||||
This API call allows you to register professions for villagers.
|
||||
|
||||
It takes 2 arguments.
|
||||
|
||||
1. title - The title to use for the profession.
|
||||
|
||||
This mus be unique; the profession will be rejected if this title is already
|
||||
used.
|
||||
|
||||
1. Record - a table containing the details of the profession, it contains the
|
||||
following fields.
|
||||
|
||||
1. name: The name displayed for the profession in the UI.
|
||||
1. texture: The texture to use for the profession
|
||||
1. jobsite: the node or group name sued to flag blocks as job sites for this
|
||||
profession
|
||||
1. trades: a table containing trades with 1 entry for each trade level.
|
||||
|
||||
You can access the current profession and job site data in
|
||||
```mobs_mc.professions``` and ```mobs_mc.jobsites```.
|
||||
|
||||
### mcl_villages.register_on_village_placed(func)
|
||||
|
||||
This function allows registering functions to be called after a village is
|
||||
laid out.
|
||||
|
||||
Note that the village may not be completed as the building post processing is
|
||||
non-deterministic to avoid overloading the server.
|
||||
|
||||
`settlement_info` is a table containing data for all the buildings in the
|
||||
village. The bell is always the first entry in the table.
|
||||
|
||||
`blockseed` is the block seed for the chunk the village was generated for.
|
||||
Villages can extend outside of this chunk.
|
||||
|
||||
```lua
|
||||
local function my_village_hook(settlement_info, blockseed)
|
||||
minetest.log("The village has " .. #settlement_info .. " buildings in it!")
|
||||
end
|
||||
|
||||
mcl_villages.register_on_village_placed(my_village_hook)
|
||||
```
|
||||
|
||||
### mcl_villages.register_on_villager_spawned(func)
|
||||
|
||||
This function allows registering functions to be called after a villager is
|
||||
placed as part of village generation.
|
||||
|
||||
`villager_ent` is the entity created by `minetest.add_entity`.
|
||||
|
||||
`blockseed` is the block seed for the chunk the village was generated for.
|
||||
Villages can extend outside of this chunk.
|
||||
|
||||
```lua
|
||||
local function my_villager_hook(villager_ent, blockseed)
|
||||
local l = villager_ent:get_luaentity()
|
||||
minetest.log("The villager's id is " .. l._id)
|
||||
end
|
||||
|
||||
mcl_villages.register_on_villager_spawned(my_villager_hook)
|
||||
```
|
||||
|
||||
## Farm Interface
|
||||
|
||||
These functions aid creating crops for use use in farms placed during village
|
||||
generation.
|
||||
|
||||
### mcl_villages.get_crop_types()
|
||||
|
||||
This allows checking what crop types are supported.
|
||||
|
||||
Currently they are: grain, root, gourd, flower, bush, tree.
|
||||
|
||||
Placement of gourds should take in to consideration the way they fruit.
|
||||
|
||||
### mcl_villages.get_crops()
|
||||
|
||||
Returns a table containing all registered crops.
|
||||
|
||||
### mcl_villages.get_weighted_crop(biome, crop_type, pr)
|
||||
|
||||
Gets a random crop for the biome and crop type.
|
||||
|
||||
### mcl_villages.register_crop(crop_def)
|
||||
|
||||
Registers a crop for use on farms.
|
||||
|
||||
crop_def is a table with the following fields:
|
||||
|
||||
* `node` the name of the crop node to place. e.g. `mcl_farming:wheat_1`.
|
||||
* `crop_type` the type crop. e.g. `grain`
|
||||
* `biomes` a table containing the weighting to give the crop.
|
||||
* Supported biome values are:
|
||||
* acacia
|
||||
* bamboo
|
||||
* desert
|
||||
* jungle
|
||||
* plains
|
||||
* savanna
|
||||
* spruce
|
||||
* If you leave a biome out ot he definition then the crop will not be available in that biome.
|
||||
e.g.
|
||||
|
||||
```lua
|
||||
mcl_villages.register_crop({
|
||||
type = "grain",
|
||||
node = "mcl_farming:wheat_1",
|
||||
biomes = {
|
||||
acacia = 10,
|
||||
bamboo = 10,
|
||||
desert = 10,
|
||||
jungle = 10,
|
||||
plains = 10,
|
||||
savanna = 10,
|
||||
spruce = 10,
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### Creating farms with replaceable crops
|
||||
|
||||
To create a farm that will utilize registered crops you follow the basic process
|
||||
for creating a farm, but you leave out the crops.
|
||||
|
||||
Once you have your farm constructed then instead of placing crops you place blocks named `mcl_villages:crop_*` over the dirt in the farm.
|
||||
|
||||
Each crop type has 8 blocks that can be used for it. This allows, but does not
|
||||
guarantee, variety of crops in a farm.
|
||||
|
||||
Each of the crop tiles has an image of a entity that it represents. This image
|
||||
is representative, not explicit.
|
||||
|
||||
i.e. The root crop tiles have an image of a carrot on them, but they will be
|
||||
swapped for a random root crop, not always carrots.
|
||||
|
||||
Each specific node will be replaced by a single item.
|
||||
|
||||
e.g. if you use `mcl_villages:crop_root_1` and `mcl_villages:crop_root_2` in your farm then all there will be at most 2 types of root crops on the farm.
|
||||
|
||||
It is random, so both types may get replaced by the same crop.
|
||||
|
||||
Remember that gourds affect 5 nodes when they crop; a good farmer won't plant
|
||||
anything on the 4 nodes a fruit wil form and your farm should not do that
|
||||
either.
|
||||
|
||||
Once you have saved the schema for your farm you register it with the building interface.
|
||||
|
||||
e.g.
|
||||
|
||||
```lua
|
||||
mcl_villages.register_building({
|
||||
name = "my_farm",
|
||||
mts = schem_path .. "/my_farm.mts",
|
||||
num_others = 3,
|
||||
})
|
||||
```
|
||||
|
||||
When a village is generated there will be a chance your farm will be placed, any
|
||||
crop blocks will be replaced by biome appropriate crops.
|
||||
|
||||
If a crop cannot be found for a crop type in a biome, then a default will be
|
||||
used. This ensure all farming blocks are full, ven if it's al the same crop.
|
||||
|
||||
The default is wheat.
|
||||
|
||||
## Village Layout
|
||||
|
||||
There are two methods for layout out villages, circle layout is more likely to be
|
||||
used for small villages and grid for large villages.
|
||||
|
||||
The circle layout uses circles (surprise) to calculate if buildings overlap. It
|
||||
creates fairly widely spaced layouts.
|
||||
|
||||
The grid layout uses a predetermined grid layout to positions buildings and uses
|
||||
AreaStore to adjust building position if there are collisions.
|
||||
|
||||
The predetermined grid is below, position 0 is the bell, the other numbers are the order of placement.
|
||||
|
||||
||||||||
|
||||
| -- | -- | -- | -- | -- | -- | -- |
|
||||
|48|41|33|25|29|37|45|
|
||||
|40|17|13| 9|11|15|43|
|
||||
|32|19| 5| 1| 3|22|35|
|
||||
|28|23| 7| 0| 8|24|27|
|
||||
|36|21| 4| 2| 6|20|31|
|
||||
|44|16|12|10|14|18|39|
|
||||
|46|38|30|26|34|42|47|
|
|
@ -21,7 +21,6 @@ Basic conversion of Settlements mod for compatibility with VoxeLibre, plus new s
|
|||
Seed-based Village Generation, multi-threading, bugfixes: kay27
|
||||
|
||||
|
||||
|
||||
=========================
|
||||
version: 0.1 alpha
|
||||
|
||||
|
@ -43,3 +42,5 @@ This mod is based on "ruins" by BlockMen
|
|||
Completely new schematics for VoxeLibre:
|
||||
MysticTempest - CC-BY-SA 4.0
|
||||
|
||||
|
||||
New schematics and improvements in mineclonia by codiac.
|
||||
|
|
|
@ -0,0 +1,154 @@
|
|||
mcl_villages.schematic_houses = {}
|
||||
mcl_villages.schematic_jobs = {}
|
||||
mcl_villages.schematic_lamps = {}
|
||||
mcl_villages.schematic_bells = {}
|
||||
mcl_villages.schematic_wells = {}
|
||||
mcl_villages.on_village_placed = {}
|
||||
mcl_villages.on_villager_placed = {}
|
||||
mcl_villages.mandatory_buildings = {}
|
||||
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
local function job_count(schem_lua)
|
||||
local count = 0
|
||||
for _, n in pairs(mobs_mc.jobsites) do
|
||||
if string.find(n, "^group:") then
|
||||
if n == "group:cauldron" then
|
||||
count = count + select(2, string.gsub(schem_lua, '"mcl_cauldrons:cauldron', ""))
|
||||
else
|
||||
local name = string.sub(n, 6, -1)
|
||||
local num = select(2, string.gsub(schem_lua, name, ""))
|
||||
if num then
|
||||
minetest.log("info", string.format("[mcl_villages] Guessing how to handle %s counting it as %d job sites", name, num))
|
||||
count = count + num
|
||||
else
|
||||
minetest.log("warning", string.format("[mcl_villages] Don't know how to handle group %s counting it as 1 job site", n))
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
else
|
||||
count = count + select(2, string.gsub(schem_lua, '{name="' .. n .. '"', ""))
|
||||
end
|
||||
end
|
||||
|
||||
return count
|
||||
end
|
||||
|
||||
local function load_schema(name, mts)
|
||||
local schem_lua = minetest.serialize_schematic(mts, "lua", { lua_use_comments = false, lua_num_indent_spaces = 0 }) .. " return schematic"
|
||||
-- MCLA node names to VL for import
|
||||
if string.find(mts, "new_villages/") then
|
||||
for _, sub in pairs(mcl_villages.mcla_to_vl) do
|
||||
schem_lua = schem_lua:gsub(sub[1], sub[2])
|
||||
end
|
||||
end
|
||||
|
||||
local schematic = loadstring(schem_lua)()
|
||||
return { name = name, size = schematic.size, schem_lua = schem_lua }
|
||||
end
|
||||
|
||||
local all_optional = { "yadjust", "no_ground_turnip", "no_clearance" }
|
||||
|
||||
local function set_all_optional(record, data)
|
||||
for _, field in ipairs(all_optional) do
|
||||
if record[field] then data[field] = record[field] end
|
||||
end
|
||||
end
|
||||
|
||||
local function set_mandatory(record, type)
|
||||
if record['is_mandatory'] then
|
||||
if not mcl_villages.mandatory_buildings[type] then mcl_villages.mandatory_buildings[type] = {} end
|
||||
table.insert(mcl_villages.mandatory_buildings[type], record["name"])
|
||||
end
|
||||
end
|
||||
|
||||
function mcl_villages.register_lamp(record)
|
||||
local data = load_schema(record["name"], record["mts"])
|
||||
set_all_optional(record, data)
|
||||
table.insert(mcl_villages.schematic_lamps, data)
|
||||
set_mandatory(record, 'lamps')
|
||||
end
|
||||
|
||||
function mcl_villages.register_bell(record)
|
||||
local data = load_schema(record["name"], record["mts"])
|
||||
set_all_optional(record, data)
|
||||
table.insert(mcl_villages.schematic_bells, data)
|
||||
set_mandatory(record, 'bells')
|
||||
end
|
||||
|
||||
function mcl_villages.register_well(record)
|
||||
local data = load_schema(record["name"], record["mts"])
|
||||
set_all_optional(record, data)
|
||||
table.insert(mcl_villages.schematic_wells, data)
|
||||
set_mandatory(record, 'wells')
|
||||
end
|
||||
|
||||
local optional_fields = { "min_jobs", "max_jobs", "num_others", "is_mandatory" }
|
||||
|
||||
function mcl_villages.register_building(record)
|
||||
local data = load_schema(record["name"], record["mts"])
|
||||
|
||||
set_all_optional(record, data)
|
||||
for _, field in ipairs(optional_fields) do
|
||||
if record[field] then data[field] = record[field] end
|
||||
end
|
||||
|
||||
local str = data["schem_lua"]
|
||||
local num_beds = select(2, string.gsub(str, '"mcl_beds:bed_[^"]+_bottom"', ""))
|
||||
if num_beds > 0 then data["num_beds"] = num_beds end
|
||||
|
||||
local job_count = job_count(data["schem_lua"])
|
||||
if job_count > 0 then
|
||||
data["num_jobs"] = job_count
|
||||
table.insert(mcl_villages.schematic_jobs, data)
|
||||
set_mandatory(record, 'jobs')
|
||||
else
|
||||
table.insert(mcl_villages.schematic_houses, data)
|
||||
set_mandatory(record, 'houses')
|
||||
end
|
||||
end
|
||||
|
||||
local crop_list = {}
|
||||
function mcl_villages.register_crop(crop_def)
|
||||
local crops = crop_list[crop_def.type] or {}
|
||||
for biome, weight in pairs(crop_def.biomes) do
|
||||
if crops[biome] == nil then crops[biome] = {} end
|
||||
crops[biome][crop_def.node] = weight
|
||||
end
|
||||
crop_list[crop_def.type] = crops
|
||||
end
|
||||
|
||||
function mcl_villages.get_crop_types()
|
||||
local ret = {}
|
||||
for k, _ in pairs(crop_list) do
|
||||
table.insert(ret, k)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
function mcl_villages.get_weighted_crop(biome, crop_type, pr)
|
||||
local crops = crop_list[crop_type]
|
||||
if not crops then return end -- unknown crop
|
||||
local crops = crops[biome] or crops["plains"]
|
||||
|
||||
local total = 0
|
||||
for _, weight in pairs(crops) do total = total + weight end
|
||||
|
||||
local rand = pr:next(0, 1e7) * 1e-7 * total
|
||||
for node, weight in pairs(crops) do
|
||||
if rand <= weight then
|
||||
return node
|
||||
end
|
||||
rand = rand - weight
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
function mcl_villages.register_on_village_placed(func)
|
||||
table.insert(mcl_villages.on_village_placed, func)
|
||||
end
|
||||
|
||||
function mcl_villages.register_on_villager_spawned(func)
|
||||
table.insert(mcl_villages.on_villager_placed, func)
|
||||
end
|
||||
|
|
@ -1,344 +1,349 @@
|
|||
--[[
|
||||
-------------------------------------------------------------------------------
|
||||
-- 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
|
||||
local min_jobs = tonumber(minetest.settings:get("mcl_villages_min_jobs")) or 1
|
||||
local max_jobs = tonumber(minetest.settings:get("mcl_villages_max_jobs")) or 12
|
||||
local placement_priority = minetest.settings:get("mcl_villages_placement_priority") or "random"
|
||||
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
local function add_building(settlement, building, count_buildings)
|
||||
table.insert(settlement, building)
|
||||
count_buildings[building.name] = (count_buildings[building.name] or 0) + 1
|
||||
count_buildings.num_jobs = count_buildings.num_jobs + (building.num_jobs or 0)
|
||||
count_buildings.num_beds = count_buildings.num_beds + (building.num_beds or 0)
|
||||
if building.group then
|
||||
count_buildings[building.group] = (count_buildings[building.group] or 0) + 1
|
||||
end
|
||||
end
|
||||
|
||||
local function layout_town(vm, minp, maxp, pr, input_settlement)
|
||||
local center = vector.new(pr:next(minp.x + 24, maxp.x - 24), maxp.y, pr:next(minp.z + 24, maxp.z - 24))
|
||||
minetest.log("action", "[mcl_villages] sudo make me a village at: " .. minetest.pos_to_string(minp).." - "..minetest.pos_to_string(maxp))
|
||||
local possible_rotations = {"0", "90", "180", "270"}
|
||||
local center_surface
|
||||
|
||||
local settlement = {}
|
||||
-- now some buildings around in a circle, radius = size of town center
|
||||
local x, y, z, r, lastr = center.x, center.y, center.z, 0, 99
|
||||
local mindist = 3
|
||||
if #input_settlement >= 12 then mindist = 2 end
|
||||
-- draw j circles around center and increase radius by math.random(2,4)
|
||||
for j = 1,20 do
|
||||
local steps = math.min(math.floor(math.pi * 2 * r / 2), 30) -- try up to 30 angles
|
||||
for a = 0, steps - 1 do
|
||||
if #settlement == #input_settlement then break end -- everything placed
|
||||
local angle = a * 71 / steps * math.pi * 2 -- prime to increase randomness
|
||||
local cpos = vector.new(math.floor(x + r * math.cos(angle) + 0.5), y, math.floor(z - r * math.sin(angle) + 0.5))
|
||||
local building = table.copy(input_settlement[#settlement + 1])
|
||||
local size = vector.copy(building.size)
|
||||
--local rotation = possible_rotations[pr:next(1, #possible_rotations)]
|
||||
local rotation = math.floor(math.atan2(center.z-cpos.z, center.x-cpos.x) / math.pi * 2+6.5)%4
|
||||
rotation = possible_rotations[1+rotation]
|
||||
if rotation == "90" or rotation == "270" then size.x, size.z = size.z, size.x end
|
||||
local tlpos = vector.offset(cpos, -math.floor((size.x-1)/2), 0, -math.floor((size.z-1)/2))
|
||||
|
||||
-- ensure we have 3 space for terraforming, and avoid problems with VoxelManip
|
||||
if tlpos.x - 3 >= minp.x and tlpos.x + size.x + 3 <= maxp.x
|
||||
and tlpos.z + 3 >= minp.z and tlpos.z + size.y + 3 <= maxp.z then
|
||||
local pos, surface_material = vl_terraforming.find_level_vm(vm, cpos, size)
|
||||
-- check distance to other buildings. Note that we still want to add baseplates etc.
|
||||
if pos and mcl_villages.surface_mat[surface_material.name] and mcl_villages.check_distance(settlement, cpos, size.x, size.z, mindist) then
|
||||
-- use town bell as new reference point for placement height
|
||||
if #settlement == 0 then
|
||||
center_surface, y = cpos, math.min(maxp.y, pos.y + mcl_villages.max_height_difference * 0.5 + 1)
|
||||
end
|
||||
-- limit height differences to town center, but gradually allow more
|
||||
if math.abs(pos.y - center_surface.y) <= mcl_villages.max_height_difference * (0.25 + math.min(r/40,0.5)) then
|
||||
local minp = vector.offset(pos, -math.floor((size.x-1)/2), building.yadjust, -math.floor((size.z-1)/2))
|
||||
building.minp = minp
|
||||
building.maxp = vector.offset(minp, size.x, size.y, size.z)
|
||||
building.pos = pos
|
||||
building.size = size
|
||||
building.rotation = rotation
|
||||
building.surface_mat = surface_material
|
||||
table.insert(settlement, building)
|
||||
-- minetest.log("verbose", "[mcl_villages] Planning "..schema["name"].." at "..minetest.pos_to_string(pos))
|
||||
lastr = r
|
||||
else
|
||||
minetest.log("verbose", "Too large height difference "..math.abs(pos.y - center_surface.y).." at distance "..r)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
r = r + pr:next(2,4)
|
||||
if r > lastr + 20 then -- too disconnected
|
||||
minetest.log("verbose", "Disconnected village "..r.." > "..lastr)
|
||||
break
|
||||
end
|
||||
end
|
||||
-- minetest.log("verbose", "Planned "..#input_settlement.." buildings, placed "..#settlement)
|
||||
if #settlement < #input_settlement and #settlement < 6 then
|
||||
minetest.log("action", "[mcl_villages] Bad village location, could only place "..#settlement.." buildings at "..minetest.pos_to_string(center))
|
||||
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
|
||||
minetest.log("action", "[mcl_villages] village plan completed at " .. minetest.pos_to_string(center))
|
||||
return settlement
|
||||
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_vars.get_chunk_number(center)] = true
|
||||
|
||||
-- go build settlement around center
|
||||
if not center_surface then
|
||||
minetest.log("action", "Cannot build village at: " .. minetest.pos_to_string(center))
|
||||
return false
|
||||
else
|
||||
minetest.log("action", "Village built.")
|
||||
--minetest.log("action", "Build village at: " .. minetest.pos_to_string(center) .. " with surface material: " .. surface_material)
|
||||
end
|
||||
function mcl_villages.create_site_plan(vm, minp, maxp, pr)
|
||||
local settlement = {}
|
||||
|
||||
-- initialize all settlement_info table
|
||||
local count_buildings, number_of_buildings, number_built = settlements.initialize_settlement_info(pr)
|
||||
local count_buildings = { num_jobs = 0, num_beds = 0, target_jobs = pr:next(min_jobs, max_jobs) }
|
||||
|
||||
-- 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_vars.get_chunk_number(pos1)
|
||||
local pos_surface, surface_material
|
||||
if chunks[chunk_number] then
|
||||
pos_surface, surface_material = settlements.find_surface(pos1)
|
||||
local bindex = pr:next(1, #mcl_villages.schematic_bells)
|
||||
local bell_info = table.copy(mcl_villages.schematic_bells[bindex])
|
||||
|
||||
if mcl_villages.mandatory_buildings['jobs'] then
|
||||
for _, bld_name in pairs(mcl_villages.mandatory_buildings['jobs']) do
|
||||
local building_info = info_for_building(bld_name, mcl_villages.schematic_jobs)
|
||||
add_building(settlement, building_info, count_buildings)
|
||||
end
|
||||
end
|
||||
|
||||
while count_buildings.num_jobs < count_buildings.target_jobs do
|
||||
local rindex = pr:next(1, #mcl_villages.schematic_jobs)
|
||||
local building_info = mcl_villages.schematic_jobs[rindex]
|
||||
|
||||
if
|
||||
(building_info.min_jobs == nil or count_buildings.target_jobs >= building_info.min_jobs)
|
||||
and (building_info.max_jobs == nil or count_buildings.target_jobs <= building_info.max_jobs)
|
||||
and (
|
||||
building_info.num_others == nil
|
||||
or (count_buildings[building_info.group or building_info.name] or 0) == 0
|
||||
or building_info.num_others * (count_buildings[building_info.group or building_info.name] or 0) < count_buildings.num_jobs
|
||||
)
|
||||
then
|
||||
add_building(settlement, building_info, count_buildings)
|
||||
end
|
||||
end
|
||||
|
||||
if mcl_villages.mandatory_buildings['houses'] then
|
||||
for _, bld_name in pairs(mcl_villages.mandatory_buildings['houses']) do
|
||||
local building_info = info_for_building(bld_name, mcl_villages.schematic_houses)
|
||||
add_building(settlement, building_info, count_buildings)
|
||||
end
|
||||
end
|
||||
|
||||
while count_buildings.num_beds <= count_buildings.num_jobs do
|
||||
local rindex = pr:next(1, #mcl_villages.schematic_houses)
|
||||
local building_info = mcl_villages.schematic_houses[rindex]
|
||||
|
||||
if
|
||||
(building_info.min_jobs == nil or count_buildings.target_jobs >= building_info.min_jobs)
|
||||
and (building_info.max_jobs == nil or count_buildings.target_jobs <= building_info.max_jobs)
|
||||
and (
|
||||
building_info.num_others == nil
|
||||
or (count_buildings[building_info.group or building_info.name] or 0) == 0
|
||||
or building_info.num_others * (count_buildings[building_info.group or building_info.name] or 0) < count_buildings.num_jobs
|
||||
)
|
||||
then
|
||||
add_building(settlement, building_info, count_buildings)
|
||||
end
|
||||
end
|
||||
|
||||
-- Based on number of villagers
|
||||
local num_wells = pr:next(1, math.ceil(count_buildings.num_beds / 10))
|
||||
for _ = 1, num_wells do
|
||||
local windex = pr:next(1, #mcl_villages.schematic_wells)
|
||||
local cur_schem = table.copy(mcl_villages.schematic_wells[windex])
|
||||
table.insert(settlement, pr:next(1, #settlement), cur_schem)
|
||||
end
|
||||
|
||||
if placement_priority == "jobs" then
|
||||
-- keep ordered as is
|
||||
elseif placement_priority == "houses" then
|
||||
table.reverse(settlement)
|
||||
else
|
||||
chunks[chunk_number] = true
|
||||
pos_surface, surface_material = settlements.find_surface(pos1, true)
|
||||
settlement = mcl_villages.shuffle(settlement, pr)
|
||||
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)
|
||||
table.insert(settlement, 1, bell_info)
|
||||
return layout_town(vm, minp, maxp, pr, settlement)
|
||||
end
|
||||
|
||||
local function spawn_iron_golem(pos)
|
||||
--minetest.log("action", "Attempt to spawn iron golem.")
|
||||
local p = minetest.find_node_near(pos,50,"mcl_core:grass_path")
|
||||
if p then
|
||||
local l=minetest.add_entity(p,"mobs_mc:iron_golem"):get_luaentity()
|
||||
if l then
|
||||
l._home = p
|
||||
end
|
||||
end
|
||||
local function init_nodes(p1, p2, pr)
|
||||
vl_structures.construct_nodes(p1, p2, {
|
||||
"mcl_itemframes:item_frame",
|
||||
"mcl_itemframes:glow_item_frame",
|
||||
"mcl_furnaces:furnace",
|
||||
"mcl_anvils:anvil",
|
||||
"mcl_books:bookshelf",
|
||||
"mcl_armor_stand:armor_stand",
|
||||
-- jobsite: "mcl_smoker:smoker",
|
||||
-- jobsite: "mcl_barrels:barrel_closed",
|
||||
-- jobsite: "mcl_blast_furnace:blast_furnace",
|
||||
-- jobsite: "mcl_brewing:stand_000",
|
||||
})
|
||||
|
||||
-- Support mods with custom job sites
|
||||
local job_sites = minetest.find_nodes_in_area(p1, p2, mobs_mc.jobsites)
|
||||
for _, v in pairs(job_sites) do vl_structures.init_node_construct(v) end
|
||||
|
||||
local nodes = vl_structures.construct_nodes(p1, p2, {"mcl_chests:chest_small", "mcl_chests:chest" })
|
||||
for _, n in pairs(nodes) do mcl_villages.fill_chest(n, pr) end
|
||||
end
|
||||
|
||||
local function spawn_villagers(minp,maxp)
|
||||
--minetest.log("action", "Attempt to spawn villagers.")
|
||||
local beds=minetest.find_nodes_in_area(vector.offset(minp,-20,-20,-20),vector.offset(maxp,20,20,20),{"mcl_beds:bed_red_bottom"})
|
||||
for _,bed in pairs(beds) do
|
||||
local m = minetest.get_meta(bed)
|
||||
if m:get_string("villager") == "" then
|
||||
local v=minetest.add_entity(bed,"mobs_mc:villager")
|
||||
if v then
|
||||
local l=v:get_luaentity()
|
||||
l._bed = bed
|
||||
m:set_string("villager",l._id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- important: the vm will be written and then is outdated!
|
||||
function mcl_villages.place_schematics(vm, settlement, blockseed, pr)
|
||||
-- first building is always the bell
|
||||
local bell_pos = vector.offset(settlement[1].minp, math.floor(settlement[1].size.x/2), 0, math.floor(settlement[1].size.z/2))
|
||||
|
||||
local function fix_village_water(minp,maxp)
|
||||
local palettenodes = minetest.find_nodes_in_area(vector.offset(minp,-20,-20,-20),vector.offset(maxp,20,20,20), "group:water_palette")
|
||||
for _, palettenodepos in pairs(palettenodes) do
|
||||
local palettenode = minetest.get_node(palettenodepos)
|
||||
minetest.set_node(palettenodepos, {name = palettenode.name})
|
||||
end
|
||||
end
|
||||
for i, building in ipairs(settlement) do
|
||||
local minp, cpos, maxp, size, rotation = building.minp, building.pos, building.maxp, building.size, building.rotation
|
||||
|
||||
local function init_nodes(p1, p2, size, rotation, pr)
|
||||
construct_node(p1, p2, "mcl_itemframes:item_frame")
|
||||
construct_node(p1, p2, "mcl_furnaces:furnace")
|
||||
construct_node(p1, p2, "mcl_anvils:anvil")
|
||||
|
||||
construct_node(p1, p2, "mcl_smoker:smoker")
|
||||
construct_node(p1, p2, "mcl_barrels:barrel_closed")
|
||||
construct_node(p1, p2, "mcl_blast_furnace:blast_furnace")
|
||||
construct_node(p1, p2, "mcl_brewing:stand_000")
|
||||
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
|
||||
local is_last = i == #settlement_info
|
||||
|
||||
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
|
||||
-- adjust the schema to match location and biome
|
||||
local surface_material = building.surface_mat or {name = "mcl_core:dirt" }
|
||||
local platform_material = building.platform_mat or building.surface_mat or {name = "mcl_core:stone" }
|
||||
local schem_lua = building.schem_lua
|
||||
schem_lua = schem_lua:gsub('"mcl_core:dirt"', '"'..platform_material.name..'"')
|
||||
schem_lua = schem_lua:gsub('"mcl_core:dirt_with_grass"', '"'..surface_material.name..'"') -- also keeping param2 would be nicer, grass color
|
||||
schem_lua = mcl_villages.substitute_materials(cpos, schem_lua, pr)
|
||||
local schematic = loadstring(schem_lua)()
|
||||
|
||||
local is_belltower = building_all_info["name"] == "belltower"
|
||||
|
||||
-- build foundation for the building an make room above
|
||||
|
||||
mcl_structures.place_schematic(
|
||||
pos,
|
||||
schematic,
|
||||
rotation,
|
||||
nil,
|
||||
true,
|
||||
nil,
|
||||
function(p1, p2, size, rotation, pr)
|
||||
if is_belltower then
|
||||
spawn_iron_golem(p1)
|
||||
else
|
||||
init_nodes(p1, p2, size, rotation, pr)
|
||||
spawn_villagers(p1,p2)
|
||||
fix_village_water(p1,p2)
|
||||
-- the foundation and air space for the building was already built before
|
||||
-- minetest.log("debug", "placing schematics for "..building.name.." at "..minetest.pos_to_string(minp).." on "..surface_material)
|
||||
minetest.place_schematic_on_vmanip(vm, minp, schematic, rotation, nil, true, { place_center_x = false, place_center_y = false, place_center_z = false })
|
||||
mcl_villages.store_path_ends(vm, minp, maxp, cpos, blockseed, bell_pos)
|
||||
mcl_villages.increase_no_paths(vm, minp, maxp) -- help the path finder
|
||||
end
|
||||
|
||||
vm:write_to_map(true) -- for path finder and light
|
||||
|
||||
-- Path planning and placement
|
||||
mcl_villages.paths(blockseed, minetest.get_biome_name(minetest.get_biome_data(bell_pos).biome))
|
||||
-- Clean up paths and initialize nodes
|
||||
for i, building in ipairs(settlement) do
|
||||
mcl_villages.clean_no_paths(building.minp, building.maxp)
|
||||
init_nodes(building.minp, building.maxp, pr)
|
||||
end
|
||||
|
||||
-- Replace center block with a temporary block, which will be used run delayed actions
|
||||
local block_name = minetest.get_node(bell_pos).name -- to restore the node afterwards
|
||||
minetest.swap_node(bell_pos, { name = "mcl_villages:village_block" })
|
||||
local meta = minetest.get_meta(bell_pos)
|
||||
meta:set_string("node_type", block_name)
|
||||
meta:set_string("blockseed", blockseed)
|
||||
meta:set_string("infotext", S("The timer for this village has not run yet!"))
|
||||
minetest.get_node_timer(bell_pos):start(1.0)
|
||||
end
|
||||
|
||||
minetest.register_node("mcl_villages:village_block", {
|
||||
drawtype = "glasslike",
|
||||
groups = { not_in_creative_inventory = 1 },
|
||||
light_source = 14, -- This is a light source so that lamps don't get placed near it
|
||||
-- Somethings don't work reliably when done in the map building
|
||||
-- so we use a timer to run them later when they work more reliably
|
||||
-- e.g. spawning mobs, running minetest.find_path
|
||||
on_timer = function(pos, _)
|
||||
local meta = minetest.get_meta(pos)
|
||||
minetest.swap_node(pos, { name = meta:get_string("node_type") })
|
||||
mcl_villages.post_process_village(meta:get_string("blockseed"))
|
||||
return false
|
||||
end,
|
||||
pr
|
||||
)
|
||||
})
|
||||
|
||||
function mcl_villages.post_process_village(blockseed)
|
||||
local village_info = mcl_villages.get_village(blockseed)
|
||||
if not village_info then return end
|
||||
-- minetest.log("Postprocessing village")
|
||||
|
||||
local settlement_info = village_info.data
|
||||
local jobs, beds = {}, {}
|
||||
|
||||
local bell_pos = vector.copy(settlement_info[1].pos)
|
||||
local bell = vector.offset(bell_pos, 0, 2, 0)
|
||||
local biome_name = minetest.get_biome_name(minetest.get_biome_data(bell_pos).biome)
|
||||
|
||||
-- Spawn Golem
|
||||
local l = minetest.add_entity(bell, "mobs_mc:iron_golem"):get_luaentity()
|
||||
if l then
|
||||
l._home = bell
|
||||
else
|
||||
minetest.log("info", "Could not create a golem!")
|
||||
end
|
||||
|
||||
-- Spawn cats
|
||||
local sp = minetest.find_nodes_in_area_under_air(vector.offset(bell, -20, -10, -20),vector.offset(bell, 20, 10, 20), { "group:opaque" })
|
||||
for _ = 1, math.random(3) do
|
||||
local v = minetest.add_entity(vector.offset(sp[math.random(#sp)], 0, 1, 0), "mobs_mc:cat")
|
||||
if v and v:get_luaentity() then
|
||||
v:get_luaentity()._home = bell_pos -- help them stay local
|
||||
else
|
||||
minetest.log("info", "Could not spawn a cat")
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- collect beds and job sites
|
||||
for _, building in pairs(settlement_info) do
|
||||
local minp, maxp = building.minp, building.maxp
|
||||
if building.num_jobs then
|
||||
local jobsites = minetest.find_nodes_in_area(minp, maxp, mobs_mc.jobsites)
|
||||
for _, job_pos in pairs(jobsites) do table.insert(jobs, job_pos) end
|
||||
end
|
||||
|
||||
if building.num_beds then
|
||||
local bld_beds = minetest.find_nodes_in_area(minp, maxp, { "group:bed" })
|
||||
for _, bed_pos in pairs(bld_beds) do
|
||||
local bed_group = minetest.get_item_group(minetest.get_node(bed_pos).name, "bed")
|
||||
-- We only spawn at bed bottoms, 1 is bottom, 2 is top
|
||||
if bed_group == 1 then table.insert(beds, bed_pos) end
|
||||
end
|
||||
end
|
||||
end
|
||||
-- TODO: shuffle jobs?
|
||||
|
||||
-- minetest.log("beds: "..#beds.." jobsites: "..#jobs)
|
||||
if beds then
|
||||
for _, bed_pos in pairs(beds) do
|
||||
minetest.forceload_block(bed_pos, true)
|
||||
local m = minetest.get_meta(bed_pos)
|
||||
m:set_string("bell_pos", minetest.pos_to_string(bell_pos))
|
||||
if m:get_string("villager") == "" then
|
||||
local v = minetest.add_entity(vector.offset(bed_pos, 0, 0.06, 0), "mobs_mc:villager")
|
||||
if v then
|
||||
local l = v:get_luaentity()
|
||||
l._bed = bed_pos
|
||||
l._bell = bell_pos
|
||||
m:set_string("villager", l._id)
|
||||
m:set_string("infotext", S("A villager sleeps here"))
|
||||
|
||||
local job_pos = table.remove(jobs, 1)
|
||||
if job_pos then villager_employ(l, job_pos) end -- HACK: merge more MCLA villager job code?
|
||||
for _, callback in pairs(mcl_villages.on_villager_placed) do callback(v, blockseed) end
|
||||
else
|
||||
minetest.log("info", "Could not create a villager!")
|
||||
end
|
||||
else
|
||||
minetest.log("info", "bed already owned by " .. m:get_string("villager")) -- should not happen unless villages overlap
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Terraform for an entire village
|
||||
function mcl_villages.terraform(vm, settlement, pr)
|
||||
-- TODO: sort top-down, then bottom-up, or opposite?
|
||||
-- we make the foundations 2 node wider than necessary, to have one node for path laying
|
||||
for i, building in ipairs(settlement) do
|
||||
if not building.no_clearance then
|
||||
local pos, size = building.pos, building.size
|
||||
pos = vector.offset(pos, -math.floor((size.x-1)/2), 0, -math.floor((size.z-1)/2))
|
||||
-- TODO: allow different clearance for different buildings?
|
||||
vl_terraforming.clearance_vm(vm, pos.x-1, pos.y, pos.z-1, size.x+2, size.y, size.z+2, 2, building.surface_mat, building.dust_mat, pr)
|
||||
end
|
||||
end
|
||||
for i, building in ipairs(settlement) do
|
||||
if not building.no_ground_turnip then
|
||||
local pos, size = building.pos, building.size
|
||||
local surface_mat = building.surface_mat
|
||||
local platform_mat = building.platform_mat or { name = mcl_villages.foundation_materials[surface_mat.name] or "mcl_core:dirt" }
|
||||
local stone_mat = building.stone_mat or { name = mcl_villages.stone_materials[surface_mat.name] or "mcl_core:stone" }
|
||||
local dust_mat = building.dust_mat
|
||||
building.platform_mat = platform_mat -- remember for use in schematic placement
|
||||
building.stone_mat = stone_mat
|
||||
pos = vector.offset(pos, -math.floor((size.x-1)/2), 0, -math.floor((size.z-1)/2))
|
||||
vl_terraforming.foundation_vm(vm, pos.x-2, pos.y, pos.z-2, size.x+4, -5, size.z+4, 2, surface_mat, platform_mat, stone_mat, dust_mat, pr)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,77 +1,295 @@
|
|||
-- 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
|
||||
-- maximum allowed difference in height for building a settlement
|
||||
mcl_villages.max_height_difference = 56
|
||||
|
||||
-- legacy type in old schematics
|
||||
minetest.register_alias("mcl_villages:stonebrickcarved", "mcl_core:stonebrickcarved")
|
||||
|
||||
--[[ 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
|
||||
--
|
||||
mcl_villages.surface_mat = {}
|
||||
mcl_villages.surface_mat["mcl_core:andesite"] = true
|
||||
mcl_villages.surface_mat["mcl_core:diorite"] = true
|
||||
mcl_villages.surface_mat["mcl_core:dirt"] = true
|
||||
mcl_villages.surface_mat["mcl_core:dirt_with_grass"] = true
|
||||
--mcl_villages.surface_mat["mcl_core:dirt_with_dry_grass"] = true
|
||||
mcl_villages.surface_mat["mcl_core:dirt_with_grass_snow"] = true
|
||||
--mcl_villages.surface_mat["mcl_core:dry_dirt_with_grass"] = true
|
||||
mcl_villages.surface_mat["mcl_core:grass_path"] = true
|
||||
mcl_villages.surface_mat["mcl_core:granite"] = true
|
||||
mcl_villages.surface_mat["mcl_core:podzol"] = true
|
||||
mcl_villages.surface_mat["mcl_core:redsand"] = true
|
||||
mcl_villages.surface_mat["mcl_core:sand"] = true
|
||||
mcl_villages.surface_mat["mcl_core:sandstone"] = true
|
||||
mcl_villages.surface_mat["mcl_core:sandstonesmooth"] = true
|
||||
mcl_villages.surface_mat["mcl_core:sandstonesmooth2"] = true
|
||||
--mcl_villages.surface_mat["mcl_core:silver_sand"] = true
|
||||
--mcl_villages.surface_mat["mcl_core:snow"] = true
|
||||
mcl_villages.surface_mat["mcl_core:stone"] = true
|
||||
mcl_villages.surface_mat["mcl_core:stone_with_coal"] = true
|
||||
mcl_villages.surface_mat["mcl_core:stone_with_iron"] = true
|
||||
mcl_villages.surface_mat["mcl_colorblocks:hardened_clay"] = true
|
||||
mcl_villages.surface_mat["mcl_colorblocks:hardened_clay_orange"] = true
|
||||
mcl_villages.surface_mat["mcl_colorblocks:hardened_clay_red"] = true
|
||||
mcl_villages.surface_mat["mcl_colorblocks:hardened_clay_white"] = true
|
||||
|
||||
-- substitute foundation materials
|
||||
mcl_villages.foundation_materials = {}
|
||||
mcl_villages.foundation_materials["mcl_core:sand"] = "mcl_core:sandstone"
|
||||
mcl_villages.foundation_materials["mcl_core:redsand"] = "mcl_core:redsandstone"
|
||||
|
||||
-- substitute stone materials in foundation
|
||||
mcl_villages.stone_materials = {}
|
||||
|
||||
mcl_villages.default_crop = "mcl_farming:wheat_1"
|
||||
|
||||
--
|
||||
-- path to schematics
|
||||
-- Biome based block substitutions
|
||||
--
|
||||
schem_path = settlements.modpath.."/schematics/"
|
||||
--
|
||||
-- list of schematics
|
||||
--
|
||||
local basic_pseudobiome_villages = minetest.settings:get_bool("basic_pseudobiome_villages", true)
|
||||
-- TODO maybe this should be in the biomes?
|
||||
mcl_villages.biome_map = {
|
||||
BambooJungle = "bamboo",
|
||||
BambooJungleEdge = "bamboo",
|
||||
BambooJungleEdgeM = "bamboo",
|
||||
BambooJungleM = "bamboo",
|
||||
|
||||
settlements.schematic_table = {
|
||||
{name = "belltower", mts = schem_path.."belltower.mts", hwidth = 5, hdepth = 5, hheight = 9, hsize = 14, max_num = 0 , rplc = basic_pseudobiome_villages },
|
||||
{name = "large_house", mts = schem_path.."large_house.mts", hwidth = 12, hdepth = 12, hheight = 9, hsize = 14, max_num = 0.08 , rplc = basic_pseudobiome_villages },
|
||||
{name = "blacksmith", mts = schem_path.."blacksmith.mts", hwidth = 8, hdepth = 11, hheight = 13, hsize = 13, max_num = 0.055, rplc = basic_pseudobiome_villages },
|
||||
{name = "butcher", mts = schem_path.."butcher.mts", hwidth = 12, hdepth = 8, hheight = 10, hsize = 14, max_num = 0.03 , rplc = basic_pseudobiome_villages },
|
||||
{name = "church", mts = schem_path.."church.mts", hwidth = 13, hdepth = 13, hheight = 14, hsize = 15, max_num = 0.04 , rplc = basic_pseudobiome_villages },
|
||||
{name = "farm", mts = schem_path.."farm.mts", hwidth = 9, hdepth = 7, hheight = 13, hsize = 13, max_num = 0.1 , rplc = basic_pseudobiome_villages },
|
||||
{name = "lamp", mts = schem_path.."lamp.mts", hwidth = 3, hdepth = 4, hheight = 13, hsize = 10, max_num = 0.1 , rplc = false },
|
||||
{name = "library", mts = schem_path.."library.mts", hwidth = 12, hdepth = 12, hheight = 8, hsize = 13, max_num = 0.04 , rplc = basic_pseudobiome_villages },
|
||||
{name = "medium_house", mts = schem_path.."medium_house.mts", hwidth = 9, hdepth = 12, hheight = 8, hsize = 14, max_num = 0.08 , rplc = basic_pseudobiome_villages },
|
||||
{name = "small_house", mts = schem_path.."small_house.mts", hwidth = 9, hdepth = 8, hheight = 8, hsize = 13, max_num = 0.7 , rplc = basic_pseudobiome_villages },
|
||||
{name = "tavern", mts = schem_path.."tavern.mts", hwidth = 12, 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 },
|
||||
Jungle = "jungle",
|
||||
JungleEdge = "jungle",
|
||||
JungleEdgeM = "jungle",
|
||||
JungleM = "jungle",
|
||||
|
||||
Desert = "desert",
|
||||
|
||||
Savanna = "acacia",
|
||||
SavannaM = "acacia",
|
||||
|
||||
Mesa = "hardened_clay",
|
||||
MesaBryce = "hardened_clay ",
|
||||
MesaPlateauF = "hardened_clay",
|
||||
MesaPlateauFM = "hardened_clay",
|
||||
|
||||
MangroveSwamp = "mangrove",
|
||||
|
||||
RoofedForest = "dark_oak",
|
||||
|
||||
BirchForest = "birch",
|
||||
BirchForestM = "birch",
|
||||
|
||||
ColdTaiga = "spruce",
|
||||
ExtremeHills = "spruce",
|
||||
ExtremeHillsM = "spruce",
|
||||
IcePlains = "spruce",
|
||||
IcePlainsSpikes = "spruce",
|
||||
MegaSpruceTaiga = "spruce",
|
||||
MegaTaiga = "spruce",
|
||||
Taiga = "spruce",
|
||||
["ExtremeHills+"] = "spruce",
|
||||
|
||||
CherryGrove = "cherry",
|
||||
|
||||
-- no change
|
||||
--FlowerForest = "oak",
|
||||
--Forest = "oak",
|
||||
--MushroomIsland = "",
|
||||
--Plains = "oak",
|
||||
--StoneBeach = "",
|
||||
--SunflowerPlains = "oak",
|
||||
--Swampland = "oak",
|
||||
}
|
||||
|
||||
--
|
||||
-- maximum allowed difference in height for building a sttlement
|
||||
--
|
||||
max_height_difference = 56
|
||||
--
|
||||
--
|
||||
--
|
||||
half_map_chunk_size = 40
|
||||
--quarter_map_chunk_size = 20
|
||||
mcl_villages.vl_to_mcla = {
|
||||
{ '"mcl_core:tree"', '"mcl_trees:tree_oak"'},
|
||||
{ '"mcl_core:darktree"', '"mcl_trees:tree_dark_oak"'},
|
||||
{ '"mcl_core:wood"', '"mcl_trees:wood_oak"'},
|
||||
{ '"mcl_core:darkwood"', '"mcl_trees:wood_dark_oak"'},
|
||||
{ '"mcl_fences:fence', '"mcl_fences:oak_fence'},
|
||||
{ '"mcl_stairs:stair_wood"', '"mcl_stairs:stair_oak"'},
|
||||
{ '"mcl_stairs:stair_wood_', '"mcl_stairs:stair_oak_'},
|
||||
{ '"mcl_stairs:slab_wood"', '"mcl_stairs:slab_oak"'},
|
||||
{ '"mcl_stairs:slab_wood_', '"mcl_stairs:slab_oak_'},
|
||||
{ '"mcl_doors:wooden_door_', '"mcl_doors:door_oak_'},
|
||||
{ '"mcl_doors:trapdoor_', '"mcl_doors:trapdoor_oak_'},
|
||||
{ '"xpanes:bar', '"mcl_panes:bar' },
|
||||
{ '"xpanes:pane', '"mcl_panes:pane' },
|
||||
{ '"mcl_itemframes:item_frame"', '"mcl_itemframes:frame"' },
|
||||
{ '"mesecons_pressureplates:pressure_plate_wood_', '"mesecons_pressureplates:pressure_plate_oak_'},
|
||||
-- tree types
|
||||
{ '"mcl_core:([a-z]*)tree"', '"mcl_trees:tree_%1"'},
|
||||
{ '"mcl_core:([a-z]*)wood"', '"mcl_trees:wood_%1"'},
|
||||
{ '"mcl_stairs:stair_darkwood"', '"mcl_stairs:stair_dark_oak"'},
|
||||
{ '"mcl_stairs:stair_([a-z]*)wood"', '"mcl_stairs:stair_%1"'},
|
||||
{ '"mcl_bamboo:bamboo_fence', '"mcl_fences:bamboo_fence'},
|
||||
{ '"mcl_bamboo:bamboo_plank', '"mcl_core:bamboowood'},
|
||||
{ '"mcl_bamboo:bamboo_block', '"mcl_core:bambootree'},
|
||||
{ '"mcl_stairs:stair_bamboo_plank', '"mcl_stairs:stair_bamboo'},
|
||||
{ '"mcl_bamboo:pressure_plate_bamboo_wood_', '"mesecons_pressureplates:pressure_plate_bamboo_'},
|
||||
{ '"mcl_bamboo:bamboo_trapdoor', '"mcl_doors:trapdoor_bamboo'},
|
||||
{ '"mcl_bamboo:bamboo_door', '"mcl_doors:door_bamboo'},
|
||||
}
|
||||
mcl_villages.mcla_to_vl = {
|
||||
-- bidirectional
|
||||
{ '"mcl_trees:tree_oak"', '"mcl_core:tree"'},
|
||||
{ '"mcl_trees:tree_dark_oak"', '"mcl_core:darktree"'},
|
||||
{ '"mcl_trees:wood_oak"', '"mcl_core:wood"'},
|
||||
{ '"mcl_trees:wood_dark_oak"', '"mcl_core:darkwood"'},
|
||||
{ '"mcl_fences:oak_fence', '"mcl_fences:fence'},
|
||||
{ '"mcl_stairs:stair_oak"', '"mcl_stairs:stair_wood"'},
|
||||
{ '"mcl_stairs:stair_oak_bark', '"mcl_stairs:stair_tree_bark'},
|
||||
{ '"mcl_stairs:stair_oak_', '"mcl_stairs:stair_wood_'},
|
||||
{ '"mcl_stairs:slab_oak"', '"mcl_stairs:slab_wood"'},
|
||||
{ '"mcl_stairs:slab_oak_', '"mcl_stairs:slab_wood_'},
|
||||
{ '"mcl_doors:door_oak_', '"mcl_doors:wooden_door_'},
|
||||
{ '"mcl_doors:trapdoor_oak_', '"mcl_doors:trapdoor_'},
|
||||
{ '"mcl_panes:bar', '"xpanes:bar'},
|
||||
{ '"mcl_panes:pane', '"xpanes:pane'},
|
||||
{ '"mcl_itemframes:frame"', '"mcl_itemframes:item_frame"'},
|
||||
{ '"mesecons_pressureplates:pressure_plate_oak_', '"mesecons_pressureplates:pressure_plate_wood_'},
|
||||
-- tree types
|
||||
{ '"mcl_trees:tree_([a-z]*)"', '"mcl_core:%1tree"'},
|
||||
{ '"mcl_trees:wood_([a-z]*)"', '"mcl_core:%1wood"'},
|
||||
{ '"mcl_stairs:stair_birch(["_])', '"mcl_stairs:stair_birchwood%1'},
|
||||
{ '"mcl_stairs:stair_spruce(["_])', '"mcl_stairs:stair_sprucewood%1'},
|
||||
{ '"mcl_stairs:stair_dark_oak(["_])', '"mcl_stairs:stair_darkwood%1'},
|
||||
{ '"mcl_stairs:stair_jungle(["_])', '"mcl_stairs:stair_junglewood%1'},
|
||||
{ '"mcl_stairs:stair_acacia(["_])', '"mcl_stairs:stair_acaciawood%1'},
|
||||
{ '"mcl_fences:bamboo_fence', '"mcl_bamboo:bamboo_fence'},
|
||||
{ '"mcl_core:bamboowood', '"mcl_bamboo:bamboo_plank'},
|
||||
{ '"mcl_core:bambootree', '"mcl_bamboo:bamboo_block'},
|
||||
{ '"mcl_stairs:stair_bamboo', '"mcl_stairs:stair_bamboo_plank'},
|
||||
{ '"mesecons_pressureplates:pressure_plate_bamboo_', '"mcl_bamboo:pressure_plate_bamboo_wood_'},
|
||||
{ '"mcl_doors:trapdoor_bamboo', '"mcl_bamboo:bamboo_trapdoor'},
|
||||
{ '"mcl_doors:door_bamboo', '"mcl_bamboo:bamboo_door'},
|
||||
}
|
||||
mcl_villages.material_substitions = {
|
||||
desert = {
|
||||
{ '"mcl_stairs:slab_oak([^"]*)"', '"mcl_stairs:slab_sandstonesmooth2%1"' }, -- divert from MCLA, no version 1?
|
||||
{
|
||||
'"mesecons_pressureplates:pressure_plate_oak_([^"]+)"',
|
||||
'"mesecons_pressureplates:pressure_plate_birchwood_%1"',
|
||||
},
|
||||
{ '"mcl_doors:trapdoor_oak([^"]*)"', '"mcl_doors:birch_trapdoor%1"' },
|
||||
{ '"mcl_doors:door_oak([^"]*)"', '"mcl_doors:birch_door%1"' },
|
||||
|
||||
{ "mcl_core:cobble", "mcl_core:sandstone" },
|
||||
{ '"mcl_stairs:stair_cobble([^"]*)"', '"mcl_stairs:stair_sandstone%1"' },
|
||||
{ '"mcl_walls:cobble([^"]*)"', '"mcl_walls:sandstone%1"' },
|
||||
{ '"mcl_stairs:slab_cobble([^"]*)"', '"mcl_stairs:slab_sandstone%1"' },
|
||||
|
||||
{ '"mcl_core:stonebrick"', '"mcl_core:redsandstone"' },
|
||||
{ '"mcl_core:stonebrick_([^"]+)"', '"mcl_core:redsandstone_%1"' },
|
||||
{ '"mcl_walls:stonebrick([^"]*)"', '"mcl_walls:redsandstone%1"' },
|
||||
{ '"mcl_stairs:stair_stonebrick"', '"mcl_stairs:stair_redsandstone"' },
|
||||
{ '"mcl_stairs:stair_stonebrick_([^"]+)"', '"mcl_stairs:stair_redsandstone_%1"' },
|
||||
|
||||
{ '"mcl_stairs:slab_brick_block([^"]*)"', '"mcl_core:redsandstonesmooth2%1"' },
|
||||
{ '"mcl_core:brick_block"', '"mcl_core:redsandstonesmooth2"' },
|
||||
|
||||
{ "mcl_trees:tree_oak", "mcl_core:redsandstonecarved" },
|
||||
{ "mcl_trees:wood_oak", "mcl_core:redsandstonesmooth" },
|
||||
{ '"mcl_fences:oak_fence([^"]*)"', '"mcl_fences:birch_fence%1"' },
|
||||
{ '"mcl_stairs:stair_oak_bark([^"]*)"', '"mcl_stairs:stair_sandstonesmooth2%1"' },
|
||||
{ '"mcl_stairs:stair_oak([^"]*)"', '"mcl_stairs:stair_sandstonesmooth2%1"' }, -- divert from MCLA, no version 1?
|
||||
{ '"mcl_core:leaves"', '"air"' }, -- addition to MCLA
|
||||
},
|
||||
spruce = {
|
||||
{ '"mcl_stairs:slab_oak([^"]*)"', '"mcl_stairs:slab_sprucewood%1"' },
|
||||
{
|
||||
'"mesecons_pressureplates:pressure_plate_oak_([^"]+)"',
|
||||
'"mesecons_pressureplates:pressure_plate_sprucewood_%1"',
|
||||
},
|
||||
{ '"mcl_doors:trapdoor_oak([^"]*)"', '"mcl_doors:spruce_trapdoor%1"' },
|
||||
{ '"mcl_doors:door_oak([^"]*)"', '"mcl_doors:spruce_door%1"' },
|
||||
{ "mcl_trees:tree_oak", "mcl_trees:tree_spruce" },
|
||||
{ "mcl_trees:wood_oak", "mcl_trees:wood_spruce" },
|
||||
{ '"mcl_fences:oak_fence([^"]*)"', '"mcl_fences:spruce_fence%1"' },
|
||||
{ '"mcl_stairs:stair_oak([^"]*)"', '"mcl_stairs:stair_spruce%1"' },
|
||||
{ '"mcl_core:leaves"', '"mcl_core:spruceleaves"' }, -- addition to MCLA
|
||||
},
|
||||
birch = {
|
||||
{ '"mcl_stairs:slab_oak([^"]*)"', '"mcl_stairs:slab_birchwood%1"' },
|
||||
{
|
||||
'"mesecons_pressureplates:pressure_plate_oak_([^"]+)"',
|
||||
'"mesecons_pressureplates:pressure_plate_birchwood_%1"',
|
||||
},
|
||||
{ '"mcl_doors:trapdoor_oak([^"]*)"', '"mcl_doors:birch_trapdoor%1"' },
|
||||
{ '"mcl_doors:door_oak([^"]*)"', '"mcl_doors:birch_door%1"' },
|
||||
{ "mcl_trees:tree_oak", "mcl_core:stripped_birch" }, -- divert from MCLA, use stripped birch, what is the name in MCLA?
|
||||
{ "mcl_trees:wood_oak", "mcl_trees:wood_birch" },
|
||||
{ '"mcl_fences:oak_fence([^"]*)"', '"mcl_fences:birch_fence%1"' },
|
||||
{ '"mcl_stairs:stair_oak([^"]*)"', '"mcl_stairs:stair_birch%1"' },
|
||||
{ '"mcl_core:leaves"', '"mcl_core:birchleaves"' }, -- addition to MCLA
|
||||
},
|
||||
acacia = {
|
||||
{ '"mcl_stairs:slab_oak([^"]*)"', '"mcl_stairs:slab_acaciawood%1"' },
|
||||
{
|
||||
'"mesecons_pressureplates:pressure_plate_oak_([^"]+)"',
|
||||
'"mesecons_pressureplates:pressure_plate_acaciawood_%1"',
|
||||
},
|
||||
{ '"mcl_doors:trapdoor_oak([^"]*)"', '"mcl_doors:acacia_trapdoor%1"' },
|
||||
{ '"mcl_doors:door_oak([^"]*)"', '"mcl_doors:acacia_door%1"' },
|
||||
{ "mcl_trees:tree_oak", "mcl_trees:tree_acacia" },
|
||||
{ "mcl_trees:wood_oak", "mcl_trees:wood_acacia" },
|
||||
{ '"mcl_fences:oak_fence([^"]*)"', '"mcl_fences:acacia_fence%1"' },
|
||||
{ '"mcl_stairs:stair_oak([^"]*)"', '"mcl_stairs:stair_acacia%1"' },
|
||||
{ '"mcl_core:leaves"', '"mcl_core:acacialeaves"' }, -- addition to MCLA
|
||||
},
|
||||
dark_oak = {
|
||||
{ '"mcl_stairs:slab_oak([^"]*)"', '"mcl_stairs:slab_darkwood%1"' },
|
||||
{
|
||||
'"mesecons_pressureplates:pressure_plate_oak_([^"]+)"',
|
||||
'"mesecons_pressureplates:pressure_plate_darkwood_%1"',
|
||||
},
|
||||
{ '"mcl_doors:trapdoor_oak([^"]*)"', '"mcl_doors:dark_oak_trapdoor%1"' },
|
||||
{ '"mcl_doors:door_oak([^"]*)"', '"mcl_doors:dark_oak_door%1"' },
|
||||
{ "mcl_trees:tree_oak", "mcl_trees:tree_dark_oak" },
|
||||
{ "mcl_trees:wood_oak", "mcl_trees:wood_dark_oak" },
|
||||
{ '"mcl_fences:oak_fence([^"]*)"', '"mcl_fences:dark_oak_fence%1"' },
|
||||
{ '"mcl_stairs:stair_oak([^"]*)"', '"mcl_stairs:stair_dark_oak%1"' },
|
||||
{ '"mcl_core:leaves"', '"mcl_core:darkleaves"' }, -- addition to MCLA
|
||||
},
|
||||
jungle = {
|
||||
{ '"mcl_stairs:slab_oak([^"]*)"', '"mcl_stairs:slab_junglewood%1"' },
|
||||
{
|
||||
'"mesecons_pressureplates:pressure_plate_oak_([^"]+)"',
|
||||
'"mesecons_pressureplates:pressure_plate_junglewood_%1"',
|
||||
},
|
||||
{ '"mcl_doors:trapdoor_oak([^"]*)"', '"mcl_doors:jungle_trapdoor%1"' },
|
||||
{ '"mcl_doors:door_oak([^"]*)"', '"mcl_doors:jungle_door%1"' },
|
||||
{ "mcl_trees:tree_oak", "mcl_trees:tree_jungle" },
|
||||
{ "mcl_trees:wood_oak", "mcl_trees:wood_jungle" },
|
||||
{ '"mcl_fences:oak_fence([^"]*)"', '"mcl_fences:jungle_fence%1"' },
|
||||
{ '"mcl_stairs:stair_oak([^"]*)"', '"mcl_stairs:stair_jungle%1"' },
|
||||
{ '"mcl_core:leaves"', '"mcl_core:jungleleaves"' }, -- addition to MCLA
|
||||
},
|
||||
bamboo = {
|
||||
{ '"mcl_stairs:slab_oak([^"]*)"', '"mcl_stairs:slab_bamboo_plank%1"' }, -- divert from MCLA
|
||||
{
|
||||
'"mesecons_pressureplates:pressure_plate_oak_([^"]+)"',
|
||||
'"mesecons_pressureplates:pressure_plate_bamboo_%1"',
|
||||
},
|
||||
{ '"mcl_doors:trapdoor_oak([^"]*)"', '"mcl_doors:trapdoor_bamboo%1"' },
|
||||
{ '"mcl_doors:door_oak([^"]*)"', '"mcl_doors:door_bamboo%1"' },
|
||||
|
||||
{ "mcl_core:cobble", "mcl_core:andesite" },
|
||||
{ '"mcl_stairs:stair_cobble([^"]*)"', '"mcl_stairs:stair_andesite%1"' },
|
||||
{ '"mcl_walls:cobble([^"]*)"', '"mcl_walls:andesite%1"' },
|
||||
{ '"mcl_stairs:slab_cobble([^"]*)"', '"mcl_stairs:slab_andesite%1"' },
|
||||
{ "mcl_trees:tree_oak", "mcl_trees:tree_bamboo" },
|
||||
{ "mcl_trees:wood_oak", "mcl_trees:wood_bamboo" },
|
||||
{ '"mcl_fences:oak_fence([^"]*)"', '"mcl_fences:bamboo_fence%1"' },
|
||||
{ '"mcl_stairs:stair_oak([^"]*)"', '"mcl_stairs:stair_bamboo%1"' },
|
||||
{ '"mcl_core:leaves"', '"air"' }, -- addition to MCLA
|
||||
},
|
||||
cherry = {
|
||||
{ '"mcl_stairs:slab_oak([^"]*)"', '"mcl_stairs:slab_cherry_blossom%1"' },
|
||||
{
|
||||
'"mesecons_pressureplates:pressure_plate_oak_([^"]+)"',
|
||||
'"mesecons_pressureplates:pressure_plate_cherry_blossom_%1"',
|
||||
},
|
||||
{ '"mcl_doors:trapdoor_oak([^"]*)"', '"mcl_doors:trapdoor_cherry_blossom%1"' },
|
||||
{ '"mcl_doors:door_oak([^"]*)"', '"mcl_doors:door_cherry_blossom%1"' },
|
||||
{ "mcl_trees:tree_oak", "mcl_trees:tree_cherry_blossom" },
|
||||
{ "mcl_trees:wood_oak", "mcl_trees:wood_cherry_blossom" },
|
||||
{ '"mcl_fences:oak_fence([^"]*)"', '"mcl_fences:cherry_blossom_fence%1"' },
|
||||
{ '"mcl_stairs:stair_oak([^"]*)"', '"mcl_stairs:stair_cherry_blossom%1"' },
|
||||
{ '"mcl_core:leaves"', '"mcl_core:leaves"' }, -- addition to MCLA
|
||||
},
|
||||
}
|
||||
|
|
|
@ -1,90 +0,0 @@
|
|||
local function mcl_log (message)
|
||||
mcl_util.mcl_log (message, "[Village - Foundation]")
|
||||
end
|
||||
|
||||
local foundation_materials = {}
|
||||
|
||||
foundation_materials["mcl_core:sand"] = "mcl_core:sandstone"
|
||||
--"mcl_core:sandstonecarved"
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
-- function to fill empty space below baseplate when building on a hill
|
||||
-------------------------------------------------------------------------------
|
||||
function settlements.ground(pos, pr, platform_material) -- role model: Wendelsteinkircherl, Brannenburg
|
||||
local p2 = vector.new(pos)
|
||||
local cnt = 0
|
||||
|
||||
local mat = "mcl_core:dirt"
|
||||
if not platform_material then
|
||||
mat = "mcl_core:dirt"
|
||||
else
|
||||
mat = platform_material
|
||||
end
|
||||
|
||||
p2.y = p2.y-1
|
||||
while true do
|
||||
cnt = cnt+1
|
||||
if cnt > 20 then break end
|
||||
if cnt>pr:next(2,4) then
|
||||
if not platform_material then
|
||||
mat = "mcl_core:stone"
|
||||
end
|
||||
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
|
||||
|
||||
local surface_mat = settlement_info[i]["surface_mat"]
|
||||
mcl_log("Surface material: " .. tostring(surface_mat))
|
||||
local platform_mat = foundation_materials[surface_mat]
|
||||
mcl_log("Foundation material: " .. tostring(platform_mat))
|
||||
|
||||
--
|
||||
-- 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}
|
||||
-- Pass in biome info and make foundations of same material (seed: apple for desert)
|
||||
settlements.ground(p, pr, platform_mat)
|
||||
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,79 +1,31 @@
|
|||
settlements = {}
|
||||
settlements.modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
mcl_villages = {}
|
||||
mcl_villages.modpath = minetest.get_modpath(minetest.get_current_modname())
|
||||
|
||||
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.grundstellungen()
|
||||
local village_boost = tonumber(minetest.settings:get("vl_villages_boost")) or 1
|
||||
|
||||
dofile(mcl_villages.modpath.."/const.lua")
|
||||
dofile(mcl_villages.modpath.."/utils.lua")
|
||||
dofile(mcl_villages.modpath.."/buildings.lua")
|
||||
dofile(mcl_villages.modpath.."/paths.lua")
|
||||
dofile(mcl_villages.modpath.."/api.lua")
|
||||
|
||||
local S = minetest.get_translator(minetest.get_current_modname())
|
||||
|
||||
local villagegen={}
|
||||
--
|
||||
-- register block for npc spawn
|
||||
--
|
||||
minetest.register_node("mcl_villages:stonebrickcarved", {
|
||||
description = S("Chiseled Stone Village Bricks"),
|
||||
_doc_items_longdesc = doc.sub.items.temp.build,
|
||||
tiles = {"mcl_core_stonebrick_carved.png"},
|
||||
drop = "mcl_core:stonebrickcarved",
|
||||
groups = {pickaxey=1, stone=1, stonebrick=1, building_block=1, material_stone=1},
|
||||
sounds = mcl_sounds.node_sound_stone_defaults(),
|
||||
is_ground_content = false,
|
||||
_mcl_blast_resistance = 6,
|
||||
_mcl_hardness = 1.5,
|
||||
})
|
||||
|
||||
minetest.register_node("mcl_villages:structblock", {drawtype="airlike",groups = {not_in_creative_inventory=1},})
|
||||
|
||||
|
||||
|
||||
--[[ Enable for testing, but use MineClone2's own spawn code if/when merging.
|
||||
--
|
||||
-- register inhabitants
|
||||
--
|
||||
if minetest.get_modpath("mobs_mc") then
|
||||
mcl_mobs:register_spawn("mobs_mc:villager", --name
|
||||
{"mcl_core:stonebrickcarved"}, --nodes
|
||||
15, --max_light
|
||||
0, --min_light
|
||||
20, --chance
|
||||
7, --active_object_count
|
||||
31000, --max_height
|
||||
nil) --day_toggle
|
||||
end
|
||||
--]]
|
||||
|
||||
--
|
||||
-- on map generation, try to build a settlement
|
||||
--
|
||||
local function build_a_settlement(minp, maxp, 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)
|
||||
end
|
||||
|
||||
local function ecb_village(blockpos, action, calls_remaining, param)
|
||||
if calls_remaining >= 1 then return end
|
||||
local minp, maxp, blockseed = param.minp, param.maxp, param.blockseed
|
||||
build_a_settlement(minp, maxp, blockseed)
|
||||
if mcl_villages.village_exists(param.blockseed) then return end
|
||||
local pr = PcgRandom(param.blockseed)
|
||||
local vm = VoxelManip(param.minp, param.maxp)
|
||||
local settlement = mcl_villages.create_site_plan(vm, param.minp, param.maxp, pr)
|
||||
if not settlement then return false, false end
|
||||
-- all foundations first, then all buildings, to avoid damaging very close buildings
|
||||
mcl_villages.terraform(vm, settlement, pr)
|
||||
mcl_villages.place_schematics(vm, settlement, param.blockseed, pr)
|
||||
mcl_villages.add_village(param.blockseed, settlement)
|
||||
--lvm:write_to_map(true) -- destorys paths as of now, as they are placed afterwards
|
||||
for _, on_village_placed_callback in pairs(mcl_villages.on_village_placed) do
|
||||
on_village_placed_callback(settlement, param.blockseed)
|
||||
end
|
||||
end
|
||||
|
||||
-- Disable natural generation in singlenode.
|
||||
|
@ -81,61 +33,412 @@ local mg_name = minetest.get_mapgen_setting("mg_name")
|
|||
if mg_name ~= "singlenode" then
|
||||
mcl_mapgen_core.register_generator("villages", nil, function(minp, maxp, blockseed)
|
||||
if maxp.y < 0 then return end
|
||||
|
||||
-- randomly try to build settlements
|
||||
if blockseed % 77 ~= 17 then return end
|
||||
--minetest.log("Rng good. Generate attempt")
|
||||
|
||||
-- needed for manual and automated settlement building
|
||||
-- don't build settlements on (too) uneven terrain
|
||||
local n=minetest.get_node_or_nil(minp)
|
||||
if n and n.name == "mcl_villages:structblock" then return end
|
||||
--minetest.log("No existing village attempt here")
|
||||
|
||||
if villagegen[minetest.pos_to_string(minp)] ~= nil then return end
|
||||
|
||||
--minetest.log("Not in village gen. Put down placeholder: " .. minetest.pos_to_string(minp) .. " || " .. minetest.pos_to_string(maxp))
|
||||
minetest.set_node(minp,{name="mcl_villages:structblock"})
|
||||
|
||||
local height_difference = settlements.evaluate_heightmap()
|
||||
if not height_difference or height_difference > max_height_difference then
|
||||
minetest.log("action", "Do not spawn village here as heightmap not good")
|
||||
return
|
||||
if village_boost == 0 then return end
|
||||
local pr = PcgRandom(blockseed)
|
||||
if pr:next(0,1e9) * 100e-9 >= village_boost then return end
|
||||
if village_boost < 25 then -- otherwise, this tends to transitively emerge too much
|
||||
minp, maxp = vector.offset(minp, -16, 0, -16), vector.offset(maxp, 16, 0, 16)
|
||||
end
|
||||
--minetest.log("Build me a village: " .. minetest.pos_to_string(minp) .. " || " .. minetest.pos_to_string(maxp))
|
||||
villagegen[minetest.pos_to_string(minp)]={minp=vector.new(minp), maxp=vector.new(maxp), blockseed=blockseed}
|
||||
minetest.emerge_area(minp, maxp, ecb_village, { minp = minp, maxp = maxp, blockseed = blockseed })
|
||||
end)
|
||||
end
|
||||
|
||||
-- Handle legacy structblocks that are not fully emerged yet.
|
||||
minetest.register_node("mcl_villages:structblock", {drawtype="airlike",groups = {not_in_creative_inventory=1}})
|
||||
minetest.register_lbm({
|
||||
name = "mcl_villages:structblock",
|
||||
run_at_every_load = true,
|
||||
nodenames = {"mcl_villages:structblock"},
|
||||
action = function(pos, node)
|
||||
minetest.set_node(pos, {name = "air"})
|
||||
if not villagegen[minetest.pos_to_string(pos)] then return end
|
||||
local minp=villagegen[minetest.pos_to_string(pos)].minp
|
||||
local maxp=villagegen[minetest.pos_to_string(pos)].maxp
|
||||
minetest.emerge_area(minp, maxp, ecb_village, villagegen[minetest.pos_to_string(minp)])
|
||||
villagegen[minetest.pos_to_string(minp)]=nil
|
||||
local minp, maxp = vector.offset(pos, -40, -40, -40), vector.offset(pos, 40, 40, 40)
|
||||
local blockseed = PcgRandom(minetest.hash_node_position(pos)):next()
|
||||
minetest.emerge_area(minp, maxp, ecb_village, { minp = minp, maxp = maxp, blockseed = blockseed})
|
||||
end
|
||||
})
|
||||
|
||||
-- manually place villages
|
||||
if minetest.is_creative_enabled("") then
|
||||
minetest.register_craftitem("mcl_villages:tool", {
|
||||
description = S("mcl_villages build tool"),
|
||||
inventory_image = "default_tool_woodshovel.png",
|
||||
-- build ssettlement
|
||||
-- build settlement
|
||||
on_place = function(itemstack, placer, pointed_thing)
|
||||
if not pointed_thing.under then return end
|
||||
if not minetest.check_player_privs(placer, "server") then
|
||||
minetest.chat_send_player(placer:get_player_name(), S("Placement denied. You need the “server” privilege to place villages."))
|
||||
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))
|
||||
local pos = pointed_thing.under
|
||||
local minp, maxp = vector.offset(pos, -40, -40, -40), vector.offset(pos, 40, 40, 40)
|
||||
local blockseed = PcgRandom(minetest.hash_node_position(pos)):next()
|
||||
minetest.emerge_area(minp, maxp, ecb_village, { minp = minp, maxp = maxp, blockseed = blockseed })
|
||||
end
|
||||
})
|
||||
mcl_wip.register_experimental_item("mcl_villages:tool")
|
||||
end
|
||||
|
||||
-- This makes the temporary node invisble unless in creative mode
|
||||
local drawtype = minetest.is_creative_enabled("") and "glasslike" or "airlike"
|
||||
|
||||
-- Special node for schematics editing: no path on this place
|
||||
minetest.register_node("mcl_villages:no_paths", {
|
||||
description = S("Prevent paths from being placed during villager generation. Replaced by air after village path generation"),
|
||||
paramtype = "light",
|
||||
drawtype = drawtype,
|
||||
inventory_image = "mcl_core_barrier.png",
|
||||
wield_image = "mcl_core_barrier.png",
|
||||
tiles = { "mcl_core_barrier.png" },
|
||||
is_ground_content = false,
|
||||
groups = { creative_breakable = 1, not_solid = 1, not_in_creative_inventory = 1 },
|
||||
})
|
||||
|
||||
-- Special node for schematics editing: path endpoint
|
||||
minetest.register_node("mcl_villages:path_endpoint", {
|
||||
description = S("Mark the node as a good place for paths to connect to"),
|
||||
is_ground_content = false,
|
||||
tiles = { "wool_white.png" },
|
||||
wield_image = "wool_white.png",
|
||||
wield_scale = { x = 1, y = 1, z = 0.5 },
|
||||
groups = { handy = 1, supported_node = 1, not_in_creative_inventory = 1 },
|
||||
sounds = mcl_sounds.node_sound_wool_defaults(),
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
drawtype = "nodebox",
|
||||
node_box = { type = "fixed", fixed = { { -0.5, -0.5, -0.5, 0.5, -0.45, 0.5 } } },
|
||||
_mcl_hardness = 0.1,
|
||||
_mcl_blast_resistance = 0.1,
|
||||
})
|
||||
|
||||
local schem_path = mcl_villages.modpath .. "/schematics/"
|
||||
|
||||
mcl_villages.register_bell({ name = "belltower", mts = schem_path .. "new_villages/belltower.mts", yadjust = 1 })
|
||||
|
||||
mcl_villages.register_well({
|
||||
name = "well",
|
||||
mts = schem_path .. "new_villages/well.mts",
|
||||
yadjust = -1,
|
||||
})
|
||||
|
||||
for i = 1, 6 do
|
||||
mcl_villages.register_lamp({
|
||||
name = "lamp",
|
||||
mts = schem_path .. "new_villages/lamp_" .. i .. ".mts",
|
||||
yadjust = 1,
|
||||
no_ground_turnip = true,
|
||||
no_clearance = true,
|
||||
})
|
||||
end
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "house_big",
|
||||
mts = schem_path .. "new_villages/house_4_bed.mts",
|
||||
min_jobs = 6,
|
||||
max_jobs = 99,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "house_large",
|
||||
mts = schem_path .. "new_villages/house_3_bed.mts",
|
||||
min_jobs = 4,
|
||||
max_jobs = 99,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "house_medium",
|
||||
mts = schem_path .. "new_villages/house_2_bed.mts",
|
||||
min_jobs = 2,
|
||||
max_jobs = 99,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "house_chimney",
|
||||
mts = schem_path .. "haeuschen2.mts",
|
||||
min_jobs = 2,
|
||||
max_jobs = 99,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "house_small",
|
||||
mts = schem_path .. "new_villages/house_1_bed.mts",
|
||||
min_jobs = 1,
|
||||
max_jobs = 99,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "blacksmith",
|
||||
mts = schem_path .. "new_villages/blacksmith.mts",
|
||||
num_others = 8,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "butcher",
|
||||
mts = schem_path .. "new_villages/butcher.mts",
|
||||
num_others = 8,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "farm",
|
||||
mts = schem_path .. "new_villages/farm.mts",
|
||||
num_others = 3,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "fish_farm",
|
||||
mts = schem_path .. "new_villages/fishery.mts",
|
||||
num_others = 8,
|
||||
yadjust = -2,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "fletcher_tiny",
|
||||
group = "g:fletcher",
|
||||
mts = schem_path .. "bogner.mts",
|
||||
num_others = 8,
|
||||
max_jobs = 6,
|
||||
yadjust = 0,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "fletcher",
|
||||
group = "g:fletcher",
|
||||
mts = schem_path .. "new_villages/fletcher.mts",
|
||||
num_others = 8,
|
||||
min_jobs = 7,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "library",
|
||||
group = "g:library",
|
||||
mts = schem_path .. "new_villages/library.mts",
|
||||
min_jobs = 12,
|
||||
max_jobs = 99,
|
||||
num_others = 15,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "librarian",
|
||||
group = "g:library",
|
||||
mts = schem_path .. "schreiber.mts",
|
||||
min_jobs = 1,
|
||||
max_jobs = 11,
|
||||
yadjust = 0,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "map_shop",
|
||||
mts = schem_path .. "new_villages/cartographer.mts",
|
||||
num_others = 15,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "mason",
|
||||
mts = schem_path .. "new_villages/mason.mts",
|
||||
num_others = 8,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "mill",
|
||||
mts = schem_path .. "new_villages/mill.mts",
|
||||
num_others = 8,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "tannery",
|
||||
mts = schem_path .. "new_villages/leather_worker.mts",
|
||||
num_others = 8,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "tool_smith",
|
||||
mts = schem_path .. "new_villages/toolsmith.mts",
|
||||
num_others = 8,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "weapon_smith",
|
||||
mts = schem_path .. "new_villages/weaponsmith.mts",
|
||||
num_others = 8,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "chapel",
|
||||
group = "g:church",
|
||||
mts = schem_path .. "new_villages/chapel.mts",
|
||||
num_others = 8,
|
||||
min_jobs = 1,
|
||||
max_jobs = 9,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "church_european",
|
||||
group = "g:church",
|
||||
mts = schem_path .. "kirche.mts",
|
||||
num_others = 20,
|
||||
min_jobs = 8,
|
||||
max_jobs = 99,
|
||||
yadjust = 0,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "church",
|
||||
group = "g:church",
|
||||
mts = schem_path .. "new_villages/church.mts",
|
||||
num_others = 20,
|
||||
min_jobs = 8,
|
||||
max_jobs = 99,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "farm_small",
|
||||
mts = schem_path .. "new_villages/farm_small_1.mts",
|
||||
num_others = 3,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "farm_small2",
|
||||
mts = schem_path .. "new_villages/farm_small_2.mts",
|
||||
num_others = 3,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_building({
|
||||
name = "farm_large",
|
||||
mts = schem_path .. "new_villages/farm_large_1.mts",
|
||||
num_others = 6,
|
||||
yadjust = 1,
|
||||
})
|
||||
|
||||
mcl_villages.register_crop({
|
||||
type = "grain",
|
||||
node = "mcl_farming:wheat_1",
|
||||
biomes = {
|
||||
acacia = 10,
|
||||
bamboo = 10,
|
||||
desert = 10,
|
||||
jungle = 10,
|
||||
plains = 10,
|
||||
savanna = 10,
|
||||
spruce = 10,
|
||||
},
|
||||
})
|
||||
|
||||
mcl_villages.register_crop({
|
||||
type = "root",
|
||||
node = "mcl_farming:carrot_1",
|
||||
biomes = {
|
||||
acacia = 10,
|
||||
bamboo = 6,
|
||||
desert = 10,
|
||||
jungle = 6,
|
||||
plains = 6,
|
||||
spruce = 10,
|
||||
},
|
||||
})
|
||||
|
||||
mcl_villages.register_crop({
|
||||
type = "root",
|
||||
node = "mcl_farming:potato_1",
|
||||
biomes = {
|
||||
acacia = 6,
|
||||
bamboo = 10,
|
||||
desert = 6,
|
||||
jungle = 10,
|
||||
plains = 10,
|
||||
spruce = 6,
|
||||
},
|
||||
})
|
||||
|
||||
mcl_villages.register_crop({
|
||||
type = "root",
|
||||
node = "mcl_farming:beetroot_0",
|
||||
biomes = {
|
||||
acacia = 3,
|
||||
bamboo = 3,
|
||||
desert = 3,
|
||||
jungle = 3,
|
||||
plains = 3,
|
||||
spruce = 3,
|
||||
},
|
||||
})
|
||||
|
||||
mcl_villages.register_crop({
|
||||
type = "gourd",
|
||||
node = "mcl_farming:melontige_1",
|
||||
biomes = {
|
||||
bamboo = 10,
|
||||
jungle = 10,
|
||||
},
|
||||
})
|
||||
|
||||
mcl_villages.register_crop({
|
||||
type = "gourd",
|
||||
node = "mcl_farming:pumpkin_1",
|
||||
biomes = {
|
||||
acacia = 10,
|
||||
bamboo = 5,
|
||||
desert = 10,
|
||||
jungle = 5,
|
||||
plains = 10,
|
||||
spruce = 10,
|
||||
},
|
||||
})
|
||||
|
||||
-- TODO: make flowers biome-specific
|
||||
for name, def in pairs(minetest.registered_nodes) do
|
||||
if def.groups.flower and not def.groups.double_plant and name ~= "mcl_flowers:wither_rose" then
|
||||
mcl_villages.register_crop({
|
||||
type = "flower",
|
||||
node = name,
|
||||
biomes = {
|
||||
acacia = 10,
|
||||
bamboo = 6,
|
||||
desert = 10,
|
||||
jungle = 6,
|
||||
plains = 6,
|
||||
spruce = 10,
|
||||
},
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- Crop placeholder nodes at different growth stages, for designing schematics
|
||||
for _, crop_type in ipairs(mcl_villages.get_crop_types()) do
|
||||
for count = 1, 8 do
|
||||
local tile = crop_type .. "_" .. count .. ".png"
|
||||
minetest.register_node("mcl_villages:crop_" .. crop_type .. "_" .. count, {
|
||||
description = S("A place to plant @1 crops", crop_type),
|
||||
is_ground_content = false,
|
||||
tiles = { tile },
|
||||
wield_image = tile,
|
||||
wield_scale = { x = 1, y = 1, z = 0.5 },
|
||||
groups = { handy = 1, supported_node = 1, not_in_creative_inventory = 1 },
|
||||
paramtype = "light",
|
||||
sunlight_propagates = true,
|
||||
drawtype = "nodebox",
|
||||
node_box = { type = "fixed", fixed = { { -0.5, -0.5, -0.5, 0.5, -0.45, 0.5 } } },
|
||||
_mcl_hardness = 0.1,
|
||||
_mcl_blast_resistance = 0.1,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name = mcl_villages
|
||||
author = Rochambeau
|
||||
author = Rochambeau, kno10
|
||||
description = This mod adds settlements on world generation.
|
||||
depends = mcl_util, mcl_mapgen_core, mcl_structures, mcl_core, mcl_loot
|
||||
optional_depends = mcl_farming, mobs_mc
|
||||
depends = mcl_core, mcl_util, mcl_mapgen_core, mcl_structures, mcl_loot, mobs_mc, vl_terraforming
|
||||
optional_depends = mcl_farming
|
||||
|
|
|
@ -1,91 +1,341 @@
|
|||
-------------------------------------------------------------------------------
|
||||
-- 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
|
||||
local light_threshold = tonumber(minetest.settings:get("mcl_villages_light_threshold")) or 5
|
||||
|
||||
end_point = settlement_info[o]["pos"]
|
||||
if starting_point ~= end_point
|
||||
then
|
||||
-- loop until end_point is reched (distance == 0)
|
||||
-- This ends up being a nested table.
|
||||
-- 1st level is the blockseed which is the village
|
||||
-- 2nd is the distance of the building from the bell
|
||||
-- 3rd is the pos of the end points
|
||||
local path_ends = {}
|
||||
|
||||
-- note: not using LVM here, as this runs after the pathfinder
|
||||
-- simple function to increase "no_paths" walls
|
||||
function mcl_villages.clean_no_paths(minp, maxp)
|
||||
local no_paths_nodes = minetest.find_nodes_in_area(minp, maxp, { "mcl_villages:no_paths" })
|
||||
if #no_paths_nodes > 0 then
|
||||
minetest.bulk_swap_node(no_paths_nodes, { name = "air" })
|
||||
end
|
||||
end
|
||||
|
||||
-- this can still run in LVM
|
||||
-- simple function to increase "no_paths" walls
|
||||
function mcl_villages.increase_no_paths(vm, minp, maxp)
|
||||
local p = vector.zero()
|
||||
for z = minp.z, maxp.z do
|
||||
p.z = z
|
||||
for x = minp.x, maxp.x do
|
||||
p.x = x
|
||||
for y = minp.y, maxp.y - 1 do
|
||||
p.y = y
|
||||
local n = vm:get_node_at(p)
|
||||
if n and n.name == "mcl_villages:no_paths" then
|
||||
p.y = y + 1
|
||||
n = vm:get_node_at(p)
|
||||
if n and n.name == "air" then
|
||||
vm:set_node_at(p, {name = "mcl_villages:no_paths" })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Insert end points in to the nested tables
|
||||
function mcl_villages.store_path_ends(vm, minp, maxp, pos, blockseed, bell_pos)
|
||||
-- We store by distance because we create paths far away from the bell first
|
||||
local dist = vector.distance(bell_pos, pos)
|
||||
local id = "block_" .. blockseed -- cannot use integers as keys
|
||||
local tab = path_ends[id]
|
||||
if not tab then
|
||||
tab = {}
|
||||
path_ends[id] = tab
|
||||
end
|
||||
if tab[dist] == nil then tab[dist] = {} end
|
||||
-- TODO: use LVM data instead of nodes? But we only process a subset of the area
|
||||
local v = vector.zero()
|
||||
for zi = minp.z, maxp.z do
|
||||
v.z = zi
|
||||
for yi = minp.y, maxp.y do
|
||||
v.y = yi
|
||||
for xi = minp.x, maxp.x do
|
||||
v.x = xi
|
||||
local n = vm:get_node_at(v)
|
||||
if n and n.name == "mcl_villages:path_endpoint" then
|
||||
table.insert(tab[dist], minetest.pos_to_string(v))
|
||||
vm:set_node_at(v, { name = "air" })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function place_lamp(pos, pr)
|
||||
local lamp_index = pr:next(1, #mcl_villages.schematic_lamps)
|
||||
local schema = mcl_villages.schematic_lamps[lamp_index]
|
||||
local schem_lua = mcl_villages.substitute_materials(pos, schema.schem_lua, pr)
|
||||
local schematic = loadstring(schem_lua)()
|
||||
|
||||
minetest.place_schematic(vector.offset(pos, 0, schema.yadjust or 0, 0), schematic, "0",
|
||||
{["air"] = "ignore"}, -- avoid destroying stairs etc.
|
||||
true,
|
||||
{ place_center_x = true, place_center_y = false, place_center_z = true }
|
||||
)
|
||||
end
|
||||
|
||||
-- TODO: port this to lvm.
|
||||
local function smooth_path(path)
|
||||
-- Smooth out bumps in path or stairs can look naf
|
||||
for pass = 1, 3 do
|
||||
for i = 2, #path - 1 do
|
||||
local prev_y = path[i - 1].y
|
||||
local y = path[i].y
|
||||
local next_y = path[i + 1].y
|
||||
local bump = minetest.get_node(path[i]).name
|
||||
|
||||
-- TODO: also replace bamboo underneath with dirt here?
|
||||
if minetest.get_item_group(bump, "water") ~= 0 then
|
||||
-- ignore in this pass
|
||||
elseif y >= next_y + 2 and y <= prev_y then
|
||||
minetest.swap_node(vector.offset(path[i], 0, -1, 0), { name = "air" })
|
||||
path[i].y = path[i].y - 1
|
||||
elseif y <= next_y - 2 and y >= prev_y then
|
||||
minetest.swap_node(path[i], { name = "mcl_core:dirt" })
|
||||
path[i].y = path[i].y + 1
|
||||
elseif y >= prev_y + 2 and y <= next_y then
|
||||
minetest.swap_node(vector.offset(path[i], 0, -1, 0), { name = "air" })
|
||||
path[i].y = path[i].y - 1
|
||||
elseif y <= prev_y - 2 and y >= prev_y then
|
||||
minetest.swap_node(path[i], { name = "mcl_core:dirt" })
|
||||
path[i].y = path[i].y + 1
|
||||
elseif y < prev_y and y < next_y then
|
||||
-- Fill in dip to flatten path
|
||||
minetest.swap_node(path[i], { name = "mcl_core:dirt" })
|
||||
path[i].y = path[i].y + 1
|
||||
elseif y > prev_y and y > next_y then
|
||||
-- Remove peak to flatten path
|
||||
minetest.swap_node(vector.offset(path[i], 0, -1, 0), { name = "air" })
|
||||
path[i].y = path[i].y - 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO: port this to lvm.
|
||||
local function place_path(path, pr, stair, slab)
|
||||
-- Smooth out bumps in path or stairs can look naf
|
||||
for i = 2, #path - 1 do
|
||||
local prev_y = path[i - 1].y
|
||||
local y = path[i].y
|
||||
local next_y = path[i + 1].y
|
||||
local bump = minetest.get_node(path[i]).name
|
||||
|
||||
if minetest.get_item_group(bump, "water") ~= 0 then
|
||||
-- Find air
|
||||
local up_pos = vector.copy(path[i])
|
||||
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
|
||||
up_pos.y = up_pos.y + 1
|
||||
local up_node = minetest.get_node(up_pos).name
|
||||
if minetest.get_item_group(up_node, "water") == 0 then
|
||||
minetest.swap_node(up_pos, { name = "air" })
|
||||
path[i] = up_pos
|
||||
break
|
||||
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"})
|
||||
end
|
||||
elseif y < prev_y and y < next_y then
|
||||
-- Fill in dip to flatten path
|
||||
-- TODO: do not break other path/stairs
|
||||
minetest.swap_node(path[i], { name = "mcl_core:dirt" })
|
||||
path[i] = vector.offset(path[i], 0, 1, 0)
|
||||
elseif y > prev_y and y > next_y then
|
||||
-- TODO: do not break other path/stairs
|
||||
-- Remove peak to flatten path
|
||||
minetest.swap_node(vector.offset(path[i], 0, -1, 0), { name = "air" })
|
||||
path[i].y = path[i].y - 1
|
||||
end
|
||||
end
|
||||
|
||||
for i, pos in ipairs(path) do
|
||||
local n0 = minetest.get_node(pos).name
|
||||
if n0 ~= "air" then minetest.swap_node(pos, { name = "air" }) end
|
||||
|
||||
local under_pos = vector.offset(pos, 0, -1, 0)
|
||||
local n = minetest.get_node(under_pos).name
|
||||
local ndef = minetest.registered_nodes[n]
|
||||
local groups = ndef and ndef.groups or {}
|
||||
local done = false
|
||||
if i > 1 and pos.y > path[i - 1].y then
|
||||
-- stairs up
|
||||
if not groups.stair then
|
||||
done = true
|
||||
local param2 = minetest.dir_to_facedir(vector.subtract(pos, path[i - 1]))
|
||||
minetest.swap_node(under_pos, { name = stair, param2 = param2 })
|
||||
end
|
||||
elseif i < #path-1 and pos.y > path[i + 1].y then
|
||||
-- stairs down
|
||||
if not groups.stair then
|
||||
done = true
|
||||
local param2 = minetest.dir_to_facedir(vector.subtract(pos, path[i + 1]))
|
||||
minetest.swap_node(under_pos, { name = stair, param2 = param2 })
|
||||
end
|
||||
elseif not groups.stair and i > 1 and pos.y < path[i - 1].y then
|
||||
-- stairs down
|
||||
local n2 = minetest.get_node(vector.offset(path[i - 1], 0, -1, 0)).name
|
||||
if not minetest.get_item_group(n2, "stair") then
|
||||
done = true
|
||||
local param2 = minetest.dir_to_facedir(vector.subtract(path[i - 1], pos))
|
||||
if i < #path - 1 then -- uglier, but easier to walk up?
|
||||
param2 = minetest.dir_to_facedir(vector.subtract(pos, path[i + 1]))
|
||||
end
|
||||
minetest.add_node(pos, { name = stair, param2 = param2 })
|
||||
pos.y = pos.y + 1
|
||||
end
|
||||
elseif not groups.stair and i < #path-1 and pos.y < path[i + 1].y then
|
||||
-- stairs up
|
||||
local n2 = minetest.get_node(vector.offset(path[i + 1], 0, -1, 0)).name
|
||||
if not minetest.get_item_group(n2, "stair") then
|
||||
done = true
|
||||
local param2 = minetest.dir_to_facedir(vector.subtract(path[i + 1], pos))
|
||||
if i > 1 then -- uglier, but easier to walk up?
|
||||
param2 = minetest.dir_to_facedir(vector.subtract(pos, path[i - 1]))
|
||||
end
|
||||
minetest.add_node(pos, { name = stair, param2 = param2 })
|
||||
pos.y = pos.y + 1
|
||||
end
|
||||
end
|
||||
|
||||
-- flat
|
||||
if not done then
|
||||
if groups.water then
|
||||
minetest.add_node(under_pos, { name = slab })
|
||||
elseif groups.sand then
|
||||
minetest.swap_node(under_pos, { name = "mcl_core:sandstonesmooth2" })
|
||||
elseif groups.soil and not groups.dirtifies_below_solid then
|
||||
minetest.swap_node(under_pos, { name = "mcl_core:grass_path" })
|
||||
end
|
||||
end
|
||||
|
||||
-- Clear space for villagers to walk
|
||||
for j = 1, 2 do
|
||||
local over_pos = vector.offset(pos, 0, j, 0)
|
||||
if minetest.get_node(over_pos).name ~= "air" then
|
||||
minetest.swap_node(over_pos, { name = "air" })
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Do lamps afterwards so we don't put them where a path will be laid
|
||||
for _, pos in ipairs(path) do
|
||||
if minetest.get_node_light(pos, 0) < light_threshold then
|
||||
local nn = minetest.find_nodes_in_area_under_air(vector.offset(pos, -1, -1, -1), vector.offset(pos, 1, 1, 1),
|
||||
{ "group:material_sand", "group:material_stone", "group:grass_block", "group:wood_slab" }
|
||||
)
|
||||
-- todo: shuffle nn?
|
||||
for _, npos in ipairs(nn) do
|
||||
local node = minetest.get_node(npos).name
|
||||
if node ~= "mcl_core:grass_path" and minetest.get_item_group(node, "stair") == 0 then
|
||||
if minetest.get_item_group(node, "wood_slab") ~= 0 then
|
||||
minetest.add_node(vector.offset(npos, 0, 1, 0), { name = "mcl_torches:torch", param2 = 1 })
|
||||
else
|
||||
minetest.swap_node(surface_point,{name="mcl_core:grass_path"})
|
||||
place_lamp(npos, pr)
|
||||
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
|
||||
|
||||
-- FIXME: ugly
|
||||
function get_biome_stair_slab(biome_name)
|
||||
-- Use the same stair and slab throughout the entire village
|
||||
-- The quotes are necessary to be matched as JSON strings
|
||||
local stair, slab = '"mcl_stairs:stair_oak"', '"mcl_stairs:slab_oak_top"'
|
||||
-- Change stair and slab for biome
|
||||
if mcl_villages.biome_map[biome_name] and mcl_villages.material_substitions[mcl_villages.biome_map[biome_name]] then
|
||||
for _, sub in pairs(mcl_villages.material_substitions[mcl_villages.biome_map[biome_name]]) do
|
||||
stair = stair:gsub(sub[1], sub[2])
|
||||
slab = slab:gsub(sub[1], sub[2])
|
||||
end
|
||||
end
|
||||
-- translate MCLA values to VL
|
||||
for _, sub in pairs(mcl_villages.mcla_to_vl) do
|
||||
stair = stair:gsub(sub[1], sub[2])
|
||||
slab = slab:gsub(sub[1], sub[2])
|
||||
end
|
||||
-- The quotes are to match what is in JSON schemas, but we don't want them now
|
||||
return stair:gsub('"', ""), slab:gsub('"', "")
|
||||
end
|
||||
|
||||
-- Work out which end points should be connected
|
||||
-- works from the outside of the village in
|
||||
function mcl_villages.paths(blockseed, biome_name)
|
||||
local pr = PcgRandom(blockseed)
|
||||
local pathends = path_ends["block_" .. blockseed]
|
||||
if pathends == nil then
|
||||
minetest.log("warning", string.format("[mcl_villages] Tried to set paths for block seed that doesn't exist %d", blockseed))
|
||||
return
|
||||
end
|
||||
|
||||
-- Stair and slab style of the village
|
||||
local stair, slab = get_biome_stair_slab(biome_name)
|
||||
-- Keep track of connections
|
||||
local connected = {}
|
||||
|
||||
-- get a list of reverse sorted keys, which are distances
|
||||
local dist_keys = {}
|
||||
for k in pairs(pathends) do table.insert(dist_keys, k) end
|
||||
table.sort(dist_keys, function(a, b) return a > b end)
|
||||
--minetest.log("Planning paths with "..#dist_keys.." nodes")
|
||||
|
||||
for i, from in ipairs(dist_keys) do
|
||||
-- ep == end_point
|
||||
for _, from_ep in ipairs(pathends[from]) do
|
||||
local from_ep_pos = minetest.string_to_pos(from_ep)
|
||||
local closest_pos, closest_bld, best = nil, nil, 10000000
|
||||
|
||||
-- Most buildings only do other buildings that are closer to the bell
|
||||
-- for the bell do any end points that don't have paths near them
|
||||
local j = from == 0 and 1 or (i + 1)
|
||||
for j = j, #dist_keys do
|
||||
local to = dist_keys[j]
|
||||
if from ~= to and connected[from .. "-" .. to] == nil and connected[to .. "-" .. from] == nil then
|
||||
for _, to_ep in ipairs(pathends[to]) do
|
||||
local to_ep_pos = minetest.string_to_pos(to_ep)
|
||||
local dist = vector.distance(from_ep_pos, to_ep_pos)
|
||||
if dist < best then
|
||||
best = dist
|
||||
closest_pos = to_ep_pos
|
||||
closest_bld = to
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if closest_pos then
|
||||
local path = minetest.find_path(from_ep_pos, closest_pos, 64, 2, 2)
|
||||
if path then smooth_path(path) end
|
||||
if not path then
|
||||
path = minetest.find_path(from_ep_pos, closest_pos, 64, 3, 3)
|
||||
if path then smooth_path(path) end
|
||||
end
|
||||
path = minetest.find_path(from_ep_pos, closest_pos, 64, 1, 1)
|
||||
if path and #path > 0 then
|
||||
place_path(path, pr, stair, slab)
|
||||
connected[from .. "-" .. closest_bld] = 1
|
||||
else
|
||||
minetest.log("warning",
|
||||
string.format(
|
||||
"[mcl_villages] No good path from %s to %s, distance %d",
|
||||
minetest.pos_to_string(from_ep_pos),
|
||||
minetest.pos_to_string(closest_pos),
|
||||
vector.distance(from_ep_pos, closest_pos)
|
||||
)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
path_ends["block_" .. blockseed] = nil
|
||||
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.
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.
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.
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.
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue