Okay, so, I've made a little sandbox, and I will retrieve part of it to ask you guys on how I could block these methods easier:
already defined player as "Player"
local ActualPlayer = Game.Players.Player1 local Player = newproxy(true) local Blocked = { kick = true, destroy = true, remove = true, } local Clones = { kick = function(p) error("Attempt to kick player blocked") end, destroy = function(p) error("Attempt to kick player blocked") end, remove = function(p) error("Attempt to kick player blocked") end, } getmetatable(Player).__index = function(a,b) if not Blocked[b:lower()] and ActualPlayer[b] and not ActualPlayer:FindFirstChild(b) then return ActualPlayer[b] elseif Blocked[b:lower()] then Clones[b:lower()](ActualPlayer) return Clones[b:lower()] elseif not Blocked[b:lower()] and ActualPlayer:FindFirstChild(b) then return ActualPlayer[b] end end Player:Destroy() Player:Remove() Player:kick()
Look at what you are returning: just simplify
if Blocked[b:lower()] then return Clone[b:lower()](ActualPlayer) else return ActualPlayer[b] end
This isn't a very good sandbox:
Player.Parent[Player.Name]:Kick()
The following is untested. It might represent a more full solution.
function isRoblox(obj) -- I wish I knew of a better way -- This isn't perfect... if type(obj) == "userdata" then local returned = false pcall(function() returned = obj.Parent[obj.Name] end) return returned end end local evade = { kick = function() error("No kicking.") end } function sandbox(obj) if not isRoblox(obj) then return obj end local box = newproxy(true); getmetatable(box).__index = function(_, key) if type(key) == "string" then local evasion = evade[key:lower()] if evasion then return evasion(obj, key) else return sandbox( obj[key] ) end else return obj[key] -- Will always error but, useful error end end end