Advertisement
Omsigames

grapes/Event.lua

Dec 25th, 2024 (edited)
27
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 3.67 KB | None | 0 0
  1. local computer = require("computer")
  2. local event, handlers, interruptingKeysDown, lastInterrupt = {
  3.     interruptingEnabled = true,
  4.     interruptingDelay = 1,
  5.     defaultInterruptingFunction = function()
  6.         error("interrupted", 0)
  7.     end,
  8.     interruptingKeyCodes = {
  9.         [29] = true,
  10.         [46] = true,
  11.         [56] = true
  12.     },
  13.     push = computer.pushSignal
  14. }, {}, {}, 0
  15.  
  16. event.interruptingFunction = event.defaultInterruptingFunction
  17.  
  18. local computerPullSignal, computerUptime, mathHuge, mathMin, skipSignalType = computer.pullSignal, computer.uptime, math.huge, math.min
  19.  
  20. --------------------------------------------------------------------------------------------------------
  21.  
  22. function event.addHandler(callback, interval, times)
  23.     checkArg(1, callback, "function")
  24.     checkArg(2, interval, "number", "nil")
  25.     checkArg(3, times, "number", "nil")
  26.  
  27.     local handler = {
  28.         callback = callback,
  29.         times = times or mathHuge,
  30.         interval = interval,
  31.         nextTriggerTime = interval and computerUptime() + interval or 0
  32.     }
  33.  
  34.     handlers[handler] = true
  35.  
  36.     return handler
  37. end
  38.  
  39. function event.removeHandler(handler)
  40.     checkArg(1, handler, "table")
  41.  
  42.     if handlers[handler] then
  43.         handlers[handler] = nil
  44.  
  45.         return true
  46.     else
  47.         return false, "Handler with given table is not registered"
  48.     end
  49. end
  50.  
  51. function event.getHandlers()
  52.     return handlers
  53. end
  54.  
  55. function event.skip(signalType)
  56.     skipSignalType = signalType
  57. end
  58.  
  59. function event.pull(preferredTimeout)  
  60.     local uptime, signalData = computerUptime()
  61.     local deadline = uptime + (preferredTimeout or mathHuge)
  62.    
  63.     repeat
  64.         -- Determining pullSignal timeout
  65.         timeout = deadline
  66.         for handler in pairs(handlers) do
  67.             if handler.nextTriggerTime > 0 then
  68.                 timeout = mathMin(timeout, handler.nextTriggerTime)
  69.             end
  70.         end
  71.  
  72.         -- Pulling signal data
  73.         signalData = { computerPullSignal(timeout - computerUptime()) }
  74.                
  75.         -- Handlers processing
  76.         for handler in pairs(handlers) do
  77.             if handler.times > 0 then
  78.                 uptime = computerUptime()
  79.  
  80.                 if
  81.                     handler.nextTriggerTime <= uptime
  82.                 then
  83.                     handler.times = handler.times - 1
  84.                     if handler.nextTriggerTime > 0 then
  85.                         handler.nextTriggerTime = uptime + handler.interval
  86.                     end
  87.  
  88.                     -- Callback running
  89.                     handler.callback(table.unpack(signalData))
  90.                 end
  91.             else
  92.                 handlers[handler] = nil
  93.             end
  94.         end
  95.  
  96.         -- Program interruption support. It's faster to do it here instead of registering handlers
  97.         if (signalData[1] == "key_down" or signalData[1] == "key_up") and event.interruptingEnabled then
  98.             -- Analysing for which interrupting key is pressed - we don't need keyboard API for this
  99.             if event.interruptingKeyCodes[signalData[4]] then
  100.                 interruptingKeysDown[signalData[4]] = signalData[1] == "key_down" and true or nil
  101.             end
  102.  
  103.             local shouldInterrupt = true
  104.             for keyCode in pairs(event.interruptingKeyCodes) do
  105.                 if not interruptingKeysDown[keyCode] then
  106.                     shouldInterrupt = false
  107.                 end
  108.             end
  109.            
  110.             if shouldInterrupt and uptime - lastInterrupt > event.interruptingDelay then
  111.                 lastInterrupt = uptime
  112.  
  113.                 event.interruptingFunction()
  114.             end
  115.         end
  116.        
  117.         -- Loop-breaking condition
  118.         if signalData[1] then
  119.             if signalData[1] == skipSignalType then
  120.                 skipSignalType = nil
  121.             else
  122.                 return table.unpack(signalData)
  123.             end
  124.         end
  125.     until uptime >= deadline
  126. end
  127.  
  128. -- Sleeps "time" of seconds via "busy-wait" concept
  129. function event.sleep(time)
  130.     checkArg(1, time, "number", "nil")
  131.  
  132.     local deadline = computerUptime() + (time or 0)
  133.     repeat
  134.         event.pull(deadline - computerUptime())
  135.     until computerUptime() >= deadline
  136. end
  137.  
  138. --------------------------------------------------------------------------------------------------------
  139.  
  140. return event
  141.  
Tags: ORMS
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement