饥荒游戏吧 关注:204,215贴子:2,999,536

16-06-22丨【mod】饥荒游戏LuaJIT引擎桥接MOD | RoG, SW, DST

取消只看楼主收藏回复

原贴排版有点问题,趁DST兼容版发布的时候另开个新贴吧。
饥荒游戏默认采用了lua 5.1.4作为脚本引擎,在优化不到位的情况下,如果游戏当前活动对象过多(可以通过Backspace查看左上角的awake得到),就会出现明显的卡顿现象。加之游戏本身是单线程的,所以满载只能跑满一个CPU核心,经常CPU占用只有20%,但是游戏已经卡得不能玩。
LuaJIT是一个Just-in Time的lua引擎,由Mike Pall开发。它可以将lua代码编译成CPU指令而不是虚拟机指令直接执行,在速度上比官方lua要快非常多(相差一到两个数量级)。具体的性能测试可到luajit官方网站(luajit.org)上看。
这个MOD的作用就是使用LuaJIT替换掉原有的lua引擎,可以缓解因为对象数过多/MOD数过多引起了卡顿问题。但是由于饥荒主程序并没有导出lua函数,因此这个替换的过程是使用了特征码匹配的。
特征码匹配没有办法保证它在所有版本的游戏中都可以正确运行,我仅仅在发贴时最近的steam正版Don't Starve v181038+ 上进行了测试。因此我需要收集一部分测试反馈。
如果您想测试它的话,请确保您已经备份好所有的存档。如果程序出现了闪退或者崩溃,请将Steam\SteamApps\common\dont_starve\bin下的扩展名为.mdmp的文件贴到github issue上。


