summaryrefslogtreecommitdiff
path: root/digilines/internal.lua
blob: 2319c1609f21ed65956ebe8f92e5c44317292004 (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
function digiline:getspec(node)
	if not minetest.registered_nodes[node.name] then return false end
	return minetest.registered_nodes[node.name].digiline
end

function digiline:importrules(spec, node)
	if type(spec) == 'function' then
		return spec(node)
	elseif spec then
		return spec
	else
		return digiline.rules.default
	end
end

function digiline:getAnyInputRules(pos)
	local node = minetest.get_node(pos)
	local spec = digiline:getspec(node)
	if not spec then return end

	if spec.wire then
		return digiline:importrules(spec.wire.rules, node)
	end
	if spec.effector then
		return digiline:importrules(spec.effector.rules, node)
	end
end

function digiline:getAnyOutputRules(pos)
	local node = minetest.get_node(pos)
	local spec = digiline:getspec(node)
	if not spec then return end

	if spec.wire then
		return digiline:importrules(spec.wire.rules, node)
	end
	if spec.receptor then
		return digiline:importrules(spec.receptor.rules, node)
	end
end

function digiline:rules_link(output, input)
	local outputrules = digiline:getAnyOutputRules(output)
	local inputrules  = digiline:getAnyInputRules (input)

	if not outputrules or not inputrules then return false end


	for _, orule in ipairs(outputrules) do
		if digiline:cmpPos(digiline:addPosRule(output, orule), input) then
			for _, irule in ipairs(inputrules) do
				if digiline:cmpPos(digiline:addPosRule(input, irule), output) then
					return true
				end
			end
		end
	end
	return false
end

function digiline:rules_link_anydir(output, input)
	return digiline:rules_link(output, input)
	or     digiline:rules_link(input, output)
end

function digiline:transmit(pos, channel, msg, checked)
	local checkedid = tostring(pos.x).."_"..tostring(pos.y).."_"..tostring(pos.z)
	if checked[checkedid] then return end
	checked[checkedid] = true

	local node = minetest.get_node(pos)
	local spec = digiline:getspec(node)
	if not spec then return end


	-- Effector actions --> Receive
	if spec.effector then
		spec.effector.action(pos, node, channel, msg)
	end

	-- Cable actions --> Transmit
	if spec.wire then
		local rules = digiline:importrules(spec.wire.rules, node)
		for _,rule in ipairs(rules) do
			if digiline:rules_link(pos, digiline:addPosRule(pos, rule)) then
				digiline:transmit(digiline:addPosRule(pos, rule), channel, msg, checked)
			end
		end
	end
end