2022-06-10 03:40:33 +03:00
mcl_structures.registered_structures = { }
2022-06-06 04:34:31 +03:00
2022-06-10 03:40:33 +03:00
function mcl_structures . place_structure ( pos , def , pr )
2022-06-10 05:34:58 +03:00
if not def then return end
2022-06-22 17:37:44 +03:00
local logging = not def.terrain_feature
2022-06-10 05:34:58 +03:00
local y_offset = 0
2022-06-10 02:06:24 +03: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-22 17:47:43 +03:00
if def.solid_ground and def.sidelen then
local node = minetest.get_node ( vector.offset ( pos , 1 , 1 , 0 ) )
2022-06-23 21:22:36 +03: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-22 17:47:43 +03:00
local air = minetest.find_nodes_in_area ( vector.offset ( pos , - def.sidelen / 2 , 1 , - def.sidelen / 2 ) , vector.offset ( pos , def.sidelen / 2 , 4 , def.sidelen / 2 ) , { " air " } )
if # solid < ( def.sidelen * def.sidelen ) or
# air < ( def.sidelen * def.sidelen ) then
2022-06-23 21:22:36 +03:00
if def.make_foundation then
minetest.bulk_set_node ( minetest.find_nodes_in_area ( ground_p1 , vector.offset ( ground_p2 , 0 , - 30 , 0 ) , { " air " } ) , node )
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 17:47:43 +03:00
end
end
end
2022-06-19 01:17:43 +03:00
if def.on_place and not def.on_place ( pos , def , pr ) then
2022-06-22 17:37:44 +03: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 01:17:43 +03:00
return false
end
2022-06-10 02:06:24 +03:00
if def.filenames then
local file = def.filenames [ pr : next ( 1 , # def.filenames ) ]
local pp = vector.offset ( pos , 0 , y_offset , 0 )
mcl_structures.place_schematic ( pp , file , " random " , nil , true , " place_center_x,place_center_z " , def.after_place , pr , { pos , def } )
2022-06-22 17:37:44 +03:00
if logging then
minetest.log ( " action " , " [mcl_structures] " .. def.name .. " placed at " .. minetest.pos_to_string ( pos ) )
end
2022-06-10 05:34:58 +03:00
return true
2022-06-10 02:49:33 +03:00
elseif def.place_func and def.place_func ( pos , def , pr ) then
2022-06-10 05:34:58 +03:00
if not def.after_place or ( def.after_place and def.after_place ( pos , def , pr ) ) then
2022-06-22 17:37:44 +03:00
if logging then
minetest.log ( " action " , " [mcl_structures] " .. def.name .. " placed at " .. minetest.pos_to_string ( pos ) )
end
2022-06-10 05:34:58 +03:00
return true
end
2022-06-10 02:06:24 +03:00
end
2022-06-22 17:37:44 +03:00
if logging then
minetest.log ( " warning " , " [mcl_structures] placing " .. def.name .. " failed at " .. minetest.pos_to_string ( pos ) )
end
2022-06-10 02:06:24 +03:00
end
2022-06-06 04:34:31 +03: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 02:06:24 +03:00
local sbgroups = { structblock = 1 , not_in_creative_inventory = 1 }
2022-06-06 04:34:31 +03:00
if def.flags then flags = def.flags end
def.name = name
2022-06-10 02:06:24 +03:00
if nospawn then
sbgroups.structblock = nil
sbgroups.structblock_lbm = 1
else
2022-06-06 04:34:31 +03:00
def.deco = minetest.register_decoration ( {
2022-06-10 02:06:24 +03:00
name = " mcl_structures:deco_ " .. name ,
2022-06-06 04:34:31 +03:00
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 ,
2022-06-13 12:59:15 +03:00
noise_params = def.noise_params ,
2022-06-06 04:34:31 +03:00
flags = flags ,
biomes = def.biomes ,
y_max = def.y_max ,
y_min = def.y_min
} )
2022-06-22 16:56:51 +03:00
def.deco_id = minetest.get_decoration_id ( " mcl_structures:deco_ " .. name )
minetest.set_gen_notify ( { decoration = true } , { def.deco_id } )
2022-06-06 04:34:31 +03:00
end
2022-06-10 02:06:24 +03:00
minetest.register_node ( " : " .. structblock , { drawtype = " airlike " , walkable = false , pointable = false , groups = sbgroups } )
2022-06-10 04:12:45 +03:00
def.structblock = structblock
2022-06-10 03:40:33 +03:00
mcl_structures.registered_structures [ name ] = def
2022-06-06 04:34:31 +03:00
end
2022-06-10 02:06:24 +03:00
--lbm for secondary structures (structblock included in base structure)
2022-06-06 04:34:31 +03:00
minetest.register_lbm ( {
name = " mcl_structures:struct_lbm " ,
run_at_every_load = true ,
2022-06-10 02:06:24 +03:00
nodenames = { " group:structblock_lbm " } ,
2022-06-06 04:34:31 +03:00
action = function ( pos , node )
local name = node.name : gsub ( " mcl_structures:structblock_ " , " " )
2022-06-10 03:40:33 +03:00
local def = mcl_structures.registered_structures [ name ]
2022-06-10 02:06:24 +03:00
if not def then return end
minetest.remove_node ( pos )
2022-06-10 03:40:33 +03:00
mcl_structures.place_structure ( pos )
2022-06-06 04:34:31 +03:00
end
} )