PageRenderTime 42ms CodeModel.GetById 25ms app.highlight 11ms RepoModel.GetById 2ms app.codeStats 0ms

/MUSHclient/lua/listener.lua

http://xymud.googlecode.com/
Lua | 263 lines | 202 code | 42 blank | 19 comment | 24 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
  9
 10module("Listener",package.seeall)
 11
 12local threads 		= {}			--协同列表
 13local listeners 	= {}			--放入group列表
 14local callbacks		= {}
 15local timeouts		= {}
 16
 17--如果不是oneshot 触发器,用这个记录数据
 18local defaultTimeout = 59
 19
 20function reset()
 21	threads 	= {}
 22	listeners 	= {}
 23	callbacks	= {}
 24	timeouts	= {}
 25	Note("Listener reset now")
 26end
 27
 28function add(event,callback)
 29	local id 	= event.name
 30	local group	= event.group
 31	--local name 	= genName(id, group, callback:getHexscript())
 32	register(id, group, callback)
 33	local match	= event.match
 34	local flag 	= event.flag
 35	check (AddTriggerEx(id, match, "", flag,
 36						custom_colour.NoChange,0, "",
 37						"Listener.OnEvent",
 38						12,
 39						100))
 40
 41	SetTriggerOption(id, "group", group)
 42	if event.line > 1 then
 43		SetTriggerOption (id, "multi_line", 1)
 44		SetTriggerOption (id, "lines_to_match", event.line)
 45	end
 46
 47	return id
 48end
 49
 50function genName(id,group,script)
 51	return id .. "_" .. group .. "_" .. script
 52end
 53
 54function getGroup(group)
 55	listeners[group] = listeners[group] or {}
 56	return listeners[group]
 57end
 58
 59function register(id, group, callback)
 60	if not listeners[group] then
 61		listeners[group] = {}
 62	end
 63	listeners[group][id] = true
 64
 65	threads[id] 	= assert(coroutine.running(), "Must be in coroutine")
 66	callbacks[id] 	= callback
 67end
 68
 69function remove(id, flag)
 70	local group = GetTriggerOption(id, "group")
 71	--正在执行是删不掉的
 72	if IsTrigger(id) then
 73		DeleteTrigger(id)
 74	end
 75	if group and listeners[group] then
 76		listeners[group][id] = nil
 77	end
 78
 79	callbacks[id] = nil
 80	if flag then
 81		threads[id] = nil
 82	end
 83end
 84
 85function removeGroup(group)
 86	local groups = listeners[group]
 87	if groups then
 88		for id in pairs(groups) do
 89			--print("删除id:"..id)
 90			threads[id] 	= nil
 91			callbacks[id]	= nil
 92		end
 93	end
 94
 95	listeners[group] = nil
 96	DeleteTriggerGroup(group)
 97end
 98
 99function resume(id, ...)
100	local thread = threads[id]
101	if not thread then
102		logfile("error.txt", "Listener resume 错误的协程id:"..id)
103		return
104	end
105	threads[id] = nil
106	local ok, err = coroutine.resume(thread,...)
107	checkresume(ok,err,thread, id)
108end
109
110function OnEvent(name,line,wildcards)
111	local callback = callbacks[name]
112	local result = {callback:invoke(name,line,wildcards)}
113	if result[1] == nil then
114		result = {name}
115	end
116
117	remove(name)
118	resume(name, unpack(result))
119end
120
121
122function OnTimeout(name)
123	--Note("Timeout:"..name)
124	local thread = threads[name]
125	--是否已经被删除了
126	if thread and name then
127		local info = name
128		if timeouts[name] then
129			info = timeouts[name]
130		end
131
132		removeTimeout(name)
133		local ok, err = coroutine.resume(thread, "timeout", info)
134		checkresume(ok,err,thread,name)
135	end
136end
137
138
139function setTimeout(seconds, info)
140	local thread = assert(coroutine.running(), "Must be in coroutine")
141	local id = "timeout" .. "_" .. GetUniqueNumber()
142	threads[id] = thread
143	if info then
144		timeouts[id] = info
145	else
146		logfile("error.txt", string.format("Listener setTimeout no name:%s", debug.traceback()))
147	end
148
149	seconds = seconds or defaultTimeout
150	--Note(string.format("addtimeout:id %s date: %s", id, os.date("%c")))
151	local hours, minutes, seconds = convert_seconds(seconds)
152	check(AddTimer(id, hours, minutes, seconds, "", bit.bor (timer_flag.Enabled,
153				   timer_flag.OneShot, timer_flag.Temporary, timer_flag.Replace),
154				   "Listener.OnTimeout"))
155    check(SetTimerOption (id, "send_to", 12))  -- send to script
156	return id
157end
158
159function removeTimeout(id)
160	--Note("removetimeout:"..id)
161	if IsTimer(id) == error_code.eOK then
162		EnableTimer(id, false)
163		if DeleteTimer(id) == error_code.eItemInUse then
164
165		end
166	end
167	threads[id] = nil
168	timeouts[id] = nil
169end
170
171
172function OnWaitTimeout(name)
173	local thread = threads[name]
174	if thread then
175		threads[name] = nil
176		local ok, err = coroutine.resume(thread, name)
177		checkresume(ok,err,thread,"timer:"..name)
178	else
179		logfile("error.txt", "Listener resume 错误的协程id:"..name)
180	end
181end
182
183function wait(seconds)
184	Note("Listener wait:"..seconds.." seconds")
185	local thread = assert(coroutine.running(), "Must be in coroutine")
186
187	local id = "Wait_" .. GetUniqueNumber()
188	threads[id] = thread
189	local hours, minutes, seconds = convert_seconds(seconds)
190
191	check(AddTimer(id, hours, minutes, seconds, "",
192                  bit.bor (timer_flag.Enabled,
193                           timer_flag.OneShot,
194                           timer_flag.Temporary,
195                           timer_flag.Replace),
196				  "Listener.OnWaitTimeout"))
197	check (SetTimerOption (id, "send_to", 12))
198	local id1 = coroutine.yield()
199	if id1 ~= id then
200		threads[id] = nil
201		logfile("error.txt", "listener wait() resume result = ".. id1.." not: "..id)
202	end
203end
204
205--不移出协同
206function resume2(id, ...)
207	local thread = threads[id]
208	if not thread then
209		logfile("error.txt", "Listener resume2 错误的协程id:"..id)
210		return
211	end
212	local ok, err = coroutine.resume(thread,...)
213	checkresume(ok,err,thread,id)
214end
215
216--不删除trigger信息
217function OnSetEvent(name,line,wildcards)
218	local callback = callbacks[name]
219	local result = {callback:invoke(name,line,wildcards)}
220	resume2(name, unpack(result))
221end
222
223function addSet(event,callback)
224	local id 	= event.name
225	local group	= event.group
226	--local name 	= genName(id, group, callback:getHexscript())
227	register(id, group, callback)
228	local match	= event.match
229	local flag 	= event.flag
230
231	check(AddTriggerEx(id, match, "", flag, -1, 0, "","Listener.OnSetEvent", 12, 100))
232
233	SetTriggerOption(id,"group",group)
234	if event.line > 1 then
235		SetTriggerOption (id, "multi_line", 1)
236		SetTriggerOption (id, "lines_to_match", event.line)
237	end
238
239	return id
240end
241
242function checkresume(ok,err,thread,name)
243	if not ok then
244		if name == nil then
245			name = "unknow"
246		end
247
248		logfile("error.txt", "Error raised in Listener module, id is:"..name)
249		logfile("error.txt", debug.traceback(thread))
250		logfile("error.txt", err)
251	end
252end
253
254----------------------------debug------------------------------
255function checklistener()
256	print("checklistener:threads")
257	tprint(threads)
258	print("checklistener:listeners")
259	tprint(listeners)
260	print("checklistener:callbacks")
261	tprint(callbacks)
262end
263