use new struct api for desert well and temples

This commit is contained in:
cora 2022-06-24 02:11:24 +02:00
parent e37358d220
commit 9381657f5d
8 changed files with 255 additions and 162 deletions

View file

@ -1262,8 +1262,6 @@ end
-- TODO: Try to use more efficient structure generating code
local function generate_structures(minp, maxp, blockseed, biomemap)
local chunk_has_desert_well = false
local chunk_has_desert_temple = false
local chunk_has_igloo = false
local struct_min, struct_max = -3, 111 --64
@ -1301,32 +1299,8 @@ local function generate_structures(minp, maxp, blockseed, biomemap)
local nn0 = minetest.get_node(p).name
-- Check if the node can be replaced
if minetest.registered_nodes[nn0] and minetest.registered_nodes[nn0].buildable_to then
-- Desert temples and desert wells
if nn == "mcl_core:sand" or (nn == "mcl_core:sandstone") then
if not chunk_has_desert_temple and not chunk_has_desert_well and ground_y > 3 then
-- Spawn desert temple
-- TODO: Check surface
if pr:next(1,12000) == 1 then
mcl_structures.call_struct(p, "desert_temple", nil, pr)
chunk_has_desert_temple = true
end
end
if not chunk_has_desert_temple and not chunk_has_desert_well and ground_y > 3 then
local desert_well_prob = minecraft_chunk_probability(1000, minp, maxp)
-- Spawn desert well
if pr:next(1, desert_well_prob) == 1 then
-- Check surface
local surface = minetest.find_nodes_in_area({x=p.x,y=p.y-1,z=p.z}, {x=p.x+5, y=p.y-1, z=p.z+5}, "mcl_core:sand")
if #surface >= 25 then
mcl_structures.call_struct(p, "desert_well", nil, pr)
chunk_has_desert_well = true
end
end
end
-- Igloos
elseif not chunk_has_igloo and (nn == "mcl_core:snowblock" or nn == "mcl_core:snow" or (minetest.get_item_group(nn, "grass_block_snow") == 1)) then
if not chunk_has_igloo and (nn == "mcl_core:snowblock" or nn == "mcl_core:snow" or (minetest.get_item_group(nn, "grass_block_snow") == 1)) then
if pr:next(1, 4400) == 1 then
-- Check surface
local floor = {x=p.x+9, y=p.y-1, z=p.z+9}
@ -2211,11 +2185,18 @@ mcl_mapgen_core.register_generator("main", basic, basic_node, 1, true)
mcl_mapgen_core.register_generator("structures",nil, function(minp, maxp, blockseed)
local gennotify = minetest.get_mapgen_object("gennotify")
local pr = PseudoRandom(blockseed + 42)
local has_struct = {}
local poshash = minetest.hash_node_position(minp)
for _,struct in pairs(mcl_structures.registered_structures) do
local has = false
if has_struct[struct.name] == nil then has_struct[struct.name] = {} end
for _, pos in pairs(gennotify["decoration#"..struct.deco_id] or {}) do
local realpos = vector.offset(pos,0,-1,0)
local realpos = vector.offset(pos,0,1,0)
minetest.remove_node(realpos)
mcl_structures.place_structure(realpos,struct,pr)
if struct.chunk_probability ~= nil and not has and pr:next(1,struct.chunk_probability) ~= 1 then
mcl_structures.place_structure(realpos,struct,pr)
has=true
end
end
end
end, 100, true)

View file

