From 45c0c576f740cafb5f31368c66f9f8bf053eb767 Mon Sep 17 00:00:00 2001 From: kay27 Date: Sun, 7 Mar 2021 03:49:34 +0400 Subject: [PATCH] Implement /spawnstruct dungeon --- mods/MAPGEN/mcl_dungeons/init.lua | 28 +++++++++++++++++++-------- mods/MAPGEN/mcl_structures/init.lua | 30 +++++++++++++++-------------- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/mods/MAPGEN/mcl_dungeons/init.lua b/mods/MAPGEN/mcl_dungeons/init.lua index 6749616dc..d7e21fce6 100644 --- a/mods/MAPGEN/mcl_dungeons/init.lua +++ b/mods/MAPGEN/mcl_dungeons/init.lua @@ -1,5 +1,7 @@ -- FIXME: Chests may appear at openings +mcl_dungeons = {} + local mg_name = minetest.get_mapgen_setting("mg_name") -- Are dungeons disabled? @@ -10,6 +12,11 @@ end local min_y = math.max(mcl_vars.mg_overworld_min, mcl_vars.mg_bedrock_overworld_max) + 1 local max_y = mcl_vars.mg_overworld_max - 1 +-- Calculate the number of dungeon spawn attempts +-- In Minecraft, there 8 dungeon spawn attempts Minecraft chunk (16*256*16 = 65536 blocks). +-- Minetest chunks don't have this size, so scale the number accordingly. +local attempts = math.ceil(((mcl_vars.chunksize * mcl_vars.MAP_BLOCKSIZE) ^ 3) / 8192) -- 63 = 80*80*80/8192 + local dungeonsizes = { { x=5, y=4, z=5}, { x=5, y=4, z=7}, @@ -91,24 +98,20 @@ if mg_name == "v6" then end --- Calculate the number of dungeon spawn attempts --- In Minecraft, there 8 dungeon spawn attempts Minecraft chunk (16*256*16 = 65536 blocks). --- Minetest chunks don't have this size, so scale the number accordingly. -local attempts = math.ceil(((mcl_vars.chunksize * mcl_vars.MAP_BLOCKSIZE) ^ 3) / 8192) -- 63 = 80*80*80/8192 - local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param) if calls_remaining >= 1 then return end local p1, p2, dim, pr = param.p1, param.p2, param.dim, param.pr local x, y, z = p1.x, p1.y, p1.z + local check = not (param.dontcheck or false) -- Check floor and ceiling: Must be *completely* solid local y_floor = y local y_ceiling = y + dim.y + 1 - for tx = x, x + dim.x do for tz = z, z + dim.z do + if check then for tx = x, x + dim.x do for tz = z, z + dim.z do if not minetest.registered_nodes[mcl_mapgen_core.get_node({x = tx, y = y_floor , z = tz}).name].walkable or not minetest.registered_nodes[mcl_mapgen_core.get_node({x = tx, y = y_ceiling, z = tz}).name].walkable then return false end - end end + end end end -- Check for air openings (2 stacked air at ground level) in wall positions local openings_counter = 0 @@ -182,7 +185,7 @@ local function ecb_spawn_dungeon(blockpos, action, calls_remaining, param) end -- Check conditions. If okay, start generating - if openings_counter < 1 or openings_counter > 5 then return end + if check and (openings_counter < 1 or openings_counter > 5) then return end minetest.log("action","[mcl_dungeons] Placing new dungeon at "..minetest.pos_to_string({x=x,y=y,z=z})) -- Okay! Spawning starts! @@ -349,4 +352,13 @@ local function dungeons_nodes(minp, maxp, blockseed) end end +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 = {x = p1.x+dim.x+1, y = p1.y+dim.y+1, z = p1.z+dim.z+1} + minetest.log("verbose","[mcl_dungeons] size=" ..minetest.pos_to_string(dim) .. ", emerge from "..minetest.pos_to_string(p1) .. " to " .. minetest.pos_to_string(p2)) + local param = {p1=p1, p2=p2, dim=dim, pr=pr, dontcheck=true} + minetest.emerge_area(p1, p2, ecb_spawn_dungeon, param) +end + mcl_mapgen_core.register_generator("dungeons", nil, dungeons_nodes, 999999) diff --git a/mods/MAPGEN/mcl_structures/init.lua b/mods/MAPGEN/mcl_structures/init.lua index 2423e7046..f016a1d4f 100644 --- a/mods/MAPGEN/mcl_structures/init.lua +++ b/mods/MAPGEN/mcl_structures/init.lua @@ -92,10 +92,10 @@ mcl_structures.call_struct = function(pos, struct_style, rotation, pr) end end -mcl_structures.generate_desert_well = function(pos) +mcl_structures.generate_desert_well = function(pos, rot) local newpos = {x=pos.x,y=pos.y-2,z=pos.z} local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_desert_well.mts" - return mcl_structures.place_schematic(newpos, path, "0", nil, true) + return mcl_structures.place_schematic(newpos, path, rot or "0", nil, true) end mcl_structures.generate_igloo = function(pos, rotation, pr) @@ -265,7 +265,7 @@ mcl_structures.generate_boulder = function(pos, rotation, pr) local newpos = {x=pos.x,y=pos.y-1,z=pos.z} - return minetest.place_schematic(newpos, path) -- don't serialize schematics for registered biome decorations, for MT 5.4.0, https://github.com/minetest/minetest/issues/10995 + return minetest.place_schematic(newpos, path, rotation) -- don't serialize schematics for registered biome decorations, for MT 5.4.0, https://github.com/minetest/minetest/issues/10995 end local function hut_placement_callback(p1, p2, size, orientation, pr) @@ -284,14 +284,14 @@ mcl_structures.generate_witch_hut = function(pos, rotation, pr) mcl_structures.place_schematic(pos, path, rotation, nil, true, nil, hut_placement_callback, pr) end -mcl_structures.generate_ice_spike_small = function(pos) +mcl_structures.generate_ice_spike_small = function(pos, rotation) local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_ice_spike_small.mts" - return minetest.place_schematic(pos, path, "random", nil, false) -- don't serialize schematics for registered biome decorations, for MT 5.4.0 + return minetest.place_schematic(pos, path, rotation or "random", nil, false) -- don't serialize schematics for registered biome decorations, for MT 5.4.0 end -mcl_structures.generate_ice_spike_large = function(pos) +mcl_structures.generate_ice_spike_large = function(pos, rotation) local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_ice_spike_large.mts" - return minetest.place_schematic(pos, path, "random", nil, false) -- don't serialize schematics for registered biome decorations, for MT 5.4.0 + return minetest.place_schematic(pos, path, rotation or "random", nil, false) -- don't serialize schematics for registered biome decorations, for MT 5.4.0 end mcl_structures.generate_fossil = function(pos, rotation, pr) @@ -309,12 +309,12 @@ mcl_structures.generate_fossil = function(pos, rotation, pr) } local r = pr:next(1, #fossils) local path = minetest.get_modpath("mcl_structures").."/schematics/"..fossils[r] - return mcl_structures.place_schematic(newpos, path, "random", nil, true) + return mcl_structures.place_schematic(newpos, path, rotation or "random", nil, true) end -mcl_structures.generate_end_exit_portal = function(pos) +mcl_structures.generate_end_exit_portal = function(pos, rot) local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_end_exit_portal.mts" - return mcl_structures.place_schematic(pos, path, "0", nil, true) + return mcl_structures.place_schematic(pos, path, rot or "0", nil, true) end local function shrine_placement_callback(p1, p2, size, rotation, pr) @@ -401,7 +401,7 @@ mcl_structures.generate_end_portal_shrine = function(pos, rotation, pr) local newpos = { x = pos.x - offset.x, y = pos.y, z = pos.z - offset.z } local path = minetest.get_modpath("mcl_structures").."/schematics/mcl_structures_end_portal_room_simple.mts" - mcl_structures.place_schematic(newpos, path, "0", nil, true, nil, shrine_placement_callback, 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) @@ -488,7 +488,7 @@ mcl_structures.generate_desert_temple = function(pos, rotation, pr) if newpos == nil then return end - mcl_structures.place_schematic(newpos, path, "random", nil, true, nil, temple_placement_callback, pr) + mcl_structures.place_schematic(newpos, path, rotation or "random", nil, true, nil, temple_placement_callback, pr) end local registered_structures = {} @@ -534,7 +534,7 @@ end -- Debug command minetest.register_chatcommand("spawnstruct", { - params = "desert_temple | desert_well | igloo | witch_hut | boulder | ice_spike_small | ice_spike_large | fossil | end_exit_portal | end_portal_shrine", + params = "desert_temple | desert_well | igloo | witch_hut | boulder | ice_spike_small | ice_spike_large | fossil | end_exit_portal | end_portal_shrine | dungeon", description = S("Generate a pre-defined structure near your position."), privs = {debug = true}, func = function(name, param) @@ -551,7 +551,7 @@ minetest.register_chatcommand("spawnstruct", { 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, pr) + mcl_structures.generate_desert_well(pos, rot) elseif param == "igloo" then mcl_structures.generate_igloo(pos, rot, pr) elseif param == "witch_hut" then @@ -568,6 +568,8 @@ minetest.register_chatcommand("spawnstruct", { mcl_structures.generate_end_exit_portal(pos, rot, pr) elseif param == "end_portal_shrine" then mcl_structures.generate_end_portal_shrine(pos, rot, pr) + elseif 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 ”.") errord = true