• <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
            不錯,希望接口可以再簡潔一點,再快一點~  回復  更多評論
              

            综合久久久久久中文字幕亚洲国产国产综合一区首 | 婷婷久久综合九色综合九七| 久久精品国产第一区二区| 久久一本综合| 国产婷婷成人久久Av免费高清| 99国产欧美久久久精品蜜芽 | 日日狠狠久久偷偷色综合免费 | 中文字幕无码久久人妻| 少妇久久久久久久久久| 日韩精品国产自在久久现线拍| 免费精品国产日韩热久久| 国产午夜福利精品久久2021| 久久久久久久综合狠狠综合| 久久亚洲精品视频| 麻豆AV一区二区三区久久| 久久夜色精品国产www| 精品久久一区二区| 99久久国产精品免费一区二区| 精品久久久久久久久久中文字幕 | 亚洲精品乱码久久久久久久久久久久 | 国产成人久久激情91| 精品国产乱码久久久久软件| 精品久久久久一区二区三区| 久久精品天天中文字幕人妻| 精品久久亚洲中文无码| 亚洲а∨天堂久久精品9966| 久久精品国产亚洲Aⅴ香蕉 | 亚洲人AV永久一区二区三区久久| 2020最新久久久视精品爱| 丁香狠狠色婷婷久久综合| 久久亚洲私人国产精品| 人妻少妇久久中文字幕| 亚洲熟妇无码另类久久久| 精品久久久久久中文字幕大豆网| 无码人妻久久一区二区三区蜜桃| 精品久久久久久无码中文字幕| 国产成人精品久久综合| 精品久久久久久久久久中文字幕| 99久久精品免费观看国产| 久久精品夜色噜噜亚洲A∨| 国产精品午夜久久|