mirror of
https://github.com/luanti-org/minetest_game.git
synced 2025-04-30 05:01:41 -04:00
92 lines
2.6 KiB
Lua
92 lines
2.6 KiB
Lua
if minetest.save_gen_notify then
|
|
dungeon_loot = {}
|
|
end
|
|
|
|
local function find_walls(cpos, is_temple)
|
|
local is_wall = function(node)
|
|
return node.name ~= "air" and node.name ~= "ignore"
|
|
end
|
|
|
|
local dirs = {{x=1, z=0}, {x=-1, z=0}, {x=0, z=1}, {x=0, z=-1}}
|
|
local get_node = minetest.get_node
|
|
|
|
local ret = {}
|
|
local mindist = {x=0, z=0}
|
|
local min = function(a, b) return a ~= 0 and math.min(a, b) or b end
|
|
for _, dir in ipairs(dirs) do
|
|
for i = 1, 9 do -- 9 = max room size / 2
|
|
local pos = vector.add(cpos, {x=dir.x*i, y=0, z=dir.z*i})
|
|
|
|
-- continue in that direction until we find a wall-like node
|
|
local node = get_node(pos)
|
|
if is_wall(node) then
|
|
local front_below = vector.subtract(pos, {x=dir.x, y=1, z=dir.z})
|
|
local above = vector.add(pos, {x=0, y=1, z=0})
|
|
|
|
-- check that it:
|
|
--- is at least 2 nodes high (not a staircase)
|
|
--- has a floor
|
|
if is_wall(get_node(front_below)) and is_wall(get_node(above)) then
|
|
table.insert(ret, {pos = pos, facing = {x=-dir.x, y=0, z=-dir.z}})
|
|
if dir.z == 0 then
|
|
mindist.x = min(mindist.x, i-1)
|
|
else
|
|
mindist.z = min(mindist.z, i-1)
|
|
end
|
|
end
|
|
-- abort even if it wasn't a wall cause something is in the way
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
local biome = minetest.get_biome_data(cpos)
|
|
biome = biome and minetest.get_biome_name(biome.biome) or ""
|
|
local type = "normal"
|
|
if is_temple or biome:find("desert") == 1 then
|
|
type = "desert"
|
|
elseif biome:find("sandstone_desert") == 1 then
|
|
type = "sandstone"
|
|
elseif biome:find("icesheet") == 1 then
|
|
type = "ice"
|
|
end
|
|
|
|
return {
|
|
walls = ret,
|
|
size = {x=mindist.x*2, z=mindist.z*2},
|
|
type = type,
|
|
}
|
|
end
|
|
|
|
function dungeon_loot._internal_find_rooms(max_rooms)
|
|
local gennotify = minetest.get_mapgen_object("gennotify")
|
|
local poslist = gennotify["dungeon"] or {}
|
|
local n_dungeons = #poslist
|
|
-- Add MGv6 desert temples to the list too
|
|
for _, entry in ipairs(gennotify["temple"] or {}) do
|
|
table.insert(poslist, entry)
|
|
end
|
|
if #poslist == 0 then
|
|
return {}
|
|
end
|
|
|
|
local candidates = {}
|
|
local num_process = math.min(#poslist, max_rooms)
|
|
for i = 1, num_process do
|
|
local room = find_walls(poslist[i], i > n_dungeons)
|
|
-- skip small rooms and everything that doesn't at least have 3 walls
|
|
if math.min(room.size.x, room.size.z) >= 4 and #room.walls >= 3 then
|
|
table.insert(candidates, room)
|
|
end
|
|
end
|
|
|
|
return candidates
|
|
end
|
|
|
|
-- if loaded inside mapgen env, do our job there and export the result
|
|
if minetest.save_gen_notify then
|
|
minetest.register_on_generated(function(vmanip, minp, maxp, blockseed)
|
|
local candidates = dungeon_loot._internal_find_rooms(9999)
|
|
minetest.save_gen_notify("dungeon_loot:candidates", candidates)
|
|
end)
|
|
end
|