FCKJesus

event

Sep 14th, 2020
741
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. local computer = require("computer")
  2. local keyboard = require("keyboard")
  3.  
  4. local event = {}
  5. local handlers = {}
  6. local lastInterrupt = -math.huge
  7.  
  8. event.handlers = handlers
  9.  
  10. function event.register(key, callback, interval, times, opt_handlers)
  11.   local handler =
  12.   {
  13.     key = key,
  14.     times = times or 1,
  15.     callback = callback,
  16.     interval = interval or math.huge,
  17.   }
  18.  
  19.   handler.timeout = computer.uptime() + handler.interval
  20.   opt_handlers = opt_handlers or handlers
  21.  
  22.   local id = 0
  23.   repeat
  24.     id = id + 1
  25.   until not opt_handlers[id]
  26.  
  27.   opt_handlers[id] = handler
  28.   return id
  29. end
  30.  
  31. local _pullSignal = computer.pullSignal
  32. setmetatable(handlers, {__call=function(_,...)return _pullSignal(...)end})
  33. computer.pullSignal = function(seconds) -- dispatch
  34.   checkArg(1, seconds, "number", "nil")
  35.   seconds = seconds or math.huge
  36.   local current_time = computer.uptime()
  37.   local deadline = computer.uptime() + seconds
  38.   repeat
  39.    
  40.     local closest = deadline
  41.     for _,handler in pairs(handlers) do
  42.       closest = math.min(handler.timeout, closest)
  43.     end
  44.  
  45.     local event_data = table.pack(handlers(closest - computer.uptime()))
  46.     local signal = event_data[1]
  47.     local copy = {}
  48.     for id,handler in pairs(handlers) do
  49.       copy[id] = handler
  50.     end
  51.     for id,handler in pairs(copy) do
  52.       -- timers have false keys
  53.       -- nil keys match anything
  54.       if (handler.key == nil or handler.key == signal) or current_time >= handler.timeout then
  55.         handler.times = handler.times - 1
  56.         handler.timeout = current_time + handler.interval
  57.         -- we have to remove handlers before making the callback in case of timers that pull
  58.         -- and we have to check handlers[id] == handler because callbacks may have unregistered things
  59.         if handler.times <= 0 and handlers[id] == handler then
  60.           handlers[id] = nil
  61.         end
  62.         -- call
  63.         local result, message = pcall(handler.callback, table.unpack(event_data, 1, event_data.n))
  64.         if not result then
  65.           pcall(event.onError, message)
  66.         elseif message == false and handlers[id] == handler then
  67.           handlers[id] = nil
  68.         end
  69.       end
  70.     end
  71.     if signal then
  72.       return table.unpack(event_data, 1, event_data.n)
  73.     end
  74.   until computer.uptime() >= deadline
  75. end
  76.  
  77. local function createPlainFilter(name, ...)
  78.   local filter = table.pack(...)
  79.   if name == nil and filter.n == 0 then
  80.     return nil
  81.   end
  82.  
  83.   return function(...)
  84.     local signal = table.pack(...)
  85.     if name and not (type(signal[1]) == "string" and signal[1]:match(name)) then
  86.       return false
  87.     end
  88.     for i = 1, filter.n do
  89.       if filter[i] ~= nil and filter[i] ~= signal[i + 1] then
  90.         return false
  91.       end
  92.     end
  93.     return true
  94.   end
  95. end
  96.  
  97. -------------------------------------------------------------------------------
  98.  
  99. function event.listen(name, callback)
  100.   checkArg(1, name, "string")
  101.   checkArg(2, callback, "function")
  102.   for _, handler in pairs(handlers) do
  103.     if handler.key == name and handler.callback == callback then
  104.       return false
  105.     end
  106.   end
  107.   return event.register(name, callback, math.huge, math.huge)
  108. end
  109.  
  110. function event.pull(...)
  111.   local args = table.pack(...)
  112.   if type(args[1]) == "string" then
  113.     return event.pullFiltered(createPlainFilter(...))
  114.   else
  115.     checkArg(1, args[1], "number", "nil")
  116.     checkArg(2, args[2], "string", "nil")
  117.     return event.pullFiltered(args[1], createPlainFilter(select(2, ...)))
  118.   end
  119. end
  120.  
  121. function event.pullFiltered(...)
  122.   local args = table.pack(...)
  123.   local seconds, filter = math.huge
  124.  
  125.   if type(args[1]) == "function" then
  126.     filter = args[1]
  127.   else
  128.     checkArg(1, args[1], "number", "nil")
  129.     checkArg(2, args[2], "function", "nil")
  130.     seconds = args[1]
  131.     filter = args[2]
  132.   end
  133.  
  134.   repeat
  135.     local signal = table.pack(computer.pullSignal(seconds))
  136.     if signal.n > 0 then
  137.       if not (seconds or filter) or filter == nil or filter(table.unpack(signal, 1, signal.n)) then
  138.         return table.unpack(signal, 1, signal.n)
  139.       end
  140.     end
  141.   until signal.n == 0
  142. end
  143.  
  144. -- users may expect to find event.push to exist
  145. event.push = computer.pushSignal
  146.  
  147. require("package").delay(event, "/lib/core/full_event.lua")
  148.  
  149. -------------------------------------------------------------------------------
  150.  
  151. return event
RAW Paste Data