北大侠客行MUD论坛

 找回密码
 注册
搜索
热搜: 新手 wiki 升级
楼主: myu

ddid帮我分析一下这个

[复制链接]
 楼主| 发表于 2010-4-17 14:28:47 | 显示全部楼层
原帖由 ddid 于 2010-4-17 02:11 PM 发表
其实分析一下wait.lua中的regexp(),这部分也就是用了AddTriggerEx(),另外通过coroutine包装一下,来控制时间,如果是频繁调用,不如自己用AddTriggerEx()和DoAfterSpicial()实现,至少没有coroutine的问题。


用coroutine的最主要原因是因为coroutine可以yield(),这样就实现了等待,可以等待某个事件出现再resume原来的线程。如果不用coroutine,光用DoAfterSpecial是不够的,没法取得这种等件事件出现的效果。之所以musher愿意使用lua而不是js,vbs的主要原因,大概也在于此吧。
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2010-4-17 14:32:11 | 显示全部楼层
原帖由 myu 于 2010-4-17 14:28 发表


用coroutine的最主要原因是因为coroutine可以yield(),这样就实现了等待,可以等待某个事件出现再resume原来的线程。如果不用coroutine,光用DoAfterSpecial是不够的,没法取得这种等件事件出现的效果。之所以 ...


嗯,有道理。js、vbs虽然也可以实现等待的效果,但概念是完全不同的。

myu加油! 继续~
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
 楼主| 发表于 2010-4-17 15:12:44 | 显示全部楼层
非常遗憾,用全局变量也不能解决问题。反而是另外运行一个mushclient客户端,两个rbt完全独立开来,倒是很长时间没有出现找不到线程的情况了
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2010-4-17 15:17:52 | 显示全部楼层
看起来还是LUA对coroutine的管理有限,超过一定限制就溢出了。
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2012-10-9 21:21:10 | 显示全部楼层
之所以musher愿意使用lua而不是js,vbs的主要原因,大概也在于此吧。
myu 发表于 2010-4-17 02:28 PM



    这个等待功能别的语言实现不了?js和vbs都不行?python呢?
    求专业人士解答~
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2013-7-5 15:26:01 | 显示全部楼层
回复 4# ddid


    我研究了下mushclient wait 函数他的这个写法有点问题
-- ----------------------------------------------------------
-- table of outstanding threads that are waiting
-- ----------------------------------------------------------
local threads = {}  -- 一个局部变量

-- ----------------------------------------------------------
-- wait.timer_resume: called by a timer to resume a thread
-- ----------------------------------------------------------
function regexp (regexp, timeout, flags)
  local id = "wait_trigger_" .. GetUniqueNumber ()  --取了一个随机变量
  threads [id] = assert (coroutine.running (), "Must be in coroutine")

  check (AddTriggerEx (id, regexp,
            "-- added by wait.regexp",
            bit.bor (flags or 0, -- user-supplied extra flags, like omit from output
                     trigger_flag.Enabled,
                     trigger_flag.RegularExpression,
                     trigger_flag.Temporary,
                     trigger_flag.Replace,
                     trigger_flag.OneShot),
            custom_colour.NoChange,
            0, "",  -- wildcard number, sound file name
            "wait.trigger_resume",
            12, 100))  -- send to script (in case we have to delete the timer)

  -- if timeout specified, also add a timer
  if timeout and timeout > 0 then
    local hours, minutes, seconds = convert_seconds (timeout)

    -- if timer fires, it deletes this trigger
    check (AddTimer (id, hours, minutes, seconds,
                   "DeleteTrigger ('" .. id .. "')",
                   bit.bor (timer_flag.Enabled,
                            timer_flag.OneShot,
                            timer_flag.Temporary,
                            timer_flag.Replace),
                   "wait.timer_resume"))
-- timer_flag.ActiveWhenClosed, close
    check (SetTimerOption (id, "send_to", "12"))  -- send to script

    -- if trigger fires, it should delete the timer we just added
    check (SetTriggerOption (id, "send", "DeleteTimer ('" .. id .. "')"))

  end -- if having a timeout

  return coroutine.yield ()  -- return line, wildcards
end -- function regexp

根据lua 的 垃圾回收机制
threads [id]的引用还有 内存代码块就不会给回收,为了解决这个问题,必须改写wait.lua 将local threads 设置成 weak table 并且将 threads={} 然后 collectgarbage() 回收内存
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2013-7-5 16:05:44 | 显示全部楼层
local threads = {}
setmetatable(threads, {__mode = "k"}) --weak table
-- ----------------------------------------------------------
-- wait.timer_resume: called by a timer to resume a thread
-- ----------------------------------------------------------
function timer_resume (name)
  local thread = threads [name]
  if thread then
    threads [name] = nil
    local ok, err = coroutine.resume (thread)
    if not ok then
       ColourNote ("deeppink", "black", "Error raised in timer function (in wait module).")
       ColourNote ("darkorange", "black", debug.traceback (thread))
       error (err)
    end -- if
  end -- if
  collectgarbage()   -- 调用GC,清掉weak表中没有引用的内存
end -- function timer_resume

-- ----------------------------------------------------------
-- wait.trigger_resume: called by a trigger to resume a thread
-- ----------------------------------------------------------
function trigger_resume (name, line, wildcards, styles)
  local thread = threads [name]
  if thread then
    threads [name] = nil
    local ok, err = coroutine.resume (thread, line, wildcards, styles)
    if not ok then
       ColourNote ("deeppink", "black", "Error raised in trigger function (in wait module)")
       ColourNote ("darkorange", "black", debug.traceback (thread))
       error (err)
    end -- if
  end -- if
  collectgarbage()   -- 调用GC,清掉weak表中没有引用的内存
end -- function trigger_resume

---------------------------------------------------------
wait.lua需要修改的地方
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2013-7-8 08:54:06 | 显示全部楼层
牛人一个,膜拜ptouch
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2013-7-11 14:55:27 | 显示全部楼层
lua 有gc 回收 不过你不强制执行 他就过段时间自动执行,不会内存使用完溢出。wait 还是比较好用。实现起来也简单
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
发表于 2013-7-11 15:03:06 | 显示全部楼层
回复 1# myu


    你这个循环体有个漏洞
local  l,w=wait.regexp("^[>\\s]*你(?:研读完毕|收起手上的)",300)
你要是超时(300s) 就会出现问题
一般wait结构体是这样的
wait.make(function()
   world.Send("do something")
   local l,w=wait.regexp(regexp1,timeout)
  if l==nil then
     --超时动作
     return
  end
  if string.find(l,regexp) then
      --动作1
    return
  end
end)

-----------------------
mc 作者写的wait.lua 函数是可靠的
北大侠客行Mud(pkuxkx.net),最好的中文Mud游戏!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|北大侠客行MUD ( 京ICP备16065414号-1 )

GMT+8, 2024-11-24 06:59 AM , Processed in 0.009284 second(s), 12 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表