123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- 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 checkedID = minetest.hash_node_position(nextPos)
- if not checked[checkedID] then
- checked[checkedID] = true
- queue_enqueue(queue, nextPos)
- end
- end
- end
- end
- end
- end
- digilines.vm_end()
- end
|