• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            戰魂小筑

            討論群:309800774 知乎關注:http://zhihu.com/people/sunicdavy 開源項目:https://github.com/davyxu

               :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
              257 隨筆 :: 0 文章 :: 506 評論 :: 0 Trackbacks

            魔獸的UI插件結構

            1.使用lua+XML作為配置

                分析:XML雖然人機交互很好,但其實沒有幾個UI是真正用純XML寫的,大多還是用編輯器比較方便。速度很慢,但尚不清楚魔獸代碼里是否進行優化

            2. Interface\Addons為插件目錄,文件夾可以堆疊

            3. 每個插件組,需要一個toc文件來做文件讀取列表描述,類似于:

            # Libraries
            embeds.xml

            AceGUIWidget-DragLink.lua
            Core.lua

            # Localization
            Locale-enUS.lua
            Locale-zhCN.lua
            Locale-zhTW.lua

            AutoBarDB.lua
            AutoBarOptions.lua
            AutoBarSearch.lua

            4.一個插件組里可以擁有多個lua文件,都共享一個獨立的全局空間

            5.WTF\Account\賬號名\服務器名\角色名\AddOns.txt文件描述哪些插件需要讀取

            根據分析:每次魔獸啟動時,都會掃描一次插件目錄,并更新這個列表,但是原有的插件讀取狀態仍然保留,類似于:

            Combuctor: enabled
            Combuctor_Config: enabled
            Parrot: disabled
            BattleInfo: disabled
            BigWigs: disabled
            BigWigs_Extras: disabled
            BigWigs_BlackTemple: disabled
            leafZone: enabled
            InFlight: disabled

            6. WTF\下的很多SavedVariables目錄都是用于保存插件狀態的,沒有對lua的擴展庫進行研究(ACE2/3等等),但是這是一種很好的保存插件數據的方法

            OZ_Config = {
                {
                    ["bottomCol"] = {
                        ["a"] = 1,
                        ["r"] = 0,
                        ["g"] = 0,
                        ["b"] = 0.6,
                    },
                    ["maxBars"] = 40,
                    ["barHeight"] = 16,
                    ["titleHeight"] = 20,
                    ["sort2"] = 0,
                    ["fadeAlpha"] = 0.3999999761581421,
                    ["textSize"] = 10,
                    ["colour"] = 2,
                    ["minBars"] = 1,
                    ["heading"] = {
                        3, -- [1]
                        0, -- [2]
                        0, -- [3]

            7.暫時沒有找到魔獸UI的核心API是否用純腳本提供的證據,但是可以推斷,按照暴雪的實力,應該是全lua api寫成。

             

             

            構建安全的lua沙箱

            所謂沙箱,就是每個插件擁有獨立的_G全局環境,即便用戶誤將print修改,其他的插件也不會受到影響. 同時,考慮到沙箱的安全性和權限,需要對沙箱函數訪問進行訂制.以下是本人摸索出的一種方案:

            先看下我的UI環境及lua嵌入架構:

            1. C++層將必要的API注冊到lua層.但都是基于id的全局函數(考慮到效率及便捷),但是實際使用時再在lua層進行OO封裝,這和WINDOWS API及MFC的原理類似

            2. C++層只提供4種原生控件: Button,Label, EditBox,MultiLineEditBox。其他的控件都是由這些組成。

            3. 可以將整個系統分為內核模式和用戶模式。

                內核模式:可以使用完整的API訪問及權限。

                用戶模式:被沙箱保護,無法訪問一些危險的API,例如io

             

            這里,我們使用lua_setfenv進行沙箱構建,首先我們必須將創建每個沙箱對應的table

            // 放入沙箱名稱
            lua_pushstring( mLua, "mysandbox" );
            // 將一個table壓入棧
            dotlua::table ts( mLua , false );
            // 調用之前載入好的一個訂制沙箱環境的函數
            gt.call<void>("SetupSandBox", ts ); 
            // 將沙箱以mysandbox的key保存在注冊表中
            lua_settable( mLua, LUA_REGISTRYINDEX );

            之后使用lua_loadfile載入需要放進沙箱的代碼

             

            // 這里將本沙箱對應的環境取出來
            lua_pushstring( mLua, "mysandbox" );
            lua_gettable( mLua, LUA_REGISTRYINDEX );
            // 棧內的情形為
            // -1  沙箱table
            // -2 chunk function
            // 這里必須調用chunk函數
            lua_setfenv( mLua, -2 );
            調用pcall執行代碼
            這里的chunk函數,來源于lua_loadfile或者lua_loadbuffer,這2個函數將代碼讀入,但并不會執行,包括定義全局函數之類的操作。
            沙箱訂制函數必須提前載入,這里發一個做參考

            function SetupSandBox( e )
                e._G = e
                -- system lib
                e.print         = print
                e.printf         = printf
                e.table         = table
                e.string         = string
                e.debug         = debug
                e.math             = math
                e.assert         = assert
                e.getmetatable     = getmetatable
                e.ipairs         = ipairs
                e.pairs         = pairs
                e.pcall         = pcall
                e.setmetatable     = setmetatable
                e.tostring         = tostring
                e.tonumber         = tonumber
                e.type             = type
                e.unpack         = unpack
                e.collectgarbage = collectgarbage
                -- class
                e.TREENODE = WIDGET_TREENODE
                e.SERIALIZE = WIDGET_SERIALIZE
                -- function
                e.CreateWidget = CreateWidget
                e._Inherit = _Inherit
            end

            只有被訂制的函數,才能被調用
             
            擴展:
             為了獲得完整的內核模式開發,但又擁有獨立的沙箱環境,可以使用setmetatable方式設置一個對全局table的引用,雖然速度慢了點。。
            當然,可以支持一套可載入dll訂制權限,并注冊更多的api給自己的腳本用
            posted on 2009-07-09 11:12 戰魂小筑 閱讀(2188) 評論(1)  編輯 收藏 引用 所屬分類: 腳本技術

            評論

            # re: 構建類魔獸UI插件的lua安全沙箱 2009-07-09 11:20 Adrian
            不錯,希望接口可以再簡潔一點,再快一點~  回復  更多評論
              

            久久人人妻人人爽人人爽| 品成人欧美大片久久国产欧美| 91麻豆国产精品91久久久| 狠狠色丁香久久婷婷综合_中| 亚洲乱码精品久久久久.. | 久久er99热精品一区二区| 久久99精品国产一区二区三区| 热综合一本伊人久久精品| 久久久久久久久久久久中文字幕| 久久国产V一级毛多内射| 无码任你躁久久久久久老妇App| 精品久久久久久国产| 国产精品久久久香蕉| 青青草国产精品久久| 午夜精品久久久久久中宇| 久久免费香蕉视频| 久久福利青草精品资源站免费| 亚洲国产精品成人久久蜜臀 | 亚洲人成网亚洲欧洲无码久久 | 2020久久精品亚洲热综合一本| 狠狠色婷婷综合天天久久丁香| 久久人人爽人人爽人人片AV高清| 国内精品久久久久影院网站| 丁香狠狠色婷婷久久综合| 性高湖久久久久久久久| A级毛片无码久久精品免费| 久久国产亚洲精品| 久久综合色之久久综合| 99热成人精品免费久久| 久久久青草久久久青草| 97久久综合精品久久久综合| 久久天天躁狠狠躁夜夜avapp| 久久久久久久久波多野高潮| 久久夜色精品国产噜噜亚洲a| 久久伊人五月天论坛| 亚洲?V乱码久久精品蜜桃| 久久久无码精品午夜| 色婷婷久久综合中文久久一本| 久久性生大片免费观看性| 久久天天躁狠狠躁夜夜不卡| 天天做夜夜做久久做狠狠|