From 05042035761b7e692630eec0ee738b13b0c23d96 Mon Sep 17 00:00:00 2001 From: Cooldude2606 Date: Fri, 8 Dec 2017 20:18:24 +0000 Subject: [PATCH] Game events can be used with threads now --- locale/ExpCore/server.lua | 98 +++++++++++++++++++++++++++++++++++---- 1 file changed, 88 insertions(+), 10 deletions(-) diff --git a/locale/ExpCore/server.lua b/locale/ExpCore/server.lua index 548576f3..9be985b5 100644 --- a/locale/ExpCore/server.lua +++ b/locale/ExpCore/server.lua @@ -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={},all={}} + global.exp_core.threads = not reset and global.exp_core.threads or {queue={},tick={},timeout={},events={},all={}} return global.exp_core.threads end @@ -80,7 +80,7 @@ function Server.run_tick_threads() local thread = Server._threads().all[uuid] if thread and thread:valid() and thread._tick then local success, err = pcall(thread._tick,thread) - if not success then error(err) end + if not success then thread:error(err) end end end) end @@ -96,6 +96,38 @@ function Server.check_timeouts() 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 +-- @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 + 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,function(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] + 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) + if not success then thread:error(err) end + end + end + end) + end) + end + table.insert(threads.events[event],thread.uuid) + return true +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 -- Server.interface('local x = 1+1 print(x)',thread) -- no return @@ -188,13 +220,21 @@ function thread:close() local threads = Server._threads() local uuid = self.uuid local _return = false - if is_type(self._close,'function') then pcall(self._close) _return = true end + if is_type(self._close,'function') then pcall(self._close,self) _return = true end local value,key = table.find(threads.queue,function(v,k,uuid) return v == uuid end,uuid) if key then table.remove(threads.queue,key) end local value,key = table.find(threads.timeout,function(v,k,uuid) return v == uuid end,uuid) 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 + 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 + end + end) + end table.remove(threads.all,uuid) return _return end @@ -209,14 +249,11 @@ function thread:resolve(...) local success, err = pcall(self._resolve,...) if success then if is_type(self._success,'function') then - pcall(self._success,err) + pcall(self._success,self,err) _return = true end else - if is_type(self._error,'function') then - pcall(self._error,err) - _return = true - end + _return = self:error(err) end end self:close() @@ -231,7 +268,7 @@ function thread:check_timeout() if not self:valid() then return false end if is_type(self.timeout,'number') and game.tick >= (self.opened+self.timeout) then if is_type(self._timeout,'function') then - pcall(self._timeout) + pcall(self._timeout,self) end _return = true self:close() @@ -239,9 +276,24 @@ function thread:check_timeout() return _return end +--- Rasies an error on this thread +-- @usage thread:error(err) -- return true +-- @param err the err to be rasied +-- @treturn bolean did the thread handdle the error +function thread:error(err) + local _return = false + if is_type(self._error,'function') then + pcall(thread._error,self,err) + _return = true + else + error(err) + end + return _return +end --- Set function to run then an event is called on a thread, none of them are 'needed' but you are advised to have atleast one -- @usage thread:on_event('close',function) -- return true -- events = ['close','timeout','tick','resolve','success','error'] +-- if event is a number then it is asumed to be a game event -- @tparam string event the name of the event that it is called on -- @tparam function callback the function which is called on the event -- @treturn was the function added @@ -251,6 +303,9 @@ function thread:on_event(event,callback) if value and is_type(callback,'function') then self['_'..value] = callback return true + elseif is_type(event,'number') and is_type(callback,'function') then + Server.add_thread_handler(event,self,callback) + return true end return false end @@ -265,4 +320,27 @@ Event.register(defines.events.on_tick,function(event) end end) -return Server \ No newline at end of file +return Server +--[[ + Thread Example: + + local thread = Server.new_thread{name='tree-decon',data={}} + -- 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 + local tree = table.remove(trees,1) + if tree.valid then tree.destroy() end + end) + thread:on_event('error',function(self,err) + -- cant see how this can cause an error + -- but this is where error handling goes + -- this is also called during on_resolve + -- but on_tick does not have on_success + end) + thread:on_event(defines.events.on_marked_for_deconstruction,function(self,event) + if event.entity.type == 'tree' then + table.insert(self.data,event.entity) + end + end) + thread:open() +]] \ No newline at end of file