building_lib/conditions.lua
BuckarooBanzay 38b0767048 autoplacer
2022-11-14 15:05:17 +01:00

142 lines
4.1 KiB
Lua

-- checks a single condition
local function check_condition(key, value, mapblock_pos)
local condition = building_lib.get_condition(key)
if condition and type(condition.can_build) == "function" then
return condition.can_build(mapblock_pos, value)
end
return true
end
-- checks a table of conditions with the given mapblock_pos
-- all entries have to match
function building_lib.check_condition_table(map, mapblock_pos)
for key, value in pairs(map) do
local success, msg = check_condition(key, value, mapblock_pos)
if not success then
-- failure and in AND mode, return immediately
return false, msg or "condition failed: '" .. key .. "'"
end
end
return true
end
local default_condition_groups = {
{["*"] = { empty = true }}
}
-- rotates a condition group by given rotation
-- TODO: only supports sizes of 1
function building_lib.rotate_condition_group(condition_group, rotation)
if rotation == 0 then
-- no rotation
return condition_group
end
local new_condition_group = {}
for selector, condition in pairs(condition_group) do
local pos = minetest.string_to_pos(selector)
if pos then
-- rotate position
local rotated_pos = mapblock_lib.rotate_pos(pos, {x=0, y=0, z=0}, rotation)
new_condition_group[minetest.pos_to_string(rotated_pos)] = condition
else
-- keep selector name
new_condition_group[pos] = condition
end
end
return new_condition_group
end
-- go through all condition groups and return true if any of them matches
function building_lib.check_condition_groups(mapblock_pos1, mapblock_pos2, condition_groups)
for _, condition_group in ipairs(condition_groups or default_condition_groups) do
local success = building_lib.check_condition_group(mapblock_pos1, mapblock_pos2, condition_group)
if success then
return true
end
end
return false, "no matching condition found"
end
function building_lib.check_condition_group(mapblock_pos1, mapblock_pos2, condition_group)
local group_match = true
for selector, conditions in pairs(condition_group) do
local it
if selector == "*" then
-- match all
it = mapblock_lib.pos_iterator(mapblock_pos1, mapblock_pos2)
elseif selector == "base" then
-- match only base positions
it = mapblock_lib.pos_iterator(mapblock_pos1, {x=mapblock_pos2.x, y=mapblock_pos1.y, z=mapblock_pos2.z})
elseif selector == "underground" then
-- match only underground positions
it = mapblock_lib.pos_iterator({
x=mapblock_pos1.x, y=mapblock_pos1.y-1, z=mapblock_pos1.z
},{
x=mapblock_pos2.x, y=mapblock_pos1.y-1, z=mapblock_pos2.z
})
else
-- try to parse a manual position
local rel_pos = minetest.string_to_pos(selector)
if rel_pos then
-- single position
local abs_pos = vector.add(mapblock_pos1, rel_pos)
it = mapblock_lib.pos_iterator(abs_pos, abs_pos)
else
return false, "unknown selector: " .. selector
end
end
while true do
local mapblock_pos = it()
if not mapblock_pos then
break
end
local success = building_lib.check_condition_table(conditions, mapblock_pos)
if not success then
group_match = false
break
end
end
if not group_match then
break
end
end
if group_match then
return true
end
end
-- checks if a building with specified group is placed there already
building_lib.register_condition("group", {
can_build = function(mapblock_pos, value)
local building_info = building_lib.get_placed_building_info(mapblock_pos)
if building_info then
local building_def = building_lib.get_building(building_info.name)
if building_def and building_def.groups and building_def.groups[value] then
return true
end
end
return false
end
})
building_lib.register_condition("name", {
can_build = function(mapblock_pos, value)
local building_info = building_lib.get_placed_building_info(mapblock_pos)
return building_info and building_info.name == value
end
})
-- checks if the mapblock position is empty
building_lib.register_condition("empty", {
can_build = function(mapblock_pos)
local building_info = building_lib.get_placed_building_info(mapblock_pos)
return building_info == nil
end
})