@ -9,16 +9,18 @@ function mcl_structures.place_structure(pos, def, 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 node = minetest.get_node(vector.offset(pos,1,1,0))
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
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"})
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
if #solid < ( def.sidelen * def.sidelen ) then
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)
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})
else
if logging then
minetest.log("warning","[mcl_structures] "..def.name.." at "..minetest.pos_to_string(pos).." not placed. No solid ground.")
@ -34,13 +36,18 @@ function mcl_structures.place_structure(pos, def, pr)
return false
end
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})
if logging then
minetest.log("action","[mcl_structures] "..def.name.." placed at "..minetest.pos_to_string(pos))
table.shuffle(def.filenames)
local file = def.filenames[1]
if file then
local ap = function(pos,def,pr) end
if def.after_place then ap = def.after_place end
mcl_structures.place_schematic(pp, file, "random", nil, true, "place_center_x,place_center_z",function(p) return ap(pos,def,pr) end,pr)
if logging then
minetest.log("action","[mcl_structures] "..def.name.." placed at "..minetest.pos_to_string(pos))
end
return true
end
return true
elseif def.place_func and def.place_func(pos,def,pr) then
if not def.after_place or ( def.after_place and def.after_place(pos,def,pr) ) then
if logging then
@ -65,23 +72,26 @@ function mcl_structures.register_structure(name,def,nospawn) --nospawn means it
sbgroups.structblock = nil
sbgroups.structblock_lbm = 1
else
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
})
def.deco_id = minetest.get_decoration_id("mcl_structures:deco_"..name)
minetest.set_gen_notify({decoration=true}, { def.deco_id })
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
})
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
minetest.register_node(":"..structblock, {drawtype="airlike", walkable = false, pointable = false,groups = sbgroups})
def.structblock = structblock
@ -94,10 +104,10 @@ minetest.register_lbm({
run_at_every_load = true,
nodenames = {"group:structblock_lbm"},
action = function(pos, node)
minetest.remove_node(pos)
local name = node.name:gsub("mcl_structures:structblock_","")
local def = mcl_structures.registered_structures[name]
if not def then return end
minetest.remove_node(pos)
mcl_structures.place_structure(pos)
end
})

View file

