diff --git a/assets/opencomputers/lua/init.lua b/assets/opencomputers/lua/init.lua index 47c0e9898..8dd43830e 100644 --- a/assets/opencomputers/lua/init.lua +++ b/assets/opencomputers/lua/init.lua @@ -19,6 +19,8 @@ command that will be executed when pressing enter. ]] +------------------------------------------------------------------------------- + --[[ Distribute signals as events. ]] local listeners = {} local weakListeners = {} @@ -36,6 +38,7 @@ end --[[ Event API table. ]] event = {} +local timers = {} --[[ Register a new event listener for the specified event. ]] function event.listen(name, callback, weak) @@ -53,12 +56,51 @@ end function event.fire(name, ...) if name then for callback, _ in pairs(listenersFor(name, false)) do - callback(name, ...) + local result, message = xpcall(callback, event.error, name, ...) + if not result and message then + error(message, 0) + end end for callback, _ in pairs(listenersFor(name, true)) do - callback(name, ...) + local result, message = xpcall(callback, event.error, name, ...) + if not result and message then + error(message, 0) + end end end + local elapsed = {} + for id, info in pairs(timers) do + if info.after < os.clock() then + elapsed[id] = info + end + end + for id, _ in pairs(elapsed) do + timers[id] = nil + end + for _, info in pairs(elapsed) do + local result, message = xpcall(info.callback, event.error) + if not result and message then + error(message, 0) + end + end +end + +--[[ Calls the specified function after the specified time. ]] +function event.after(timeout, callback) + local id = #timers + timers[id] = {after = os.clock() + timeout, callback = callback} + return id +end + +function event.cancel(timerId) + checkArg(1, timerId, "number") + timers[timerId] = nil +end + +--[[ Error handler for ALL event callbacks. If this returns a value, + the computer will crash. Otherwise it'll keep going. ]] +function event.error(message) + return message end --[[ Suspends a thread for the specified amount of time. ]] @@ -66,10 +108,17 @@ function coroutine.sleep(seconds) checkArg(1, seconds, "number") local target = os.clock() + seconds repeat - event.fire(os.signal(nil, target - os.clock())) + local closest = target + for _, info in pairs(timers) do + if info.after < closest then + closest = info.after + end + end + event.fire(os.signal(nil, closest - os.clock())) until os.clock() >= target end +------------------------------------------------------------------------------- --[[ Keep track of connected components across address changes. ]] local components = {} @@ -122,6 +171,7 @@ event.listen("component_changed", function(_, newAddress, oldAddress) components[id].address = newAddress end) +------------------------------------------------------------------------------- --[[ Setup terminal API. ]] local idGpu, idScreen = 0, 0 @@ -166,16 +216,6 @@ event.listen("screen_resized", function(_, address, w, h) end end) -term = {} - -function term.gpu() - return boundGpu -end - -function term.screenSize() - return screenWidth, screenHeight -end - local function bindIfPossible() if idGpu > 0 and idScreen > 0 then if not boundGpu then @@ -192,6 +232,16 @@ local function bindIfPossible() end end +term = {} + +function term.gpu() + return boundGpu +end + +function term.screenSize() + return screenWidth, screenHeight +end + function term.gpuId(id) if id then checkArg(1, id, "number") @@ -272,6 +322,7 @@ write = function(...) end end +------------------------------------------------------------------------------- --[[ Primitive command line. ]] local command = "" diff --git a/assets/opencomputers/lua/kernel.lua b/assets/opencomputers/lua/kernel.lua index 3b3e8d7f3..ccad74a03 100644 --- a/assets/opencomputers/lua/kernel.lua +++ b/assets/opencomputers/lua/kernel.lua @@ -232,7 +232,8 @@ return pcall(function() deadline = os.realTime() + 3 local result = {coroutine.resume(init, table.unpack(data))} if result[1] then - -- Init should never return, so we have a system yield. + -- Init should never return, so we have a yield. The first yielded + -- value can only be set by system yields. result = result[2] else -- Some other error, go kill ourselves. diff --git a/li/cil/oc/common/tileentity/TileEntityComputer.scala b/li/cil/oc/common/tileentity/TileEntityComputer.scala index 1cd9c5301..cad3569d3 100644 --- a/li/cil/oc/common/tileentity/TileEntityComputer.scala +++ b/li/cil/oc/common/tileentity/TileEntityComputer.scala @@ -44,7 +44,10 @@ class TileEntityComputer(isClient: Boolean) extends TileEntityRotatable with ICo } } - override protected def onReconnect() = computer.signal("address_change", address) + override protected def onReconnect() = { + super.onReconnect() + computer.signal("address_change", address) + } // ----------------------------------------------------------------------- // // General