Repository: unified-naming-convention/NamingStandard Branch: main Commit: 305c31e4f469 Files: 17 Total size: 92.2 KB Directory structure: gitextract_jozbinvc/ ├── CONTRIBUTING.md ├── README.md ├── TEMPLATE.md ├── UNCCheckEnv.lua └── api/ ├── Drawing.md ├── WebSocket.md ├── cache.md ├── closures.md ├── console.md ├── crypt.md ├── debug.md ├── filesystem.md ├── input.md ├── instances.md ├── metatable.md ├── misc.md └── scripts.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing ## Guidelines * Adding a new function can be done by copying TEMPLATE.md, renaming it, and editing it as needed. * You may provide edits of existing functions, just edit and submit it. * When possible, organise files in their respective category folders. * When writing the function signature, please make sure it is **valid typed Luau syntax**. Documentation for typed luau can be found [here](https://luau-lang.org/typecheck#union-types). * When referencing arguments of a function in the description, please use `` in order to make `it look nice like so`. * Please confirm a function has not already been added to the API before you submit it. * Functions must be named appropriately, if you are contributing one - the following criteria applies for the naming: * No brand names should be visible in your documentation. * This also includes function alias' - UNC aims to be a vanilla naming convention, not a branded one * The function name must be **descriptive of what the function does**. * Aliases for shortening function names without good reason are *not* allowed. For example, `hookfunc` is not a alias supported by UNC. Function names should be written out in full. * The description must be coherent, if the function is basic enough to not warrant one - you may put "N/A" in the description. * Functions don't always require an alias, you may just also put N/A in that field. ## Submitting your edits and/or additions This can be done through [github pull requests](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests). Clone the repository, make your changes, then submit a pull request. The pull request will be reviewed by several members of the UNC before it is merged. ================================================ FILE: README.md ================================================ # Unified Naming Convention aka UNC, is an organization between executor developers to provide a unified scripting API for our scripters. ## UNC Has Retired 👋 Who would've thought a globally documented API would be **such a hit**? We sure did! UNC was a great concept and it's lifespan proved it, focusing on building an excellent API for scripters allowed for those scripters to create great scripts, making our software just that more usable. Two years ago, UNC helped to resolve the issue of poorly named functions. Today, it's founders at ([Script-Ware](https://script-ware.com/)) have stopped engineering script execution software for Roblox where these functions are used. You are welcome to keep using UNC as a benchmark for software, but it will eventually grow out of date with newer features. We're sorry! We hope one day we'll make it up to you. --- ~~**Please go to our official website for better styled information: https://scriptunc.org/**~~ This website has since been removed, you can find all of the same information below. ## Why? Over the years scripting has gotten more and more complex to support multiple executors. This is because of the many unique naming conventions various executors use. Consider the following scenario. You want to know if a function belongs to the executor or not. In order for this code to be cross compatiable with all executors code like this is needed: ```lua local is_executor_closure = is_syn_closure or is_fluxus_closure or is_sentinel_closure or is_krnl_closure or is_proto_closure or is_calamari_closure or is_electron_closure or is_elysian_closure ``` This is reality for scripters who want cross compatibilty in their scripts. Scripters shouldn't have to do such laborous work just to attain cross compatability. The UNC seeks to solve this problem using naming conventions everyone agrees upon and follows. One variant of a script should naturally work on all script executors which have their environment properly fitted to the UNC. ## How? The UNC provides standards for naming conventions as well as API functionality. The standard is written in markdown on this GitHub. Edits or additions are done through pull requests. Edits and additions are manually approved by the UNC council and discussed by everyone. ## Supporting UNC As a product owner, your support of UNC by following the API will result in a far smoother experience for scripters, as they are able to work on scripts that they can confidently say will work on **most** products. Once you have implemented UNC's API, you can display so by adding the badge to your website, thread or application. You can find the badge here: ~~https://scriptunc.org/badge~~ (This badge has since been removed from our website) This will notify people of your alliance in providing scripters with an easier method of engineering scripts that your consumers can enjoy. NOTICE: If you, as a product owner, do not have all of these functions but yet support the ones you do - you then support UNC! You are more than able to display the badge on your website. ## Checking your environment You can run the UNC environment checking script to see how well your executor environment supports the UNC standard. Find the script [here.](UNCCheckEnv.lua) The script determines what is missing, and writes the results to file under workspace. ## Contributing Go [here](CONTRIBUTING.md) for a guide on contributing. ================================================ FILE: TEMPLATE.md ================================================ ## FunctionName `⏰ Yields` `🌎 Global` `🪲 Inconsistent` `🔎 Needs Investigation` `📌 Custom Tag` ```lua function FunctionName(param: string): () ``` Describe the function in a neat and concise manner. May include multiple lines, paragraphs, or info cards. > ### 🔎 Notes, tips, info > Additional information or URLs. > ### ⚠️ Warnings, risks > Exercise caution. > ### ⛔ Danger! > Avoid making this mistake. > ### 🪲 Bugs, issues > Document known issues. ### Parameters * `param` - The parameter description. ### Aliases * `functionAlias` * `badAlias` - Optional justification. ### Example A description of the example that follows. ```lua print(FunctionName()) --> (void) ``` ================================================ FILE: UNCCheckEnv.lua ================================================ local passes, fails, undefined = 0, 0, 0 local running = 0 local function getGlobal(path) local value = getfenv(0) while value ~= nil and path ~= "" do local name, nextValue = string.match(path, "^([^.]+)%.?(.*)$") value = value[name] path = nextValue end return value end local function test(name, aliases, callback) running += 1 task.spawn(function() if not callback then print("⏺️ " .. name) elseif not getGlobal(name) then fails += 1 warn("⛔ " .. name) else local success, message = pcall(callback) if success then passes += 1 print("✅ " .. name .. (message and " • " .. message or "")) else fails += 1 warn("⛔ " .. name .. " failed: " .. message) end end local undefinedAliases = {} for _, alias in ipairs(aliases) do if getGlobal(alias) == nil then table.insert(undefinedAliases, alias) end end if #undefinedAliases > 0 then undefined += 1 warn("⚠️ " .. table.concat(undefinedAliases, ", ")) end running -= 1 end) end -- Header and summary print("\n") print("UNC Environment Check") print("✅ - Pass, ⛔ - Fail, ⏺️ - No test, ⚠️ - Missing aliases\n") task.defer(function() repeat task.wait() until running == 0 local rate = math.round(passes / (passes + fails) * 100) local outOf = passes .. " out of " .. (passes + fails) print("\n") print("UNC Summary") print("✅ Tested with a " .. rate .. "% success rate (" .. outOf .. ")") print("⛔ " .. fails .. " tests failed") print("⚠️ " .. undefined .. " globals are missing aliases") end) -- Cache test("cache.invalidate", {}, function() local container = Instance.new("Folder") local part = Instance.new("Part", container) cache.invalidate(container:FindFirstChild("Part")) assert(part ~= container:FindFirstChild("Part"), "Reference `part` could not be invalidated") end) test("cache.iscached", {}, function() local part = Instance.new("Part") assert(cache.iscached(part), "Part should be cached") cache.invalidate(part) assert(not cache.iscached(part), "Part should not be cached") end) test("cache.replace", {}, function() local part = Instance.new("Part") local fire = Instance.new("Fire") cache.replace(part, fire) assert(part ~= fire, "Part was not replaced with Fire") end) test("cloneref", {}, function() local part = Instance.new("Part") local clone = cloneref(part) assert(part ~= clone, "Clone should not be equal to original") clone.Name = "Test" assert(part.Name == "Test", "Clone should have updated the original") end) test("compareinstances", {}, function() local part = Instance.new("Part") local clone = cloneref(part) assert(part ~= clone, "Clone should not be equal to original") assert(compareinstances(part, clone), "Clone should be equal to original when using compareinstances()") end) -- Closures local function shallowEqual(t1, t2) if t1 == t2 then return true end local UNIQUE_TYPES = { ["function"] = true, ["table"] = true, ["userdata"] = true, ["thread"] = true, } for k, v in pairs(t1) do if UNIQUE_TYPES[type(v)] then if type(t2[k]) ~= type(v) then return false end elseif t2[k] ~= v then return false end end for k, v in pairs(t2) do if UNIQUE_TYPES[type(v)] then if type(t2[k]) ~= type(v) then return false end elseif t1[k] ~= v then return false end end return true end test("checkcaller", {}, function() assert(checkcaller(), "Main scope should return true") end) test("clonefunction", {}, function() local function test() return "success" end local copy = clonefunction(test) assert(test() == copy(), "The clone should return the same value as the original") assert(test ~= copy, "The clone should not be equal to the original") end) test("getcallingscript", {}) test("getscriptclosure", {"getscriptfunction"}, function() local module = game:GetService("CoreGui").RobloxGui.Modules.Common.Constants local constants = getrenv().require(module) local generated = getscriptclosure(module)() assert(constants ~= generated, "Generated module should not match the original") assert(shallowEqual(constants, generated), "Generated constant table should be shallow equal to the original") end) test("hookfunction", {"replaceclosure"}, function() local function test() return true end local ref = hookfunction(test, function() return false end) assert(test() == false, "Function should return false") assert(ref() == true, "Original function should return true") assert(test ~= ref, "Original function should not be same as the reference") end) test("iscclosure", {}, function() assert(iscclosure(print) == true, "Function 'print' should be a C closure") assert(iscclosure(function() end) == false, "Executor function should not be a C closure") end) test("islclosure", {}, function() assert(islclosure(print) == false, "Function 'print' should not be a Lua closure") assert(islclosure(function() end) == true, "Executor function should be a Lua closure") end) test("isexecutorclosure", {"checkclosure", "isourclosure"}, function() assert(isexecutorclosure(isexecutorclosure) == true, "Did not return true for an executor global") assert(isexecutorclosure(newcclosure(function() end)) == true, "Did not return true for an executor C closure") assert(isexecutorclosure(function() end) == true, "Did not return true for an executor Luau closure") assert(isexecutorclosure(print) == false, "Did not return false for a Roblox global") end) test("loadstring", {}, function() local animate = game:GetService("Players").LocalPlayer.Character.Animate local bytecode = getscriptbytecode(animate) local func = loadstring(bytecode) assert(type(func) ~= "function", "Luau bytecode should not be loadable!") assert(assert(loadstring("return ... + 1"))(1) == 2, "Failed to do simple math") assert(type(select(2, loadstring("f"))) == "string", "Loadstring did not return anything for a compiler error") end) test("newcclosure", {}, function() local function test() return true end local testC = newcclosure(test) assert(test() == testC(), "New C closure should return the same value as the original") assert(test ~= testC, "New C closure should not be same as the original") assert(iscclosure(testC), "New C closure should be a C closure") end) -- Console test("rconsoleclear", {"consoleclear"}) test("rconsolecreate", {"consolecreate"}) test("rconsoledestroy", {"consoledestroy"}) test("rconsoleinput", {"consoleinput"}) test("rconsoleprint", {"consoleprint"}) test("rconsolesettitle", {"rconsolename", "consolesettitle"}) -- Crypt test("crypt.base64encode", {"crypt.base64.encode", "crypt.base64_encode", "base64.encode", "base64_encode"}, function() assert(crypt.base64encode("test") == "dGVzdA==", "Base64 encoding failed") end) test("crypt.base64decode", {"crypt.base64.decode", "crypt.base64_decode", "base64.decode", "base64_decode"}, function() assert(crypt.base64decode("dGVzdA==") == "test", "Base64 decoding failed") end) test("crypt.encrypt", {}, function() local key = crypt.generatekey() local encrypted, iv = crypt.encrypt("test", key, nil, "CBC") assert(iv, "crypt.encrypt should return an IV") local decrypted = crypt.decrypt(encrypted, key, iv, "CBC") assert(decrypted == "test", "Failed to decrypt raw string from encrypted data") end) test("crypt.decrypt", {}, function() local key, iv = crypt.generatekey(), crypt.generatekey() local encrypted = crypt.encrypt("test", key, iv, "CBC") local decrypted = crypt.decrypt(encrypted, key, iv, "CBC") assert(decrypted == "test", "Failed to decrypt raw string from encrypted data") end) test("crypt.generatebytes", {}, function() local size = math.random(10, 100) local bytes = crypt.generatebytes(size) assert(#crypt.base64decode(bytes) == size, "The decoded result should be " .. size .. " bytes long (got " .. #crypt.base64decode(bytes) .. " decoded, " .. #bytes .. " raw)") end) test("crypt.generatekey", {}, function() local key = crypt.generatekey() assert(#crypt.base64decode(key) == 32, "Generated key should be 32 bytes long when decoded") end) test("crypt.hash", {}, function() local algorithms = {'sha1', 'sha384', 'sha512', 'md5', 'sha256', 'sha3-224', 'sha3-256', 'sha3-512'} for _, algorithm in ipairs(algorithms) do local hash = crypt.hash("test", algorithm) assert(hash, "crypt.hash on algorithm '" .. algorithm .. "' should return a hash") end end) --- Debug test("debug.getconstant", {}, function() local function test() print("Hello, world!") end assert(debug.getconstant(test, 1) == "print", "First constant must be print") assert(debug.getconstant(test, 2) == nil, "Second constant must be nil") assert(debug.getconstant(test, 3) == "Hello, world!", "Third constant must be 'Hello, world!'") end) test("debug.getconstants", {}, function() local function test() local num = 5000 .. 50000 print("Hello, world!", num, warn) end local constants = debug.getconstants(test) assert(constants[1] == 50000, "First constant must be 50000") assert(constants[2] == "print", "Second constant must be print") assert(constants[3] == nil, "Third constant must be nil") assert(constants[4] == "Hello, world!", "Fourth constant must be 'Hello, world!'") assert(constants[5] == "warn", "Fifth constant must be warn") end) test("debug.getinfo", {}, function() local types = { source = "string", short_src = "string", func = "function", what = "string", currentline = "number", name = "string", nups = "number", numparams = "number", is_vararg = "number", } local function test(...) print(...) end local info = debug.getinfo(test) for k, v in pairs(types) do assert(info[k] ~= nil, "Did not return a table with a '" .. k .. "' field") assert(type(info[k]) == v, "Did not return a table with " .. k .. " as a " .. v .. " (got " .. type(info[k]) .. ")") end end) test("debug.getproto", {}, function() local function test() local function proto() return true end end local proto = debug.getproto(test, 1, true)[1] local realproto = debug.getproto(test, 1) assert(proto, "Failed to get the inner function") assert(proto() == true, "The inner function did not return anything") if not realproto() then return "Proto return values are disabled on this executor" end end) test("debug.getprotos", {}, function() local function test() local function _1() return true end local function _2() return true end local function _3() return true end end for i in ipairs(debug.getprotos(test)) do local proto = debug.getproto(test, i, true)[1] local realproto = debug.getproto(test, i) assert(proto(), "Failed to get inner function " .. i) if not realproto() then return "Proto return values are disabled on this executor" end end end) test("debug.getstack", {}, function() local _ = "a" .. "b" assert(debug.getstack(1, 1) == "ab", "The first item in the stack should be 'ab'") assert(debug.getstack(1)[1] == "ab", "The first item in the stack table should be 'ab'") end) test("debug.getupvalue", {}, function() local upvalue = function() end local function test() print(upvalue) end assert(debug.getupvalue(test, 1) == upvalue, "Unexpected value returned from debug.getupvalue") end) test("debug.getupvalues", {}, function() local upvalue = function() end local function test() print(upvalue) end local upvalues = debug.getupvalues(test) assert(upvalues[1] == upvalue, "Unexpected value returned from debug.getupvalues") end) test("debug.setconstant", {}, function() local function test() return "fail" end debug.setconstant(test, 1, "success") assert(test() == "success", "debug.setconstant did not set the first constant") end) test("debug.setstack", {}, function() local function test() return "fail", debug.setstack(1, 1, "success") end assert(test() == "success", "debug.setstack did not set the first stack item") end) test("debug.setupvalue", {}, function() local function upvalue() return "fail" end local function test() return upvalue() end debug.setupvalue(test, 1, function() return "success" end) assert(test() == "success", "debug.setupvalue did not set the first upvalue") end) -- Filesystem if isfolder and makefolder and delfolder then if isfolder(".tests") then delfolder(".tests") end makefolder(".tests") end test("readfile", {}, function() writefile(".tests/readfile.txt", "success") assert(readfile(".tests/readfile.txt") == "success", "Did not return the contents of the file") end) test("listfiles", {}, function() makefolder(".tests/listfiles") writefile(".tests/listfiles/test_1.txt", "success") writefile(".tests/listfiles/test_2.txt", "success") local files = listfiles(".tests/listfiles") assert(#files == 2, "Did not return the correct number of files") assert(isfile(files[1]), "Did not return a file path") assert(readfile(files[1]) == "success", "Did not return the correct files") makefolder(".tests/listfiles_2") makefolder(".tests/listfiles_2/test_1") makefolder(".tests/listfiles_2/test_2") local folders = listfiles(".tests/listfiles_2") assert(#folders == 2, "Did not return the correct number of folders") assert(isfolder(folders[1]), "Did not return a folder path") end) test("writefile", {}, function() writefile(".tests/writefile.txt", "success") assert(readfile(".tests/writefile.txt") == "success", "Did not write the file") local requiresFileExt = pcall(function() writefile(".tests/writefile", "success") assert(isfile(".tests/writefile.txt")) end) if not requiresFileExt then return "This executor requires a file extension in writefile" end end) test("makefolder", {}, function() makefolder(".tests/makefolder") assert(isfolder(".tests/makefolder"), "Did not create the folder") end) test("appendfile", {}, function() writefile(".tests/appendfile.txt", "su") appendfile(".tests/appendfile.txt", "cce") appendfile(".tests/appendfile.txt", "ss") assert(readfile(".tests/appendfile.txt") == "success", "Did not append the file") end) test("isfile", {}, function() writefile(".tests/isfile.txt", "success") assert(isfile(".tests/isfile.txt") == true, "Did not return true for a file") assert(isfile(".tests") == false, "Did not return false for a folder") assert(isfile(".tests/doesnotexist.exe") == false, "Did not return false for a nonexistent path (got " .. tostring(isfile(".tests/doesnotexist.exe")) .. ")") end) test("isfolder", {}, function() assert(isfolder(".tests") == true, "Did not return false for a folder") assert(isfolder(".tests/doesnotexist.exe") == false, "Did not return false for a nonexistent path (got " .. tostring(isfolder(".tests/doesnotexist.exe")) .. ")") end) test("delfolder", {}, function() makefolder(".tests/delfolder") delfolder(".tests/delfolder") assert(isfolder(".tests/delfolder") == false, "Failed to delete folder (isfolder = " .. tostring(isfolder(".tests/delfolder")) .. ")") end) test("delfile", {}, function() writefile(".tests/delfile.txt", "Hello, world!") delfile(".tests/delfile.txt") assert(isfile(".tests/delfile.txt") == false, "Failed to delete file (isfile = " .. tostring(isfile(".tests/delfile.txt")) .. ")") end) test("loadfile", {}, function() writefile(".tests/loadfile.txt", "return ... + 1") assert(assert(loadfile(".tests/loadfile.txt"))(1) == 2, "Failed to load a file with arguments") writefile(".tests/loadfile.txt", "f") local callback, err = loadfile(".tests/loadfile.txt") assert(err and not callback, "Did not return an error message for a compiler error") end) test("dofile", {}) -- Input test("isrbxactive", {"isgameactive"}, function() assert(type(isrbxactive()) == "boolean", "Did not return a boolean value") end) test("mouse1click", {}) test("mouse1press", {}) test("mouse1release", {}) test("mouse2click", {}) test("mouse2press", {}) test("mouse2release", {}) test("mousemoveabs", {}) test("mousemoverel", {}) test("mousescroll", {}) -- Instances test("fireclickdetector", {}, function() local detector = Instance.new("ClickDetector") fireclickdetector(detector, 50, "MouseHoverEnter") end) test("getcallbackvalue", {}, function() local bindable = Instance.new("BindableFunction") local function test() end bindable.OnInvoke = test assert(getcallbackvalue(bindable, "OnInvoke") == test, "Did not return the correct value") end) test("getconnections", {}, function() local types = { Enabled = "boolean", ForeignState = "boolean", LuaConnection = "boolean", Function = "function", Thread = "thread", Fire = "function", Defer = "function", Disconnect = "function", Disable = "function", Enable = "function", } local bindable = Instance.new("BindableEvent") bindable.Event:Connect(function() end) local connection = getconnections(bindable.Event)[1] for k, v in pairs(types) do assert(connection[k] ~= nil, "Did not return a table with a '" .. k .. "' field") assert(type(connection[k]) == v, "Did not return a table with " .. k .. " as a " .. v .. " (got " .. type(connection[k]) .. ")") end end) test("getcustomasset", {}, function() writefile(".tests/getcustomasset.txt", "success") local contentId = getcustomasset(".tests/getcustomasset.txt") assert(type(contentId) == "string", "Did not return a string") assert(#contentId > 0, "Returned an empty string") assert(string.match(contentId, "rbxasset://") == "rbxasset://", "Did not return an rbxasset url") end) test("gethiddenproperty", {}, function() local fire = Instance.new("Fire") local property, isHidden = gethiddenproperty(fire, "size_xml") assert(property == 5, "Did not return the correct value") assert(isHidden == true, "Did not return whether the property was hidden") end) test("sethiddenproperty", {}, function() local fire = Instance.new("Fire") local hidden = sethiddenproperty(fire, "size_xml", 10) assert(hidden, "Did not return true for the hidden property") assert(gethiddenproperty(fire, "size_xml") == 10, "Did not set the hidden property") end) test("gethui", {}, function() assert(typeof(gethui()) == "Instance", "Did not return an Instance") end) test("getinstances", {}, function() assert(getinstances()[1]:IsA("Instance"), "The first value is not an Instance") end) test("getnilinstances", {}, function() assert(getnilinstances()[1]:IsA("Instance"), "The first value is not an Instance") assert(getnilinstances()[1].Parent == nil, "The first value is not parented to nil") end) test("isscriptable", {}, function() local fire = Instance.new("Fire") assert(isscriptable(fire, "size_xml") == false, "Did not return false for a non-scriptable property (size_xml)") assert(isscriptable(fire, "Size") == true, "Did not return true for a scriptable property (Size)") end) test("setscriptable", {}, function() local fire = Instance.new("Fire") local wasScriptable = setscriptable(fire, "size_xml", true) assert(wasScriptable == false, "Did not return false for a non-scriptable property (size_xml)") assert(isscriptable(fire, "size_xml") == true, "Did not set the scriptable property") fire = Instance.new("Fire") assert(isscriptable(fire, "size_xml") == false, "⚠️⚠️ setscriptable persists between unique instances ⚠️⚠️") end) test("setrbxclipboard", {}) -- Metatable test("getrawmetatable", {}, function() local metatable = { __metatable = "Locked!" } local object = setmetatable({}, metatable) assert(getrawmetatable(object) == metatable, "Did not return the metatable") end) test("hookmetamethod", {}, function() local object = setmetatable({}, { __index = newcclosure(function() return false end), __metatable = "Locked!" }) local ref = hookmetamethod(object, "__index", function() return true end) assert(object.test == true, "Failed to hook a metamethod and change the return value") assert(ref() == false, "Did not return the original function") end) test("getnamecallmethod", {}, function() local method local ref ref = hookmetamethod(game, "__namecall", function(...) if not method then method = getnamecallmethod() end return ref(...) end) game:GetService("Lighting") assert(method == "GetService", "Did not get the correct method (GetService)") end) test("isreadonly", {}, function() local object = {} table.freeze(object) assert(isreadonly(object), "Did not return true for a read-only table") end) test("setrawmetatable", {}, function() local object = setmetatable({}, { __index = function() return false end, __metatable = "Locked!" }) local objectReturned = setrawmetatable(object, { __index = function() return true end }) assert(object, "Did not return the original object") assert(object.test == true, "Failed to change the metatable") if objectReturned then return objectReturned == object and "Returned the original object" or "Did not return the original object" end end) test("setreadonly", {}, function() local object = { success = false } table.freeze(object) setreadonly(object, false) object.success = true assert(object.success, "Did not allow the table to be modified") end) -- Miscellaneous test("identifyexecutor", {"getexecutorname"}, function() local name, version = identifyexecutor() assert(type(name) == "string", "Did not return a string for the name") return type(version) == "string" and "Returns version as a string" or "Does not return version" end) test("lz4compress", {}, function() local raw = "Hello, world!" local compressed = lz4compress(raw) assert(type(compressed) == "string", "Compression did not return a string") assert(lz4decompress(compressed, #raw) == raw, "Decompression did not return the original string") end) test("lz4decompress", {}, function() local raw = "Hello, world!" local compressed = lz4compress(raw) assert(type(compressed) == "string", "Compression did not return a string") assert(lz4decompress(compressed, #raw) == raw, "Decompression did not return the original string") end) test("messagebox", {}) test("queue_on_teleport", {"queueonteleport"}) test("request", {"http.request", "http_request"}, function() local response = request({ Url = "https://httpbin.org/user-agent", Method = "GET", }) assert(type(response) == "table", "Response must be a table") assert(response.StatusCode == 200, "Did not return a 200 status code") local data = game:GetService("HttpService"):JSONDecode(response.Body) assert(type(data) == "table" and type(data["user-agent"]) == "string", "Did not return a table with a user-agent key") return "User-Agent: " .. data["user-agent"] end) test("setclipboard", {"toclipboard"}) test("setfpscap", {}, function() local renderStepped = game:GetService("RunService").RenderStepped local function step() renderStepped:Wait() local sum = 0 for _ = 1, 5 do sum += 1 / renderStepped:Wait() end return math.round(sum / 5) end setfpscap(60) local step60 = step() setfpscap(0) local step0 = step() return step60 .. "fps @60 • " .. step0 .. "fps @0" end) -- Scripts test("getgc", {}, function() local gc = getgc() assert(type(gc) == "table", "Did not return a table") assert(#gc > 0, "Did not return a table with any values") end) test("getgenv", {}, function() getgenv().__TEST_GLOBAL = true assert(__TEST_GLOBAL, "Failed to set a global variable") getgenv().__TEST_GLOBAL = nil end) test("getloadedmodules", {}, function() local modules = getloadedmodules() assert(type(modules) == "table", "Did not return a table") assert(#modules > 0, "Did not return a table with any values") assert(typeof(modules[1]) == "Instance", "First value is not an Instance") assert(modules[1]:IsA("ModuleScript"), "First value is not a ModuleScript") end) test("getrenv", {}, function() assert(_G ~= getrenv()._G, "The variable _G in the executor is identical to _G in the game") end) test("getrunningscripts", {}, function() local scripts = getrunningscripts() assert(type(scripts) == "table", "Did not return a table") assert(#scripts > 0, "Did not return a table with any values") assert(typeof(scripts[1]) == "Instance", "First value is not an Instance") assert(scripts[1]:IsA("ModuleScript") or scripts[1]:IsA("LocalScript"), "First value is not a ModuleScript or LocalScript") end) test("getscriptbytecode", {"dumpstring"}, function() local animate = game:GetService("Players").LocalPlayer.Character.Animate local bytecode = getscriptbytecode(animate) assert(type(bytecode) == "string", "Did not return a string for Character.Animate (a " .. animate.ClassName .. ")") end) test("getscripthash", {}, function() local animate = game:GetService("Players").LocalPlayer.Character.Animate:Clone() local hash = getscripthash(animate) local source = animate.Source animate.Source = "print('Hello, world!')" task.defer(function() animate.Source = source end) local newHash = getscripthash(animate) assert(hash ~= newHash, "Did not return a different hash for a modified script") assert(newHash == getscripthash(animate), "Did not return the same hash for a script with the same source") end) test("getscripts", {}, function() local scripts = getscripts() assert(type(scripts) == "table", "Did not return a table") assert(#scripts > 0, "Did not return a table with any values") assert(typeof(scripts[1]) == "Instance", "First value is not an Instance") assert(scripts[1]:IsA("ModuleScript") or scripts[1]:IsA("LocalScript"), "First value is not a ModuleScript or LocalScript") end) test("getsenv", {}, function() local animate = game:GetService("Players").LocalPlayer.Character.Animate local env = getsenv(animate) assert(type(env) == "table", "Did not return a table for Character.Animate (a " .. animate.ClassName .. ")") assert(env.script == animate, "The script global is not identical to Character.Animate") end) test("getthreadidentity", {"getidentity", "getthreadcontext"}, function() assert(type(getthreadidentity()) == "number", "Did not return a number") end) test("setthreadidentity", {"setidentity", "setthreadcontext"}, function() setthreadidentity(3) assert(getthreadidentity() == 3, "Did not set the thread identity") end) -- Drawing test("Drawing", {}) test("Drawing.new", {}, function() local drawing = Drawing.new("Square") drawing.Visible = false local canDestroy = pcall(function() drawing:Destroy() end) assert(canDestroy, "Drawing:Destroy() should not throw an error") end) test("Drawing.Fonts", {}, function() assert(Drawing.Fonts.UI == 0, "Did not return the correct id for UI") assert(Drawing.Fonts.System == 1, "Did not return the correct id for System") assert(Drawing.Fonts.Plex == 2, "Did not return the correct id for Plex") assert(Drawing.Fonts.Monospace == 3, "Did not return the correct id for Monospace") end) test("isrenderobj", {}, function() local drawing = Drawing.new("Image") drawing.Visible = true assert(isrenderobj(drawing) == true, "Did not return true for an Image") assert(isrenderobj(newproxy()) == false, "Did not return false for a blank table") end) test("getrenderproperty", {}, function() local drawing = Drawing.new("Image") drawing.Visible = true assert(type(getrenderproperty(drawing, "Visible")) == "boolean", "Did not return a boolean value for Image.Visible") local success, result = pcall(function() return getrenderproperty(drawing, "Color") end) if not success or not result then return "Image.Color is not supported" end end) test("setrenderproperty", {}, function() local drawing = Drawing.new("Square") drawing.Visible = true setrenderproperty(drawing, "Visible", false) assert(drawing.Visible == false, "Did not set the value for Square.Visible") end) test("cleardrawcache", {}, function() cleardrawcache() end) -- WebSocket test("WebSocket", {}) test("WebSocket.connect", {}, function() local types = { Send = "function", Close = "function", OnMessage = {"table", "userdata"}, OnClose = {"table", "userdata"}, } local ws = WebSocket.connect("ws://echo.websocket.events") assert(type(ws) == "table" or type(ws) == "userdata", "Did not return a table or userdata") for k, v in pairs(types) do if type(v) == "table" then assert(table.find(v, type(ws[k])), "Did not return a " .. table.concat(v, ", ") .. " for " .. k .. " (a " .. type(ws[k]) .. ")") else assert(type(ws[k]) == v, "Did not return a " .. v .. " for " .. k .. " (a " .. type(ws[k]) .. ")") end end ws:Close() end) ================================================ FILE: api/Drawing.md ================================================ # Drawing The **Drawing** class provides an interface for drawing shapes and text above the game window. --- ## Drawing.new `🏛️ Constructor` ```lua function Drawing.new(type: string): Drawing ``` Create a new drawing object of the specified type. The possible types are 'Line', 'Text', 'Image', 'Circle', 'Square', 'Quad', and 'Triangle'. ### Parameters * `type` - The type of drawing object to create. ### Example ```lua local circle = Drawing.new("Circle") circle.Radius = 50 circle.Color = Color3.fromRGB(255, 0, 0) circle.Filled = true circle.NumSides = 32 circle.Position = Vector2.new(300, 300) circle.Transparency = 0.7 circle.Visible = true task.wait(1) circle:Destroy() ``` --- ## Drawing.Fonts `⭕ Static` `🔒 Read-only` ```lua Drawing.Fonts: { UI: 0, System: 1, Plex: 2, Monospace: 3, } ``` A table containing the available font names. The style of each font varies depending on the executor. ### Fonts
Show font table > | Executor | Fonts | > | --------- | ----- | > | Script-Ware | ![Script-Ware Fonts](../images/fonts-sw.png) | > | Krnl | ![Krnl Fonts](../images/fonts-krnl.png) |
### Example ```lua for name, font in pairs(Drawing.Fonts) do local text = Drawing.new("Text") text.Text = "The quick brown fox (" .. name .. ")" text.Font = font text.Size = 48 text.Position = Vector2.new(150, 100 + font * 50) text.Visible = true task.delay(2, function () text:Destroy() end) end ``` --- ## Drawing `🖥️ Class` ```lua drawing = Drawing.new(type) ``` ### BaseDrawing The base class of which all drawing objects inherit. Cannot be instantiated. | Property | Type | Description | | -------- | ---- | ----------- | | `Visible` | boolean | Whether the drawing is visible. Defaults to `false` on some executors. | | `ZIndex` | number | Determines the order in which a Drawing renders relative to other drawings. | | `Transparency` | number | The opacity of the drawing (1 is opaque, 0 is transparent). | | `Color` | Color3 | The color of the drawing. | | `Destroy(): ()` | function | Destroys the drawing. | ### Line Renders a line starting at `From` and ending at `To`. | Property | Type | Description | | -------- | ---- | ----------- | | `From` | Vector2 | The starting point of the line. | | `To` | Vector2 | The ending point of the line. | | `Thickness` | number | The thickness of the line. | ### Text Renders text at `Position`. | Property | Type | Description | | -------- | ---- | ----------- | | `Text` | string | The text to render. | | `TextBounds` | 🔒 Vector2 | The size of the text. Cannot be set. | | `Font` | Drawing.Font | The font to use. | | `Size` | number | The size of the text. | | `Position` | Vector2 | The position of the text. | | `Center` | boolean | Whether the text should be centered horizontally. | | `Outline` | boolean | Whether the text should be outlined. | | `OutlineColor` | Color3 | The color of the outline. | ### Image Draws the image data to the screen. `Data` *must* be the raw image data. | Property | Type | Description | | -------- | ---- | ----------- | | `Data` | string | The raw image data. | | `Size` | Vector2 | The size of the image. | | `Position` | Vector2 | The position of the image. | | `Rounding` | number | The rounding of the image. | ### Circle Draws a circle that is centered at `Position`. This is not a perfect circle! The greater the value for `NumSides`, the more accurate the circle will be. | Property | Type | Description | | -------- | ---- | ----------- | | `NumSides` | number | The number of sides of the circle. | | `Radius` | number | The radius of the circle. | | `Position` | Vector2 | The position of the center of the circle. | | `Thickness` | number | If `Filled` is false, specifies the thickness of the outline. | | `Filled` | boolean | Whether the circle should be filled. | ### Square Draws a rectangle starting at `Position` and ending at `Position` + `Size`. | Property | Type | Description | | -------- | ---- | ----------- | | `Size` | Vector2 | The size of the square. | | `Position` | Vector2 | The position of the top-left corner of the square. | | `Thickness` | number | If `Filled` is false, specifies the thickness of the outline. | | `Filled` | boolean | Whether the square should be filled. | ### Quad Draws a four-sided figure connecting to each of the four points. | Property | Type | Description | | -------- | ---- | ----------- | | `PointA` | Vector2 | The first point. | | `PointB` | Vector2 | The second point. | | `PointC` | Vector2 | The third point. | | `PointD` | Vector2 | The fourth point. | | `Thickness` | number | If `Filled` is false, specifies the thickness of the outline. | | `Filled` | boolean | Whether the quad should be filled. | ### Triangle Draws a triangle connecting to each of the three points. | Property | Type | Description | | -------- | ---- | ----------- | | `PointA` | Vector2 | The first point. | | `PointB` | Vector2 | The second point. | | `PointC` | Vector2 | The third point. | | `Thickness` | number | If `Filled` is false, specifies the thickness of the outline. | | `Filled` | boolean | Whether the triangle should be filled. | --- ## cleardrawcache `🌎 Global` ```lua function cleardrawcache(): () ``` Destroys every drawing object in the cache. Invalidates references to the drawing objects. ### Example ```lua for i = 1, 10 do local circle = Drawing.new("Circle") circle.Radius = 50 circle.Color = Color3.fromRGB(255, 0, 0) circle.Filled = true circle.NumSides = 32 circle.Position = Vector2.new(math.random(300, 1200), math.random(300, 1200)) circle.Transparency = 0.7 circle.Visible = true end task.wait(1) cleardrawcache() ``` --- ## getrenderproperty `🌎 Global` ```lua function getrenderproperty(drawing: Drawing, property: string): any ``` Gets the value of a property of a drawing. Functionally identical to `drawing[property]`. ### Parameters * `drawing` - The drawing to get the property of. * `property` - The property to get. ### Example ```lua local circle = Drawing.new("Circle") getrenderproperty(circle, "Color") ``` --- ## isrenderobj `🌎 Global` ```lua function isrenderobj(object: any): boolean ``` Returns whether the given object is a valid Drawing. ### Parameters * `object` - Any object. ### Example ```lua print(isrenderobj(Drawing.new("Circle"))) --> true print(isrenderobj({})) --> false ``` --- ## setrenderproperty `🌎 Global` ```lua function setrenderproperty(drawing: Drawing, property: string, value: any): () ``` Sets the value of a property of a drawing. Functionally identical to `drawing[property] = value`. ### Parameters * `drawing` - The drawing to set the property of. * `property` - The property to set. * `value` - The value to set the property to. ### Example ```lua local circle = Drawing.new("Circle") setrenderproperty(circle, "Color", Color3.fromRGB(255, 0, 0)) ``` ================================================ FILE: api/WebSocket.md ================================================ # WebSocket The **WebSocket** class provides a simple interface for sending and receiving data over a WebSocket connection. --- ## WebSocket.connect `🏛️ Constructor` ```lua function WebSocket.connect(url: string): WebSocket ``` Establishes a WebSocket connection to the specified URL. ### Parameters * `url` - The URL to connect to. ### Example ```lua local ws = WebSocket.connect("ws://localhost:8080") ws.OnMessage:Connect(function(message) print(message) end) ws.OnClose:Connect(function() print("Closed") end) ws:Send("Hello, World!") ``` --- ## WebSocket `🖥️ Class` ```lua ws = WebSocket.connect(url) ``` ### Methods | Method | Description | | ------ | ----------- | | `Send(message: string): ()` | Sends a message over the WebSocket connection. | | `Close(): ()` | Closes the WebSocket connection. | ### Events | Event | Description | | ----- | ----------- | | `OnMessage(message: string): ()` | Fired when a message is received over the WebSocket connection. | | `OnClose(): ()` | Fired when the WebSocket connection is closed. | ================================================ FILE: api/cache.md ================================================ # Cache The **cache** library provides methods for modifying the internal Instance cache. Note that some of the methods are only available as global functions. They will be tagged with `🌎 Global`. --- ## cache.invalidate ```lua function invalidate(object: Instance): () ``` Deletes `object` from the Instance cache. Effectively invalidates `object` as a reference to the underlying Instance. ### Parameters * `object` - The object to invalidate. ### Example ```lua local Lighting = game:GetService("Lighting") cache.invalidate(game:GetService("Lighting")) print(Lighting, Lighting == game:GetService("Lighting")) --> Lighting, false ``` --- ## cache.iscached ```lua function iscached(object: Instance): boolean ``` Checks whether `object` exists in the Instance cache. ### Parameters * `object` - The object to find. ### Example ```lua local Lighting = game:GetService("Lighting") cache.invalidate(Lighting) print(cache.iscached(Lighting)) --> false ``` --- ## cache.replace ```lua function replace(object: Instance, newObject: Instance): () ``` Replaces `object` in the Instance cache with `newObject`. ### Parameters * `object` - The object to replace. * `newObject` - The new object to replace `object` with. ### Example ```lua local Lighting = game:GetService("Lighting") local Players = game:GetService("Players") cache.replace(Lighting, Players) print(Lighting) --> Players ``` --- ## cloneref `🌎 Global` ```lua function cloneref(object: Instance): Instance ``` Returns a copy of the Instance reference to `object`. This is useful for managing an Instance without directly referencing it. ### Parameters * `object` - The Instance to clone. ### Example ```lua local Lighting = game:GetService("Lighting") local LightingClone = cloneref(Lighting) print(Lighting == LightingClone) --> false ``` --- ## compareinstances `🌎 Global` ```lua function compareinstances(a: Instance, b: Instance): boolean ``` Returns whether objects `a` and `b` both reference the same Instance. ### Parameters * `a` - The first Instance to compare. * `b` - The second Instance to compare. ### Example ```lua local Lighting = game:GetService("Lighting") local LightingClone = cloneref(Lighting) print(Lighting == LightingClone) --> false print(compareinstances(Lighting, LightingClone)) --> true ``` ================================================ FILE: api/closures.md ================================================ # Closures The **closure** functions are used to create, identify, and interact with Luau closures. --- ## checkcaller ```lua function checkcaller(): boolean ``` Returns whether the function currently running was called by the executor. This is useful for metamethod hooks that behave differently when called by the game. ### Example Prevent the executor from invoking `__namecall` with the global `game` object: ```lua local refs = {} refs.__namecall = hookmetamethod(game, "__namecall", function(...) local self = ... local isRunningOnExecutor = checkcaller() if isRunningOnExecutor then -- The executor invoked the __namecall method, so this will not affect the -- scripts in the game. if self == game then error("No __namecall on game allowed") end end return refs.__namecall(...) end) game:Destroy() --> Error "No __namecall on game allowed" ``` --- ## clonefunction ```lua clonefunction(func: T): T ``` Generates a new closure based on the bytecode of function `func`. ### Parameters * `func` - The function to recreate. ### Example ```lua local function foo() print("Hello, world!") end local bar = clonefunction(foo) foo() --> Hello, world! bar() --> Hello, world! print(foo == bar) --> false ``` --- ## getcallingscript ```lua function getcallingscript(): BaseScript ``` Returns the script responsible for the currently running function. ### Example Prevent scripts in PlayerGui from invoking the `__namecall` hook: ```lua local refs = {} local bannedScripts = game:GetService("Players").LocalPlayer.PlayerGui refs.__namecall = hookmetamethod(game, "__namecall", function(...) local caller = getcallingscript() -- Use '.' notation to call the IsDescendantOf method without invoking -- __namecall and causing a recursive loop. local isBanned = caller.IsDescendantOf(caller, bannedScripts) if isBanned then error("Not allowed to invoke __namecall") end return refs.__namecall(...) end) ``` --- ## hookfunction ```lua function hookfunction(func: T, hook: function): T ``` Replaces `func` with `hook` internally, where `hook` will be invoked in place of `func` when called. Returns a new function that can be used to access the original definition of `func`. > ### ⚠️ Warning > If `func` is a Luau function (`islclosure(func) --> true`), the upvalue count of `hook` must be less than or equal to that of `func`.\ > Read more about upvalues on [Lua visibility rules](http://www.lua.org/manual/5.1/manual.html#2.6). ### Parameters * `func` - The function to hook. * `hook` - The function to redirect calls to. ### Aliases * `replaceclosure` ### Example ```lua local function foo() print("Hello, world!") end local fooRef = hookfunction(foo, function(...) print("Hooked!") end) foo() --> Hooked! fooRef() --> Hello, world! ``` --- ## iscclosure ```lua function iscclosure(func: function): boolean ``` Returns whether or not `func` is a closure whose source is written in C. ### Parameters * `func` - The function to check. ### Example ```lua print(iscclosure(print)) --> true print(iscclosure(function() end)) --> false ``` --- ## islclosure ```lua function islclosure(func: function): boolean ``` Returns whether or not `func` is a closure whose source is written in Luau. ### Parameters * `func` - The function to check. ### Example ```lua print(islclosure(print)) --> false print(islclosure(function() end)) --> true ``` --- ## isexecutorclosure ```lua function isexecutorclosure(func: function): boolean ``` Returns whether or not `func` was created by the executor. ### Parameters * `func` - The function to check. ### Aliases * `checkclosure` * `isourclosure` ### Example ```lua print(isexecutorclosure(isexecutorclosure)) --> true print(isexecutorclosure(function() end)) --> true print(isexecutorclosure(print)) --> false ``` --- ## loadstring ```lua function loadstring(source: string, chunkname: string?): (function?, string?) ``` Generates a chunk from the given source code. The environment of the returned function is the global environment. If there are no compilation errors, the chunk is returned by itself; otherwise, it returns `nil` plus the error message. `chunkname` is used as the chunk name for error messages and debug information. When absent, it defaults to a **random string**. > ### ⛔ Danger > Vanilla Lua allows `source` to contain Lua bytecode, but it is a security vulnerability.\ > This is a feature that should not be implemented. ### Parameters * `source` - The source code to compile. * `chunkname` - Optional name of the chunk. ### Example ```lua local func, err = loadstring("print('Hello, world!')") assert(func, err)() --> Hello, world! local func, err = loadstring("print('Hello") assert(func, err)() --> Errors "Malformed string" ``` --- ## newcclosure ```lua function newcclosure(func: T): T ``` Returns a C closure that wraps `func`. The result is functionally identical to `func`, but identifies as a C closure, and may have different metadata. > ### ⚠️ Warning > Attempting to yield inside a C closure will throw an error.\ > Instead, use the task library to defer actions to different threads. ### Parameters * `func` - The function to wrap. ### Example ```lua local foo = function() end local bar = newcclosure(foo) print(iscclosure(foo)) --> false print(iscclosure(bar)) --> true ``` ================================================ FILE: api/console.md ================================================ # Console The **console** functions are used to interact with one console window. Behavior and examples documented on this page are based on Script-Ware. --- ## rconsoleclear ```lua function rconsoleclear(): () ``` Clears the output of the console window. ### Aliases * `consoleclear` ### Example ```lua -- Create the console window rconsolesettitle("New console") rconsoleprint("Hello, world!") rconsolecreate() -- Clears the output "Hello, world!" rconsoleclear() ``` --- ## rconsolecreate ```lua function rconsolecreate(): () ``` Opens the console window. Text previously output to the console will not be cleared. > ### 🔎 Note > Some executors also allow functions like `rconsoleprint` to open the console.\ > This is confusing behavior that should not be relied on. ### Aliases * `consolecreate` ### Example Create a program that generates a mountainous landscape: ```lua -- Create the console window rconsolesettitle("Beautiful Mountains") rconsolecreate() local function generate() -- Generate a random decimal number for noise local seed = math.random(100, 999) + math.random() -- Prints 25 lines of text for i = 1, 25 do local noise = math.noise(i / 8, seed) + 0.5 local height = math.floor(noise * 50) local line = string.rep("*", height) rconsoleprint(line .. "\n") end -- Prompts the user to generate a new set of mountains -- or exit the console window rconsoleprint("\nEnter 'Y' to generate a new landscape, or nothing to exit\n") local input = rconsoleinput() if string.lower(input) == "y" then rconsoleclear() generate() else rconsoledestroy() end end generate() ``` --- ## rconsoledestroy ```lua function rconsoledestroy(): () ``` Closes the console window and clears its output. The title will not be changed. ### Aliases * `consoledestroy` ### Example ```lua -- Create a console window titled "New console" and with the output "Hello, world!" rconsolesettitle("New console") rconsoleprint("Hello, world!") rconsolecreate() -- Close the console window, clearing its output rconsoledestroy() -- Reopen the console window titled "New console" with no output rconsolecreate() ``` --- ## rconsoleinput `⏰ Yields` ```lua function rconsoleinput(): string ``` Waits for the user to input text into the console window. Returns the result. ### Aliases * `consoleinput` ### Example ```lua -- Create the console window rconsolesettitle("Your Info") rconsoleprint("What is your name?\nMy name is: ") rconsolecreate() -- Retrieve the user's input local name = rconsoleinput() rconsoleprint("Hello, " .. name .. "!") -- Cleanup task.wait(1) rconsoledestroy() ``` --- ## rconsoleprint ```lua function rconsoleprint(text: string): () ``` Prints `text` to the console window. Does not clear existing text or create a new line. ### Parameters * `text` - The text to append to the output. ### Aliases * `consoleprint` ### Example ```lua -- Create a console window titled "New console" with the -- output "Hello, world!! How are you today?" rconsolesettitle("New console") rconsoleprint("Hello, world!") rconsoleprint("! How are you today?") rconsolecreate() ``` --- ## rconsolesettitle ```lua function rconsolesettitle(title: string): () ``` Sets the title of the console window to `title`. ### Parameters * `title` - The new title. ### Aliases * `rconsolename` * `consolesettitle` ### Example ```lua -- Create a console window titled "My console" rconsolesettitle("My console") rconsolecreate() ``` ================================================ FILE: api/crypt.md ================================================ # Crypt The **crypt** library provides methods for the encryption and decryption of string data. Behavior and examples documented on this page are based on Script-Ware. --- ## crypt.base64encode ```lua function crypt.base64encode(data: string): string ``` Encodes a string of bytes into Base64. ### Parameters * `data` - The data to encode. ### Aliases * `crypt.base64.encode` * `crypt.base64_encode` * `base64.encode` * `base64_encode` ### Example ```lua local base64 = crypt.base64encode("Hello, World!") local raw = crypt.base64decode(base64) print(base64) --> SGVsbG8sIFdvcmxkIQ== print(raw) --> Hello, World! ``` --- ## crypt.base64decode ```lua function crypt.base64decode(data: string): string ``` Decodes a Base64 string to a string of bytes. ### Parameters * `data` - The data to decode. ### Aliases * `crypt.base64.decode` * `crypt.base64_decode` * `base64.decode` * `base64_decode` ### Example ```lua local base64 = crypt.base64encode("Hello, World!") local raw = crypt.base64decode(base64) print(base64) --> SGVsbG8sIFdvcmxkIQ== print(raw) --> Hello, World! ``` --- ## crypt.encrypt `🪲 Compatibility` `🔎 RFC` ```lua function crypt.encrypt(data: string, key: string, iv: string?, mode: string?): (string, string) ``` Encrypts an unencoded string using AES encryption. Returns the base64 encoded and encrypted string, and the IV. If an AES IV is not provided, a random one will be generated for you, and returned as a 2nd base64 encoded string. The cipher modes are 'CBC', 'ECB', 'CTR', 'CFB', 'OFB', and 'GCM'. The default is 'CBC'. > ### 🪲 Compatibility issues > Too few executors support this function and a reliable example cannot be made. ### Parameters * `data` - The unencoded content. * `key` - A base64 256-bit key. * `iv` - Optional base64 AES initialization vector. * `mode` - The AES cipher mode. --- ## crypt.decrypt `🪲 Compatibility` `🔎 RFC` ```lua function crypt.decrypt(data: string, key: string, iv: string, mode: string): string ``` Decrypts the base64 encoded and encrypted content. Returns the raw string. The cipher modes are 'CBC', 'ECB', 'CTR', 'CFB', 'OFB', and 'GCM'. > ### 🪲 Compatibility issues > Too few executors support this function and a reliable example cannot be made. ### Parameters * `data` - The base64 encoded and encrypted content. * `key` - A base64 256-bit key. * `iv` - The base64 AES initialization vector. * `mode` - The AES cipher mode. --- ## crypt.generatebytes ```lua function crypt.generatebytes(size: number): string ``` Generates a random sequence of bytes of the given size. Returns the sequence as a base64 encoded string. ### Parameters * `size` - The number of bytes to generate. ### Example ```lua local bytes = crypt.generatebytes(16) print(bytes) --> bXlzcWwgYm9vbGVhbnM= print(#crypt.base64decode(bytes)) --> 16 ``` --- ## crypt.generatekey ```lua function crypt.generatekey(): string ``` Generates a base64 encoded 256-bit key. The result can be used as the second parameter for the `crypt.encrypt` and `crypt.decrypt` functions. ### Example ```lua local bytes = crypt.generatekey() print(#crypt.base64decode(bytes)) --> 32 (256 bits) ``` --- ## crypt.hash ```lua function crypt.hash(data: string, algorithm: string): string ``` Returns the result of hashing the data using the given algorithm. Some algorithms include 'sha1', 'sha384', 'sha512', 'md5', 'sha256', 'sha3-224', 'sha3-256', and 'sha3-512'. ### Parameters * `data` - The unencoded content. * `algorithm` - A hash algorithm. ### Example ```lua local hash = crypt.hash("Hello, World!", "md5") print(hash) --> 65A8E27D8879283831B664BD8B7F0AD4 ``` ================================================ FILE: api/debug.md ================================================ # Debug The **debug** library is an extension of the Luau debug library, providing greater control over Luau functions. --- ## debug.getconstant `⛔ Exception` ```lua function debug.getconstant(func: function | number, index: number): any ``` Returns the constant at `index` in the constant table of the function or level `func`. Throws an error if the constant does not exist. ### Parameters * `func` - A function or stack level. * `index` - The numerical index of the constant to retrieve. ### Example ```lua local function foo() print("Hello, world!") end print(debug.getconstant(foo, 1)) --> "print" print(debug.getconstant(foo, 2)) --> nil print(debug.getconstant(foo, 3)) --> "Hello, world!" ``` --- ## debug.getconstants ```lua function debug.getconstants(func: function | number): {any} ``` Returns the constant table of the function or level `func`. > ### 🔎 Tip > Traversing the table with `ipairs` is not recommended, as constants can be `nil` or skipped entirely. ### Parameters * `func` - A function or stack level. ### Example ```lua local function foo() local num = 5000 .. 50000 print("Hello, world!", num, warn) end for i, v in pairs(debug.getconstants(foo)) do print(i, v) end --> 1 50000 --> 2 "print" --> 4 "Hello, world!" --> 5 "warn" ``` --- ## debug.getinfo `🪲 Inconsistent` ```lua function debug.getinfo(func: function | number): DebugInfo ``` Returns debugger information about a function or stack level. ### DebugInfo | Field | Type | Description | | ----- | ---- | ----------- | | `source` | string | The name of the chunk that created the function. | | `short_src` | string | A "printable" version of `source` to be used in error messages. | | `func` | function | The function itself. | | `what` | string | The string "Lua" if the function is a Luau function, or "C" if it is a C function. | | `currentline` | number | The current line where the given function is executing. When no line information is available, `currentline` is set to -1. | | `name` | string | The name of the function. If it cannot find a name, then `name` is a blank string. | | `nups` | number | The number of upvalues in the function. | | `numparams` | number | The number of parameters in the function (always 0 for C functions). | | `is_vararg` | number | Whether the function has a variadic argument (1 if it does, 0 if it does not). | > ### 🪲 Compatibility > Some executors are missing certain fields. ### Parameters * `func` - A function or stack level. ### Example ```lua local function foo() print("Hello, world!") end for k, v in pairs(debug.getinfo(foo)) do print(k, v, "(" .. type(v) .. ")") end ``` --- ## debug.getproto `⛔ Exception` `🛡️ Security` ```lua function debug.getproto(func: function | number, index: number, active: boolean?): function | {function} ``` Returns the proto at `index` in the function or level `func` if `active` is false. If `active` is true, then every active function of the proto is returned. > ### 🛡️ Security > In some executors, the proto is non-functional if `active` is false. Debug information is preserved.\ > To retrieve a callable function, you can set `active` to true and index the first proto. ### Parameters * `func` - A function or stack level. * `index` - The numerical index of the proto to retrieve. * `active` - Whether to return its list of active closures. ### Example ```lua local function myFunction() local function proto() print("Hello, world!") end end local proto = debug.getproto(myFunction, 1, true)[1] proto() --> Hello, world! ``` --- ## debug.getprotos `🛡️ Security` ```lua function debug.getprotos(func: function | number): {function} ``` Returns a list of protos of the function or level `func`. > ### 🛡️ Security > In some executors, the proto is non-functional, but debug information is preserved.\ > To retrieve a callable function, see [`debug.getproto`](#debuggetproto). ### Parameters * `func` - A function or stack level. ### Example ```lua local function myFunction() local function _1() print("Hello,") end local function _2() print("world!") end end for i in ipairs(debug.getprotos(myFunction)) do local proto = debug.getproto(myFunction, i, true)[1] proto() end --> Hello, --> world! ``` --- ## debug.getstack `⛔ Exception` ```lua function debug.getstack(level: number, index: number?): any | {any} ``` Returns the value at `index` in the stack frame `level`. Throws an error if no value could be found. If `index` is not specified, then the entire stack frame is returned. ### Parameters * `level` - The stack frame to look up. * `index` - The numerical index of the value to retrieve. ### Example ```lua local _ = "a" .. "b" print(debug.getstack(1, 1)) --> ab ``` ```lua local _ = "a" .. "b" table.foreach(debug.getstack(1), print) --> ab --> table.foreach() --> debug.getstack() --> 1 ``` --- ## debug.getupvalue `⛔ Exception` ```lua function debug.getupvalue(func: function | number, index: number): any ``` Returns the upvalue at `index` in the function or level `func`. Throws an error if the upvalue does not exist. An upvalue is a local variable used by an inner function, and is also called an *external local variable*. Read more on [Lua visibility rules](http://www.lua.org/manual/5.1/manual.html#2.6). > ### 🔎 Note > Some Luau optimizations automatically inline certain constants like strings and integers.\ > They can be retrieved through [`debug.getconstant`](#debuggetconstant) instead. ### Parameters * `func` - A function or stack level. * `index` - The numerical index of the upvalue to retrieve. ### Example ```lua local upvalue = function () end local function foo() print(upvalue) end print(debug.getupvalue(foo, 1)) --> upvalue ``` An example of Luau optimization: ```lua local upvalue = "Hello, world!" local function foo() print(upvalue) end print(debug.getupvalue(foo, 1)) --> Errors "upvalue index out of range" print(debug.getconstant(foo, 3)) --> Hello, world! ``` --- ## debug.getupvalues ```lua function debug.getupvalues(func: function | number): {any} ``` Returns a list of upvalues of the function or level `func`. > ### 🔎 Tip > Traversing the table with `ipairs` is not recommended, as upvalues can be `nil` or skipped entirely. ### Parameters * `func` - A function or stack level. ### Example ```lua local upvalue1, upvalue2 = function () end, function () end local function foo() print(upvalue1, upvalue2) end for k, v in pairs(debug.getupvalues(foo)) do print(k, v, "(" .. type(v) .. ")") end --> 1 upvalue1() (function) --> 2 upvalue2() (function) ``` --- ## debug.setconstant `⛔ Exception` ```lua function debug.setconstant(func: function | number, index: number, value: any): () ``` Sets the constant at `index` in the function or level `func` to `value`. > ### ⛔ Exception > The type of `value` must match the type of the constant at `index`. ### Parameters * `func` - A function or stack level. * `index` - The numerical index of the constant to set. * `value` - The value to set. ### Example ```lua local function foo() print("Goodbye, world!") end debug.setconstant(foo, 3, "Hello, world!") foo() --> Hello, world! ``` --- ## debug.setstack `⛔ Exception` ```lua function debug.setstack(level: number, index: number, value: any): () ``` Sets the register at `index` in the stack frame `level` to `value`. > ### ⛔ Exception > The type of `value` must match the type of the register at `index`. ### Parameters * `level` - The stack frame to look up. * `index` - The numerical index of the register to set. * `value` - The value to set. ### Example ```lua local function foo() -- Change the first value from "Goodbye, world!" to "Hello, world!" return "Goodbye, world!", debug.setstack(1, 1, "Hello, world!") end print(foo()) --> Hello, world! ``` --- ## debug.setupvalue ```lua function debug.setupvalue(func: function | number, index: number, value: any): () ``` Sets the upvalue at `index` in the function or level `func` to `value`. ### Parameters * `func` - A function or stack level. * `index` - The numerical index of the upvalue to set. * `value` - The value to set. ### Example ```lua local function somethingImportant() print("Goodbye, world!") end local function foo() somethingImportant() end debug.setupvalue(foo, 1, function () print("Hello, world!") end) foo() --> Hello, world! ``` ================================================ FILE: api/filesystem.md ================================================ # Filesystem The **filesystem** functions allow read and write access to a designated folder in the directory of the executor, typically called *workspace*. --- ## readfile ```lua function readfile(path: string): string ``` Returns the contents of the file located at `path`. ### Parameters * `path` - The path to the file. ### Example ```lua writefile("file.txt", "Hello, world!") print(readfile("file.txt")) --> Hello, world! ``` --- ## listfiles ```lua function listfiles(path: string): {string} ``` Returns a list of files and folders in the folder located at `path`. The returned list contains whole paths. ### Parameters * `path` - The path to the folder. ### Example Prints every file and folder in *workspace*. ```lua local function descend(path, level) level = level or 0 for _, file in ipairs(listfiles(path)) do print(string.rep(" ", level) .. file) if isfolder(file) then descend(file, level + 1) end end end descend(".") ``` --- ## writefile ```lua function writefile(path: string, data: string): () ``` Writes `data` to the file located at `path` if it is not a folder. ### Parameters * `path` - A path to the file. * `data` - The data to write. ### Example ```lua writefile("file.txt", "Hello, world!") print(readfile("file.txt")) --> Hello, world! ``` --- ## makefolder ```lua function makefolder(path: string): () ``` Creates a folder at `path` if it does not already exist. ### Parameters * `path` - The target location. ### Example ```lua makefolder("folder") writefile("folder/file.txt", "Hello, world!") print(readfile("folder/file.txt")) --> Hello, world! ``` --- ## appendfile ```lua function appendfile(path: string, data: string): () ``` Appends `data` to the end of the file located at `path`. Creates the file if it does not exist. ### Parameters * `path` - A path to the file. * `data` - The data to append. ### Example ```lua writefile("services.txt", "A list of services:\n") for _, service in ipairs(game:GetChildren()) do if service.ClassName ~= "" then appendfile("services.txt", service.ClassName .. "\n") end end ``` --- ## isfile ```lua function isfile(path: string): boolean ``` Returns whether or not `path` points to a file. ### Parameters * `path` - The path to check. ### Example ```lua writefile("file.txt", "Hello, world!") print(isfile("file.txt")) --> true ``` --- ## isfolder ```lua function isfolder(path: string): boolean ``` Returns whether or not `path` points to a folder. ### Parameters * `path` - The path to check. ### Example ```lua makefolder("folder") print(isfolder("folder")) --> true ``` --- ## delfile ```lua function delfile(path: string): () ``` Removes the file located at `path`. ### Parameters * `path` - The path to the file. ### Example ```lua writefile("file.txt", "Hello, world!") print(isfile("file.txt")) --> true delfile("file.txt") print(isfile("file.txt")) --> false ``` --- ## delfolder ```lua function delfolder(path: string): () ``` Removes the folder located at `path`. ### Parameters * `path` - The path to the folder. ### Example ```lua makefolder("folder") print(isfolder("folder")) --> true delfolder("folder") print(isfolder("folder")) --> false ``` --- ## loadfile ```lua function loadfile(path: string, chunkname: string?): (function?, string?) ``` Generates a chunk from the file located at `path`. The environment of the returned function is the global environment. If there are no compilation errors, the chunk is returned by itself; otherwise, it returns `nil` plus the error message. `chunkname` is used as the chunk name for error messages and debug information. When absent, it defaults to a **random string**. ### Parameters * `path` - A path to the file containing Luau code. * `chunkname` - Optional name of the chunk. ### Example ```lua writefile("file.lua", "local number = ...; return number + 1") local func, err = loadfile("file.lua") local output = assert(func, err)(1) print(output) --> 2 ``` --- ## dofile ```lua function dofile(path: string): () ``` Attempts to load the file located at `path` and execute it on a new thread. > ### 🔎 Note > Some executors may provide the file name to the top-level vararg of the file (`...`). ### Parameters * `path` - The path to the file. ### Example ```lua writefile("code.lua", "print('Hello, world!')") dofile("code.lua") --> "Hello, world!" ``` ================================================ FILE: api/input.md ================================================ # Input The **input** functions allow you to dispatch inputs on behalf of the user. --- ## isrbxactive ```lua function isrbxactive(): boolean ``` Returns whether the game's window is in focus. Must be true for other input functions to work. ### Aliases * `isgameactive` ### Example ```lua if isrbxactive() then mouse1click() end ``` --- ## mouse1click ```lua function mouse1click(): () ``` Dispatches a left mouse button click. --- ## mouse1press ```lua function mouse1press(): () ``` Dispatches a left mouse button press. --- ## mouse1release ```lua function mouse1release(): () ``` Dispatches a left mouse button release. --- ## mouse2click ```lua function mouse2click(): () ``` Dispatches a right mouse button click. --- ## mouse2press ```lua function mouse2press(): () ``` Dispatches a right mouse button press. --- ## mouse2release ```lua function mouse2release(): () ``` Dispatches a right mouse button release. --- ## mousemoveabs ```lua function mousemoveabs(x: number, y: number): () ``` Moves the mouse cursor to the specified absolute position. ### Parameters * `x` - The x-coordinate of the mouse cursor. * `y` - The y-coordinate of the mouse cursor. ### Example Move the cursor in a circle around the screen: ```lua -- Wait for the game window to be selected while not isrbxactive() do task.wait() end local size = workspace.CurrentCamera.ViewportSize for i = 0, 50 do local x = math.sin(i / 50 * math.pi * 2) / 2 + 0.5 local y = math.cos(i / 50 * math.pi * 2) / 2 + 0.5 mousemoveabs(x * size.X, y * size.Y) task.wait(0.05) end ``` --- ## mousemoverel ```lua function mousemoverel(x: number, y: number): () ``` Adjusts the mouse cursor by the specified relative amount. ### Parameters * `x` - The x-offset of the mouse cursor. * `y` - The y-offset of the mouse cursor. ### Example Moves the cursor in a small circle: ```lua -- Wait for the game window to be selected while not isrbxactive() do task.wait() end for i = 0, 20 do local x = math.sin(i / 20 * math.pi * 2) local y = math.cos(i / 20 * math.pi * 2) mousemoverel(x * 100, y * 100) task.wait(0.05) end ``` --- ## mousescroll ```lua function mousescroll(pixels: number): () ``` Dispatches a mouse scroll by the specified number of pixels. ### Parameters * `pixels` - The number of pixels to scroll. ================================================ FILE: api/instances.md ================================================ # Instances The **Instance** functions are used to interact with game objects and their properties. --- ## fireclickdetector ```lua function fireclickdetector(object: ClickDetector, distance: number?, event: string?): () ``` Dispatches a click or hover event to the given ClickDetector. When absent, `distance` defaults to zero, and `event` defaults to "MouseClick". Possible input events include 'MouseClick', 'RightMouseClick', 'MouseHoverEnter', and 'MouseHoverLeave'. ### Parameters * `object` - The ClickDetector to dispatch to. * `distance` - Optional distance to the object. * `event` - Optional event to fire. ### Example ```lua local clickDetector = workspace.Door.Button.ClickDetector fireclickdetector(clickDetector, 10 + math.random(), "MouseClick") ``` --- ## getcallbackvalue ```lua function getcallbackvalue(object: Instance, property: string): function? ``` Returns the function assigned to a callback property of `object`, which cannot be indexed normally. ### Parameters * `object` - The object to get the callback property from. * `property` - The name of the callback property. ### Example ```lua local bindable = Instance.new("BindableFunction") function bindable.OnInvoke() print("Hello, world!") end print(getcallbackvalue(bindable, "OnInvoke")) --> function() print(bindable.OnInvoke) --> Throws an error ``` --- ## getconnections ```lua function getconnections(signal: RBXScriptSignal): {Connection} ``` Creates a list of Connection objects for the functions connected to `signal`. ### Connection | Field | Type | Description | | ----- | ---- | ----------- | | `Enabled` | boolean | Whether the connection can receive events. | | `ForeignState` | boolean | Whether the function was connected by a foreign Luau state (i.e. CoreScripts). | | `LuaConnection` | boolean | Whether the connection was created in Luau code. | | `Function` | function? | The function bound to this connection. Nil when `ForeignState` is true. | | `Thread` | thread? | The thread that created the connection. Nil when `ForeignState` is true. | | Method | Description | | ----- | ----------- | | `Fire(...: any): ()` | Fires this connection with the provided arguments. | | `Defer(...: any): ()` | [Defers](https://devforum.roblox.com/t/beta-deferred-lua-event-handling/1240569) an event to connection with the provided arguments. | | `Disconnect(): ()` | Disconnects the connection. | | `Disable(): ()` | Prevents the connection from firing. | | `Enable(): ()` | Allows the connection to fire if it was previously disabled. | ### Parameters * `signal` - The signal to retrieve connections from. ### Example ```lua local connections = getconnections(game.DescendantAdded) for _, connection in ipairs(connections) do connection:Disable() end ``` --- ## getcustomasset ```lua function getcustomasset(path: string, noCache: boolean): string ``` Returns a `rbxasset://` content id for the asset located at `path`, allowing you to use unmoderated assets. Internally, files are copied to the game's content directory. If `noCache` is false, the file will be cached, allowing subsequent calls to `getcustomasset` to return the same content id. ### Parameters * `path` - The path to the asset. * `noCache` - Whether or not to cache the asset. ### Example ```lua local image = Instance.new("ImageLabel") image.Image = getcustomasset("image.png") print(image.Image) --> rbxasset://nTYyO6iSF3mND4FJ/image.png ``` --- ## gethiddenproperty ```lua function gethiddenproperty(object: Instance, property: string): (any, boolean) ``` Returns the value of a hidden property of `object`, which cannot be indexed normally. If the property is hidden, the second return value will be `true`. Otherwise, it will be `false`. ### Parameters * `object` - The object to index. * `property` - The name of the hidden property. ### Example ```lua local fire = Instance.new("Fire") print(gethiddenproperty(fire, "size_xml")) --> 5, true print(gethiddenproperty(fire, "Size")) --> 5, false ``` --- ## gethui ```lua function gethui(): Folder ``` Returns a hidden GUI container. Should be used as an alternative to CoreGui and PlayerGui. GUI objects parented to this container will be protected from common detection methods. ### Example ```lua local gui = game:GetObjects("rbxassetid://1234")[1] gui.Parent = gethui() ``` --- ## getinstances ```lua function getinstances(): {Instance} ``` Returns a list of every Instance referenced on the client. ### Example ```lua local objects = getinstances() local gameCount = 0 local miscCount = 0 for _, object in ipairs(objects) do if object:IsDescendantOf(game) then gameCount += 1 else miscCount += 1 end end print(gameCount) --> The number of objects in the `game` hierarchy. print(miscCount) --> The number of objects outside of the `game` hierarchy. ``` --- ## getnilinstances ```lua function getnilinstances(): {Instance} ``` Like `getinstances`, but only includes Instances that are not descendants of a service provider. ### Example ```lua local objects = getnilinstances() for _, object in ipairs(objects) do if object:IsA("LocalScript") then print(object, "is a LocalScript") end end ``` --- ## isscriptable `🪲 Compatibility` ```lua function isscriptable(object: Instance, property: string): boolean ``` Returns whether the given property is scriptable (does not have the `notscriptable` tag). If `true`, the property is scriptable and can be indexed normally. If `nil`, the property does not exist. > ### 🪲 Known Issues > This appears to be backwards on Script-Ware. An example will not be provided until behavior is consistent. ### Parameters * `object` - The object to index. * `property` - The name of the property. --- ## sethiddenproperty ```lua function sethiddenproperty(object: Instance, property: string, value: any): boolean ``` Sets the value of a hidden property of `object`, which cannot be set normally. Returns whether the property was hidden. ### Parameters * `object` - The object to index. * `property` - The name of the hidden property. * `value` - The value to set. ### Example ```lua local fire = Instance.new("Fire") print(sethiddenproperty(fire, "Size", 5)) --> false (not hidden) print(sethiddenproperty(fire, "size_xml", 15)) --> true (hidden) print(gethiddenproperty(fire, "size_xml")) --> 15, true (hidden) ``` --- ## setrbxclipboard ```lua function setrbxclipboard(data: string): boolean ``` Sets the Studio client's clipboard to the given `rbxm` or `rbxmx` model data. This allows data from the game to be copied into a Studio client. ### Parameters * `data` - The model data to copy to the clipboard. ### Example ```lua local data = readfile("model.rbxm") setrbxclipboard(data) -- Can be pasted into Studio ``` --- ## setscriptable `🪲 Compatibility` ```lua function setscriptable(object: Instance, property: string, value: boolean): boolean ``` Set whether the given property is scriptable. Returns whether the property was scriptable prior to changing it. > ### 🪲 Known Issues > This appears to be backwards on Script-Ware. An example will not be provided until behavior is consistent. ### Parameters * `object` - The object to index. * `property` - The name of the property. * `value` - Whether the property should be scriptable. ================================================ FILE: api/metatable.md ================================================ # Metatable The **metatable** functions allow elevated access to locked metatables. --- ## getrawmetatable ```lua function getrawmetatable(object: table): table ``` Returns the metatable of `object`, where the `__metatable` field would normally lock the metatable. ### Parameters * `object` - An object with a metatable. ### Example ```lua local object = setmetatable({}, { __metatable = "Locked!" }) print(getmetatable(object)) --> Locked! print(getrawmetatable(object)) --> table ``` --- ## hookmetamethod ```lua function hookmetamethod(object: table, method: string, hook: function): function ``` Replaces `func` with `hook` internally, where `hook` will be invoked in place of `func` when called. Returns a new function that can be used to access the original definition of `func`. > ### ⚠️ Not yieldable > The function `hook` is **not** allowed to yield or block the thread. > ### ⚠️ Recursion > Try not to invoke `method` from within the function `hook`!\ > For example, do not index a property of an Instance from within a hook to `__index`. ### Parameters * `object` - An object with a metatable. * `method` - The name of the method to hook. * `hook` - The function to replace `func` with. ### Example Prevent scripts in PlayerGui from invoking the `__namecall` hook: ```lua local refs = {} local bannedScripts = game:GetService("Players").LocalPlayer.PlayerGui refs.__namecall = hookmetamethod(game, "__namecall", function(...) local caller = getcallingscript() -- Use '.' notation to call the IsDescendantOf method without invoking -- __namecall and causing a recursive loop. local isBanned = caller.IsDescendantOf(caller, bannedScripts) if isBanned then error("Not allowed to invoke __namecall") end return refs.__namecall(...) end) ``` --- ## getnamecallmethod ```lua function getnamecallmethod(): string ``` Returns the name of the method that invoked the `__namecall` metamethod. ### Example Bans the use of `game:service()`: ```lua local refs = {} refs.__namecall = hookmetamethod(game, "__namecall", function(...) local self = ... local method = getnamecallmethod() if self == game and method == "service" then error("Not allowed to run game:service()") end return refs.__namecall(...) end) ``` --- ## isreadonly ```lua function isreadonly(object: table): boolean ``` Returns whether `object` is frozen or read-only. Identical to `table.isfrozen`. ### Parameters * `object` - A table or userdata. ### Example ```lua local object = {} table.freeze(object) print(isreadonly(object)) --> true ``` --- ## setrawmetatable ```lua function setrawmetatable(object: table, metatable: table): () ``` Sets the metatable of `object` to `metatable`, where the `__metatable` field would normally lock the metatable. ### Parameters * `object` - A table or userdata. * `metatable` - The metatable to set. ### Example ```lua local object = setmetatable({}, {}) print(getmetatable(object)) --> table setrawmetatable(object, { __metatable = "Hello, world!" }) print(getmetatable(object)) --> Hello, world! ``` --- ## setreadonly ```lua function setreadonly(object: table, readonly: boolean): () ``` Sets whether `object` is frozen or read-only. ### Parameters * `object` - A table or userdata. * `readonly` - Whether or not `object` should be frozen. ### Example ```lua local object = {} table.freeze(object) print(isreadonly(object)) --> true setreadonly(object, false) print(isreadonly(object)) --> false ``` ================================================ FILE: api/misc.md ================================================ # Miscellaneous The **miscellaneous** functions are a temporary collection of functions that are not yet categorized. --- ## identifyexecutor ```lua function identifyexecutor(): (string, string) ``` Returns the name and version of the current executor. ### Aliases * `getexecutorname` --- ## lz4compress ```lua function lz4compress(data: string): string ``` Compresses `data` using LZ4 compression. ### Parameters * `data` - The uncompressed data. ### Example ```lua local text = "Hello, world! Hello, world! Goodbye, world!" print(#text) --> 43 print(#lz4compress(text)) --> 34 ``` --- ## lz4decompress ```lua function lz4decompress(data: string, size: number): string ``` Decompresses `data` using LZ4 compression, with the decompressed size specified by `size`. ### Parameters * `data` - The compressed data. * `size` - The size of the decompressed data. ### Example ```lua local text = "Hello, world! Hello, world!" local compressed = lz4compress(text) print(lz4decompress(compressed, #text)) --> "Hello, world! Hello, world!" ``` --- ## messagebox `⏰ Yields` ```lua function messagebox(text: string, caption: string, flags: number): number ``` Creates a message box with the specified text, caption, and flags. Yields until the message box is closed, and returns the user input code. Documentation regarding the flags and return codes can be found [here](https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox). ### Parameters * `text` - The text to display in the message box. * `caption` - The caption of the message box. * `flags` - The flags to use. ### Example Prompts the user with a message box with three options and a warning icon: ```lua local MB_ICONWARNING = 0x00000030 local MB_CANCELTRYCONTINUE = 0x00000006 local MB_DEFBUTTON2 = 0x00000100 local IDCANCEL = 0x00000002 local IDTRYAGAIN = 0x00000004 local IDCONTINUE = 0x00000005 local input = messagebox( "Resource not available\nDo you want to try again?", "Resource not found", bit32.bor(MB_ICONWARNING, MB_CANCELTRYCONTINUE, MB_DEFBUTTON2) ) if input == IDCANCEL then print("Canceled") elseif input == IDTRYAGAIN then print("Try again") elseif input == IDCONTINUE then print("Continue") end ``` --- ## queue_on_teleport ```lua function queue_on_teleport(code: string): () ``` Queues the specified script to be executed after the player teleports to a different place. ### Parameters * `code` - The script to execute. ### Aliases * `queueonteleport` - Will supercede this function in the future. ### Example ```lua local source = game:GetObjects("rbxassetid://1234")[1].Source queue_on_teleport(source) loadstring(source)() ``` --- ## request `⏰ Yields` ```lua function request(options: HttpRequest): HttpResponse ``` Sends an HTTP request using the specified options. Yields until the request is complete, and returns the response. ### Request | Field | Type | Description | | ----- | ---- | ----------- | | `Url` | string | The URL for the request. | | `Method` | string | The HTTP method to use. Can be `GET`, `POST`, `PATCH`, or `PUT`. | | `Body` | string? | The body of the request. | | `Headers` | table? | A table of headers. | | `Cookies` | table? | A table of cookies. | ### Response | Field | Type | Description | | ----- | ---- | ----------- | | `Body` | string | The body of the response. | | `StatusCode` | number | The number status code of the response. | | `StatusMessage` | string | The status message of the response. | | `Success` | boolean | Whether or not the request was successful. | | `Headers` | table | A dictionary of headers. | ### Headers The executor provides the following headers for identification on a web server: | Header | Description | | ------ | ----------- | | `PREFIX-User-Identifier` | A string unique to each user, and does not change if the script executor is used across computers. | | `PREFIX-Fingerprint` | The hardware identifier of the user. | | `User-Agent` | The name and version of the executor. | ### Parameters * `options` - The options to use. ### Aliases * `http.request` * `http_request` ### Example ```lua local response = request({ Url = "http://example.com/", Method = "GET", }) print(response.StatusCode .. " - " .. response.StatusMessage) --> 200 - HTTP/1.1 200 OK ``` --- ## setclipboard ```lua function setclipboard(text: string): () ``` Copies `text` to the clipboard. ### Parameters * `text` - The text to copy. ### Aliases * `toclipboard` ### Example ```lua local character = game:GetService("Players").LocalPlayer.Character local components = table.pack(character.PrimaryPart.CFrame:GetComponents()) setclipboard("CFrame.new(" .. table.concat(components, ", ") .. ")") ``` --- ## setfpscap ```lua function setfpscap(fps: number): () ``` Sets the in-game FPS cap to `fps`. If `fps` is 0, the FPS cap is disabled. ### Parameters * `fps` - The FPS cap. ### Example ```lua setfpscap(0) -- Unlocks the FPS cap ``` ================================================ FILE: api/scripts.md ================================================ # Scripts The **script** functions provide access to script environments and internal state. --- ## getgc ```lua function getgc(includeTables: boolean?): {function | userdata | table} ``` Returns a list of objects in the Luau garbage collector. If `includeTables` is false, tables will not be included in the list. ### Parameters * `includeTables` - Whether or not to include tables in the list. ### Example **TODO** - Write a real-world example use case. --- ## getgenv ```lua function getgenv(): { [string]: any } ``` Returns the custom global environment of the executor. It can be used to add global functions or share variables between scripts. ### Example Prevent a script from being run twice: ```lua if getgenv().__IS_LOADED then error("This script is already loaded!") end getgenv().__IS_LOADED = true ``` --- ## getloadedmodules ```lua function getloadedmodules(excludeCore: boolean?): {ModuleScript} ``` Returns a list of ModuleScripts that have been loaded. If `excludeCore` is true, CoreScript-related modules will not be included in the list. ### Parameters * `excludeCore` - Whether or not to exclude core modules from the list. ### Example ```lua local modules = getloadedmodules(true) for _, module in ipairs(modules) do print(module:GetFullName()) end ``` --- ## getrenv ```lua function getrenv(): { [string]: any } ``` Returns the global environment of the game client. It can be used to access the global functions that LocalScripts and ModuleScripts use. ### Example Prevent scripts in PlayerScripts from being required: ```lua local refs = {} local bannedScripts = game:GetService("Players").LocalPlayer.PlayerScripts refs.require = hookfunction(require, function(...) local module = ... if typeof(module) == "Instance" and module:IsA("ModuleScript") and module:IsDescendantOf(bannedScripts) then error("You are not allowed to require this module!") end return refs.require(...) end) ``` --- ## getrunningscripts ```lua function getrunningscripts(): {LocalScript | ModuleScript} ``` Returns a list of scripts that are currently running. ### Example ```lua local scripts = getrunningscripts() for _, object in ipairs(scripts) do print(object:GetFullName(), "(" .. object.ClassName .. ")") end ``` --- ## getscriptbytecode ```lua function getscriptbytecode(script: LocalScript | ModuleScript): string ``` Returns the raw Luau bytecode of the given script. ### Parameters * `script` - A client-running LocalScript or ModuleScript. ### Aliases * `dumpstring` ### Example ```lua local animate = game:GetService("Players").LocalPlayer.Character.Animate local bytecode = getscriptbytecode(animate) ``` --- ## getscriptclosure ```lua function getscriptclosure(script: LocalScript | ModuleScript): function ``` Generates a new closure using the bytecode of `script`. ### Parameters * `script` - The script to recreate. ### Aliases * `getscriptfunction` ### Example Compare the return value of a ModuleScript: ```lua local module = game:GetService("CoreGui").RobloxGui.Modules.Common.Constants local constants = getrenv().require(module) local generatedConstants = getscriptclosure(module)() print(constants == generatedConstants) --> false for k, v in pairs(constants) do print(k, typeof(v) == typeof(generatedConstants[k])) --> true end ``` --- ## getscripthash ```lua function getscripthash(script: LocalScript | ModuleScript): string ``` Returns a SHA384 hash of the script's bytecode. This is useful for detecting changes to a script's source code. ### Parameters * `script` - A client-running LocalScript or ModuleScript. ### Example ```lua local animate = game:GetService("Players").LocalPlayer.Character.Animate local hash = getscripthash(animate) task.delay(1.5, function () animate.Source = "print('Hello World!')" end) for i = 1, 5 do task.wait(0.5) local newHash = getscripthash(animate) if hash ~= newHash then print("The script has changed!") hash = newHash else print("The script has not changed.") end end ``` --- ## getscripts ```lua function getscripts(): {LocalScript | ModuleScript} ``` Returns a list of every script in the game. ### Example ```lua local scripts = getscripts() for _, object in ipairs(scripts) do print(object:GetFullName(), "(" .. object.ClassName .. ")") end ``` --- ## getsenv ```lua function getsenv(script: LocalScript | ModuleScript): { [string]: any } ``` Returns the global environment of the given script. It can be used to access variables and functions that are not defined as local. ### Parameters * `script` - A client-running LocalScript or ModuleScript. ### Example ```lua local animate = game:GetService("Players").LocalPlayer.Character.Animate local environment = getsenv(animate) for k, v in pairs(environment) do print(k, v, "(" .. typeof(v) .. ")") end ``` --- ## getthreadidentity ```lua function getthreadidentity(): number ``` Returns the identity of the current thread. Learn more about thread identities [here](https://roblox.fandom.com/wiki/Security_context). ### Aliases * `getidentity` * `getthreadcontext` ### Example ```lua local identity = getthreadidentity() print(identity) --> 7 ``` --- ## setthreadidentity ```lua function setthreadidentity(identity: number): () ``` Sets the current thread identity. Learn more about thread identities [here](https://roblox.fandom.com/wiki/Security_context). ### Aliases * `setidentity` * `setthreadcontext` ### Example ```lua setthreadidentity(3) print(getthreadidentity()) --> 3 ```