-
Notifications
You must be signed in to change notification settings - Fork 38
/
internal.lua
126 lines (109 loc) · 3.08 KB
/
internal.lua
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
126
function digilines.getspec(node)
local def = minetest.registered_nodes[node.name]
if not def then return false end
return def.digilines or def.digiline
end
function digilines.importrules(spec, node)
if type(spec) == 'function' then
return spec(node)
elseif spec then
return spec
else
return digilines.rules.default
end
end
function digilines.getAnyInputRules(pos)
local node = digilines.get_node_force(pos)
local spec = digilines.getspec(node)
if not spec then return end
if spec.wire then
return digilines.importrules(spec.wire.rules, node)
end
if spec.effector then
return digilines.importrules(spec.effector.rules, node)
end
end
function digilines.getAnyOutputRules(pos)
local node = digilines.get_node_force(pos)
local spec = digilines.getspec(node)
if not spec then return end
if spec.wire then
return digilines.importrules(spec.wire.rules, node)
end
if spec.receptor then
return digilines.importrules(spec.receptor.rules, node)
end
end
function digilines.rules_link(output, input)
local outputrules = digilines.getAnyOutputRules(output)
local inputrules = digilines.getAnyInputRules (input)
if not outputrules or not inputrules then return false end
for _, orule in ipairs(outputrules) do
if digilines.cmpPos(digilines.addPosRule(output, orule), input) then
for _, irule in ipairs(inputrules) do
if digilines.cmpPos(digilines.addPosRule(input, irule), output) then
return true
end
end
end
end
return false
end
function digilines.rules_link_anydir(output, input)
return digilines.rules_link(output, input)
or digilines.rules_link(input, output)
end
local function queue_new()
return {nextRead = 1, nextWrite = 1}
end
local function queue_empty(queue)
return queue.nextRead == queue.nextWrite
end
local function queue_enqueue(queue, object)
local nextWrite = queue.nextWrite
queue[nextWrite] = object
queue.nextWrite = nextWrite + 1
end
local function queue_dequeue(queue)
local nextRead = queue.nextRead
local object = queue[nextRead]
queue[nextRead] = nil
queue.nextRead = nextRead + 1
return object
end
function digilines.transmit(pos, channel, msg, checked)
local checkedID = minetest.hash_node_position(pos)
if checked[checkedID] then
return
end
checked[checkedID] = true
digilines.vm_begin()
local queue = queue_new()
queue_enqueue(queue, pos)
while not queue_empty(queue) do
local curPos = queue_dequeue(queue)
local node = digilines.get_node_force(curPos)
local spec = digilines.getspec(node)
if spec then
-- Effector actions --> Receive
if spec.effector then
spec.effector.action(curPos, node, channel, msg)
end
-- Cable actions --> Transmit
if spec.wire then
local rules = digilines.importrules(spec.wire.rules, node)
for _, rule in ipairs(rules) do
local nextPos = digilines.addPosRule(curPos, rule)
if digilines.rules_link(curPos, nextPos) then
local checkedID2 = minetest.hash_node_position(nextPos)
if not checked[checkedID2] then
checked[checkedID2] = true
queue_enqueue(queue, nextPos)
end
end
end
end
end
end
digilines.vm_end()
end