Working on fixing desyncs

This commit is contained in:
Cooldude2606
2017-12-08 23:08:44 +00:00
parent c8d65ff1de
commit bc1e81cb9c
2 changed files with 66 additions and 24 deletions

View File

@@ -40,7 +40,7 @@ end
-- all stores the threads indexed uuid, the other three only store the uuid's to index in the all table
function Server._threads(reset)
global.exp_core = not reset and global.exp_core or {}
global.exp_core.threads = not reset and global.exp_core.threads or {queue={},tick={},timeout={},events={},all={}}
global.exp_core.threads = not reset and global.exp_core.threads or {queue={},tick={},timeout={},events={},all={},paused={},named={}}
return global.exp_core.threads
end
@@ -49,6 +49,18 @@ function Server.new_thread(obj)
return thread:create(obj)
end
--- Used to get a thread via it's uuid or by name if one is given
-- @usage Server.get_thread('decon') -- return thread
-- @param mixed either a uuid or the name given to a thread
-- @treturn table the thread by that name or uuid
function Server.get_thread(mixed)
local threads = Server._threads()
if threads.named[mixed] then return threads.all[threads.named[mixed]]
elseif threads.paused[mixed] then return threads.all[threads.paused[mixed]]
elseif threads.all[mixed] then return threads.all[mixed]
else return false end
end
--- Adds a thread into the resolve queue, can be used to lower lag
-- @usage Server.queue_thread(thread) -- return true/false
-- @tparam table the thread to add to the queue must have a resolve function (must be open)
@@ -69,15 +81,16 @@ function Server.close_all_threads(with_force)
for uuid,thread in pairs(Server.threads()) do
thread:close()
end
else
Server._threads(true)
end
Server._threads(true)
end
--- Runs all the theads which have opened with an on_tick event
-- @ussage Server.run_tick_threads()
function Server.run_tick_threads()
table.each(Server._threads().tick,function(uuid)
local thread = Server._threads().all[uuid]
local thread = Server.get_thread(uuid)
if thread and thread:valid() and thread._tick then
local success, err = pcall(thread._tick,thread)
if not success then thread:error(err) end
@@ -89,7 +102,7 @@ end
-- @ussage Server.check_timeouts()
function Server.check_timeouts()
table.each(Server._threads().timeout,function(uuid)
local thread = Server._threads().all[uuid]
local thread = Server.get_thread(uuid)
if thread and thread:valid() then
thread:check_timeout()
end
@@ -98,12 +111,12 @@ end
--- Calles all threads on a certain game event (used with script.on_event)
-- @tparam table event the event that is called
function Server.game_event(event)
function Server._thread_handler(event)
local event_id = event.name
local threads = Server._threads().events[event_id]
if not threads then return end
table.each(threads,function(uuid)
local thread = Server._threads().all[uuid]
local thread = Server.get_thread(uuid)
if thread and thread:valid() then
if is_type(thread._events[event_id],'function') then
local success, err = pcall(thread._events[event_id],thread,event)
@@ -113,24 +126,24 @@ function Server.game_event(event)
end)
end
--- Adds a thread to a game event (used in thread:on_event)
-- @usage Server.add_thread_handler(defines.event,thread,function)
-- @tparam number event the event to run the thread on
-- @tparam table thread the thread that will have the callback
-- @tparam function callback the function that the thread will run
for _,event in pairs(defines.events) do Event.register(event,Server._thread_handler) end
--[[ cant be used V
--- Adds a event handler to tell threads about events
-- @usage Server.add_thread_handler(defines.event)
-- @tparam number event the event to run the thread handler on
-- @treturn bolean if the handler was added
function Server.add_thread_handler(event,thread,callback)
if not is_type(event,'number') or not is_type(thread,'table') or not is_type(callback,'function') then return false end
function Server.add_thread_handler(event)
if not is_type(event,'number') then return false end
local threads = Server._threads()
if not thread._events then thread._events = {} end
thread._events[event] = callback
if not threads.events[event] then
threads.events[event] = {}
Event.register(event,Server.game_event)
Event.register(event,Server._thread_handler)
return true
end
table.insert(threads.events[event],thread.uuid)
return true
return false
end
]]
--- Given a string or function it will run that function and return any values
-- @usage Server.interface('local x = 1+1 print(x) return x') -- return 2
@@ -207,13 +220,22 @@ end
-- @usage thread:open() -- return true
-- @treturn bolean if the thread was opened
function thread:open()
if not self:valid(true) then return false end
if not self:valid(true) or self.opened then return false end
local threads = Server._threads()
local uuid = self.uuid
self.opened = game.tick
threads.all[uuid] = self
threads.all[uuid] = threads.all[uuid] or self
if is_type(self.timeout,'number') then table.insert(threads.timeout,uuid) end
if is_type(self._tick,'function') then table.insert(threads.tick,uuid) end
if is_type(self.name,'string') then threads.named[self.name] = threads.named[self.name] or self.uuid end
if is_type(self._events,'table') then
table.each(self._events,function(callback,event,threads,uuid)
-- cant be used V
--Server.add_thread_handler(event)
if not threads.events[event] then threads.events[event] = {} end
table.insert(threads.events[event],uuid)
end,threads,self.uuid)
end
return true
end
@@ -231,16 +253,18 @@ function thread:close()
if key then table.remove(threads.timeout,key) end
local value,key = table.find(threads.tick,function(v,k,uuid) return v == uuid end,uuid)
if key then table.remove(threads.tick,key) end
if self._events then
if is_type(self._events,'table') then
table.each(self._events,function(callback,event)
if threads.events[event] then
local value,key = table.find(threads.events[event],function(v,k,uuid) return v == uuid end,uuid)
if key then table.remove(threads.events[event],key) end
if #threads.events[event] == 0 then Event.remove(event,Server.game_event) end
-- cant be used V
--if #threads.events[event] == 0 then Event.remove(event,Server.game_event) threads.events[event] = nil end
end
end)
end
table.remove(threads.all,uuid)
if is_type(self.name,'string') then threads.paused[self.name] = self.uuid self.opened = nil
else table.remove(threads.all,uuid) end
return _return
end
@@ -309,7 +333,8 @@ function thread:on_event(event,callback)
self['_'..value] = callback
return true
elseif is_type(event,'number') and is_type(callback,'function') then
Server.add_thread_handler(event,self,callback)
if not thread._events then thread._events = {} end
thread._events[event] = callback
return true
end
return false
@@ -333,6 +358,7 @@ return Server
-- user thread:on_event('tick') rather than thread:on_event(defines.events.on_tick) as it makes less lag
thread:on_event('tick',function(self)
local trees = self.data
if #trees == 0 then return end
local tree = table.remove(trees,1)
if tree.valid then tree.destroy() end
end)
@@ -347,4 +373,10 @@ return Server
end
end)
thread:open()
local thread = Server.new_thread{name='print-place',data={}}
thread:on_event(defines.events.on_built_entity,function(self,event)
game.print('Events')
end)
thread:open()
]]

View File

@@ -40,6 +40,16 @@ local Event = { --luacheck: allow defined top
}
}
--[[ edit by cooldude2606 to allow change during run-time without desyncs -- still going to use this but FACTORIO NO LIKE
Event.__registry = Event._registry
Event._registry = function()
if game and global then
if not global.event_registry then global.event_registry = Event.__registry end
return global.event_registry
end
return Event.__registry
end]]
--- Registers a function for a given event. If a nil handler is passed remove all events and stop listening for that event.
-- Events are dispatched in the order they are registered.
-- @usage Event.register(defines.events.on_tick, function(event) print event.tick end)