/MUSHclient/lua/listener.lua

http://xymud.googlecode.com/ · Lua · 263 lines · 202 code · 42 blank · 19 comment · 29 complexity · 49a782edeb0025ed79588f0f08f66130 MD5 · raw file

  1. -- ameng 2010/12/1
  2. -- 增加临时trigger并监听之使用方法
  3. -- event = Event.new("^[> ]*袁守诚给你一本〖无字天书〗。$", "yaozhou", "yaobishuizhou")
  4. -- call = Callback.new("s: return 'ok'")
  5. -- Listener.add(event, call)
  6. -- if listen("yaozhou") == "ok" then --等待返回
  7. -- 这些封在了helper addListener listen 函数
  8. module("Listener",package.seeall)
  9. local threads = {} --协同列表
  10. local listeners = {} --放入group列表
  11. local callbacks = {}
  12. local timeouts = {}
  13. --如果不是oneshot 触发器用这个记录数据
  14. local defaultTimeout = 59
  15. function reset()
  16. threads = {}
  17. listeners = {}
  18. callbacks = {}
  19. timeouts = {}
  20. Note("Listener reset now")
  21. end
  22. function add(event,callback)
  23. local id = event.name
  24. local group = event.group
  25. --local name = genName(id, group, callback:getHexscript())
  26. register(id, group, callback)
  27. local match = event.match
  28. local flag = event.flag
  29. check (AddTriggerEx(id, match, "", flag,
  30. custom_colour.NoChange,0, "",
  31. "Listener.OnEvent",
  32. 12,
  33. 100))
  34. SetTriggerOption(id, "group", group)
  35. if event.line > 1 then
  36. SetTriggerOption (id, "multi_line", 1)
  37. SetTriggerOption (id, "lines_to_match", event.line)
  38. end
  39. return id
  40. end
  41. function genName(id,group,script)
  42. return id .. "_" .. group .. "_" .. script
  43. end
  44. function getGroup(group)
  45. listeners[group] = listeners[group] or {}
  46. return listeners[group]
  47. end
  48. function register(id, group, callback)
  49. if not listeners[group] then
  50. listeners[group] = {}
  51. end
  52. listeners[group][id] = true
  53. threads[id] = assert(coroutine.running(), "Must be in coroutine")
  54. callbacks[id] = callback
  55. end
  56. function remove(id, flag)
  57. local group = GetTriggerOption(id, "group")
  58. --正在执行是删不掉的
  59. if IsTrigger(id) then
  60. DeleteTrigger(id)
  61. end
  62. if group and listeners[group] then
  63. listeners[group][id] = nil
  64. end
  65. callbacks[id] = nil
  66. if flag then
  67. threads[id] = nil
  68. end
  69. end
  70. function removeGroup(group)
  71. local groups = listeners[group]
  72. if groups then
  73. for id in pairs(groups) do
  74. --print("删除id:"..id)
  75. threads[id] = nil
  76. callbacks[id] = nil
  77. end
  78. end
  79. listeners[group] = nil
  80. DeleteTriggerGroup(group)
  81. end
  82. function resume(id, ...)
  83. local thread = threads[id]
  84. if not thread then
  85. logfile("error.txt", "Listener resume 错误的协程id:"..id)
  86. return
  87. end
  88. threads[id] = nil
  89. local ok, err = coroutine.resume(thread,...)
  90. checkresume(ok,err,thread, id)
  91. end
  92. function OnEvent(name,line,wildcards)
  93. local callback = callbacks[name]
  94. local result = {callback:invoke(name,line,wildcards)}
  95. if result[1] == nil then
  96. result = {name}
  97. end
  98. remove(name)
  99. resume(name, unpack(result))
  100. end
  101. function OnTimeout(name)
  102. --Note("Timeout:"..name)
  103. local thread = threads[name]
  104. --是否已经被删除了
  105. if thread and name then
  106. local info = name
  107. if timeouts[name] then
  108. info = timeouts[name]
  109. end
  110. removeTimeout(name)
  111. local ok, err = coroutine.resume(thread, "timeout", info)
  112. checkresume(ok,err,thread,name)
  113. end
  114. end
  115. function setTimeout(seconds, info)
  116. local thread = assert(coroutine.running(), "Must be in coroutine")
  117. local id = "timeout" .. "_" .. GetUniqueNumber()
  118. threads[id] = thread
  119. if info then
  120. timeouts[id] = info
  121. else
  122. logfile("error.txt", string.format("Listener setTimeout no name:%s", debug.traceback()))
  123. end
  124. seconds = seconds or defaultTimeout
  125. --Note(string.format("addtimeout:id %s date: %s", id, os.date("%c")))
  126. local hours, minutes, seconds = convert_seconds(seconds)
  127. check(AddTimer(id, hours, minutes, seconds, "", bit.bor (timer_flag.Enabled,
  128. timer_flag.OneShot, timer_flag.Temporary, timer_flag.Replace),
  129. "Listener.OnTimeout"))
  130. check(SetTimerOption (id, "send_to", 12)) -- send to script
  131. return id
  132. end
  133. function removeTimeout(id)
  134. --Note("removetimeout:"..id)
  135. if IsTimer(id) == error_code.eOK then
  136. EnableTimer(id, false)
  137. if DeleteTimer(id) == error_code.eItemInUse then
  138. end
  139. end
  140. threads[id] = nil
  141. timeouts[id] = nil
  142. end
  143. function OnWaitTimeout(name)
  144. local thread = threads[name]
  145. if thread then
  146. threads[name] = nil
  147. local ok, err = coroutine.resume(thread, name)
  148. checkresume(ok,err,thread,"timer:"..name)
  149. else
  150. logfile("error.txt", "Listener resume 错误的协程id:"..name)
  151. end
  152. end
  153. function wait(seconds)
  154. Note("Listener wait:"..seconds.." seconds")
  155. local thread = assert(coroutine.running(), "Must be in coroutine")
  156. local id = "Wait_" .. GetUniqueNumber()
  157. threads[id] = thread
  158. local hours, minutes, seconds = convert_seconds(seconds)
  159. check(AddTimer(id, hours, minutes, seconds, "",
  160. bit.bor (timer_flag.Enabled,
  161. timer_flag.OneShot,
  162. timer_flag.Temporary,
  163. timer_flag.Replace),
  164. "Listener.OnWaitTimeout"))
  165. check (SetTimerOption (id, "send_to", 12))
  166. local id1 = coroutine.yield()
  167. if id1 ~= id then
  168. threads[id] = nil
  169. logfile("error.txt", "listener wait() resume result = ".. id1.." not: "..id)
  170. end
  171. end
  172. --不移出协同
  173. function resume2(id, ...)
  174. local thread = threads[id]
  175. if not thread then
  176. logfile("error.txt", "Listener resume2 错误的协程id:"..id)
  177. return
  178. end
  179. local ok, err = coroutine.resume(thread,...)
  180. checkresume(ok,err,thread,id)
  181. end
  182. --不删除trigger信息
  183. function OnSetEvent(name,line,wildcards)
  184. local callback = callbacks[name]
  185. local result = {callback:invoke(name,line,wildcards)}
  186. resume2(name, unpack(result))
  187. end
  188. function addSet(event,callback)
  189. local id = event.name
  190. local group = event.group
  191. --local name = genName(id, group, callback:getHexscript())
  192. register(id, group, callback)
  193. local match = event.match
  194. local flag = event.flag
  195. check(AddTriggerEx(id, match, "", flag, -1, 0, "","Listener.OnSetEvent", 12, 100))
  196. SetTriggerOption(id,"group",group)
  197. if event.line > 1 then
  198. SetTriggerOption (id, "multi_line", 1)
  199. SetTriggerOption (id, "lines_to_match", event.line)
  200. end
  201. return id
  202. end
  203. function checkresume(ok,err,thread,name)
  204. if not ok then
  205. if name == nil then
  206. name = "unknow"
  207. end
  208. logfile("error.txt", "Error raised in Listener module, id is:"..name)
  209. logfile("error.txt", debug.traceback(thread))
  210. logfile("error.txt", err)
  211. end
  212. end
  213. ----------------------------debug------------------------------
  214. function checklistener()
  215. print("checklistener:threads")
  216. tprint(threads)
  217. print("checklistener:listeners")
  218. tprint(listeners)
  219. print("checklistener:callbacks")
  220. tprint(callbacks)
  221. end