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 |  |
> | Krnl |  |
### 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
```