aboutsummaryrefslogtreecommitdiff
path: root/ch_core/interiors.lua
diff options
context:
space:
mode:
Diffstat (limited to 'ch_core/interiors.lua')
-rw-r--r--ch_core/interiors.lua125
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")