SimpleDecompile
Key Required VerifiedUniversal

SimpleDecompile

Universal Scriptvxstyvxsty 601.6K views 651 executesUpdated Jan 27, 2024
1.1/ 5(23 votes)
51822% Positive
Lua Script•390 lines (16647 chars)
local Settings = {
    IncludeNils = false -- If true, functions that's names cannot be obtained (Most likely empty functions) will also be included in the decompiled code.
}
local HTTPs = game:GetService('HttpService');
function encode(a)
    return HTTPs:JSONEncode(a)
end
function decode(a)
    return HTTPs:JSONDecode(a)
end
if not isfolder("SimpleDecompile") then
    makefolder("SimpleDecompile")
    writefile("SimpleDecompile/config.json", encode(Settings))
elseif isfolder("SimpleDecompile") and isfile("SimpleDecompile/config.json") then
    Settings = decode(readfile("SimpleDecompile/config.json"))
end
function startswith(str, thing)
    if str:sub(1, #thing) == thing then
        return true
    else
        return false
    end
end
function pKey(key)
    if startswith(tostring(key), "__") then
        return tostring(key)
    end
    if type(key) == "number" then
        return "[" .. tostring(key) .. "]"
    else
        return '["' .. tostring(key) .. '"]'
    end
end
function pKey1(key, val)
 if type(key) == "number" then
  if typeof(val):lower() == "boolean" then
   return "bool_" .. tostring(key)
  else
   return typeof(val):lower() .. "_" .. tostring(key)
  end
 elseif type(key) == 'string' then
  return val
 end
end
function isStrFunc(str)
 for i, v in getrenv() do
  if tostring(i) == str and type(v) == "function" then return true end
 end
 return false
end
function gcsenv(Scr)
    local funcs = {}
    for i, v in next, getgc(true) do
        if (type(v) == "function" and islclosure(v) and getfenv(v).script == Scr) then
            table.insert(funcs, v)
        end
    end
    return funcs
end

function GetMetaMethods(regularTable)
    local meta = getmetatable(regularTable)
    if not meta then
        return {}
    end
    setreadonly(meta, false)
    local mms = {}
    for i, v in meta do
        if startswith(tostring(i), "__") then
            table.insert(mms, {Name = i, Value = v})
        end
    end
    return mms
end
function GetFullName(instance)
    local p = instance
    local lo = {}
    while (p ~= game and p.Parent ~= nil) do
        table.insert(lo, p)
        p = p.Parent
    end
    local fullName
    if #lo == 0 then
        return "nil -- Instance parented to nil"
    end
    if lo[#lo].ClassName ~= "Workspace" then
        fullName = 'game:GetService("' .. lo[#lo].ClassName .. '")'
    else
        fullName = "workspace"
    end
    for i = #lo - 1, 1, -1 do
        fullName = fullName .. ':FindFirstChild("' .. lo[i].Name .. '")'
    end
    return fullName
end
function processTableDescendants(tbl, indent, tblname)
    indent = indent or 0
    tblname = tblname or "{}"
    local metacount = 1
    local result = ""
    local count = 1
    for key, value in pairs(tbl) do
        if type(value) == "table" and not startswith(tostring(key), "__") then
            result = result .. string.rep("  ", indent) .. pKey(key) .. " = {"
            if #value == 0 then
                result = result .. "}"
            else
                result = result .. "\n" .. processTableDescendants(value, indent + 1)
                result = result .. string.rep("  ", indent) .. "}\n"
            end
            if getrawmetatable(value) ~= nil then
                result =
                    result ..
                    string.rep("  ", indent) ..
                        "local meta" .. tostring(metacount) .. " = setmetatable(" .. tostring(tblname) .. ", {})\n"
                metacount = metacount + 1
                for _, v in GetMetaMethods(value) do
                    result =
                        result ..
                        string.rep("  ", indent) .. "meta" .. tostring(metacount) .. "." .. tostring(v.Name) .. " = "
                    if typeof(v.Value) == "table" then
                        result =
                            result ..
                            string.rep("  ", indent) ..
                                "{" ..
                                    processTableDescendants(v.Value, indent + 1) ..
                                        "\n" .. string.rep("  ", indent) .. "}"
                    elseif typeof(v.Value) == "function" then
                        result = result .. string.rep("  ", indent) .. "function() --[[ Function Source ]] end"
                    else
                        result = result .. string.rep("  ", indent) .. tostring(v.Value)
                    end
                    result = result .. ";\n"
                end
            end
        elseif type(value) == "function" and not startswith(tostring(key), "__") then
            result =
                result ..
                string.rep("  ", indent) ..
                    pKey(key) .. " = function() --[[Function Source]] end" .. string.rep("  ", indent + 1)
        elseif typeof(value):lower() == "vector3" and not startswith(tostring(key), "__") then
            result =
                result ..
                string.rep("  ", indent) ..
                    pKey(key) ..
                        " = Vector3.new(" ..
                            tostring(value.X) .. ", " .. tostring(value.Y) .. ", " .. tostring(value.Z) .. ");\n"
        elseif typeof(value):lower() == "vector2" and not startswith(tostring(key), "__") then
            result =
                result ..
                string.rep("  ", indent) ..
                    pKey(key) .. " = Vector2.new(" .. tostring(value.X) .. ", " .. tostring(value.Y) .. ");\n"
        elseif typeof(value):lower() == "udim" and not startswith(tostring(key), "__") then
            result =
                result ..
                string.rep("  ", indent) ..
                    pKey(key) .. " = UDim.new(" .. tostring(value.Scale) .. ", " .. tostring(value.Offset) .. ");\n"
        elseif typeof(value):lower() == "udim2" and not startswith(tostring(key), "__") then
            result =
                result ..
                string.rep("  ", indent) ..
                    pKey(key) ..
                        " = UDim2.new(" ..
                            tostring(value.X.Scale) ..
                                ", " ..
                                    tostring(value.X.Offset) ..
                                        ", " .. tostring(value.Y.Scale) .. ", " .. tostring(value.Y.Offset) .. ");\n"
        elseif typeof(value):lower() == "instance" and not startswith(tostring(key), "__") then
            result = result .. string.rep("  ", indent) .. pKey(key) .. " = " .. GetFullName(value) .. ";\n"
        elseif typeof(value) == "string" and not startswith(tostring(key), "__") then
            result = result .. string.rep("  ", indent) .. pKey(key) .. ' = "' .. tostring(value) .. '";\n'
        elseif typeof(value) == "number" and not startswith(tostring(key), "__") then
            result = result .. string.rep("  ", indent) .. pKey(key) .. " = " .. tostring(value) .. ";\n"
        elseif typeof(value) == "nil" and not startswith(tostring(key), "__") then -- nil value
            result = result .. string.rep("  ", indent) .. pKey(key) .. " = " .. tostring(value) .. ";\n"
        elseif typeof(value):lower() == "cframe" and not startswith(tostring(key), "__") then -- Enum/Other value
            result = result .. string.rep("  ", indent) .. pKey(key) .. " = CFrame.new(" .. tostring(value) .. ");\n"
        elseif typeof(value):lower() == "color3" and not startswith(tostring(key), "__") then
            result =
                result ..
                string.rep("  ", indent) ..
                    pKey(key) ..
                        " = Color3.fromRGB(" ..
                            tostring(value.R * 255) ..
                                ", " .. tostring(value.G * 255) .. ", " .. tostring(value.B * 255) .. ");\n"
        end
    end
    if #tbl == 0 then
        return result
    else
        return "\n" .. result
    end
end
function DecompileFunction(func, excludename, indent, customname)
    if not indent then
        indent = 1
    end
    local metatablecount = 1
    local inf, String = debug.getinfo(func), "function " .. tostring(debug.getinfo(func).name) .. "("

    if excludename then
        String = "function("
    end
    if customname then
        String = "function " .. customname .. "("
    end
    if tostring(inf.is_vararg) == "1" then
        String = String .. "...\n"
    else
        local ab={"a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"}
        if inf.numparams > 0 then
            local paramcount = inf.numparams
            for i = 1, paramcount do
                String = String .. ab[i]
                if i < paramcount then
                    String = String .. ", "
                end
            end
            if paramcount > #ab then
                String = String .. ", ..."
            end
        end
        String = String .. ")"
        StringHolder = String
        String = ""
        UString = ""
        for i, v in getupvalues(func) do
        if typeof(v):lower() == "vector2" then
            UString = UString .. ("\n%s = Vector2.new(%d, %d)"):format(pKey1(i, v), v.X, v.Y)
        elseif typeof(v):lower() == "vector3" then
            UString = UString .. ("\n%s = Vector3.new(%d, %d, %d)"):format(pKey1(i, v), v.X, v.Y, v.Z)
        elseif typeof(v):lower() == "udim" then
            UString = UString .. ("\n%s = UDim.new(%d, %d)"):format(pKey1(i, v), v.Scale, v.Offset)
        elseif typeof(v):lower() == "udim2" then
            UString =
                UString ..
                ("\n%s = UDim2.new(%d, %d, %d, %d)"):format(
                    pKey1(i, v),
                    v.X.Scale,
                    v.X.Offset,
                    v.Y.Scale,
                    v.Y.Offset
                )
        elseif typeof(v):lower() == "number" then
            if os.time() - v < 1 then
                UString = UString .. ("\n%s = %s --[[ Possibly os.time() ]]"):format(pKey1(i, v), tostring(v))
            elseif tick() - v < 1 then
                UString = UString .. ("\n%s = %s -- [[ Possibly tick() ]]"):format(pKey1(i, v), tostring(v))
            else
                -- Reasons not to add userid checks: False alarms (Really rare, But why would they it in a modulescript or a localscript.)
                UString = UString .. ("\n%s = %s"):format(pKey1(i, v), tostring(v))
            end
        elseif typeof(v):lower() == "instance" then
            UString = UString .. ("\n%s = %s"):format(v.Name:gsub(" ", "_"),GetFullName(v))
        elseif typeof(v):lower() == "color3" then
            UString = UString .. ("\n%s = Color3.fromRGB(%d, %d, %d"):format(pKey1(i, v), v.R * 255, v.G * 255, v.B * 255)
        elseif typeof(v):lower() == "string" then
            UString = UString .. ('\n%s = "%s"'):format(pKey1(i, v), v)
        elseif typeof(v):lower() == "boolean" then
            UString = UString .. ("\n%s = %s"):format(pKey1(i, v), tostring(v))
        elseif typeof(v):lower() == "cframe" then
            UString = UString .. ("\n%s = CFrame.new(%s)"):format(pKey1(i, v), tostring(v))
        end
     end
    end
    if #getupvalues(func) == 0 then
        String = StringHolder
    else
        String = UString .. "\n" .. StringHolder or ''
    end
    local consts = string.rep("  ", indent) .. "--[[ Detected roblox functions list"
    local Aconsts = ""
    local UnknownProtos = 0
    for i, v in getconstants(func) do
     if isStrFunc(v) then
      consts = consts .. "\n" .. string.rep("  ", indent) ..v.."()"
     else
      Aconsts = Aconsts .. "\n" .. string.rep("  ", indent) .. "local c_" .. tostring(i) .. " = '" .. tostring(v) .. "'"
     end
    end
    consts = consts .. "\n" .. string.rep("  ", indent) .. "]]\n"
    for i, v in getprotos(func) do
        if debug.getinfo(v).name == nil then
            UnknownProtos = UnknownProtos + 1
            String =
                String ..
                ("\n%slocal %s\n"):format(
                    string.rep("  ", indent),
                    DecompileFunction(v, false, indent + 1, "nil" .. tostring(UnknownProtos))
                )
        else
            String = String .. ("\n%slocal %s\n"):format(string.rep("  ", indent), DecompileFunction(v, false, indent + 1))
        end
    end
    return String .. "\n" .. consts .. Aconsts .. "\n" .. string.rep(" ", indent) .. "end"
end

function DecompileScript(Script)
    local Decompiled = "--[[ DECOMPILED WITH SIMPLEDECOMPILE ]]\n"
    if typeof(Script) == "Instance" and Script.ClassName == "ModuleScript" then
        local s, e =
            pcall(
            function()
                for i, v in require(Script) do
                    if type(v) == "table" then
                        if #v == 0 then
                            if type(i) == "number" then
                                Decompiled = Decompiled .. ("\nlocal table_%d = {}; --[[ EMPTY TABLE ]]\n"):format(pKey1(i, v))
                            else
                                Decompiled = Decompiled .. ("\nlocal %s = {}; --[[ EMPTY TABLE ]]\n"):format(i)
                            end
                        else
                            if type(i) == "number" then
                                Decompiled =
                                    Decompiled ..
                                    ("local table_%d = {\n%s};\n"):format(
                                        pKey1(i, v),
                                        processTableDescendants(v, 0, "t_" .. tostring(i))
                                    )
                            else
                                Decompiled =
                                    Decompiled ..
                                    ("local %s = {\n%s};\n"):format(
                                        i,
                                        processTableDescendants(v, 0, "t_" .. tostring(i))
                                    )
                            end
                        end
                elseif type(v) == 'function' then
                 if type(i) == 'number' then
                    Decompiled = Decompiled .. ("\n%s"):format(DecompileFunction(v, false, 0, "f_"..tostring(i)))
                 else
                    Decompiled = Decompiled .. ("\n%s"):format(DecompileFunction(v, false, 0))
                 end
                end
             end
            end
        )
        if not s then
            return "-- Error occured when trying to iterate over ModuleScript, Message: " .. e
        end
        return Decompiled
    end
    local s, e =
        pcall(
        function()
            local uks = 1
            for i, v in getsenv(Script) do
                if type(v) == "table" then
                    if #v == 0 then
                        if type(i) == "number" then
                            Decompiled = Decompiled .. ("\nlocal table_%d = {}; --[[ EMPTY TABLE ]]\n"):format(pKey1(i, v))
                        else
                            Decompiled = Decompiled .. ("\nlocal %s = {}; --[[ EMPTY TABLE ]]\n"):format(i)
                        end
                    else
                        if type(i) == "number" then
                            Decompiled =
                                Decompiled ..
                                ("local table_%d = {\n%s};"):format(
                                    pKey1(i, v),
                                    processTableDescendants(v, 0, "t_" .. tostring(i))
                                )
                        else
                            Decompiled =
                                Decompiled ..
                                ("local %s = {\n%s};\n"):format(i, processTableDescendants(v, 0, "t_" .. tostring(i)))
                        end
                    end
                end
            end
            for i, v in gcsenv(Script) do -- garbage collection senv
                local name = debug.getinfo(v).name
                if name == nil and Settings.IncludeNils then
                    Decompiled = Decompiled .. ("\n%s"):format(DecompileFunction(v, false, 0, "nil" .. tostring(uks)))
                    uks = uks + 1
                elseif name ~= nil then
                    Decompiled = Decompiled .. ("\n%s"):format(DecompileFunction(v, false, 0))
                end
            end
        end
    )
    if not s then
        return " --An error occured while attempting to iterate over Script's enviroment!\nMessage: " .. e
    end
    return Decompiled
end

getgenv().decompile = DecompileScript
return DecompileScript

Features & Information

Can decompile LocalScripts & ModuleScripts v1.0.0: Can read upvalues Can read Vector3, Vector2, UDim, UDim2 values Can fully read tables Can read instance paths What it can't do as of now: Read while loops Read for loops Read function arguements's names (For example decompiling this function HelloWorld(Greet, Bye) would return function HelloWorld(a,b) It currently uses the alphabet as arguement counters) Use function arguements Use constants Hardly read constants How do I use it? Put this in your autoexec folder, Get the script you want to decompile's path, enter in your executor: decompile(scriptPath) If you want to print the result do print(decompile(scriptPath)) decompile returns a string value. v1.0.1 Changelogs: [+] A LOT better reading for constants: Instead of the usual local v8 = 'task' local v9 = 'wait', I implemented a feature that detects libraries (os, math, utf8, bit32, debug, string, table, ...) and checks if the next constant is a function of the library. [+] Better proccessTableDescendants code: You might've checked the previous code and said, why the hell is he doing if type(key) == "number" ... instead of making a function for it?!!, I did that. [+] Better instance path reading Instead of the previous (instance:GetFullName() function) I created a function called GetFullName that returns a better looking path, For example Previous: game.Players.LocalPlayer.leaderstats.Cash Current: game:GetService("Players").LocalPlayer:FindFirstChild("leaderstats"):FindFirstChild("Cash") Also added an if check to check if the first service is Workspace and used workspace:FindFirstChild instead of game:GetService("Workspace") [-] Added 2 extra arguements for the DecompileFunction function (exclude name, indent count) You don't need to worry about those as if they don't exist the script automatically adds them. [+] Added support for Enum values and fixed a string bug, If you had a string value in a table it wouldn't add quotes around it, Now it does. v1.0.2 Changelogs: [+] Fixed the main decompile function having incorrect arguements for DecompileFunction [+] Metatables & Metamethods support [_] To do list: Reading .new functions better. v1.0.3 Changelogs: [+] Fixed error when trying to iterate over a script [+] Added better metamethod decompiling (For example: Script now does meta1 = setmetatable(v1, {}); meta1.__index = function... instead of just putting the metamethods in the table itself.) [+] Fixed error where if an instance was parented to nil it would break the script, Script now returns Instance = nil -- Instance parented to nil [_] To do: Add better decompiling: Make script generate possible code instead of just returning constants & upvalues. // I do not promise this will be added, I will try to work on it tho. [+] Fixed ModuleScript error v1.0.4 The Ultimate Update Code sample: ``` local a = false local b = 1.712 local c = "hello world" function abc() print(a, b, c) end ``` [+] Upvalues reading much easier! Now you don't have to worry about having trouble reading upvalue names because i got you covered! Reading abc's upvalues will return either: bool_1 = false (a) number_2 = 1.712 (b) string_3 = "hello world" (c) or a = false b = 1.712 c = "hello world" instead of v1 = false v2 = 1.712 v3 = "hello world" Note: If the output was the first result then it's gonna be (DATATYPE_UPVALUE INDEX) [-] Removed libraries (task, utf8, ...) checks from constants. [+] Better instance naming, Instead of doing v1 = path... now it does the instance's name (Example: Part = workspace.Parts.Part, HumanoidRootPart = game.Players.LocalPlayer.Character.HumanoidRootPart) [+] MORE FUNCTION READING: You are now able to read garbage collection functions from a script that you weren't able to read before! [+] Settings: Only one setting at the moment but you can switch it from your workspace/SimpleDecompile/config.json files, It is the IncludeNils setting [?] What is includeNils? IncludeNils determines whethere you can see the functions that's names are nil, If true will show the functions, if false will exclude them, usually they're found in the garbage collection [+] Better Protos: Instead of your usual "local function nil(a, b).... local function nil(a) -- again" It now has different identifiers for each proto, nil1, nil2, nil3... [+] Better Formatting: Fixed the dumb --[[Found %d roblox functions in the function]]'s indentations, Now it also shows a clearer list. [+] Now loadstringing returns the decompile function, (Aka you can do local functionName = loadstring(game:HttpGet("ThisScript'sURL")(), functionName(script)) I say this is one of the best updates to come to SimpleDecompile, Please make sure to leave a favorite or thumbs up. TODO: Buffer reading and buffer decompiling.
#unique#verified#decompiler#mobile#pc

Community Comments (33)

REDzREDzJan 27, 2024(edited)

Cool

REDzREDzJan 27, 2024(edited)

Can this code see loops?

vxstyvxstyJan 28, 2024(edited)

@REDz read the features

beriberiberiberiJan 30, 2024(edited)

yo uh, I'm a bit stupid so I can't figure out how to use this

vxstyvxstyJan 30, 2024(edited)

@nixelpizel decompile(LocalScript/ModuleScript path, false -- If you want exclude the function's name in the code, 0 -- Indent count)

Purple_ApplePurple_AppleFeb 4, 2024(edited)

Cool. hope to see more updates in the future!

vxstyvxstyFeb 4, 2024(edited)

@tycoonman95 working on one right now!

vxstyvxstyFeb 4, 2024(edited)

@Liver_zMods_001 First execute the script / put it into your autoexec, Second execute local Decompiled = decompile(game.Players.LocalPlayer.PlayerGui.Home.hud.GunFrame.TextButton.LocalScript) Do whatever you want with the Decompiled variable, It's also a string. You can print it, save it to a file, do whatever you want.

realflamerealflameFeb 17, 2024(edited)

im getting the following error: :148: attempt to iterate over a nil value when trying to decompile a script

vxstyvxstyFeb 17, 2024(edited)

@flamedev I have already made a fix but i cannot update right now because i am working on a better metamethod support update, Sorry for the inconvience and this will be fixed quickly.

vxstyvxstyFeb 17, 2024(edited)

@flamedev @tycoonman95 I updated the script. flamedev I fixed the issue you reported.

realflamerealflameFeb 20, 2024(edited)

--An error occured while attempting to iterate over Script's enviroment! Message: :185: :160: invalid argument #1 to 'getsenv' (LocalScript or ModuleScript expected) when trying to decompile module script

vxstyvxstyFeb 20, 2024(edited)

@flamedev Ah, if you want to decompile the module you must require it, I will fix that.

vxstyvxstyFeb 20, 2024(edited)

@flamedev Fixed it

realflamerealflameFeb 22, 2024(edited)

@vxsty Works! Very good decompiler! vouch

vxstyvxstyFeb 22, 2024(edited)

First: You should only put the ModuleScript or LocalScript path, Second: You didn't add a print(decompile(...)) If you want to print it add a print before the decompile. @F_hub99

SkireScriptsSkireScriptsMar 8, 2024(edited)

@vxsty what is the rec exe? idk what to try and dont wanna waste time

vxstyvxstyMar 8, 2024(edited)

@SkireScripts What? I've never heard of such thing. Perhaps you mean't ro-exec? That's a roblox pc executor. (PAID)

Mr_PoopyPantsMr_PoopyPantsMar 11, 2024(edited)

Add a gui

vxstyvxstyMar 11, 2024(edited)

@F_hub99 Is it really neccessary? You can just use hydroxide and copy the path then decompile it.

vxstyvxstyMar 12, 2024(edited)

@flamedev what? That isn't a problem with my script you're loadstringing 2 different things, 3 if mine is included. Also arceus x is horrible, use delta (If you want)

realflamerealflameMar 12, 2024(edited)

oh, mb, also the pastebin is ur script raw

vxstyvxstyMar 13, 2024(edited)

@flamedev never made one, It's possibly just a stolen version of mine

ssamsam315ssamsam315Apr 11, 2024(edited)

@vxsty You should make one for wave honestly that would be fire.

vxstyvxstyApr 11, 2024(edited)

@ssamsam315 This should work for wave.

giganticspy91giganticspy91May 6, 2024(edited)

Error occured when trying to iterate over ModuleScript, Message: :308: invalid argument #2 to 'format' (number expected, got string) I get this with IncludeNils = true using kramp btw

vxstyvxstyMay 6, 2024(edited)

@giganticspy91 Use simpledecompile v2 if you're not using krampus, Krampus has an already implemented obfuscator you can use that.

giganticspy91giganticspy91May 6, 2024(edited)

okay just wondering if this was any better. I have problems with unluau

yarikku05yarikku05Jul 8, 2024(edited)

I dont get alot of stuff. I want to get an entire game with working scripts and guis and the map how?

vxstyvxstyJul 8, 2024(edited)

@yarikku05 saveinstance()

BjarnosBjarnosSep 4, 2024(edited)

Patched.

vxstyvxstySep 4, 2024(edited)

@Bjarnos It isn't your executor just doesn't support core functions.

jenson_bensonjenson_bensonAug 29, 2025

what do i paste it on

More Scripts for Universal Scripts