2022-06-10 02:40:33 +02:00
mcl_structures.registered_structures = { }
2022-06-06 03:34:31 +02:00
2022-06-24 03:36:21 +02:00
local function generate_loot ( pos , def , pr )
local hl = def.sidelen / 2
local p1 = vector.offset ( pos , - hl , - hl , - hl )
local p2 = vector.offset ( pos , hl , hl , hl )
for it , lt in pairs ( def.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
2022-06-24 14:02:29 +02:00
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
2022-06-10 02:40:33 +02:00
function mcl_structures . place_structure ( pos , def , pr )
2022-06-10 04:34:58 +02:00
if not def then return end
2022-06-22 16:37:44 +02:00
local logging = not def.terrain_feature
2022-06-10 04:34:58 +02:00
local y_offset = 0
2022-06-10 01:06:24 +02:00
if type ( def.y_offset ) == " function " then
y_offset = def.y_offset ( pr )
elseif def.y_offset then
y_offset = def.y_offset
end
2022-06-24 02:11:24 +02:00
local pp = vector.offset ( pos , 0 , y_offset , 0 )
2022-06-22 16:47:43 +02:00
if def.solid_ground and def.sidelen then
2022-06-24 02:11:24 +02:00
local bn = minetest.get_biome_name ( minetest.get_biome_data ( pos ) . biome )
local node_top = minetest.registered_biomes [ bn ] . node_top
local node_fill = minetest.registered_biomes [ bn ] . node_filler
2022-06-23 20:22:36 +02:00
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 " } )
2022-06-24 02:11:24 +02:00
if # solid < ( def.sidelen * def.sidelen ) then
2022-06-23 20:22:36 +02:00
if def.make_foundation then
2022-06-24 02:11:24 +02:00
minetest.bulk_set_node ( minetest.find_nodes_in_area ( ground_p1 , ground_p2 , { " air " , " group:liquid " } ) , { name = node_top } )
minetest.bulk_set_node ( minetest.find_nodes_in_area ( vector.offset ( ground_p1 , 0 , - 1 , 0 ) , vector.offset ( ground_p2 , 0 , - 30 , 0 ) , { " air " , " group:liquid " } ) , { name = node_fill } )
2022-06-23 20:22:36 +02:00
else
if logging then
minetest.log ( " warning " , " [mcl_structures] " .. def.name .. " at " .. minetest.pos_to_string ( pos ) .. " not placed. No solid ground. " )
end
return false
2022-06-22 16:47:43 +02:00
end
end
end
2022-06-19 00:17:43 +02:00
if def.on_place and not def.on_place ( pos , def , pr ) then
2022-06-22 16:37:44 +02:00
if logging then
minetest.log ( " warning " , " [mcl_structures] " .. def.name .. " at " .. minetest.pos_to_string ( pos ) .. " not placed. Conditions not satisfied. " )
end
2022-06-19 00:17:43 +02:00
return false
end
2022-06-10 01:06:24 +02:00
if def.filenames then
2022-06-24 04:10:21 +02:00
if # def.filenames <= 0 then return false end
local r = pr : next ( 1 , # def.filenames )
local file = def.filenames [ r ]
2022-06-24 02:11:24 +02:00
if file then
local ap = function ( pos , def , pr ) end
if def.after_place then ap = def.after_place end
2022-06-24 03:36:21 +02:00
mcl_structures.place_schematic ( pp , file , " random " , nil , true , " place_center_x,place_center_z " , function ( p )
if def.loot then generate_loot ( pos , def , pr ) end
return ap ( pos , def , pr )
end , pr )
2022-06-24 02:11:24 +02:00
if logging then
minetest.log ( " action " , " [mcl_structures] " .. def.name .. " placed at " .. minetest.pos_to_string ( pos ) )
end
return true
2022-06-22 16:37:44 +02:00
end
2022-06-10 01:49:33 +02:00
elseif def.place_func and def.place_func ( pos , def , pr ) then
2022-06-10 04:34:58 +02:00
if not def.after_place or ( def.after_place and def.after_place ( pos , def , pr ) ) then
2022-06-22 16:37:44 +02:00
if logging then
minetest.log ( " action " , " [mcl_structures] " .. def.name .. " placed at " .. minetest.pos_to_string ( pos ) )
end
2022-06-10 04:34:58 +02:00
return true
end
2022-06-10 01:06:24 +02:00
end
2022-06-22 16:37:44 +02:00
if logging then
minetest.log ( " warning " , " [mcl_structures] placing " .. def.name .. " failed at " .. minetest.pos_to_string ( pos ) )
end
2022-06-10 01:06:24 +02:00
end
2022-06-06 03:34:31 +02:00
function mcl_structures . register_structure ( name , def , nospawn ) --nospawn means it will be placed by another (non-nospawn) structure that contains it's structblock i.e. it will not be placed by mapgen directly
local structblock = " mcl_structures:structblock_ " .. name
local flags = " place_center_x, place_center_z, force_placement "
local y_offset = 0
2022-06-10 01:06:24 +02:00
local sbgroups = { structblock = 1 , not_in_creative_inventory = 1 }
2022-06-06 03:34:31 +02:00
if def.flags then flags = def.flags end
def.name = name
2022-06-10 01:06:24 +02:00
if nospawn then
sbgroups.structblock = nil
sbgroups.structblock_lbm = 1
else
2022-06-24 02:11:24 +02:00
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 ,
decoration = structblock ,
deco_type = " simple " ,
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
} )
2022-06-24 03:36:21 +02:00
minetest.register_node ( " : " .. structblock , { drawtype = " airlike " , walkable = false , pointable = false , groups = sbgroups } )
def.structblock = structblock
2022-06-24 02:11:24 +02:00
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 )
2022-06-06 03:34:31 +02:00
end
2022-06-10 02:40:33 +02:00
mcl_structures.registered_structures [ name ] = def
2022-06-06 03:34:31 +02:00
end
2022-06-10 01:06:24 +02:00
--lbm for secondary structures (structblock included in base structure)
2022-06-06 03:34:31 +02:00
minetest.register_lbm ( {
name = " mcl_structures:struct_lbm " ,
run_at_every_load = true ,
2022-06-10 01:06:24 +02:00
nodenames = { " group:structblock_lbm " } ,
2022-06-06 03:34:31 +02:00
action = function ( pos , node )
2022-06-24 02:11:24 +02:00
minetest.remove_node ( pos )
2022-06-06 03:34:31 +02:00
local name = node.name : gsub ( " mcl_structures:structblock_ " , " " )
2022-06-10 02:40:33 +02:00
local def = mcl_structures.registered_structures [ name ]
2022-06-10 01:06:24 +02:00
if not def then return end
2022-06-10 02:40:33 +02:00
mcl_structures.place_structure ( pos )
2022-06-06 03:34:31 +02:00
end
} )