diff options
Diffstat (limited to 'ch_core/interiors.lua')
-rw-r--r-- | ch_core/interiors.lua | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/ch_core/interiors.lua b/ch_core/interiors.lua new file mode 100644 index 0000000..c7b15a4 --- /dev/null +++ b/ch_core/interiors.lua @@ -0,0 +1,125 @@ +ch_core.open_submod("interiors", {}) + +local normal = 0 +local passable = 1 +local evadable = 2 + +minetest.register_on_mods_loaded(function() + local passable_drawtypes = { + airlike = true, + firelike = true, + flowingliquid = true, + liquid = true, + plantlike = true, + plantlike_rooted = true, + signlike = true, + torchlike = true, + } + for _, ndef in pairs(minetest.registered_nodes) do + if passable_drawtypes[ndef.drawtype or "normal"] then -- or ndef.sunlight_propagates == true + ndef._ch_interior = passable + else + local groups = ndef.groups + if groups == nil then + ndef._ch_interior = normal + elseif groups.leaves then + ndef._ch_interior = passable + elseif groups.tree then + ndef._ch_interior = evadable + else + ndef._ch_interior = normal + end + end + end +end) + +local get_node = minetest.get_node +local registered_nodes = minetest.registered_nodes + +local function has_passable_neighbour(pos) + local ndef + pos.x = pos.x - 1 -- -x + ndef = registered_nodes[get_node(pos).name] + if ndef ~= nil and ndef._ch_interior == passable then + return true + end + pos.z = pos.z - 1 -- -x -z + ndef = registered_nodes[get_node(pos).name] + if ndef ~= nil and ndef._ch_interior == passable then + return true + end + pos.x = pos.x + 1 -- -z + ndef = registered_nodes[get_node(pos).name] + if ndef ~= nil and ndef._ch_interior == passable then + return true + end + pos.x = pos.x + 1 -- +x -z + ndef = registered_nodes[get_node(pos).name] + if ndef ~= nil and ndef._ch_interior == passable then + return true + end + pos.z = pos.z + 1 -- +x + ndef = registered_nodes[get_node(pos).name] + if ndef ~= nil and ndef._ch_interior == passable then + return true + end + pos.z = pos.z + 1 -- +x +z + ndef = registered_nodes[get_node(pos).name] + if ndef ~= nil and ndef._ch_interior == passable then + return true + end + pos.x = pos.x - 1 -- +z + ndef = registered_nodes[get_node(pos).name] + if ndef ~= nil and ndef._ch_interior == passable then + return true + end + pos.x = pos.x - 1 -- -x +z + ndef = registered_nodes[get_node(pos).name] + if ndef ~= nil and ndef._ch_interior == passable then + return true + end + return false +end + +--[[ + Prozkoumá, zda se zadaná pozice jeví být v interiéru. + Při použití na hráčskou postavu (player:get_pos()) je potřeba k souřadnici y přičíst 0.5. +]] +function ch_core.is_in_interior(pos) + local nlight = minetest.get_natural_light(pos, 0.5) or 0 + if nlight <= 0 then + return true + elseif nlight >= minetest.LIGHT_MAX then + return false + else + local ndef, ntype + local ray = minetest.raycast(pos, vector.offset(pos, 0, 20, 0), false, false) + for pointed_thing in ray do + if pointed_thing.type == "node" then + ndef = registered_nodes[get_node(pointed_thing.under)] + if ndef == nil then + return true -- under unknown node => interior + end + ntype = ndef._ch_interior + if ntype ~= passable then + if ntype == evadable then + local pos2 = vector.offset(pointed_thing.under, 0, 1, 0) + ndef = registered_nodes[get_node(pos2).name] + if ndef == nil or ndef._ch_interior == evadable then + return true -- under two evadable nodes => interior + end + pos2.y = pointed_thing.under.y + if not has_passable_neighbour(pointed_thing.under) then + return true -- under evadable node with no passable neighbour => interior + end + else + return true -- under full node => interior + end + end + end + end + return false + end +end + +ch_core.close_submod("interiors") |