2022-06-10 03:40:33 +03:00
mcl_structures.registered_structures = { }
2022-06-06 04:34:31 +03:00
2022-06-25 00:24:51 +03:00
function mcl_structures . fill_chests ( p1 , p2 , loot , pr )
for it , lt in pairs ( loot ) do
2022-06-24 04:36:21 +03:00
local nodes = minetest.find_nodes_in_area ( p1 , p2 , it )
for _ , p in pairs ( nodes ) do
2022-06-25 00:24:51 +03:00
local lootitems = mcl_loot.get_multi_loot ( lt , pr )
2022-06-24 04:36:21 +03:00
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-25 00:24:51 +03: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 )
if def.loot then mcl_structures.fill_chests ( p1 , p2 , def.loot , pr ) end
end
2022-06-24 15:02:29 +03: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 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-24 03:11:24 +03:00
local pp = vector.offset ( pos , 0 , y_offset , 0 )
2022-06-22 17:47:43 +03:00
if def.solid_ground and def.sidelen then
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 )
2022-06-24 22:47:44 +03:00
2022-06-23 21:22:36 +03:00
local solid = minetest.find_nodes_in_area ( ground_p1 , ground_p2 , { " group:solid " } )
2022-06-24 03:11:24 +03:00
if # solid < ( def.sidelen * def.sidelen ) then
2022-06-23 21:22:36 +03:00
if def.make_foundation then
2022-06-25 00:24:51 +03:00
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 minetest.get_mapgen_setting ( " 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.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
2022-07-01 05:25:34 +03:00
local replace = { " air " , " group:liquid " , " mcl_core:snow " , " group:tree " , " group:leaves " }
minetest.bulk_set_node ( minetest.find_nodes_in_area ( ground_p1 , ground_p2 , replace ) , { name = node_top } )
2022-06-25 00:24:51 +03:00
if node_dust then
minetest.bulk_set_node ( minetest.find_nodes_in_area ( vector.offset ( ground_p1 , 0 , 1 , 0 ) , vector.offset ( ground_p2 , 0 , 1 , 0 ) , { " air " } ) , { name = node_dust } )
end
2022-07-01 05:25:34 +03:00
minetest.bulk_set_node ( minetest.find_nodes_in_area ( vector.offset ( ground_p1 , 0 , - 1 , 0 ) , vector.offset ( ground_p2 , 0 , - 4 , 0 ) , replace ) , { name = node_filler } )
minetest.bulk_set_node ( minetest.find_nodes_in_area ( vector.offset ( ground_p1 , 0 , - 5 , 0 ) , vector.offset ( ground_p2 , 0 , - 30 , 0 ) , replace ) , { name = node_stone } )
2022-06-23 21:22:36 +03:00
else
if logging then
2022-06-25 07:16:18 +03:00
minetest.log ( " warning " , " [mcl_structures] " .. def.name .. " at " .. minetest.pos_to_string ( pp ) .. " not placed. No solid ground. " )
2022-06-23 21:22:36 +03:00
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
2022-06-25 07:16:18 +03:00
minetest.log ( " warning " , " [mcl_structures] " .. def.name .. " at " .. minetest.pos_to_string ( pp ) .. " not placed. Conditions not satisfied. " )
2022-06-22 17:37:44 +03:00
end
2022-06-19 01:17:43 +03:00
return false
end
2022-06-10 02:06:24 +03:00
if def.filenames then
2022-06-24 05:10:21 +03:00
if # def.filenames <= 0 then return false end
local r = pr : next ( 1 , # def.filenames )
local file = def.filenames [ r ]
2022-06-24 03:11:24 +03:00
if file then
local ap = function ( pos , def , pr ) end
if def.after_place then ap = def.after_place end
2022-06-24 04:36:21 +03: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 03:11:24 +03:00
if logging then
2022-06-25 07:16:18 +03:00
minetest.log ( " action " , " [mcl_structures] " .. def.name .. " placed at " .. minetest.pos_to_string ( pp ) )
2022-06-24 03:11:24 +03:00
end
return true
2022-06-22 17:37:44 +03:00
end
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
2022-06-25 07:16:18 +03:00
minetest.log ( " action " , " [mcl_structures] " .. def.name .. " placed at " .. minetest.pos_to_string ( pp ) )
2022-06-22 17:37:44 +03:00
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-24 03:11:24 +03: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-25 01:31:28 +03:00
minetest.register_node ( " : " .. structblock , { drawtype = " airlike " , walkable = false , pointable = false , groups = sbgroups } )
2022-06-24 04:36:21 +03:00
def.structblock = structblock
2022-06-24 03:11:24 +03: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 04:34:31 +03:00
end
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 )
2022-06-24 03:11:24 +03:00
minetest.remove_node ( pos )
2022-06-06 04:34:31 +03:00
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
2022-06-10 03:40:33 +03:00
mcl_structures.place_structure ( pos )
2022-06-06 04:34:31 +03:00
end
} )