惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
Jina AI
Jina AI
IT之家
IT之家
J
Java Code Geeks
博客园_首页
Stack Overflow Blog
Stack Overflow Blog
量子位
I
InfoQ
博客园 - 【当耐特】
阮一峰的网络日志
阮一峰的网络日志
WordPress大学
WordPress大学
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 司徒正美
V
V2EX
博客园 - Franky
U
Unit 42
S
SegmentFault 最新的问题
美团技术团队
The Register - Security
The Register - Security
Last Week in AI
Last Week in AI
G
Google Developers Blog
aimingoo的专栏
aimingoo的专栏
博客园 - 叶小钗
M
MIT News - Artificial intelligence
博客园 - 聂微东
腾讯CDC
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
T
Troy Hunt's Blog
B
Blog
P
Palo Alto Networks Blog
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy International News Feed
K
Kaspersky official blog
The GitHub Blog
The GitHub Blog
C
Cisco Blogs
Microsoft Azure Blog
Microsoft Azure Blog
F
Fortinet All Blogs
S
Schneier on Security
C
CERT Recently Published Vulnerability Notes
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Engineering at Meta
Engineering at Meta
TaoSecurity Blog
TaoSecurity Blog
小众软件
小众软件
T
Threatpost
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
Martin Fowler
Martin Fowler
AWS News Blog
AWS News Blog
V
Visual Studio Blog
Simon Willison's Weblog
Simon Willison's Weblog
H
Heimdal Security Blog

博客园 - 绿叶

Suspicions about the new platform dynamic sorting expression builder How to create your own api with ACL in Magento 台服信长之野望全后台辅助外挂 SEO Elite ver 4.0 R93 Patcher Remove 5 seconds constraint in Garena(GGC) - 绿叶 巧用Marshal.GetDelegateForFunctionPointer--C#如何调用按键精灵插件dll Using .Net, Flex, and Red5 to create a flash web application 做了个C#的Hotkey简单封装,希望对大家有帮助 功夫世界外挂发布测试 我的第一个全后台CALL外挂-功夫世界外挂 通过修改Mutex来达到大航海OL多开 如何利用WPE对大航海Online进行港内瞬移,瞬时生产和快速进港 MonoRail PetShop Source Code Released MS PetShop3 -> MonoRail PetShop 完成移植 移植MSPetShop3到Castle MonoRail -Model与DAL层的移植(AR) 对 "闭包-closure" 的一些见解 圈内Castle文章索引 利用Castle Framework发email是如此easy
Robot development framework in Mush Client (Lua)
绿叶 · 2008-07-12 · via 博客园 - 绿叶

Play mud games? Using Mush Client to write robot? Let's see what I show you~

This is a framework I wrote for writing robot with Lua Script in Mush Client.
The framework enables you dealing with every action/command base on the message/event type, and do it in sequence, which means you needn't pay attention to enable or disable a trigger, and just focuing on the logical of your robot.
The idea of the framework is liking a Windows Message/Event D

riven mode. A serial of events you can define, and handle them in a callback function. The key point is an event can be defined as triggered how many times within a period or infinite time.
Moreover, a command sender I created helps you send commands for repetition, delaying, or you can extend it to process some special commands by adding codes in Command:Send function. The command sender will ensure all of your commands sent in sequence according to the order you invoke the Command:Add function.

In order to use this framework to develop your robot, you can follow this way:
1. define an event you wanna handle.
2. create a trigger in mush to fire this event.
3. write a call back function for this event.
4. in the callback function, you are able to do some response by sending commands using command sender.

for example:
you can create a trigger like:

you can handle events like:

-- 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


Here is the codes of this framework, copy it to your lua script file, then you can use it.

---------------------------------------------------------
--
 OO, implement class module
--
-------------------------------------------------------

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] = vtblsetmetatable(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
        })
    
endreturn 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 == nilthen
        
-- 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 == nilthen
        
-- 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
endfunction 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
endfunction Callback:Invoke(event, )
    
-- logging
    helper:Print("Event:", event.type" Timeout:", event.isTimeout, " Triggered:", event.triggered)
    
-- call handler
    self:Do(event, )
endfunction Callback:Do(event, )
    helper:Print(
"Do Noting")
end

---------------------------------------------------------
--
 listener
--
-------------------------------------------------------

Listener 
= class()function Listener:ctor()
    self.id 
= CreateGUID()
endfunction 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 ~= 0then -- create timer using type as timer name
        helper:AddTimer(self.event.type, self.event.timeout)
    
end
    
-- add self in listener list
    dispatcher:AddListener(self)
endfunction 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)
endfunction 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, )
endfunction 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 
= {}
endfunction EventDispatcher:AddListener(listener)
    self.listeners[listener.id] 
= listener
endfunction EventDispatcher:RemoveListener(listener)
    self.listeners[listener.id] 
= nil
endfunction EventDispatcher:IsListening(listener)
    
return (self.listeners[listener.id] ~= nil)
endfunction 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
endfunction EventDispatcher:SendEvent(eventType, )
    
local matchs = self:Match(eventType)
    
if (#matchs ~= 0then
        
for k, v in pairs (matchs) do
            v:OnEvent()
        
end
    
end
endfunction EventDispatcher:SendTimeout(timerName)
    
local matchs = self:Match(timerName)
    
if (#matchs ~= 0then
        
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 
= {}
endfunction Helper:Print()
    
if self.isPrint then
        Note()
    
end
endfunction 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)
endfunction 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)
endfunction 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
endfunction 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, 11== "#"then -- convert repeat command
            local sb, se = string.find(v, "%s+")
            
assert(sb ~= nil and se ~= nil"wrong repeat command format")
            
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
        
else
            retVal[
#retVal + 1= v
        
end
    
end
    
return retVal
endfunction 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()
endfunction Command:Clear()
    self.cmds 
= {}
endfunction Command:Wakeup()
    
if (self.thread == nilthen
        cmdSender.thread 
= coroutine.create(cmdSender.Do)
    
end
    
if (not self.isRunning) then
        
coroutine.resume(self.thread)
    
end
endfunction Command:Do()
    
while true do
        
local cmd = nil
        
if (#cmdSender.cmds ~= 0then
            cmd 
= cmdSender.cmds[1-- pick cmd in queue
            table.remove (cmdSender.cmds, 1-- remove cmd in queue
        end
        
if (cmd ~= nilthen
            cmdSender.isRunning 
= true
            
if (string.sub(cmd, 11== "@"then
                
local interval = tonumber(string.sub(cmd, 2))
                
if (interval > 0then
                    helper:Print(
"delay:", interval)
                    DoAfterSpecial(interval, 
"coroutine.resume(cmdSender.thread)"12)
                    
coroutine.yield()
                
end
            
else
                cmdSender:Send(cmd)
            
end
        
else
            cmdSender.isRunning 
= false
            
coroutine.yield()
        
end
    
end
endfunction Command:Send(cmd)
    helper:Print(
"cmd:", cmd)
    
if (IsAlias(cmd) == error_code.eOK) then
        SendImmediate(GetAliasInfo(cmd, 
2))
    
else
        SendImmediate(cmd)
    
end
end

cmdSender 

= Command.new()