IP属地:浙江1楼2016-06-22 18:02回复
    作者:PaintDream (alias Aegisys)
    GitHub:https://github.com/paintdream
    微博:PaintDream
    ZHIHU:PaintsNow
    DontStarveLuaJIT简介,安装,下载,bug反馈(首选这里下载):
    https://paintdream.github.io/DontStarveLuaJIT/
    百度网盘备份:(更新不一定非常及时)
    http://pan.baidu.com/s/1o7OHHGm
    STEAM上的讨论贴:
    http://steamcommunity.com/workshop/discussions/-1/351659808490971005/?appid=219740


    IP属地:浙江2楼2016-06-22 18:06
    收起回复
      以后原贴不再更新。


      IP属地:浙江4楼2016-06-22 18:15
      收起回复
        目测发现联机版不能恢复存档。。。


        IP属地:浙江6楼2016-06-22 18:30
        收起回复
          有童鞋愿意提供一个稳定的国内server供DST测试吗?
          我只有一个账号,只能在联机的主机里测试==


          IP属地:浙江18楼2016-06-23 13:09
          收起回复
            发现一个可以简单绕过arg = {...}兼容性的办法==
            如果成功的话大家基本上都不用改MOD源码了。


            IP属地:浙江19楼2016-06-23 16:15
            收起回复
              看了一下午parser,终于把忘得差不多的编译原理复习了一通。。。
              新版MOD已经发布,从这一版开始,不再需要修改任何的lua文件。
              已经修改过的改回去或者不改都行。


              IP属地:浙江20楼2016-06-23 21:40
              收起回复
                6.25 更新:添加了对DST dedicated server以及洞穴的支持。


                IP属地:浙江24楼2016-06-25 20:59
                回复
                  好像找到崩溃的原因了


                  IP属地:浙江28楼2016-06-26 10:21
                  收起回复
                    @sharpwind95
                    @lild100
                    @可待year
                    @渊_雎
                    @__PeakChen
                    修复了无意义转义符导致的启动即崩溃的问题。
                    请大家试下6.26版本是否还会有崩溃~
                    感谢大家的反馈!


                    IP属地:浙江29楼2016-06-26 10:43
                    收起回复
                      已经找了并修复了问题。
                      6.26.2版已经发布,这一版在所替换的文件上没有什么变动。唯一的区别是添加了如下修改lua代码的要求:
                      如果是联机版,还需要使用文本编辑器打开“[您的Don't Starve安装目录]/data/scripts/util.lua”文件。
                      定位到如下代码行:
                      function RunInSandboxSafe(untrusted_code, error_handler)
                      error_handler = error_handler or function (str) print("Klei, you have missed this line: " .. str) end --<<<<
                      if untrusted_code:byte(1) == 27 then return nil, "binary bytecode prohibited" end
                      local untrusted_function, message = loadstring(untrusted_code)
                      if not untrusted_function then return nil, message end
                      setfenv(untrusted_function, {} )
                      return xpcall(untrusted_function, error_handler )
                      end
                      在-<<<<标记处如上所示添加一行代码。
                      保存 util.lua 文件。
                      =============================================
                      以下是为什么非得要大家修改的原因。
                      这个函数是用于跑沙盒(一般用于读纯数据的配置文件)中的代码的。error_handler是当沙盒中的代码出错时需要调用的函数。从上面的声明可以看出,error_handler是必须要传入的第二个参数。
                      然而Klei在其他的脚本中,有相当一部分调用它时只用了一个参数。
                      这样导致的问题就是,如果程序运行时因为这个Sandbox挂掉了,那么程序就会直接挂出error_handler is nil的错误,而don't starve的主程序不会对这个错误进行处理,直接退出并挂掉。所以这就是为什么个别MOD在modinfo.lua里挂掉就会导致整个程序退出的原因。
                      通常情况下,如果mod有问题,那么这时应该会弹出一个“警告”界面,上面写着崩溃时的lua stack traceback(就是所谓”看不懂的一堆英文“)。这是因为klei在注册运行时的sandbox时,正确使用了两个参数,因而在崩溃时会显示崩溃页面。
                      下面讲讲为什么luajit在mod没有错误时也会崩溃的原因。
                      luajit引入了部分优化处理,它可以预先计算出匹配的参数数量并且直接生成x86指令,因此,当RunInSandboxSafe声明的时候,它看到了它需要两个参数来调用。那么,一但它看到有其他函数调用到RunInSandboxSafe时不使用两个参数时,就会直接报error_handler is nil。
                      一句话来说,luajit预测到了klei程序员在这里犯下的错误并在真正的错误还没发生的时候报了警。
                      ================================================
                      因此我的做法就是,如果error_handler没有提供,就自己生成一个。这样就解决了报错了问题。
                      这条新加的语句不仅仅可以解决我的mod的兼容性问题,更大的好处是,即使你使用原版饥荒,因游戏bug而出错的时候也将看到的是警告界面而不是直接闪退掉。这样如果你把警告截图贴上来求助,大家都能看出是哪个MOD出的问题从而给你建议。如果没有修改的话,程序闪退,大家都无从下手。


                      IP属地:浙江31楼2016-06-26 22:17
                      回复
                        之前由于我的联机版的这个文件已经被我改过(我测试的时候发现咦它怎么直接崩了我加一行代码吧),然后就忘掉了。
                        导致后果大家都说报错的时候我运行的还好好的。。

                        @sharpwind95
                        @lild100
                        @可待year
                        @渊_雎
                        @__PeakChen
                        再次感谢大家的反馈!


                        IP属地:浙江32楼2016-06-26 22:18
                        收起回复
                          @ 可待year
                          你的mdmp我看了,通过call stack backtrace只能看到是挂在游戏原来的代码里,而且中间并没有调用到我的函数。。。通过对上下文的分析,可以确认具体的崩溃是由于klei程序员没有对一个指针的有效性进行检查而造成的,但是要查出这个指针为什么会无效就很麻烦了,因为mdmp文件能提供的内存信息非常有限。
                          有仅有的log来看,你可以打开/data/scripts/componentactions.lua的82行:
                          inventoryitem = function(inst, doer, actions)
                          if inst.replica.inventoryitem and inst.replica.inventoryitem:CanBePickedUp() and doer.replica.inventory ~= nil and --<<<修改下这里
                          not (inst:HasTag("catchable") or inst:HasTag("fire")) then
                          table.insert(actions, ACTIONS.PICKUP)
                          end
                          end,
                          看看会不会再挂了。
                          我怎么搞也没办法复现你的崩溃问题(包括下载了你的MODS列表,又使用了盗版的联机试了试)。所以只能猜一下了。


                          IP属地:浙江37楼2016-06-27 23:38
                          收起回复
                            得空看了下代码,感觉Corrupt Save file,inventoryitem nil,以及捡东西消失是同一个bug..
                            晚上再搞==有点饿


                            IP属地:浙江44楼2016-07-02 16:33
                            收起回复
                              7.13 bug修复:
                              修复了一个因luajit字符串解析扩展无法兼容部分错误格式字符串的问题。


                              IP属地:浙江52楼2016-07-13 02:01
                              回复