Welcome to Proohio Documentation
Your complete guide to Proohio scripting
What is Proohio?
Proohio is a powerful Lua script execution engine for Roblox. This documentation provides comprehensive information about all available functions and their usage.
Quick Navigation
- Home - Welcome page and overview
- Closure - Function manipulation and closure utilities
- Cryptography - Encryption and hashing functions
- Debug - Debugging and inspection tools
- Drawing - Rendering and graphics functions
- Environment - Environment manipulation utilities
checkcaller
Check if function was called from executor thread
boolean checkcaller()
Returns true if the current function was called from the executor thread, false otherwise.
Example Usage
if checkcaller() then
print("Called from executor")
else
print("Called from game script")
end
clonefunction
Create an exact copy of a function
clonefunction creates and returns a new function that has the exact same behaviour as the passed function.
Notes on clonefunction
- The new (cloned) function returned by clonefunction should have the same environment as the original function.
- Any sort of modification to the original function should not affect the clone. This means that stuff like hooking the original function will leave the clone unaffected.
Parameters
| Parameter | Description |
|---|---|
| functionToClone | The function to clone. |
Example
Cloning functions with clonefunction
local function dummy_function()
print("Hello")
end
local cloned_function = clonefunction(dummy_function)
print(debug.info(cloned_function, "l")) -- Output: 1
print(debug.info(cloned_function, "n")) -- Output: dummy_function
print(cloned_function == dummy_function) -- Output: false
print(getfenv(cloned_function) == getfenv(dummy_function)) -- Output: true
getfunctionhash
Get SHA384 hash of function instructions
getfunctionhash returns the hex-represented SHA384 hash of a provided function's instructions (code) and constants.
C closures are not supported
This function will throw an error if called on a C closure, such as print, since C closures have no reliable information to hash. The error should be something along the lines of "lua function expected"
Notes on getfunctionhash
In order to have reliable knowledge over what the function changes, constants should also be added to the hash alongside the l.p->code. Add the constants at the beginning of the instructions, and hash that.
We suggest following this implementation in order to keep the same functionality across multiple executors, since it will be more convenient for the users not having to change their hashes if they do migrate to a different executor.
Full credits go to Dottik and Ragnar regarding the source provided above.
Parameters
| Parameter | Description |
|---|---|
| functionToHash | The function to retrieve the hash of. |
Example
Checking the SHA384 hash of functions with getfunctionhash
local function is_sha384_hex(hash)
return #hash == 96 and hash:match("^[0-9a-fA-F]+$") ~= nil
end
local dummy_function_0 = function() end
local dummy_function_1 = function(...) end
local dummy_function_2 = function() end
local dummy_function_3 = function() return "Constant" end
local dummy_function_4 = function() return "Constant2" end
print(is_sha384_hex(getfunctionhash(dummy_function_0))) -- Output: true
print(getfunctionhash(dummy_function_0) == getfunctionhash(dummy_function_1)) -- Output: false
print(getfunctionhash(dummy_function_0) == getfunctionhash(dummy_function_2)) -- Output: true
print(getfunctionhash(dummy_function_3) == getfunctionhash(dummy_function_4)) -- Output: false
hookfunction
Hook a function with another function
hookfunction allows you to hook a function with another wanted function, returning the original unhooked function.
Notes on hookfunction
- The hook should not have more upvalues than the function you want to hook. There are ways to bypass the upvalue restriction, such as using newlclosure or newcclosure to wrap the hook
- All possible hooking closure pairs should be supported throughout L, NC, C (where NC = newcclosure)
Parameters
| Parameter | Description |
|---|---|
| functionToHook | The function that will be hooked |
| hook | The function that will be used as a hook |
Example
Hooking functions with hookfunction
local function dummy_func()
print("I am not hooked!")
end
local function dummy_hook()
print("I am hooked!")
end
dummy_func() -- Output: I am not hooked!
local old_func = hookfunction(dummy_func, dummy_hook)
dummy_func() -- Output: I am hooked!
old_func() -- Output: I am not hooked!
hookmetamethod
Hook metamethods of objects
hookmetamethod takes any Luau object that can have a metatable, and attempts to hook the specified metamethod of the object. Internally, it essentially uses hookfunction to hook specific metamethods.
Notes on hookmetamethod
hookmetamethod can be safely implemented from within Luau, as long as hookfunction is already properly implemented in C++.
Parameters
| Parameter | Description |
|---|---|
| object | The object which has a metatable. |
| metamethodName | The name of the metamethod to hook. |
| hook | The function that will be used as a hook. |
Example
Easily hooking metamethods with hookmetamethod
local original; original = hookmetamethod(game, "__index", function(...)
local key = select(2, ...)
print(key)
return original(...)
end)
local _ = game.PlaceId -- Output: "PlaceId"
hookmetamethod(game, "__index", original) -- Restores game's __index
iscclosure
Check if function is a C closure
iscclosure checks whether a given function is a C closure or not.
Parameters
| Parameter | Description |
|---|---|
| func | The function to check. |
Example
Checking whether functions are C closures with iscclosure
local function dummy_lua_function()
print("This is an executor Luau closure")
end
local dummy_cfunction = newcclosure(function()
print("This is an Executor C Closure")
end)
local dummy_standard_function = print
local dummy_global_cfunction = getgc
print(iscclosure(dummy_cfunction)) -- Output: true
print(iscclosure(dummy_global_cfunction)) -- Output: true
print(iscclosure(dummy_standard_function)) -- Output: true
print(iscclosure(dummy_lua_function)) -- Output: false
isexecutorclosure
Check if function is an executor closure
isexecutorclosure checks whether a given function is a closure of the executor. This also includes closures retrieved using getscriptclosure or loadstring
Parameters
| Parameter | Description |
|---|---|
| func | The function to check. |
Example
Identifying executor closures with isexecutorclosure
local function dummy_lua_function()
print("This is an executor Luau closure")
end
local dummy_cfunction = newcclosure(function()
print("This is an executor C closure")
end)
local dummy_standard_cfunction = print
local dummy_global_cfunction = getgc
print(isexecutorclosure(dummy_lua_function)) -- Output: true
print(isexecutorclosure(dummy_cfunction)) -- Output: true
print(isexecutorclosure(dummy_global_cfunction)) -- Output: true
print(isexecutorclosure(dummy_standard_cfunction)) -- Output: false
islclosure
Check if function is a Luau closure
islclosure checks whether a given function is a Luau closure or not.
Parameters
| Parameter | Description |
|---|---|
| func | The function to check. |
Example
Verifying Luau closures with islclosure
local function dummy_lua_function()
print("This is an executor Luau closure")
end
local dummy_cfunction = newcclosure(function()
print("This is an executor C closure")
end)
local dummy_standard_cfunction = print
print(islclosure(dummy_lua_function)) -- Output: true
print(islclosure(dummy_standard_cfunction)) -- Output: false
print(islclosure(dummy_cfunction)) -- Output: false
newcclosure
Wrap Luau function as C closure
newcclosure takes any Luau function and wraps it into a C closure. When the returned function is called, it invokes the original Luau closure with the provided arguments, then passes the closure's returned values back to the caller.
Important Notes
Do not implement this with coroutines
Many executors seem to be implementing this function using coroutine functions in Luau. Such functions will not pass sUNC checks.
- The wrapped function must be yieldable, meaning that the function should be able to call task.wait, for example.
- Error spoofing: Luau and C errors are different. You must ensure that errors from functions wrapped with newcclosure appear as C closure errors!
- Upvalues: The function returned by newcclosure must have no upvalues.
Parameters
| Parameter | Description |
|---|---|
| functionToWrap | A function to be wrapped. |
Examples
Example 1
Basic C closure wrapping example with newcclosure
local dummy_function = function(...)
return ...
end
print(iscclosure(dummy_function)) -- Output: false
local wrapped_function = newcclosure(dummy_function)
print(iscclosure(wrapped_function)) -- Output: true
local function_results = wrapped_function("Hello")
print(function_results) -- Output: Hello
Example 2
This example illustrates how Luau functions wrapped as a C closure should also be yieldable, therefore also showcasing how coroutine implementations of newcclosure would not work.
Yieldable C functions made with newcclosure
local dummy_yielding_function = newcclosure(function()
print("Before")
task.wait(1.5)
print("After")
end)
dummy_yielding_function()
-- Output:
-- Before
-- yield for 1.5 seconds
-- After
restorefunction
Restore hooked function to original
restorefunction restores a hooked function back to the very first original function, even if it has been hooked multiple times.
This will throw an error if the requested function is not already hooked
Parameters
| Parameter | Description |
|---|---|
| functionToRestore | The hooked function that you want to restore |
Examples
Example 1
Restoring a hooked function
function dummy_func()
print("I am not hooked!")
end
hookfunction(dummy_func, function()
print("I am hooked!")
end)
dummy_func() -- Output: I am hooked!
restorefunction(dummy_func)
dummy_func() -- Output: I am not hooked!
Example 2
Restoring a unhooked function
function dummy_func()
print("I am not hooked!")
end
dummy_func() -- Output: I am not hooked!
restorefunction(dummy_func) -- Error: restorefunction: function is not hooked
syn.crypt.encrypt
Encrypt data with a key using standard encryption
Syntax
<string> syn.crypt.encrypt(<string> data, <string> key)
Description
Encrypts the provided data using the specified key. This function uses a standard encryption algorithm to secure your data.
Parameters
| Parameter | Description |
|---|---|
| data | The data to encrypt |
| key | The encryption key |
Returns
Returns the encrypted data as a string.
syn.crypt.decrypt
Decrypt data with a key using standard decryption
Syntax
<string> syn.crypt.decrypt(<string> data, <string> key)
Description
Decrypts the provided encrypted data using the specified key. This function reverses the encryption process.
Parameters
| Parameter | Description |
|---|---|
| data | The encrypted data to decrypt |
| key | The decryption key (must match encryption key) |
Returns
Returns the decrypted data as a string.
syn.crypt.base64.encode
Encode data using Base64 encoding
Syntax
<string> syn.crypt.base64.encode(<string> data)
Description
Encodes the provided data using Base64 encoding. Base64 is commonly used to encode binary data for transmission over text-based protocols.
Parameters
| Parameter | Description |
|---|---|
| data | The data to encode |
Returns
Returns the Base64 encoded data as a string.
syn.crypt.base64.decode
Decode Base64 encoded data
Syntax
<string> syn.crypt.base64.decode(<string> data)
Description
Decodes Base64 encoded data back to its original form. This function reverses the Base64 encoding process.
Parameters
| Parameter | Description |
|---|---|
| data | The Base64 encoded data to decode |
Returns
Returns the decoded data as a string.
syn.crypt.hash
Generate a hash of the provided data
Syntax
<string> syn.crypt.hash(<string> data)
Description
Generates a hash of the provided data using a standard hashing algorithm. Hashes are one-way functions used for data integrity verification.
Parameters
| Parameter | Description |
|---|---|
| data | The data to hash |
Returns
Returns the hash as a string.
crypt.generatekey
Generate a random key of specified length
Syntax
<string> crypt.generatekey(<number?> length)
Description
Generates a random key of the specified length. If no length is provided, defaults to 32 bytes. The generated key is returned as a base64 encoded string for easy storage and transmission.
Parameters
| Parameter | Description |
|---|---|
| length (optional) | The length of the key to generate in bytes. Defaults to 32 if not specified. |
Returns
Returns a base64 encoded random key as a string.
Example
local key = crypt.generatekey(16)
print(key) -- Outputs a base64 encoded 16-byte random key
-- Using default length (32 bytes)
local default_key = crypt.generatekey()
print(default_key) -- Outputs a base64 encoded 32-byte random key
crypt.generatebytes
Generate random bytes of specified count
Syntax
<string> crypt.generatebytes(<number?> count)
Description
Generates random bytes of the specified count. If no count is provided, defaults to 16 bytes. The generated bytes are returned as a base64 encoded string for easy handling and storage.
Parameters
| Parameter | Description |
|---|---|
| count (optional) | The number of random bytes to generate. Defaults to 16 if not specified. |
Returns
Returns base64 encoded random bytes as a string.
Example
local random_bytes = crypt.generatebytes(24)
print(random_bytes) -- Outputs base64 encoded 24 random bytes
-- Using default count (16 bytes)
local default_bytes = crypt.generatebytes()
print(default_bytes) -- Outputs base64 encoded 16 random bytes
debug.getconstant
Returns the constant at the specified index from a Luau function
C closures are not supported
This function will throw an error if called on a C closure, such as print, since C closures have no accessible constants.
Description
debug.getconstant returns the constant at the specified index from a Luau function. If no constant exists at that index, it returns nil instead.
This is useful when you want to inspect specific constant values (such as strings, numbers, or booleans) without dumping the entire list.
Syntax
function debug.getconstant(func: (...any) -> (...any) | number, index: number): number | string | boolean | nil
Parameters
| Parameter | Description |
|---|---|
| func | The Luau function (or stack level) whose constant to retrieve. |
| index | The position of the desired constant. |
Examples
Getting a valid constant
local function dummy_function()
local dummy_string = "foo bar"
string.split(dummy_string, " ")
end
local result = debug.getconstant(dummy_function, 2)
print(result) -- Output: string
Getting an out-of-range constant
local function dummy_function()
local dummy_string = "foo bar"
string.split(dummy_string, " ")
end
local result = debug.getconstant(dummy_function, 3)
print(result) -- Output: nil
Calling on a C closure should error
print(debug.getconstant(print, 1)) -- Should error due to being a C closure
debug.getconstants
Returns a list of all constants used within a Luau function's bytecode
C closures are not supported
This function will throw an error if called on a C closure, such as print, since C closures have no accessible constants.
Description
debug.getconstants returns a list of all constants used within a Luau function's bytecode. This includes literal values like numbers, strings, booleans, and nil.
Syntax
function debug.getconstants(func: (...any) -> (...any) | number): { number | string | boolean | nil }
Parameters
| Parameter | Description |
|---|---|
| func | The Luau function (or stack level) whose constants will be returned. |
Examples
Retrieving constants from a Luau function
local function dummy_function()
local dummy_string = "foo bar"
string.split(dummy_string, " ")
end
local constants = debug.getconstants(dummy_function)
for constant_index, constant in constants do
print(`[{constant_index}]: {constant}`)
end
-- Output:
-- [1]: "string"
-- [2]: "split"
-- [4]: "foo bar"
-- [5]: " "
Calling on a C closure should error
print(debug.getconstants(print)) -- Should error due to being a C closure
debug.getproto
Returns a specific function prototype from a Luau function by index
C closures are not supported
This function will throw an error if called on a C closure, such as print, since C closures do not contain function prototypes.
Inactive protos
Protos retrieved without the activated should not be callable; this leads to vulnerabilities. The usage of inactive protos is to retrieve information off of them.
Description
debug.getproto returns a specific function prototype from a Luau function by index. Optionally, it can search for active functions of the proto, if the activated parameter is set to true.
These are internal function definitions (e.g. nested functions) that exist as part of the compiled bytecode, even if they aren't assigned or called.
Syntax
function debug.getproto(func: (...any) -> (...any) | number, index: number, activated: boolean?): (...any) -> (...any) | { (...any) -> (...any) }
Parameters
| Parameter | Description |
|---|---|
| func | The Luau function (or stack level) to extract a proto from. |
| index | The index of the prototype to return. |
| activated? | If true, returns a table of currently active functions based on the proto. |
Examples
Retrieving nested prototypes
local function dummy_function()
local function dummy_proto_1()
print("Hello")
end
local function dummy_proto_2()
print("Hello2")
end
end
debug.getproto(dummy_function, 1)() -- Uncallable
debug.getproto(dummy_function, 2)() -- Uncallable
Retrieving an active function from a proto
local function dummy_function()
local function dummy_proto()
return "hi"
end
return dummy_proto
end
local real_proto = dummy_function()
local retrieved_proto = debug.getproto(dummy_function, 1, true)[1]
print(real_proto == retrieved_proto) -- Output: true
print(retrieved_proto()) -- Output: hi
debug.getprotos
Returns all function prototypes defined within the specified Luau function
C closures are not supported
This function will throw an error if called on a C closure, such as print, since C closures do not contain function prototypes.
Inactive protos
Protos retrieved without the activated should not be callable; this leads to vulnerabilities. The usage of inactive protos is to retrieve information off of them.
Description
debug.getprotos returns all function prototypes defined within the specified Luau function.
These are internal function definitions (e.g. nested functions) that exist as part of the compiled bytecode, even if they aren't assigned or called.
Syntax
function debug.getprotos(func: (...any) -> (...any) | number): { (...any) -> (...any) }
Parameters
| Parameter | Description |
|---|---|
| func | The Luau function (or stack level) to extract protos from. |
Example
Getting nested function prototypes
local function DummyFunction0()
local function DummyFunction1() end
local function DummyFunction2() end
end
for index, proto in pairs(debug.getprotos(DummyFunction0)) do
print(index, debug.info(proto, "n"))
end
-- Output:
-- 1 DummyFunction1
-- 2 DummyFunction2
debug.getstack
Retrieves values from the stack at the specified call level
C closures are not supported
This function will throw an error if the stack level points to a C closure, such as getstack(0).
Description
debug.getstack retrieves values from the stack at the specified call level.
This function is useful for inspecting local variables or arguments at different layers of the stack frame. If no index is given, all values at that stack level are returned as a list.
Syntax
function debug.getstack(level: number, index: number?): any | { any }
Parameters
| Parameter | Description |
|---|---|
| level | The stack level to inspect. 1 is the current function. |
| index? | The specific slot/index at that stack level to read. |
Examples
Retrieving multiple values from the stack
local count = 0
local function recursive_function()
count += 1
if count > 6 then return end
local a = 29
local b = true
local c = "Example"
a += 1
b = false
c ..= "s"
print(debug.getstack(1, count))
recursive_function()
end
recursive_function()
-- Output (varies depending on Count):
-- 30
-- false
-- Examples
-- function: 0x... (print)
-- function: 0x... (getstack)
-- etc.
Retrieving values from the caller's stack
local function dummy_function()
return "Hello"
end
local var = 5
var += 1
(function()
print(debug.getstack(2)[1]()) -- Output: Hello
print(debug.getstack(2)[2]) -- Output: 6
end)()
debug.getupvalue
Returns the upvalue at the specified index from a Luau function's closure
C closures are not supported
This function will throw an error if called on a C closure, such as print, for security reasons.
Description
debug.getupvalue returns the upvalue at the specified index from a Luau function's closure. If the index is invalid or out of bounds, an error will occur.
Syntax
function debug.getupvalue(func: (...any) -> (...any) | number, index: number): any
Parameters
| Parameter | Description |
|---|---|
| func | The Luau function (or stack level) to retrieve an upvalue from. |
| index | The position of the upvalue. |
Examples
Retrieving a function upvalue
local UpFunction = function()
print("Hello from up")
end
local function DummyFunction()
UpFunction()
end
local Retrieved = debug.getupvalue(DummyFunction, 1)
Retrieved() -- Output: Hello from up
Invalid index on a function with no upvalues
local function DummyFunction() end
debug.getupvalue(DummyFunction, 0) -- Should error
Calling on a C closure should error
debug.getupvalue(print, 1) -- Should error due to C closure
debug.getupvalues
Returns a list of upvalues captured by a Luau function
C closures are not supported
This function will throw an error if called on a C closure, such as print, for security reasons.
Description
debug.getupvalues returns a list of upvalues captured by a Luau function. These are the external variables that a function closes over from its surrounding scope.
If the function has no upvalues, the result will be an empty table.
Syntax
function debug.getupvalues(func: (...any) -> (...any) | number): { any }
Parameters
| Parameter | Description |
|---|---|
| func | The Luau function (or stack level) to retrieve upvalues from. |
Examples
Retrieving upvalues from a closure
local var1 = false
local var2 = "Hi"
local function dummy_function()
var1 = true
var2 ..= ", hello"
end
for index, value in pairs(debug.getupvalues(dummy_function)) do
print(index, value)
end
-- Output:
-- 1 false
-- 2 Hi
Calling with a function that has no upvalues
local function dummy_function()
return 123
end
print(next(debug.getupvalues(dummy_function))) -- Output: nil
Calling on a C closure should error
print(debug.getupvalues(print)) -- Should error due to being a C closure
debug.setconstant
Modifies a constant at the specified index in a Luau function bytecode
C closures are not supported
This function will throw an error if called on a C closure, such as print, since C closures have no accessible constants.
Mutable globals
If game is a mutable global, the constant indexes will be different.
Description
debug.setconstant modifies a constant at the specified index in a Luau function bytecode.
This can be used to change hardcoded behavior within functions without modifying their source code - although it requires knowing the correct constant index beforehand.
Syntax
function debug.setconstant(func: (...any) -> (...any) | number, index: number, value: number | string | boolean | nil): ()
Parameters
| Parameter | Description |
|---|---|
| func | The Luau function (or stack level) whose constant to modify. |
| index | The position of the constant to change. |
| value | The new constant value to set. |
Example
Overwriting a constant string in a function
local function dummy_function()
print(game.Name)
end
debug.setconstant(dummy_function, 4, "Players")
dummy_function() -- Output: Players
debug.setstack
Replaces a value in a specified stack frame
C closures are not supported
This function will throw an error if the stack level points to a C closure, such as setstack(0, 1, 0).
Description
debug.setstack replaces a value in a specified stack frame.
This allows for powerful manipulation of runtime variables or arguments, particularly useful in advanced debugging or dynamic patching scenarios.
Syntax
function debug.setstack(level: number, index: number, value: any): ()
Parameters
| Parameter | Description |
|---|---|
| level | The stack level to target. 1 refers to the current function. |
| index | The index/slot in the stack frame to replace. |
| value | The new value to assign at that stack slot. |
Examples
Replacing the 'error' function on the stack with our own
error(debug.setstack(1, 1, function()
return function()
print("Replaced")
end
end))() -- Output: Replaced
Replacing a numeric local in a parent scope
local outer_value = 10
local function inner_function()
outer_value += 9
debug.setstack(2, 1, 100)
end
inner_function()
print(outer_value) -- Output: 100
debug.setupvalue
Replaces an upvalue at the specified index in a Luau function, with a new value
C closures not supported
This function will throw an error if called on a C closure, such as print, for security reasons.
Description
debug.setupvalue replaces an upvalue at the specified index in a Luau function, with a new value.
This allows for controlled modification of function state, often used in hooking or testing environments.
Syntax
function debug.setupvalue(func: (...any) -> (...any) | number, index: number, value: any): ()
Parameters
| Parameter | Description |
|---|---|
| func | The function (or stack level) whose upvalue to replace. |
| index | The index of the upvalue to be replaced. |
| value | The new value to assign to the upvalue. |
Example
Replacing a numeric upvalue
local upvalue = 90
local function dummy_function()
upvalue += 1
print(upvalue)
end
dummy_function() -- Output: 91
debug.setupvalue(dummy_function, 1, 99)
dummy_function() -- Output: 100
cleardrawcache
cleardrawcache removes all active drawing objects created with Drawing.new.
Syntax
function cleardrawcache(): ()
Parameters
| Parameter | Description |
|---|---|
| (none) | This function takes no parameters. |
Example
Clearing all drawing objects at once
local camera = game.Workspace.CurrentCamera
local viewport = camera.ViewportSize
local pos = Vector2.new(viewport.X / 2, viewport.Y / 2)
local circle = Drawing.new("Circle")
circle.Radius = 50
circle.Color = Color3.fromRGB(255, 0, 0)
circle.Filled = true
circle.NumSides = 60
circle.Position = pos
circle.Transparency = 1
circle.Visible = true
task.defer(cleardrawcache)
print(circle.__OBJECT_EXISTS) -- Output: true
task.wait()
print(circle.__OBJECT_EXISTS) -- Output: false
getrenderproperty
getrenderproperty retrieves the value of a property from a Drawing object. This behaves identically to using object[property], but is useful when working with dynamic property names or for reflection-like access.
Syntax
function getrenderproperty(drawing: Drawing, property: string): any
Parameters
| Parameter | Description |
|---|---|
| drawing | A valid Drawing object. |
| property | The name of the property to retrieve. |
Example
Reading drawing properties
local circle = Drawing.new("Circle")
circle.Radius = 50
circle.Visible = true
print(getrenderproperty(circle, "Radius")) -- Output: 50
print(getrenderproperty(circle, "Visible")) -- Output: true
isrenderobj
isrenderobj checks whether a given value is a valid Drawing object.
This is useful for validation in functions or modules that work with custom render systems.
Syntax
function isrenderobj(object: any): boolean
Parameters
| Parameter | Description |
|---|---|
| object | The value to check for Drawing validity. |
Example
Checking if an object is a render object
local square = Drawing.new("Square")
print(isrenderobj(square)) -- Output: true
print(isrenderobj(workspace)) -- Output: false
print(isrenderobj("not a draw")) -- Output: false
setrenderproperty
setrenderproperty assigns a value to a property of a Drawing object. This behaves identically to object[property] = value, but is useful for dynamic or abstracted property access.
Syntax
function setrenderproperty(drawing: Drawing, property: string, value: any): ()
Parameters
| Parameter | Description |
|---|---|
| drawing | A valid Drawing object. |
| property | The name of the property to assign. |
| value | The value to assign to the specified property. |
Example
Setting drawing properties
local circle = Drawing.new("Circle")
setrenderproperty(circle, "Radius", 50)
setrenderproperty(circle, "Visible", true)
print(circle.Radius) -- Output: 50
print(circle.Visible) -- Output: true
Drawing.new
Creates a new drawing object with the specified type. Returns the drawing object.
Syntax
function Drawing.new(type: string): object
Parameters
| Parameter | Type | Description |
|---|---|---|
| type | string | The type of drawing object to create ("Line", "Text", "Circle", "Square", "Triangle") |
Drawing Types
Base Properties (All Types)
| Property | Type | Description |
|---|---|---|
| Visible | bool | Whether the drawing object is visible |
| Remove | void | Method to remove the drawing object |
| Color | Color3 | The color of the drawing object |
Line
| Property | Type | Description |
|---|---|---|
| Transparency | number | Transparency (opposite to Roblox) |
| Thickness | number | Line thickness |
| From | Vector2 | Starting point of the line |
| To | Vector2 | Ending point of the line |
Text
| Property | Type | Description |
|---|---|---|
| Text | string | The text content |
| Transparency | number | Text transparency |
| Size | number | Font size |
| Center | bool | Whether text is centered |
| Outline | bool | Whether text has outline |
| OutlineColor | Color3 | Color of the text outline |
| Position | Vector2 | Text position |
| TextBounds | Vector2 [readonly] | Bounds of the text |
| Font | number | Font type (see Drawing.Fonts) |
Circle
| Property | Type | Description |
|---|---|---|
| Transparency | number | Circle transparency |
| Thickness | number | Border thickness |
| NumSides | number | Number of sides for the circle |
| Radius | number | Circle radius |
| Filled | bool | Whether circle is filled |
| Position | Vector2 | Circle center position |
Square
| Property | Type | Description |
|---|---|---|
| Transparency | number | Square transparency |
| Thickness | number | Border thickness |
| Size | Vector2 | Square dimensions |
| Position | Vector2 | Square position |
| Filled | bool | Whether square is filled |
Triangle
| Property | Type | Description |
|---|---|---|
| Transparency | number | Triangle transparency |
| Thickness | number | Border thickness |
| PointA | Vector2 | First triangle point |
| PointB | Vector2 | Second triangle point |
| PointC | Vector2 | Third triangle point |
| Filled | bool | Whether triangle is filled |
Example
Creating and configuring a line drawing
local line = Drawing.new("Line")
line.Visible = true
line.From = Vector2.new(0,0)
line.To = Vector2.new(200,200)
line.Color = Color3.fromRGB(255,255,255)
line.Thickness = 2
line.Transparency = 1
line:Remove() --Nothing will appear since its getting removed straight away.
Drawing.Fonts
Returns a table populated with available fonts for use with Drawing text objects.
Syntax
function Drawing.Fonts(): table
Parameters
| Parameter | Description |
|---|---|
| (none) | This function takes no parameters. |
Available Fonts
| Font | Number |
|---|---|
| UI | 0 |
| System | 1 |
| Plex | 2 |
| Monospace | 3 |
Example
Getting available fonts
local fonts = Drawing.Fonts()
for fontName, fontNumber in pairs(fonts) do
print(fontName .. ": " .. fontNumber)
end
-- Output:
-- UI: 0
-- System: 1
-- Plex: 2
-- Monospace: 3
getgc
Returns a list of non-dead garbage-collectable values
Description
getgc returns a list of non-dead garbage-collectable values. These include functions, userdatas, and optionally tables.
Syntax
declare getgc:
((includeTables: true) -> { { AnyTable } | AnyFunction | userdata }) &
((includeTables: false?) -> { AnyFunction })
Parameters
| Parameter | Description |
|---|---|
| includeTables? | If true, also includes tables in the returned list. Defaults to false. |
Examples
Function-only GC scan
local dummy_table = {}
local function dummy_function() end
task.wait(0.05) -- Step a bit
for _, value in pairs(getgc()) do
if value == dummy_function then
print(`Found function: {dummy_function}`)
elseif value == dummy_table then
print(`Found table?: {dummy_table}`) -- This shouldn't print
end
end
Full GC scan including tables
local dummy_table = {}
local function dummy_function() end
task.wait(0.05) -- Step a bit
for _, value in pairs(getgc(true)) do
if value == dummy_function then
print(`Found function: {dummy_function}`) -- Should print
elseif value == dummy_table then
print(`Found table: {dummy_table}`) -- Should also print
end
end
getgenv
Returns the executor's global environment table
Description
getgenv returns the executor's global environment table, which is shared across all executor-made threads. This environment is writable and persistent during the session, making it useful for sharing state or functions across different scripts.
Syntax
function getgenv(): { any }
Parameters
This function takes no parameters.
Example
getgenv should not be affected by the global table/getfenv
getgenv().dummy_val = "value"
getfenv().dummy_val_2 = 1
print(dummy_val, getgenv().dummy_val_2) -- Output: value, 1
getgenv().dummy_val = "value2"
dummy_val = nil
print(dummy_val) -- Output: value2
getreg
Returns the Luau registry table
Description
getreg returns the Luau registry table. The registry is a special table which is used internally to store references like threads, functions, and data shared between C and Luau (userdata).
Syntax
function getreg(): { [any]: any }
Parameters
This function takes no parameters.
Example
Closing a thread via getreg
local loop_thread = task.spawn(function()
while task.wait(1) do
print("I am still running...")
end
end)
task.wait(0.2) -- Let the loop run for a bit
for _, value in pairs(getreg()) do
if value ~= loop_thread then continue end
print(`Found loop thread: {loop_thread}`) -- Should print
coroutine.close(loop_thread) -- Should close the thread
break
end
getrenv
Returns the Roblox global environment
Description
getrenv returns the Roblox global environment, which is used by the entire game. Changes to this environment will affect your executor environment as well.
Syntax
function getrenv(): { any }
Parameters
This function takes no parameters.
Example
Overriding Roblox environment functions
getrenv().warn = "Hello!"
print(type(warn)) -- Output: string
getrenv().game = nil
print(game) -- Output: nil
filtergc - Function Filter Options
Function filters for filtergc
Description
Function filters let you refine what types of Luau functions should be returned when using filtergc with "function" as the filter type. Each key in the filter table specifies a criterion that must be matched by the function for it to be returned.
Available Options
| Key | Type | Description | Default |
|---|---|---|---|
| Name | string? | If provided, filters out functions which don't match this name. | nil |
| IgnoreExecutor | boolean? | If true, filters out functions that were created inside the executor. | true |
| Hash | string? | Filters by the hash of the function. See getfunctionhash. | nil |
| Constants | { any }? | Also includes functions that contain the matching constants in the provided list. | nil |
| Upvalues | { any }? | Also includes functions that contain the matching upvalues in the provided list. | nil |
Examples
Using Name (returns a table by default)
local function dummy_function() end
local retrieved = filtergc("function", {
Name = "dummy_function",
IgnoreExecutor = false
})
print(typeof(retrieved)) -- Output: table
print(retrieved[1] == dummy_function) -- Output: true
Using Name with returnOne = true
local function dummy_function() end
local retrieved = filtergc("function", {
Name = "dummy_function",
IgnoreExecutor = false
}, true)
print(typeof(retrieved)) -- Output: function
print(retrieved == dummy_function) -- Output: true
Type Signature
type FunctionFilterOptions = {
Name: string?,
IgnoreExecutor: boolean?,
Hash: string?,
Constants: { string }?,
Upvalues: { any }?
}
filtergc - Table Filter Options
Table filters for filtergc
Description
Table filters define what types of Luau tables should be returned when using filtergc with "table" as the filter type. Each key in the filter table specifies a condition the table must meet in order to be returned.
Available Options
| Key | Type | Description | Default |
|---|---|---|---|
| Keys | { any }? | If provided, also includes tables that contain all the specified keys. | nil |
| Values | { any }? | If provided, only includes tables that contain all the specified values. | nil |
| KeyValuePairs | { [any]: any }? | If provided, only includes tables that contain all key-value pairs in this table. | nil |
| Metatable | table? | If provided, only includes tables whose metatable matches the given one. | nil |
Examples
Matching by Keys
local dummy_table = { ["dummy_key"] = "" }
local retrieved = filtergc("table", {
Keys = { "dummy_key" },
}, true)
print(retrieved == dummy_table) -- Output: true
Matching by KeyValuePairs
local dummy_table = { ["dummy_key"] = "dummy_value" }
local retrieved = filtergc("table", {
KeyValuePairs = { ["dummy_key"] = "dummy_value" },
}, true)
print(retrieved == dummy_table) -- Output: true
Matching by Metatable
local dummy_table = setmetatable({}, { __index = getgenv() })
local retrieved = filtergc("table", {
Metatable = getmetatable(dummy_table)
}, true)
print(retrieved == dummy_table) -- Output: true
Type Signature
type TableFilterOptions = {
Keys: { [any]: any }?,
Values: { [any]: any }?,
KeyValuePairs: { [any]: any }?,
Metatable: { [any]: any }?,
}
filtergc
Fine-tuned garbage collector search for functions and tables
Description
filtergc allows you to retrieve specific garbage-collected values from Luau's memory, using fine-tuned filters.
This function is most often used to find game-defined functions or internal tables by matching constants, keys, metatables, and more. It behaves similarly to getgc, but offers simplicity, efficiency, and more control over what gets returned.
Type Signature
export type AnyFunction = (...any) -> (...any)
export type AnyTable = { [any]: any }
declare filtergc:
(( filterType: "function", filterOptions: FunctionFilterOptions, returnOne: true) -> AnyFunction? ) &
((( filterType: "function", filterOptions: FunctionFilterOptions, returnOne: false?) -> ( AnyFunction | { AnyFunction } ) )) &
(( filterType: "table", filterOptions: TableFilterOptions, returnOne: true) -> { AnyTable? } ) &
(( filterType: "table", filterOptions: TableFilterOptions, returnOne: false? ) -> { AnyTable })
Parameters
| Parameter | Description |
|---|---|
| filterType | The type of value to search for. |
| filterOptions | A set of rules used to match functions or tables. See below. |
| returnOne? | If true, returns the first match, instead of a table of matches. |
Filter option types
- Each filter type has its own valid fields:
- See Function Filters for matching functions by name, constants, upvalues, and more.
- See Table Filters for matching tables by keys, values, metatables, and more.
Notes
- Garbage-collected values must still be referenced by a live thread to be found.
- Some filters (like
ConstantsorHash) do not apply to C functions.
Examples
Function Filters
-- Using Name (returns a table by default)
local function dummy_function() end
local retrieved = filtergc("function", {
Name = "dummy_function",
IgnoreExecutor = false
})
print(typeof(retrieved)) -- Output: table
print(retrieved[1] == dummy_function) -- Output: true
-- Using Name with returnOne = true
local function dummy_function() end
local retrieved = filtergc("function", {
Name = "dummy_function",
IgnoreExecutor = false
}, true)
print(typeof(retrieved)) -- Output: function
print(retrieved == dummy_function) -- Output: true
-- Using Hash
local function dummy_function()
return "Hello"
end
local dummy_function_hash = getfunctionhash(dummy_function)
local retrieved = filtergc("function", {
Hash = dummy_function_hash,
IgnoreExecutor = false
}, true)
print(getfunctionhash(retrieved) == dummy_function_hash) -- Output: true
print(retrieved == dummy_function) -- Output: true
-- Matching by Constants and Upvalues
local upvalue = 5
local function dummy_function()
upvalue += 1
print(game.Players.LocalPlayer)
end
local retrieved = filtergc("function", {
Constants = { "print", "game", "Players", "LocalPlayer", 1 },
Upvalues = { 5 },
IgnoreExecutor = false
}, true)
print(retrieved == dummy_function) -- Output: trueType signature for FunctionFilterOptions
type FunctionFilterOptions = {
Name: string?,
IgnoreExecutor: boolean?,
Hash: string?,
Constants: { string }?,
Upvalues: { any }?
}Table Filters
-- Matching by Keys
local dummy_table = { ["dummy_key"] = "" }
local retrieved = filtergc("table", {
Keys = { "dummy_key" },
}, true)
print(retrieved == dummy_table) -- Output: true
-- Matching by KeyValuePairs
local dummy_table = { ["dummy_key"] = "dummy_value" }
local retrieved = filtergc("table", {
KeyValuePairs = { ["dummy_key"] = "dummy_value" },
}, true)
print(retrieved == dummy_table) -- Output: true
-- Matching by Metatable
local dummy_table = setmetatable({}, { __index = getgenv() })
local retrieved = filtergc("table", {
Metatable = getmetatable(dummy_table)
}, true)
print(retrieved == dummy_table) -- Output: trueType signature for TableFilterOptions
type TableFilterOptions = {
Keys: { [any]: any }?,
Values: { [any]: any }?,
KeyValuePairs: { [any]: any }?,
Metatable: { [any]: any }?,
}