![]() |
|
|
#5 |
|
中级会员
![]() ![]() ![]() ![]() ![]() ![]() ![]()
注册: 08年07月03日
来自: 长安城
帖子: 140
声望力: 20
声望:
14
![]() 现金:101两梁山币
资产:301两梁山币
致谢数: 0
获感谢文章数:0
获会员感谢数:0 |
回复: MUSH417 xlqy各门派综合机器人
event_v2.lua文件 -- handle "event1" --Listener.new():Register(Event.new("event1"), EventHandler1.new()) --EventHander1 = class(Callback) --function EventHander1:Do(event, ) -- do something -- cmdSender:Add("cmd1;#3 cmd2;@2;cmd3") -- #3 means repeat 3 times, @2 means delay 2 seconds --end -- handle "event2" five times --Listener.new():Register(Event.new("event2, 0, 5"), EventHandler2.new()) --EventHander2 = class(Callback) --function EventHander2:Do(event, ) -- -- do something -- cmdSender:Add({"cmd4", "@3", "#2 cmd5"}) -- accept commands in a table --end -- handle "event3" twice within 10 seconds. if it is not triggered twice within 10 seconds, a timeout event is sent. --Listener.new():Register(Event.new("event3, 10, 2"), EventHandler3.new()) --EventHander3 = class(Callback) --function EventHander3:Do(event, ) -- -- do something -- if (event.isTimeout) then -- cmdSender:Add("cmd6") -- else -- cmdSender:Add({"cmd7", "cmd8"}) -- end --end --------------------------------------------------------- -- OO, implement class module --------------------------------------------------------- pre_kk = false local _class = {} function class(super) local class_type = {} class_type.ctor = false class_type.super = super class_type.new = function(...) local obj = {} do local create create = function(c, ...) if c.super then create(c.super, ...) end if c.ctor then c.ctor(obj, ...) end end create(class_type, ...) end setmetatable(obj, { __index = _class[class_type] }) return obj end local vtbl = {} _class[class_type] = vtbl setmetatable(class_type, { __newindex = function(t, k, v) vtbl[k] = v end }) if super then setmetatable(vtbl, { __index = function(t,k) local ret = _class[super][k] vtbl[k] = ret return ret end }) end return class_type end --------------------------------------------------------- -- event --- type: type of an event --- timeout: in a particular time(in seconds) didn't receive the event will fire a timeout event --- times: the event will be triggered how many times, then will be self removed --------------------------------------------------------- Event = class() function Event:ctor(type, timeout, times) self.type = type if (timeout == nil and times == nil) then -- if both timeout and times are not set, then can be triggered any times (set times to zero) self.timeout = 0 self.times = 0 elseif (timeout ~= nil and times == nil) then -- if timeout is set, times is not set, then can be trigger only once self.timeout = timeout self.times = 1 else -- if both timeout and times are set, then can be trigger any times within timeout self.timeout = timeout self.times = times end self.isTimeout = false self.triggered = 0 end function Event:Reset() self.isTimeout = false self.triggered = 0 end --------------------------------------------------------- -- callback: callback function when receved an event --------------------------------------------------------- Callback = class() function Callback:ctor(insideFunc) self.func = insideFunc end function Callback:Invoke(event, ...) -- logging helper:Print("Event:", event.type, " Timeout:", event.isTimeout, " Triggered:", event.triggered) -- call handler self:Do(event, ...) end function Callback:Do(event, ...) helper:Print("Do Noting") end --------------------------------------------------------- -- listener --------------------------------------------------------- Listener = class() function Listener:ctor() self.id = CreateGUID() end function Listener:Register(event, callback) assert(event.type ~= nil, "event type is nil") self.event = event self.callback = callback -- create timer if has timeout if (event.timeout ~= 0) then -- create timer using type as timer name helper:AddTimer(self.event.type, self.event.timeout) end -- add self in listener list dispatcher:AddListener(self) end function Listener:Remove() assert(self.event ~= nil, "have to register event then remove it") -- if has timer and the timer is not timeout, delete it if (self.event.timeout ~= 0 and not self.event.isTimeout) then helper:RemoveTimer(self.event.type) end -- remove self in listener list dispatcher:RemoveListener(self) end function Listener:OnEvent(...) -- add triggered times self.event.triggered = self.event.triggered + 1 -- check if reach triggered times if (self.event.times ~= 0 and self.event.triggered == self.event.times) then self:Remove() end -- call back self.callback:Invoke(self.event, ...) end function Listener:OnTimeout() -- set isTimeout and call back self.event.isTimeout = true -- delete listener self:Remove() -- call back self.callback:Invoke(self.event) end --------------------------------------------------------- -- event dispatcher --------------------------------------------------------- EventDispatcher = class() function EventDispatcher:ctor() self.listeners = {} end function EventDispatcher:AddListener(listener) self.listeners[listener.id] = listener end function EventDispatcher:RemoveListener(listener) self.listeners[listener.id] = nil end function EventDispatcher:IsListening(listener) return (self.listeners[listener.id] ~= nil) end function EventDispatcher:Match(eventType) local matchs = {} for k, v in pairs (self.listeners) do if (v.event.type == eventType) then table.insert(matchs, v) end end return matchs end function EventDispatcher:SendEvent(eventType, ...) local matchs = self:Match(eventType) if (#matchs ~= 0) then for k, v in pairs (matchs) do v:OnEvent(...) end end end function EventDispatcher:SendTimeout(timerName) local matchs = self:Match(timerName) if (#matchs ~= 0) then for k, v in pairs (matchs) do v:OnTimeout() end end end -- only one instance dispatcher = EventDispatcher.new() --------------------------------------------------------- -- Helper --------------------------------------------------------- Helper = class() function Helper:ctor() self.isPrint = false self.cmds = {} end function Helper:Print(...) if self.isPrint then Note(...) end end function Helper:AddTimer(name, interval) local hours = math.floor(interval / 3600) interval = interval - (hours * 3600) local minutes = math.floor(interval / 60) local seconds = interval - (minutes * 60) local status = AddTimer (name, hours, minutes, seconds, "dispatcher:SendTimeout(\"" .. name .. "\")", timer_flag.OneShot + timer_flag.Temporary + timer_flag.Replace, "") assert(status == error_code.eOK, "fail to create timer:" .. name) SetTimerOption(name, "send_to", 12) EnableTimer(name, true) ResetTimer(name) end function Helper:ResetTimer(name, interval) assert(IsTimer(name), "timer doesn't exist") EnableTimer(name, false) local hours = math.floor(interval / 3600) interval = interval - (hours * 3600) local minutes = math.floor(interval / 60) local seconds = interval - (minutes * 60) SetTimerOption(name, "hour", hours) SetTimerOption(name, "minute", minutes) SetTimerOption(name, "second", seconds) EnableTimer(name, true) ResetTimer(name) end function Helper:RemoveTimer(name) EnableTimer(name, false) DeleteTimer(name) end -- only one instance helper = Helper.new() --------------------------------------------------------- -- Command --- Repeat: #4 xx (repeat 4 times for command xx) --- Delay: @3 (delay 3 seconds) --------------------------------------------------------- Command = class() function Command:ctor() self.cmds = {} self.isRunning = false self.thread = nil self.count = 0 self.nowait = false self.time = os.time() end function Command:ToTable(cmds) assert(type(cmds) == "string", "commands must be string type") local retVal = {} for k, v in pairs(utils.split(cmds, ";")) do if (string.sub(v, 1, 1) == "#") then -- convert repeat command local sb, se = string.find(v, "%s+") assert(sb ~= nil and se ~= nil, "wrong repeat command format") local scc = string.sub(v, 2, sb -1) if scc == "t+" or scc == "T+" or scc == "T-" or scc == "t-" or scc == "w+" or scc == "w-" then retVal[#retVal + 1] = v else local times = tonumber(string.sub(v, 2, sb - 1)) local cmd = string.sub(v, se + 1) for i = 1, times, 1 do retVal[#retVal + 1] = cmd end end else retVal[#retVal + 1] = v end end return retVal end function Command:Add(cmds) if (type(cmds) == "string") then cmds = self:ToTable(cmds) end assert(type(cmds) == "table", "commands must be string or table type") -- add cmds for k, v in pairs (cmds) do self.cmds[#self.cmds + 1] = v end -- wakeup to process self:Wakeup() end function Command:Insert(cmds) if (type(cmds) == "string") then cmds = self:ToTable(cmds) end assert(type(cmds) == "table", "commands must be string or table type") -- insert cmds for k, v in pairs (cmds) do --self.cmds[#self.cmds + 1] = v table.insert(self.cmds, 1, v) end -- wakeup to process self:Wakeup() end function Command:Clear() self.cmds = {} self.nowait = false Note("cmdSender clear...") end function Command:Wakeup() if (self.thread == nil) then cmdSender.thread = coroutine.create(cmdSender.Do) end if (not self.isRunning) then local dcounts = (os.time() - self.time) * 25 self.count = self.count - dcounts if self.count < 0 then self.count = 0 end coroutine.resume(self.thread) end end function Command:Len() return #self.cmds end function Command:Do() while true do local cmd = nil if cmdSender.nowait == false and cmdSender.count > 10 then Note("wait 0.3 second...") cmdSender.count = 0 DoAfterSpecial(0.3, "coroutine.resume(cmdSender.thread)", 12) coroutine.yield() else if (#cmdSender.cmds ~= 0) then cmd = cmdSender.cmds[1] -- pick cmd in queue table.remove (cmdSender.cmds, 1) -- remove cmd in queue end if (cmd ~= nil) then cmdSender.isRunning = true if (string.sub(cmd, 1, 1) == "@") then local interval = tonumber(string.sub(cmd, 2)) if (interval > 0) then cmdSender.count = cmdSender.count - interval if cmdSender.count < 0 then cmdSender.count = 0 end interval=interval/10 helper:Print("delay:", interval) Note("等待"..interval.."秒...") DoAfterSpecial(interval, "coroutine.resume(cmdSender.thread)", 12) pre_kk = false coroutine.yield() end else if (string.sub(cmd, 1, 1) == "#") then -- convert repeat command if string.sub(cmd, 2, 2) == "w" then if string.sub(cmd, 3, 3) == "+" then cmdSender.nowait = true else if string.sub(cmd, 3, 3) == "-" then cmdSender.nowait = false else cmdSender:Send(cmd) end end else local sb, se = string.find(cmd, "%s+") assert(sb ~= nil and se ~= nil, "wrong repeat command format") local scc = string.sub(cmd, 2, sb -1) if scc == "t+" or scc == "T+" then local group = string.sub(cmd, se + 1) Note("Enable trigger Group "..group); EnableTriggerGroup(group, true) else if scc == "t-" or scc == "T-" then local group = string.sub(cmd, se + 1) EnableTriggerGroup(group, false) Note("Disable trigger Group "..group); else cmdSender:Send(cmd) end end end else if (string.sub(cmd, 1, 1) == '{') then Note("no waiting...") cmdSender.nowait = true else if (string.sub(cmd, 1, 1) == '}') then cmdSender.nowait = false Note("stop no waiting...") else cmdSender:Send(cmd) end end end end else cmdSender.isRunning = false --if cmdSender.count > 0 then -- cmdSender.count = cmdSender.count - 1 --end cmdSender.time = os.time() coroutine.yield() end end end end function Command:Send(cmd) helper:Print("cmd:", cmd) SendImmediate(cmd) self.count = self.count + 1 end cmdSender = Command.new() |
|
|