internal.lua 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. function digilines.getspec(node)
  2. local def = minetest.registered_nodes[node.name]
  3. if not def then return false end
  4. return def.digilines or def.digiline
  5. end
  6. function digilines.importrules(spec, node)
  7. if type(spec) == 'function' then
  8. return spec(node)
  9. elseif spec then
  10. return spec
  11. else
  12. return digilines.rules.default
  13. end
  14. end
  15. function digilines.getAnyInputRules(pos)
  16. local node = digilines.get_node_force(pos)
  17. local spec = digilines.getspec(node)
  18. if not spec then return end
  19. if spec.wire then
  20. return digilines.importrules(spec.wire.rules, node)
  21. end
  22. if spec.effector then
  23. return digilines.importrules(spec.effector.rules, node)
  24. end
  25. end
  26. function digilines.getAnyOutputRules(pos)
  27. local node = digilines.get_node_force(pos)
  28. local spec = digilines.getspec(node)
  29. if not spec then return end
  30. if spec.wire then
  31. return digilines.importrules(spec.wire.rules, node)
  32. end
  33. if spec.receptor then
  34. return digilines.importrules(spec.receptor.rules, node)
  35. end
  36. end
  37. function digilines.rules_link(output, input)
  38. local outputrules = digilines.getAnyOutputRules(output)
  39. local inputrules = digilines.getAnyInputRules (input)
  40. if not outputrules or not inputrules then return false end
  41. for _, orule in ipairs(outputrules) do
  42. if digilines.cmpPos(digilines.addPosRule(output, orule), input) then
  43. for _, irule in ipairs(inputrules) do
  44. if digilines.cmpPos(digilines.addPosRule(input, irule), output) then
  45. return true
  46. end
  47. end
  48. end
  49. end
  50. return false
  51. end
  52. function digilines.rules_link_anydir(output, input)
  53. return digilines.rules_link(output, input)
  54. or digilines.rules_link(input, output)
  55. end
  56. local function queue_new()
  57. return {nextRead = 1, nextWrite = 1}
  58. end
  59. local function queue_empty(queue)
  60. return queue.nextRead == queue.nextWrite
  61. end
  62. local function queue_enqueue(queue, object)
  63. local nextWrite = queue.nextWrite
  64. queue[nextWrite] = object
  65. queue.nextWrite = nextWrite + 1
  66. end
  67. local function queue_dequeue(queue)
  68. local nextRead = queue.nextRead
  69. local object = queue[nextRead]
  70. queue[nextRead] = nil
  71. queue.nextRead = nextRead + 1
  72. return object
  73. end
  74. function digilines.transmit(pos, channel, msg, checked)
  75. local checkedID = minetest.hash_node_position(pos)
  76. if checked[checkedID] then
  77. return
  78. end
  79. checked[checkedID] = true
  80. digilines.vm_begin()
  81. local queue = queue_new()
  82. queue_enqueue(queue, pos)
  83. while not queue_empty(queue) do
  84. local curPos = queue_dequeue(queue)
  85. local node = digilines.get_node_force(curPos)
  86. local spec = digilines.getspec(node)
  87. if spec then
  88. -- Effector actions --> Receive
  89. if spec.effector then
  90. spec.effector.action(curPos, node, channel, msg)
  91. end
  92. -- Cable actions --> Transmit
  93. if spec.wire then
  94. local rules = digilines.importrules(spec.wire.rules, node)
  95. for _, rule in ipairs(rules) do
  96. local nextPos = digilines.addPosRule(curPos, rule)
  97. if digilines.rules_link(curPos, nextPos) then
  98. local checkedID = minetest.hash_node_position(nextPos)
  99. if not checked[checkedID] then
  100. checked[checkedID] = true
  101. queue_enqueue(queue, nextPos)
  102. end
  103. end
  104. end
  105. end
  106. end
  107. end
  108. digilines.vm_end()
  109. end