aboutsummaryrefslogtreecommitdiff
path: root/ch_core/interiors.lua
blob: c7b15a4a9a0540dc2845c0ab771662ad0799ac60 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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")