@ -0,0 +1,107 @@
local modname = minetest.get_current_modname()
local S = minetest.get_translator(modname)
local modpath = minetest.get_modpath(modname)
local function temple_placement_callback(p1, p2, pr)
-- 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})
if node_below and node_below.name == "mcl_core:sandstone" then
minetest.swap_node(pos, {name="air"})
end
end
end
-- Find chests.
-- FIXME: Searching this large area just for the chets is not efficient. Need a better way to find the chests;
-- probably let's just infer it from newpos because the schematic always the same.
local chests = minetest.find_nodes_in_area(p1, p2, "mcl_chests:chest")
-- Add desert temple loot into chests
for c=1, #chests do
local lootitems = mcl_loot.get_multi_loot({
{
stacks_min = 2,
stacks_max = 4,
items = {
{ itemstring = "mcl_mobitems:bone", weight = 25, amount_min = 4, amount_max=6 },
{ itemstring = "mcl_mobitems:rotten_flesh", weight = 25, amount_min = 3, amount_max=7 },
{ itemstring = "mcl_mobitems:spider_eye", weight = 25, amount_min = 1, amount_max=3 },
{ itemstring = "mcl_books:book", weight = 20, func = function(stack, pr)
mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr)
end },
{ itemstring = "mcl_mobitems:saddle", weight = 20, },
{ itemstring = "mcl_core:apple_gold", weight = 20, },
{ itemstring = "mcl_core:gold_ingot", weight = 15, amount_min = 2, amount_max = 7 },
{ itemstring = "mcl_core:iron_ingot", weight = 15, amount_min = 1, amount_max = 5 },
{ itemstring = "mcl_core:emerald", weight = 15, amount_min = 1, amount_max = 3 },
{ itemstring = "", weight = 15, },
{ itemstring = "mcl_mobitems:iron_horse_armor", weight = 15, },
{ itemstring = "mcl_mobitems:gold_horse_armor", weight = 10, },
{ itemstring = "mcl_mobitems:diamond_horse_armor", weight = 5, },
{ itemstring = "mcl_core:diamond", weight = 5, amount_min = 1, amount_max = 3 },
{ itemstring = "mcl_core:apple_gold_enchanted", weight = 2, },
}
},
{
stacks_min = 4,
stacks_max = 4,
items = {
{ itemstring = "mcl_mobitems:bone", weight = 10, amount_min = 1, amount_max = 8 },
{ itemstring = "mcl_mobitems:rotten_flesh", weight = 10, amount_min = 1, amount_max = 8 },
{ itemstring = "mcl_mobitems:gunpowder", weight = 10, amount_min = 1, amount_max = 8 },
{ itemstring = "mcl_core:sand", weight = 10, amount_min = 1, amount_max = 8 },
{ itemstring = "mcl_mobitems:string", weight = 10, amount_min = 1, amount_max = 8 },
}
}}, pr)
mcl_structures.init_node_construct(chests[c])
local meta = minetest.get_meta(chests[c])
local inv = meta:get_inventory()
mcl_loot.fill_inventory(inv, "main", lootitems, pr)
end
-- Initialize pressure plates and randomly remove up to 5 plates
local pplates = minetest.find_nodes_in_area(p1, p2, "mesecons_pressureplates:pressure_plate_stone_off")
local pplates_remove = 5
for p=1, #pplates do
if pplates_remove > 0 and pr:next(1, 100) >= 50 then
-- Remove plate
minetest.remove_node(pplates[p])
pplates_remove = pplates_remove - 1
else
-- Initialize plate
minetest.registered_nodes["mesecons_pressureplates:pressure_plate_stone_off"].on_construct(pplates[p])
end
end
end
mcl_structures.register_structure("desert_temple",{
place_on = {"group:sand"},
noise_params = {
offset = 0,
scale = 0.0000822,
spread = {x = 250, y = 250, z = 250},
seed = 34115,
octaves = 3,
persist = -0.4,
flags = "absvalue",
},
flags = "place_center_x, place_center_z",
solid_ground = true,
make_foundation = true,
sidelen = 18,
y_offset = -12,
chunk_probability = 256,
y_max = mcl_vars.mg_overworld_max,
y_min = 1,
biomes = { "Desert" },
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)
temple_placement_callback(p1, p2, pr)
end,
filenames = { modpath.."/schematics/mcl_structures_desert_temple.mts" },
})

View file

