2015-07-31 2 views
0

Недавно я начал создавать построитель скриптов. Единственная часть, на которой я застрял, - это заставить песочницу работать.Roblox Script Builder Sandbox

Я попытался после этого урока: http://wiki.roblox.com/index.php?title=Sandboxing, но без толку

Я не в полной мере понять, о том, как это сделать, но мне удалось пойти так далеко, как это:

local needssandboxing = function(i) end 

sandbox = {} 
sandbox.cache = {} 

local function safeDestroy(obj) 
    if obj.ClassName == "Script" then 
     print("You cannot destroy a Script") 
    elseif obj == "Base" then 
     print("You cannot destroy the Base.") 
end 


    obj:Destroy() 
end 

local function safeGetChildren(obj) 
    local res = {} 

    for k,v in pairs(obj:GetChildren()) do 
    if not v.Name:match("^Hide") then 
      table.insert(res,v) 
     end 
    end 

    return res 
end 

sandbox.mt = { 
    __index = function(self, k) 
     local original = sandbox.cache[self] 
     local v = original[k] 

     if k:lower() == "destroy" then 
      return sandbox.any(safeDestroy) 

     elseif k:lower() == "getchildren" or k:lower() == "children" then 
      return sandbox.any(safeGetChildren) 
     end 

     return sandbox.any(v) 
    end, 

    __newindex = function(self, k, v) 
     local original = sandbox.cache[self] 
     original[k] = unsandbox.any(v) 
    end 
} 

function sandbox.any(a) 
    if sandbox.cache[a] then 
     return a 

    elseif type(a) == "function" then 
     return sandbox.func(a) 

    elseif type(a) == "table" then 
     return sandbox.table(a) 

    else 
     return value 
    end 
end 

function sandbox.object(o) 
    local sandboxed = setmetatable({}, sandbox.mt) 

    sandbox.cache[sandboxed] = o 

    return sandboxed 
end 

function sandbox.func(f) 
    local sandboxed = function(...) 
     return sandbox(f(unsandbox(...))) 
    end 

    sandbox.cache[sandboxed] = f 

    return sandboxed 
end 

function sandbox.table(t) 
    local sandboxed = {} 

    for k, v in pairs(t) do 
     sandboxed[sandbox.any(k)] = sandbox.any(v) 
    end 

    return sandboxed 
end 

unsandbox = {} 

unsandbox.any = function(a) 
    if sandbox.cache[a] then 
     return sandbox.cache[a] 

    elseif type(a) == "function" then 
     return unsandbox.func(a) 

    elseif type(a) == "table" then 
     return unsandbox.table(a) 

    else 
     return a 
    end 
end 

unsandbox.table = function(t) 
    local unsandboxed = {} 

    for k, v in pairs(t) do 
     unsandboxed[unsandbox.any(k)] = unsandbox.any(v) 
    end 

    return unsandboxed 
end 

unsandbox.func = function(f) 
    local raw = function(...) 
     return unsandbox(f(sandbox(...))) 
    end 

    sandbox.cache[f] = raw 

    return raw 
end 

local callable_mt = { 
    __call = function(self, first, ...) 
     if select('#', ...) == 0 then 
      return self.any(first) 
     else 
      return self.any(first), self(...) 
     end 
    end 
} 

setmetatable(sandbox, callable_mt) 
setmetatable(unsandbox, callable_mt) 

Но я не знаю, как его использовать. Я пробовал:

sandbox(function() 
    local r = game.Workspace:GetChildren() 
    for i=1, #r do 
     print(r[i]) 
    end 
end) 

Это абсолютно ничего не делает. Есть ли что-то, что я делаю неправильно?

ответ

1

В вашем коде нет функции sandbox(), поэтому вы пытаетесь вызвать несуществующую функцию.

Попробуйте это:

sandbox.func(function() 
    local r = game.Workspace:GetChildren() 
    for i=1, #r do 
     print(r[i]) 
    end 
end) 
1

сам Песочница не является функцией, но __call Метаметод позволяет ему называться функции, даже если это таблица.

Ваш код должен быть размещен внутри сценария со следующим кодом. Затем, когда вы хотите загрузить сценарий, поставить StringValue под названием «Кодекс» в скрипте с набором значение свойства скрипта, который вы хотите выполнить:

local realEnvironment = getfenv(0); 
local fakeEnvironment = setmetatable({}, {__index = function (self, i) 
    if (realEnvironment[i]) then --Check if object exists at all 
     return sandbox(realEnvironment[i]) --return sandboxed object 
    end; 
end, __metatable = 'This is a locked metatable!'}); --An environment to only return sandboxed objects 
setfenv(0,fakeEnvironment);--Set the global environment 
setfenv(1,fakeEnvironment);--Set the current function stack 
assert(loadstring(script:WaitForChild('Code').Value))(); 

Последняя строка ждет ребенка «Code», затем вызывает на нем loadstring, assert проверяет, имеет ли он синтаксическую ошибку, и если это произойдет, это приведет к ошибке, которая, если не возвращает функцию, которая затем вызывается (нет необходимости устанавливать ENV функции, потому что мы устанавливаем глобальные среды).