Here is the very very basic example that I came up with. I seperated it into two files just for simplicity during testing. They could easily be modified into a single program if you so wished (run the one that reads the log file first, then delete log file, and run the one that records events).
I have done very basic tests with this, and from what I could tell it worked. If you find anything that does not please tell me.
Code that records the input and writes it to a file:
local yield = coroutine.yield
local resume = coroutine.resume
_ENV.coroutine.yield = function(...)
local event = {yield(...)}
if event[#event] ~= "Yield event" then
local h = fs.open("log","a")
h.writeLine(table.concat(event,";")..";")
h.close()
else
event[#event] = nil
end
return unpack(event)
end
_ENV.coroutine.resume = function(co,...)
local event = {...}
event[#event+1] = "Yield event"
return resume(co,unpack(event))
end
-- End logging
Code that reads the file and handles the events:
--fast foward
local h = fs.open("log","r")
local file = h.readAll()
h.close()
--Processing the file
local events = {}
for event in file:gmatch("(..-)\n") do
local first = true
for word in event:gmatch("(..-);") do
if first then
events[#events+1] = {word}
first = false
else
table.insert(events[#events],word)
end
end
end
--end processing
local oldRaw = os.pullEventRaw
local oldPullEvent = os.pullEvent
_ENV.os.pullEventRaw = function(filter,pullEvent)
if #events == 0 then
_ENV.os.pullEventRaw = oldRaw
return oldRaw(filter)
else
for i = 1, #events do
if (events[1][1] == filter) or filter==nil then
if pullEvent and events[1] == "terminate" then
error("terminated")
end
local temp = events[1]
table.remove(events,1)
return unpack(temp)
else
table.remove(events,1)
end
end
_ENV.os.pullEventRaw = oldRaw
return oldRaw(filter)
end
end
_ENV.os.pullEvent = function(filter)
if #events == 0 then
_ENV.os.pullEvent = oldPullEvent
return oldPullEvent(filter)
else
return _ENV.os.pullEventRaw(filter,true)
end
end
Keep in mind this is only half of what needs to be done to accomplish persistence. In order to achieve complete persistence it would be best to randomly seed math.random and save whatever you seeded it with. In addition things must be overwritten, such as fs.open. In order to have complete persistence, a copy of all files that are opened must be made, and fs.open should mess with those instead of the actual ones. There are a few other things that must be done, but recording and requeueing the events is the hardest part of it.
Edit: just going to note this is a proof of concept if anything. I can think of a few things that will break it, but this is to be used more of as a thing to look at to show it is possible.