@ -67,6 +67,7 @@ local function init_node_construct(pos)
end
return false
end
mcl_structures.init_node_construct = init_node_construct
-- The call of Struct
function mcl_structures.call_struct(pos, struct_style, rotation, pr)
@ -74,11 +75,7 @@ function mcl_structures.call_struct(pos, struct_style, rotation, pr)
if not rotation then
rotation = "random"
end
if struct_style == "desert_temple" then
return mcl_structures.generate_desert_temple(pos, rotation, pr)
elseif struct_style == "desert_well" then
return mcl_structures.generate_desert_well(pos, rotation)
elseif struct_style == "igloo" then
if struct_style == "igloo" then
return mcl_structures.generate_igloo(pos, rotation, pr)
elseif struct_style == "witch_hut" then
return mcl_structures.generate_witch_hut(pos, rotation)
@ -101,12 +98,6 @@ function mcl_structures.call_struct(pos, struct_style, rotation, pr)
end
end
function mcl_structures.generate_desert_well(pos, rot)
local newpos = {x=pos.x,y=pos.y-2,z=pos.z}
local path = modpath.."/schematics/mcl_structures_desert_well.mts"
return mcl_structures.place_schematic(newpos, path, rot or "0", nil, true)
end
function mcl_structures.generate_igloo(pos, rotation, pr)
-- Place igloo
local success, rotation = mcl_structures.generate_igloo_top(pos, pr)
@ -443,93 +434,6 @@ function mcl_structures.generate_end_portal_shrine(pos, rotation, pr)
mcl_structures.place_schematic(newpos, path, rotation or "0", nil, true, nil, shrine_placement_callback, pr)
end
local function temple_placement_callback(p1, p2, size, rotation, pr)
-- 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})
if node_below and node_below.name == "mcl_core:sandstone" then
minetest.swap_node(pos, {name="air"})
end
end
end
-- Find chests.
-- FIXME: Searching this large area just for the chets is not efficient. Need a better way to find the chests;
-- probably let's just infer it from newpos because the schematic always the same.
local chests = minetest.find_nodes_in_area(p1, p2, "mcl_chests:chest")
-- Add desert temple loot into chests
for c=1, #chests do
local lootitems = mcl_loot.get_multi_loot({
{
stacks_min = 2,
stacks_max = 4,
items = {
{ itemstring = "mcl_mobitems:bone", weight = 25, amount_min = 4, amount_max=6 },
{ itemstring = "mcl_mobitems:rotten_flesh", weight = 25, amount_min = 3, amount_max=7 },
{ itemstring = "mcl_mobitems:spider_eye", weight = 25, amount_min = 1, amount_max=3 },
{ itemstring = "mcl_books:book", weight = 20, func = function(stack, pr)
mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr)
end },
{ itemstring = "mcl_mobitems:saddle", weight = 20, },
{ itemstring = "mcl_core:apple_gold", weight = 20, },
{ itemstring = "mcl_core:gold_ingot", weight = 15, amount_min = 2, amount_max = 7 },
{ itemstring = "mcl_core:iron_ingot", weight = 15, amount_min = 1, amount_max = 5 },
{ itemstring = "mcl_core:emerald", weight = 15, amount_min = 1, amount_max = 3 },
{ itemstring = "", weight = 15, },
{ itemstring = "mcl_mobitems:iron_horse_armor", weight = 15, },
{ itemstring = "mcl_mobitems:gold_horse_armor", weight = 10, },
{ itemstring = "mcl_mobitems:diamond_horse_armor", weight = 5, },
{ itemstring = "mcl_core:diamond", weight = 5, amount_min = 1, amount_max = 3 },
{ itemstring = "mcl_core:apple_gold_enchanted", weight = 2, },
}
},
{
stacks_min = 4,
stacks_max = 4,
items = {
{ itemstring = "mcl_mobitems:bone", weight = 10, amount_min = 1, amount_max = 8 },
{ itemstring = "mcl_mobitems:rotten_flesh", weight = 10, amount_min = 1, amount_max = 8 },
{ itemstring = "mcl_mobitems:gunpowder", weight = 10, amount_min = 1, amount_max = 8 },
{ itemstring = "mcl_core:sand", weight = 10, amount_min = 1, amount_max = 8 },
{ itemstring = "mcl_mobitems:string", weight = 10, amount_min = 1, amount_max = 8 },
}
}}, pr)
init_node_construct(chests[c])
local meta = minetest.get_meta(chests[c])
local inv = meta:get_inventory()
mcl_loot.fill_inventory(inv, "main", lootitems, pr)
end
-- Initialize pressure plates and randomly remove up to 5 plates
local pplates = minetest.find_nodes_in_area(p1, p2, "mesecons_pressureplates:pressure_plate_stone_off")
local pplates_remove = 5
for p=1, #pplates do
if pplates_remove > 0 and pr:next(1, 100) >= 50 then
-- Remove plate
minetest.remove_node(pplates[p])
pplates_remove = pplates_remove - 1
else
-- Initialize plate
minetest.registered_nodes["mesecons_pressureplates:pressure_plate_stone_off"].on_construct(pplates[p])
end
end
end
function mcl_structures.generate_desert_temple(pos, rotation, pr)
-- No Generating for the temple ... Why using it ? No Change
local path = modpath.."/schematics/mcl_structures_desert_temple.mts"
local newpos = {x=pos.x,y=pos.y-12,z=pos.z}
--local size = {x=22, y=24, z=22}
if newpos == nil then
return
end
mcl_structures.place_schematic(newpos, path, rotation or "random", nil, true, nil, temple_placement_callback, pr)
end
local structure_data = {}
--[[ Returns a table of structure of the specified type.
@ -572,6 +476,31 @@ local function dir_to_rotation(dir)
end
dofile(modpath.."/api.lua")
dofile(modpath.."/desert_temple.lua")
dofile(modpath.."/jungle_temple.lua")
mcl_structures.register_structure("desert_well",{
place_on = {"group:sand"},
noise_params = {
offset = 0,
scale = 0.00012,
spread = {x = 250, y = 250, z = 250},
seed = 233,
octaves = 3,
persist = 0.001,
flags = "absvalue",
},
flags = "place_center_x, place_center_z",
not_near = { "desert_temple_new" },
solid_ground = true,
sidelen = 4,
chunk_probability = 64,
y_max = mcl_vars.mg_overworld_max,
y_min = 1,
y_offset = -2,
biomes = { "Desert" },
filenames = { modpath.."/schematics/mcl_structures_desert_well.mts" },
})
-- Debug command
minetest.register_chatcommand("spawnstruct", {
@ -589,11 +518,7 @@ minetest.register_chatcommand("spawnstruct", {
local pr = PseudoRandom(pos.x+pos.y+pos.z)
local errord = false
local message = S("Structure placed.")
if param == "desert_temple" then
mcl_structures.generate_desert_temple(pos, rot, pr)
elseif param == "desert_well" then
mcl_structures.generate_desert_well(pos, rot)
elseif param == "igloo" then
if param == "igloo" then
mcl_structures.generate_igloo(pos, rot, pr)
elseif param == "witch_hut" then
mcl_structures.generate_witch_hut(pos, rot, pr)

View file

@ -0,0 +1,70 @@
local modname = minetest.get_current_modname()
local S = minetest.get_translator(modname)
local modpath = minetest.get_modpath(modname)
local function temple_placement_callback(p1, p2, pr)
--dont remove foliage - looks kind of nice for a jt
local chests = minetest.find_nodes_in_area(p1, p2, "mcl_chests:trapped_chest_small")
-- Add jungle temple loot into chests
for c=1, #chests do
local lootitems = mcl_loot.get_multi_loot({
{
stacks_min = 2,
stacks_max = 6,
items = {
{ 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_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, },
{ itemstring = "mcl_core:emerald", weight = 2, amount_min = 1, amount_max = 3 },
{ itemstring = "mcl_books:book", weight = 1, func = function(stack, pr)
mcl_enchanting.enchant_uniform_randomly(stack, {"soul_speed"}, pr)
end },
{ itemstring = "mcl_mobitems:iron_horse_armor", weight = 1, },
{ itemstring = "mcl_mobitems:gold_horse_armor", weight = 1, },
{ itemstring = "mcl_mobitems:diamond_horse_armor", weight = 1, },
{ itemstring = "mcl_core:apple_gold_enchanted", weight = 2, },
}
}}, pr)
mcl_structures.init_node_construct(chests[c])
local meta = minetest.get_meta(chests[c])
local inv = meta:get_inventory()
mcl_loot.fill_inventory(inv, "main", lootitems, pr)
end
-- TODO: initialize traps
end
mcl_structures.register_structure("jungle_temple",{
place_on = {"group:grass_block","group:dirt","mcl_core:dirt_with_grass"},
noise_params = {
offset = 0,
scale = 0.0000812,
spread = {x = 250, y = 250, z = 250},
seed = 31585,
octaves = 3,
persist = -0.2,
flags = "absvalue",
},
flags = "place_center_x, place_center_z",
solid_ground = true,
make_foundation = true,
y_offset = -5,
chunk_probability = 256,
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",
},
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)
temple_placement_callback(p1, p2, pr)
end,
})

View file

@ -1,4 +1,4 @@
name = mcl_structures
author = Wuzzy, cora
description = Structure placement for MCL2
depends = mcl_loot
depends = mcl_init, mcl_loot