├── .gitattributes ├── .github └── workflows │ └── publish.yml ├── .gitignore ├── .markdownlint.json ├── .vscode ├── extensions.json └── settings.json ├── CONTRIBUTING.md ├── README.md ├── TODO.md ├── designAssets └── r.sunc.su.psd ├── docs ├── About │ ├── assets │ │ └── test-results │ │ │ ├── RubisTestResult.png │ │ │ └── r.sunc.su.png │ ├── contributing.md │ ├── test-results.md │ └── what-is-sunc.md ├── CNAME ├── Closures │ ├── README.md │ ├── checkcaller.md │ ├── clonefunction.md │ ├── getfunctionhash.md │ ├── hookfunction.md │ ├── hookmetamethod.md │ ├── iscclosure.md │ ├── isexecutorclosure.md │ ├── islclosure.md │ ├── newcclosure.md │ └── restorefunction.md ├── Cryptography │ ├── README.md │ ├── base64decode.md │ └── base64encode.md ├── Debug │ ├── README.md │ ├── getconstant.md │ ├── getconstants.md │ ├── getproto.md │ ├── getprotos.md │ ├── getstack.md │ ├── getupvalue.md │ ├── getupvalues.md │ ├── setconstant.md │ ├── setstack.md │ └── setupvalue.md ├── Drawing │ ├── README.md │ ├── cleardrawcache.md │ ├── getrenderproperty.md │ ├── isrenderobj.md │ └── setrenderproperty.md ├── Environment │ ├── README.md │ ├── filtergc │ │ ├── FunctionFilterOptions.md │ │ ├── README.md │ │ └── TableFilterOptions.md │ ├── getgc.md │ ├── getgenv.md │ ├── getreg.md │ └── getrenv.md ├── Filesystem │ ├── README.md │ ├── appendfile.md │ ├── delfile.md │ ├── delfolder.md │ ├── getcustomasset.md │ ├── isfile.md │ ├── isfolder.md │ ├── listfiles.md │ ├── loadfile.md │ ├── makefolder.md │ ├── readfile.md │ └── writefile.md ├── Instances │ ├── README.md │ ├── cloneref.md │ ├── compareinstances.md │ ├── fireclickdetector.md │ ├── fireproximityprompt.md │ ├── firetouchinterest.md │ ├── getcallbackvalue.md │ ├── gethui.md │ ├── getinstances.md │ └── getnilinstances.md ├── Metatable │ ├── README.md │ ├── getrawmetatable.md │ ├── isreadonly.md │ ├── setrawmetatable.md │ └── setreadonly.md ├── Miscellaneous │ ├── README.md │ ├── identifyexecutor.md │ └── request.md ├── README.md ├── Reflection │ ├── README.md │ ├── gethiddenproperty.md │ ├── getthreadidentity.md │ ├── sethiddenproperty.md │ ├── setscriptable.md │ └── setthreadidentity.md ├── Scripts │ ├── README.md │ ├── getcallingscript.md │ ├── getloadedmodules.md │ ├── getrunningscripts.md │ ├── getscriptbytecode.md │ ├── getscriptclosure.md │ ├── getscripthash.md │ ├── getscripts.md │ ├── getsenv.md │ └── loadstring.md ├── Signals │ ├── Connection.md │ ├── README.md │ ├── firesignal.md │ ├── getconnections.md │ └── replicatesignal.md ├── WebSocket │ └── README.md ├── assets │ ├── dancing-alienchik.webp │ ├── sUNC_FlatSquare.png │ └── sUNC_Full.png └── stylesheets │ ├── extra.css │ └── extra.js ├── mkdocs.yml ├── overrides └── partials │ ├── copyright.html │ └── integrations │ └── analytics │ └── custom.html ├── parser ├── docExtractor.lua ├── efficientArray.lua ├── exclusions.lua ├── indexExtractor.lua ├── install.sh ├── main.lua └── package.lua └── requirements.txt /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalisation 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish to docs.sunc.su 2 | on: 3 | push: 4 | branches: 5 | - master 6 | - main 7 | workflow_dispatch: 8 | permissions: 9 | contents: write 10 | jobs: 11 | deploy: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | - name: Configure Git Credentials 16 | run: | 17 | git config user.name github-actions[bot] 18 | git config user.email 41898282+github-actions[bot]@users.noreply.github.com 19 | - uses: actions/setup-python@v5 20 | with: 21 | python-version: 3.x 22 | name: Set Cache ID 23 | - run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV 24 | - uses: actions/cache@v4 25 | with: 26 | key: mkdocs-material-${{ env.cache_id }} 27 | path: .cache 28 | restore-keys: | 29 | mkdocs-material- 30 | - name: Build bot and viewer JSON metadata 31 | run: | 32 | cd parser 33 | 34 | sudo chmod +x ./install.sh 35 | ./install.sh 36 | 37 | luvit main.lua 38 | 39 | cd ../ 40 | 41 | rm -rf parser 42 | - run: pip install mkdocs-material 43 | - run: pip install -r requirements.txt 44 | - run: mkdocs gh-deploy --force 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Python venv exclusion for the internal documentation platform 2 | .venv 3 | venv 4 | 5 | **.bat 6 | 7 | # Luvit dependencies 8 | parser/deps 9 | docs/built-info/* 10 | 11 | # macOS hidden files 12 | **._* 13 | **.DS_* -------------------------------------------------------------------------------- /.markdownlint.json: -------------------------------------------------------------------------------- 1 | { 2 | "MD046": false, 3 | "MD013": false, 4 | "MD059": false, 5 | "MD033": false 6 | } 7 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "redhat.vscode-yaml", 4 | "DavidAnson.vscode-markdownlint", 5 | "JohnnyMorganz.luau-lsp" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "yaml.schemas": { 3 | "https://squidfunk.github.io/mkdocs-material/schema.json": "mkdocs.yml" 4 | }, 5 | "yaml.customTags": [ 6 | "!ENV scalar", 7 | "!ENV sequence", 8 | "!relative scalar", 9 | "tag:yaml.org,2002:python/name:material.extensions.emoji.to_svg", 10 | "tag:yaml.org,2002:python/name:material.extensions.emoji.twemoji", 11 | "tag:yaml.org,2002:python/name:pymdownx.superfences.fence_code_format", 12 | "tag:yaml.org,2002:python/object/apply:pymdownx.slugs.slugify mapping" 13 | ], 14 | 15 | "[markdown]": { 16 | "editor.formatOnSave": true, 17 | "editor.formatOnPaste": true, 18 | "editor.defaultFormatter": "DavidAnson.vscode-markdownlint" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # 📝 Contribution Guidelines 2 | 3 | In order to make the sUNC documentation more organised and better for readers, we recommend you follow the contribution guidelines. 4 | 5 | Please view the contribution guidelines [here](./docs/About/contributing.md) or via the [sUNC Documentation website](https://docs.sunc.su/About/contributing/). 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # [sUNC Documentation](https://docs.sunc.su) 2 | 3 | [![Publish to docs.sunc.su](https://github.com/sUNC-Utilities/docs.sunc.su/actions/workflows/publish.yml/badge.svg)](https://github.com/sUNC-Utilities/docs.sunc.su/actions/workflows/publish.yml) 4 | 5 | Welcome to the repository for sUNC's online documentation. 6 | Documentation is hosted at and it aims to replace the legacy way of simply documenting via markdown in the [old documentation repository](https://github.com/sUNC-Utilities/Global-Functions-Documentation). 7 | 8 | ## What is sUNC? 9 | 10 | Please view the README about sUNC at [docs/About/what-is-sunc.md](./docs/About/what-is-sunc.md) or look at the entire ["About" directory](./docs/About/). 11 | 12 | ## Contributing 13 | 14 | Please make a **PULL REQUEST** with your changes so that they can be reviewed. 15 | 16 | In general, commits and pushes (or any interaction with the main branch) is disabled for all users, including administrators. This aims to reduce commit conflicts - please use pull requests instead so that changes can be discussed. 17 | 18 |
19 | Internally working on the documentation system 20 | 21 | If you are internally working on the actual documentation **platform** itself, please use a Python Virtual Environment (venv). 22 | 23 | ```sh 24 | python3 -m venv venv 25 | ``` 26 | 27 | After which you must install the requirements of the project using `pip`. 28 | 29 | ```sh 30 | python3 -m pip install -r requirements.txt 31 | ``` 32 | 33 | Once all dependencies are installed, you may see a preview of your work using `mkdocs serve`. 34 | 35 |
36 | -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | # To-Do List 2 | 3 | Manually going through every bit of the old documentation (and the latest commits whilst doing this simultaneously) has taught me (Richy) a lot about sUNC and its functions. However it has also exposed many small mistakes/flaws in the original documentation which I referenced to make this entire repository. 4 | 5 | ## To-Do List for me (Richy) 6 | 7 | - cross-reference with old documentation to ensure we arent missing any functions in the new documentation 8 | - Specify in documentation standard that "an" and "a" should be based off of how a word SOUNDS in front of it, and not a strict vowel check. 9 | - Write a linter for this documentation: 10 | - Warn when there is a `code snippet` that doesnt have syntax highlighting applied to it 11 | - It should not error when it encounters just one error immediately. errors/warnings for linting must be appended to an array and then printed last. os.exit code shoudl be error if strict errors appended but no os.exit error code if there are only warnings. 12 | - Must check when "Lua" is used individually instead of "Luau". also detect "Lua's", etc. because Luau is used, not Lua. 13 | - Must check when the long hyphens are used or the non-standard quotes are used (the fancy ones instead of the programmer ones) 14 | - add emoji checking, allowing them only on level 3 headings (`###`). nowhere else. 15 | - In the documentation standard, mention how contractions like "isn't" and "can't" shouldnt be use. e.g. use "it is" instead of "it's" (Also check for contractions in review 2) 16 | - ensure there is a luau type definition for the following things: 17 | - Drawing object 18 | - filtergc function filter options ✅ 19 | - giltergc table filter options ✅ 20 | - Update documentation with changed for hookmetamethod, named "pixe***** yap" in old docs commit 21 | - maybe write a templates directory inside of contribution which contains the annotations like `!!! info` etc, empty parameter tables, code snippets with syntax highlighting, etc. essentially a cheat sheat. 22 | 23 | - contribution guidelines must mention that markdown MUST be formatted/linted using david anson's markdownlint plugin in vscode. too bad jetbrains users 24 | - search for code snippets and ensure they have relevant, appropriate links 25 | - search for "TODO" messages to fix todo items 26 | -------------------------------------------------------------------------------- /designAssets/r.sunc.su.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sUNC-Utilities/docs.sunc.su/789f3e7dff1943484e533b70419fddc6ad1ad050/designAssets/r.sunc.su.psd -------------------------------------------------------------------------------- /docs/About/assets/test-results/RubisTestResult.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sUNC-Utilities/docs.sunc.su/789f3e7dff1943484e533b70419fddc6ad1ad050/docs/About/assets/test-results/RubisTestResult.png -------------------------------------------------------------------------------- /docs/About/assets/test-results/r.sunc.su.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sUNC-Utilities/docs.sunc.su/789f3e7dff1943484e533b70419fddc6ad1ad050/docs/About/assets/test-results/r.sunc.su.png -------------------------------------------------------------------------------- /docs/About/contributing.md: -------------------------------------------------------------------------------- 1 | # How to contribute 2 | 3 | Welcome to the sUNC documentation project! We worked tirelessly to standardise and make the documentation beautiful and readable for everyone. 4 | 5 | This guide outlines the official standards for contributing to the sUNC documentation, including how libraries and functions should be structured and written. 6 | 7 | Consistency makes our documentation readable, searchable, and enjoyable to explore. 8 | 9 | --- 10 | 11 | ## Documenting entire libraries 12 | 13 | Each library **must** be placed in a folder named after the library itself. Inside this folder, you must include a `README.md` file, which serves as the **index page** for that library, in both this documentation website and also when browsing the documentation repository on GitHub. 14 | 15 | ### Index page requirements 16 | 17 | - Introduce the purpose of the library 18 | - Summarise what you **can** and **cannot** do with it 19 | 20 | Index pages *do not* need to follow this strict format, but they should ***aim*** for clarity and helpfulness. 21 | 22 | --- 23 | 24 | ## General documentation style 25 | 26 | All documentation pages (including function pages and index pages) **must**: 27 | 28 | - Use inline links to relevant [Wikipedia](https://wikipedia.org), [Roblox Luau](https://create.roblox.com/docs), or other sUNC pages with referencing key terms. 29 | - Use the correct inline link formats, e.g.: 30 | 31 | ```md 32 | [`#!luau task.defer`](https://create.roblox.com/docs/reference/engine/libraries/task#defer) 33 | ``` 34 | 35 | As you can see, the example above uses a code snippet with `luau` syntax highlighting enabled, whilst also being a hyperlink to the Roblox API documentation for [`#!luau task.defer`](https://create.roblox.com/docs/reference/engine/libraries/task#defer). 36 | 37 | --- 38 | 39 | ## Function documentation 40 | 41 | Each function must have **its own file**, named after the function (e.g. `newcclosure.md`). 42 | 43 | ### Title Format 44 | 45 | The title of the page must be written as: 46 | 47 | ```md 48 | # `function_name` 49 | ``` 50 | 51 | !!! failure "Important" 52 | 53 | Do not include emojis in function **titles**. 54 | 55 | ### Notices 56 | 57 | Place all important `!!!` callouts (warnings, errors, info) **immediately under the title**. These should include anything the user must know before using the function. 58 | 59 | --- 60 | 61 | ### Description 62 | 63 | Provide a description of the function directly after any notices. 64 | 65 | When referencing the function name, **always** use the code snippet format: 66 | 67 | ```md 68 | `#!luau function_name` allows you to do this and that. 69 | ``` 70 | 71 | --- 72 | 73 | ### Type definition 74 | 75 | !!! info "Type definitions are important!" 76 | 77 | You **must** always include a Luau-style type definition when documenting a function. 78 | 79 | Include the Luau type definition **at the bottom of the first section**, with Luau syntax highlighting but **no *individual line highlighting* or line numbers**: 80 | 81 | ```luau 82 | function newcclosure(functionToWrap: (A...) -> R...): (A...) -> R... 83 | ``` 84 | 85 | Make sure it precedes the parameters table. 86 | 87 | --- 88 | 89 | ### Parameters 90 | 91 | The parameters must always be neatly described in a function, like so: 92 | 93 | ```md 94 | ## Parameters 95 | 96 | | Parameter | Description | 97 | |-------------------------|-------------------------------------| 98 | | `#!luau parameter_name` | Short description of the parameter. | 99 | ``` 100 | 101 | Use [**snake_case**](https://en.wikipedia.org/wiki/Snake_case) for **every variable**, and [**camelCase**](https://en.wikipedia.org/wiki/Camel_case) for **parameters** to easily distinguish between the two. 102 | 103 | There should be **no horizontal rule** (`---`) between the *type definition* and the *parameters* section. 104 | 105 | --- 106 | 107 | ### Providing users with examples 108 | 109 | Every function page **must** include at least one example. 110 | 111 | !!! info "Use 'Example' or 'Examples' based on how many examples you have" 112 | 113 | To make the documentation experience more logical and also grammatically correct, please do the following: 114 | - Make the heading `#!md ## Example` if there is only one example. 115 | - Make the heading `#!md ## Examples` if there is more than one example. 116 | Each example should have its own subheading, e.g. `#!md ### Example 1`, `#!md ### Example 2`. 117 | 118 | Each example should use the following format: 119 | 120 | ```md 121 | ## Example 122 | 123 | ` ` `luau title="Short but descriptive title for your code" linenums="1" 124 | -- an example is here 125 | print("Hello world!") 126 | print("This is some example code") 127 | ` ` ` 128 | 129 | ``` 130 | 131 | - Examples must use `luau` syntax highlighting. 132 | - Line numbers **must** be enabled using `linenums="1"`. 133 | - Each example **must** have a `title` describing in short what the code does. 134 | -------------------------------------------------------------------------------- /docs/About/test-results.md: -------------------------------------------------------------------------------- 1 | # How do test results work? 2 | 3 | sUNC is known for its strict tests. Ever since it was made, it was built to expose falsified environments and spoofed globaly by testing for functionality - not just checking for their presence or shallow checking. 4 | 5 | --- 6 | 7 | ## Using the dedicated game 8 | 9 | As of **sUNC V2**, all tests must be conducted in the official sUNC testing game. This game may be found in our [Discord server](https://discord.gg/FNNfTUpFYv). 10 | 11 | We chose to do so, because by having a dedicated server, we're able to provide you with the new sUNC Rubis test results. This allows us to provide you with verified and reproducible results, instead of people sending meaningless screenshots of their console output. 12 | 13 | --- 14 | 15 | ## Viewing your test results 16 | 17 | Once your test is complete, sUNC will generate a short redirect link via `r.sunc.su` like this: 18 | 19 | ![An `r.sunc.su` redirect link generated](./assets/test-results/r.sunc.su.png) 20 | 21 | This generated link redirects to **Numelon Rubiš**: 22 | 23 | ![An sUNC Test Result being displayed with Numelon Rubiš](./assets/test-results/RubisTestResult.png) 24 | 25 | The results page offers a clean, visually appealing UI that lays out which functions passed and which failed, why they failed, and cryptographic guarantees of authenticity. 26 | 27 | --- 28 | 29 | ## Verified integrity 30 | 31 | Rubiš doesn't just store your sUNC test results, it also **verifies** them. 32 | 33 | - Every result is **cryptographically signed** by the sUNC test game servers. 34 | - Any tampered or faked data is **flagged as unverified**. 35 | 36 | Even if someone tries to replicate the link or manually upload fake data and use it with the results viewer (since [Rubiš is also a public paste service](https://rubis.app) which is usable by anyone), it will not work. 37 | -------------------------------------------------------------------------------- /docs/About/what-is-sunc.md: -------------------------------------------------------------------------------- 1 | # sUNC introduction 2 | 3 | ## What is "sUNC"? 4 | 5 | **sUNC** stands for **senS' Unified Naming Convention**. It is a tool designed to check if an executor can properly run essential global functions, following the existing [Unified Naming Convention](https://github.com/unified-naming-convention/NamingStandard/tree/main). 6 | 7 | Unlike the original UNC (which is now outdated and prone to spoofing), sUNC ensures that functions actually work as intended, by testing them as if they were to be used in a real scenario. 8 | However, we are not in any way calling UNC "bad". We are simply stating that people should not be using UNC to deeply test their environment, as it was never intended to do so. 9 | 10 | ## How would I know what fails? 11 | 12 | We are not gatekeeping function tests, despite the script being obfuscated. 13 | You are welcome to ask the owner (@sens6222 on Discord) **if you are struggling with passing certain tests**. We keep it this way for now, due to executors already faking their environments to suit the original UNC. 14 | 15 | Note that it's also possible to see the detailed reason of a function's failure at the top of the `Developer Console` in game, or on the dedicated sUNC Rubiš site. 16 | 17 | ## Will sUNC be discontinued? 18 | 19 | Not in the near future, we hope. However, if sUNC were to be discontinued, we will open source the project after 1-2 months. 20 | 21 | ----- 22 | 23 | ## Credits 24 | 25 | - [Original UNC Documentation](https://github.com/unified-naming-convention/NamingStandard/tree/main) 26 | -------------------------------------------------------------------------------- /docs/CNAME: -------------------------------------------------------------------------------- 1 | docs.sunc.su -------------------------------------------------------------------------------- /docs/Closures/README.md: -------------------------------------------------------------------------------- 1 | # Closures 2 | 3 | The **Closures** library enables the inspection, modification and creation of Luau closures with precise control. 4 | 5 | It is one of the most powerful tools available, exposing internals in a way that Luau does not natively support out of the box. 6 | 7 | This library is incredibly useful for hooking functions to modify game logic to your own advantage, and any other creative uses you can think of. 8 | 9 | --- 10 | 11 | ## What is a closure? 12 | 13 | The term [*"closure"*](https://en.wikipedia.org/wiki/Closure_(computer_programming)) comes from [functional programming](https://en.wikipedia.org/wiki/Functional_programming) and refers to a function ***plus*** the environment it carries (its **upvalues**). 14 | 15 | In Luau, **every function is implemented as a closure** implicitly, even if it doesn't capture anything. 16 | 17 | --- 18 | 19 | ## What can you do? 20 | 21 | With the `Closures` library, you can: 22 | 23 | - **Hook** existing functions or metamethods with [`#!luau hookfunction`](./hookfunction.md) and [`#!luau hookmetamethod`](./hookmetamethod.md) 24 | - **Check** whether the current execution is from your script using [`#!luau checkcaller`](./checkcaller.md) for **hooking** 25 | - **Clone** a function while keeping the same behavior to avoid tampering, with [`#!luau clonefunction`](./clonefunction.md) 26 | - **Wrap** a Luau closure into a C closure using [`#!luau newcclosure`](./newcclosure.md) 27 | - **Check** a function's closure type with [`#!luau iscclosure`](./iscclosure.md), [`#!luau islclosure`](./islclosure.md) or [`#!luau isexecutorclosure`](./isexecutorclosure.md). 28 | - **Hash** a function with [`#!luau getfunctionhash`](./getfunctionhash.md) 29 | 30 | --- 31 | 32 | ## What can't you do? 33 | 34 | Although closure capabilities are powerful, there are natural boundaries: 35 | 36 | - You cannot inspect **true C closures' internals** - they are not Luau-defined, compiled, and therefore opaque by design. 37 | - Attempting to implement [`#!luau newcclosure`](./newcclosure.md) in Luau (e.g. via [`#!luau coroutine.wrap`](https://create.roblox.com/docs/reference/engine/libraries/coroutine#wrap)) **will fail sUNC verification**. 38 | -------------------------------------------------------------------------------- /docs/Closures/checkcaller.md: -------------------------------------------------------------------------------- 1 | # `checkcaller` 2 | 3 | `#!luau checkcaller` returns a boolean indicating whether the **current function was invoked from the executor's own thread**. This is useful for differentiating between your own calls and those made by the game. 4 | 5 | It is often used in [`#!luau hookfunction`](../Closures/hookfunction.md) and/or [`#!luau hookmetamethod`](../Closures/hookmetamethod.md). 6 | 7 | ```luau 8 | function checkcaller(): boolean 9 | ``` 10 | 11 | ## Parameters 12 | 13 | | Parameter | Description | 14 | |-----------|--------------------| 15 | | *(none)* | This function takes no parameters. | 16 | 17 | --- 18 | 19 | ## Example 20 | 21 | ```luau title="Identifying the source of a __namecall" linenums="1" 22 | local from_caller 23 | 24 | local original; original = hookmetamethod(game, "__namecall", function(...) 25 | if not from_caller then 26 | from_caller = checkcaller() 27 | end 28 | 29 | return original(...) 30 | end) 31 | 32 | task.wait(0.1) -- Step a bit 33 | hookmetamethod(game, "__namecall", original) 34 | 35 | print(from_caller) -- Output: false 36 | print(checkcaller()) -- Output: true (current thread) 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/Closures/clonefunction.md: -------------------------------------------------------------------------------- 1 | # `clonefunction` 2 | 3 | !!! info "Notes on `#!luau clonefunction`" 4 | 5 | The new (cloned) function returned by `#!luau clonefunction` should have the same environment as the original function. 6 | 7 | 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**. 8 | 9 | `#!luau clonefunction` creates and returns a new function that has the exact same behaviour as the passed function. 10 | 11 | ```luau 12 | function clonefunction(functionToClone: (A...) -> R...): (A...) -> R... 13 | ``` 14 | 15 | ## Parameters 16 | 17 | | Parameter | Description | 18 | |-----------|-------------| 19 | | `#!luau functionToClone` | The function to clone. | 20 | 21 | --- 22 | 23 | ## Example 24 | 25 | ```luau title="Cloning functions with clonefunction" linenums="1" 26 | local function dummy_function() 27 | print("Hello") 28 | end 29 | 30 | local cloned_function = clonefunction(dummy_function) 31 | 32 | print(debug.info(cloned_function, "l")) -- Output: 1 33 | print(debug.info(cloned_function, "n")) -- Output: dummy_function 34 | print(cloned_function == dummy_function) -- Output: false 35 | print(getfenv(cloned_function) == getfenv(dummy_function)) -- Output: true 36 | 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/Closures/getfunctionhash.md: -------------------------------------------------------------------------------- 1 | # `getfunctionhash` 2 | 3 | `#!luau getfunctionhash` returns the ***hex-represented*** [SHA384 hash](https://en.wikipedia.org/wiki/SHA-2) of a provided function's instructions (code) and constants. 4 | 5 | !!! warning "C closures are not supported" 6 | 7 | This function will throw an error if called on a C closure, such as [`#!luau print`](https://create.roblox.com/docs/reference/engine/globals/LuaGlobals#print), since C closures have no reliable information to hash. The error should be something along the lines of `lua function expected` 8 | 9 | !!! info "Notes on `#!luau getfunctionhash`" 10 | 11 | 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. 12 | 13 | We suggest following [this implementation](https://rubis.app/view?scrap=mwDweOS6zirsPJtc&type=cpp) 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. 14 | 15 | Full credits go to Dottik and Ragnar regarding the source provided above. 16 | 17 | ```luau 18 | function getfunctionhash(functionToHash: (...any) -> (...any)): string 19 | ``` 20 | 21 | ## Parameters 22 | 23 | | Parameter | Description | 24 | |-----------|-------------| 25 | | `#!luau functionToHash` | The function to retrieve the hash of. | 26 | 27 | --- 28 | 29 | ## Example 30 | 31 | ```luau title="Checking the SHA384 hash of functions with getfunctionhash" linenums="1" 32 | local function is_sha384_hex(hash) 33 | return #hash == 96 and hash:match("^[0-9a-fA-F]+$") ~= nil 34 | end 35 | 36 | local dummy_function_0 = function() end 37 | local dummy_function_1 = function(...) end 38 | local dummy_function_2 = function() end 39 | local dummy_function_3 = function() return "Constant" end 40 | local dummy_function_4 = function() return "Constant2" end 41 | 42 | print(is_sha384_hex(getfunctionhash(dummy_function_0))) -- Output: true 43 | print(getfunctionhash(dummy_function_0) == getfunctionhash(dummy_function_1)) -- Output: false 44 | print(getfunctionhash(dummy_function_0) == getfunctionhash(dummy_function_2)) -- Output: true 45 | print(getfunctionhash(dummy_function_3) == getfunctionhash(dummy_function_4)) -- Output: false 46 | ``` 47 | -------------------------------------------------------------------------------- /docs/Closures/hookfunction.md: -------------------------------------------------------------------------------- 1 | # `hookfunction` 2 | 3 | !!! info "Notes on `#!luau hookfunction`" 4 | 5 | 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 `#!luau newlclosure` or [`#!luau newcclosure`](./newcclosure.md) to wrap the `#!luau hook` 6 | 7 | All possible hooking closure pairs should be supported throughout L, NC, C (where NC = [`#!luau newcclosure`](./newcclosure.md)) 8 | 9 | `#!luau hookfunction` allows you to hook a function with another wanted function, returning the original unhooked function. 10 | 11 | ```luau 12 | function hookfunction(functionToHook: (A1...) -> R1..., hook: (A2...) -> R2...): (A1...) -> R1... 13 | ``` 14 | 15 | ## Parameters 16 | 17 | | Parameter | Description | 18 | |-----------|-------------| 19 | | `#!luau functionToHook` | The function that will be hooked | 20 | | `#!luau hook` | The function that will be used as a hook | 21 | 22 | --- 23 | 24 | ## Example 25 | 26 | ```luau title="Hooking functions with hookfunction" linenums="1" 27 | local function dummy_func() 28 | print("I am not hooked!") 29 | end 30 | 31 | local function dummy_hook() 32 | print("I am hooked!") 33 | end 34 | 35 | dummy_func() -- Output: I am not hooked! 36 | 37 | local old_func = hookfunction(dummy_func, dummy_hook) 38 | 39 | dummy_func() -- Output: I am hooked! 40 | old_func() -- Output: I am not hooked! 41 | ``` 42 | -------------------------------------------------------------------------------- /docs/Closures/hookmetamethod.md: -------------------------------------------------------------------------------- 1 | # `hookmetamethod` 2 | 3 | !!! info "Notes on `#!luau hookmetamethod`" 4 | 5 | `#!luau hookmetamethod` can be safely implemented from within Luau, **as long as [`#!luau hookfunction`](./hookfunction.md) is already properly implemented in C++**. 6 | 7 | `#!luau hookmetamethod` takes any Luau object that can have a metatable, and attempts to hook the specified metamethod of the object. Internally, it essentially uses [`#!luau hookfunction`](./hookfunction.md) to hook specific metamethods. 8 | 9 | ```luau 10 | function hookmetamethod(object: { any } | userdata, metamethodName: string, hook: (...any) -> (...any)): (...any) -> (...any) 11 | ``` 12 | 13 | ## Parameters 14 | 15 | | Parameter | Description | 16 | |-----------|-------------| 17 | | `#!luau object` | The object which has a metatable. | 18 | | `#!luau metamethodName` | The name of the metamethod to hook. | 19 | | `#!luau hook` | The function that will be used as a hook. | 20 | 21 | --- 22 | 23 | ## Example 24 | 25 | ```luau title="Easily hooking metamethods with hookmetamethod" linenums="1" 26 | local original; original = hookmetamethod(game, "__index", function(...) 27 | local key = select(2, ...) 28 | print(key) 29 | return original(...) 30 | end) 31 | 32 | local _ = game.PlaceId -- Output: "PlaceId" 33 | 34 | hookmetamethod(game, "__index", original) -- Restores game's __index 35 | ``` 36 | -------------------------------------------------------------------------------- /docs/Closures/iscclosure.md: -------------------------------------------------------------------------------- 1 | # `iscclosure` 2 | 3 | `#!luau iscclosure` checks whether a given function is a C closure or not. 4 | 5 | ```luau 6 | function iscclosure(func: (...any) -> (...any)): boolean 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |-----------|-------------| 13 | | `#!luau func` | The function to check. | 14 | 15 | --- 16 | 17 | ## Example 18 | 19 | ```luau title="Checking whether functions are C closures with iscclosure" linenums="1" 20 | local function dummy_lua_function() 21 | print("This is an executor Luau closure") 22 | end 23 | 24 | local dummy_cfunction = newcclosure(function() 25 | print("This is an Executor C Closure") 26 | end) 27 | 28 | local dummy_standard_function = print 29 | local dummy_global_cfunction = getgc 30 | 31 | print(iscclosure(dummy_cfunction)) -- Output: true 32 | print(iscclosure(dummy_global_cfunction)) -- Output: true 33 | print(iscclosure(dummy_standard_function)) -- Output: true 34 | print(iscclosure(dummy_lua_function)) -- Output: false 35 | ``` 36 | -------------------------------------------------------------------------------- /docs/Closures/isexecutorclosure.md: -------------------------------------------------------------------------------- 1 | # `isexecutorclosure` 2 | 3 | `#!luau isexecutorclosure` checks whether a given function is a closure of the executor. This also includes closures retrieved using [`#!luau getscriptclosure`](../Scripts/getloadedmodules.md) or [`#!luau loadstring`](../Scripts/loadstring.md) 4 | 5 | ```luau 6 | function isexecutorclosure(func: (...any) -> (...any)): boolean 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |-----------|-------------| 13 | | `#!luau func` | The function to check. | 14 | 15 | --- 16 | 17 | ## Example 18 | 19 | ```luau title="Identifying executor closures with isexecutorclosure" linenums="1" 20 | local function dummy_lua_function() 21 | print("This is an executor Luau closure") 22 | end 23 | 24 | local dummy_cfunction = newcclosure(function() 25 | print("This is an executor C closure") 26 | end) 27 | 28 | local dummy_standard_cfunction = print 29 | local dummy_global_cfunction = getgc 30 | 31 | print(isexecutorclosure(dummy_lua_function)) -- Output: true 32 | print(isexecutorclosure(dummy_cfunction)) -- Output: true 33 | print(isexecutorclosure(dummy_global_cfunction)) -- Output: true 34 | print(isexecutorclosure(dummy_standard_cfunction)) -- Output: false 35 | ``` 36 | -------------------------------------------------------------------------------- /docs/Closures/islclosure.md: -------------------------------------------------------------------------------- 1 | # `islclosure` 2 | 3 | `#!luau islclosure` checks whether a given function is a Luau closure or not. 4 | 5 | ```luau 6 | function islclosure(func: (...any) -> (...any)): boolean 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |-----------|-------------| 13 | | `#!luau func` | The function to check. | 14 | 15 | --- 16 | 17 | ## Example 18 | 19 | ```luau title="Verifying Luau closures with islclosure" linenums="1" 20 | local function dummy_lua_function() 21 | print("This is an executor Luau closure") 22 | end 23 | 24 | local dummy_cfunction = newcclosure(function() 25 | print("This is an executor C closure") 26 | end) 27 | 28 | local dummy_standard_cfunction = print 29 | 30 | print(islclosure(dummy_lua_function)) -- Output: true 31 | print(islclosure(dummy_standard_cfunction)) -- Output: false 32 | print(islclosure(dummy_cfunction)) -- Output: false 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/Closures/newcclosure.md: -------------------------------------------------------------------------------- 1 | # `newcclosure` 2 | 3 | !!! failure "Do not implement this with coroutines" 4 | 5 | Many executors seem to be implementing this function using [`#!luau coroutine`](https://create.roblox.com/docs/reference/engine/libraries/coroutine) functions in Luau. Such functions **will not pass sUNC checks**. 6 | 7 | The wrapped function **must** be yieldable, meaning that the function should be able to call [`#!luau task.wait`](https://create.roblox.com/docs/reference/engine/libraries/task#wait), for example. 8 | 9 | !!! failure "Error spoofing" 10 | 11 | Luau and C errors are different. You must ensure that errors from functions wrapped with `#!luau newcclosure` appear as C closure errors! 12 | 13 | !!! info "Upvalues" 14 | 15 | The function returned by `#!luau newcclosure` must have no upvalues. 16 | 17 | `#!luau newcclosure` takes any Luau function and wraps it into a C closure. 18 | 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. 19 | 20 | ```luau 21 | function newcclosure(functionToWrap: (A...) -> R...): (A...) -> R... 22 | ``` 23 | 24 | ## Parameters 25 | 26 | | Parameter | Description | 27 | |-------------------------|---------------------------| 28 | | `#!luau functionToWrap` | A function to be wrapped. | 29 | 30 | --- 31 | 32 | ## Examples 33 | 34 | ### Example 1 35 | 36 | ```luau title="Basic C closure wrapping example with newcclosure" linenums="1" 37 | local dummy_function = function(...) 38 | return ... 39 | end 40 | 41 | print(iscclosure(dummy_function)) -- Output: false 42 | 43 | local wrapped_function = newcclosure(dummy_function) 44 | 45 | print(iscclosure(wrapped_function)) -- Output: true 46 | 47 | local function_results = wrapped_function("Hello") 48 | print(function_results) -- Output: Hello 49 | ``` 50 | 51 | ### Example 2 52 | 53 | This example illustrates how Luau functions wrapped as a C closure should also be yieldable, therefore also showcasing how coroutine implementations of `#!luau newcclosure` would not work. 54 | 55 | ```luau title="Yieldable C functions made with newcclosure" linenums="1" 56 | local dummy_yielding_function = newcclosure(function() 57 | print("Before") 58 | task.wait(1.5) 59 | print("After") 60 | end) 61 | 62 | dummy_yielding_function() 63 | -- Output: 64 | -- Before 65 | -- yield for 1.5 seconds 66 | -- After 67 | ``` 68 | -------------------------------------------------------------------------------- /docs/Closures/restorefunction.md: -------------------------------------------------------------------------------- 1 | # `restorefunction` 2 | 3 | !!! warning "This will throw an error if the requested function is not already hooked" 4 | 5 | `#!luau restorefunction` restores a hooked function back to its unhooked state. 6 | 7 | ```luau 8 | function restorefunction(functionToRestore: (...any) -> (...any)): () 9 | ``` 10 | 11 | ## Parameters 12 | 13 | | Parameter | Description | 14 | |------------------|----------------------------------------------------------| 15 | | `#!luau functionToRestore` | The hooked function that you want to restore | 16 | 17 | --- 18 | 19 | ## Examples 20 | 21 | ### Example 1 22 | 23 | ```luau title="Restoring a hooked function" linenums="1" 24 | function dummy_func() 25 | print("I am not hooked!") 26 | end 27 | 28 | hookfunction(dummy_func, function() 29 | print("I am hooked!") 30 | end) 31 | 32 | dummy_func() -- Output: I am hooked! 33 | restorefunction(dummy_func) 34 | dummy_func() -- Output: I am not hooked! 35 | 36 | ``` 37 | 38 | ### Example 2 39 | 40 | ```luau title="Restoring a unhooked function" linenums="1" 41 | function dummy_func() 42 | print("I am not hooked!") 43 | end 44 | 45 | dummy_func() -- Output: I am not hooked! 46 | restorefunction(dummy_func) -- Error: restorefunction: function is not hooked 47 | 48 | ``` 49 | -------------------------------------------------------------------------------- /docs/Cryptography/README.md: -------------------------------------------------------------------------------- 1 | # Cryptography 2 | 3 | !!! info 4 | 5 | sUNC does not check for every function contained within the original UNC. 6 | 7 | The **Cryptography** library provides a simple inferface for [Base64](https://en.wikipedia.org/wiki/Base64) encoding and decoding. 8 | 9 | - [`#!luau crypt.base64decode(data: string): string`](./base64decode.md) 10 | - [`#!luau crypt.base64encode(data: string): string`](./base64encode.md) 11 | 12 | These allow you to convert binary data into a readable string format, and vice versa. 13 | 14 | --- 15 | 16 | ## ⚠️ Note on *"Security"* 17 | 18 | Everyone should *hopefully* be aware that Base64 is **not encryption**. It is a reversible encoding method, and anyone can decode it. 19 | 20 | Do **not** use Base64 to store or transmit sensitive or secure data - it offers zero protection. 21 | 22 | The same caution applies to the other functions in this library. Though they may function correctly, they are prone to hooking, as they are global functions. If you're looking for security, it is recommended to use a custom/third-party library. 23 | -------------------------------------------------------------------------------- /docs/Cryptography/base64decode.md: -------------------------------------------------------------------------------- 1 | # `crypt.base64decode` 2 | 3 | `#!luau crypt.base64decode` decodes a [Base64-encoded](https://en.wikipedia.org/wiki/Base64) string back into its original form. 4 | 5 | ```luau 6 | function crypt.base64decode(data: string): string 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |-----------|-------------| 13 | | `#!luau data` | The Base64-encoded string to decode. | 14 | 15 | --- 16 | 17 | ## Example 18 | 19 | ```luau 20 | local bytecode = game:HttpGet("https://api.rubis.app/v2/scrap/zuxQZuM9Tnl5MRbo/raw") 21 | writefile("sound.mp3", crypt.base64decode(bytecode)) -- This file should be a valid and working MP3 file. 22 | ``` 23 | -------------------------------------------------------------------------------- /docs/Cryptography/base64encode.md: -------------------------------------------------------------------------------- 1 | # `crypt.base64encode` 2 | 3 | `#!luau crypt.base64encode` encodes a string with [Base64](https://en.wikipedia.org/wiki/Base64) encoding. 4 | 5 | ```luau 6 | function crypt.base64encode(data: string): string 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |-----------|-------------| 13 | | `#!luau data` | The string to encode. | 14 | 15 | --- 16 | 17 | ## Example 18 | 19 | ```luau 20 | print(crypt.base64encode("DummyString\0\2")) -- Output: RHVtbXlTdHJpbmcAAg== 21 | ``` 22 | -------------------------------------------------------------------------------- /docs/Debug/README.md: -------------------------------------------------------------------------------- 1 | # Debug 2 | 3 | The **Debug** library offers powerful tools for inspecting and modifying Luau functions at a bytecode level. 4 | 5 | It allows you to access constants, upvalues, stack frames, and internal structures of functions that would otherwise be hidden - making it especially useful for reverse engineering and hooking. 6 | 7 | --- 8 | 9 | ## What can you do? 10 | 11 | With the Debug library, you can: 12 | 13 | - **Inspect** constants with [`#!luau debug.getconstants`](./getconstants.md), [`#!luau debug.getconstant`](./getconstant.md) 14 | - **Modify** constants using [`#!luau debug.setconstant`](./setconstant.md) 15 | - **Access** upvalues using [`#!luau debug.getupvalues`](./getupvalues.md) and [`#!luau debug.getupvalue`](./getupvalue.md) 16 | - **Replace** upvalues with [`#!luau debug.setupvalue`](./setupvalue.md) 17 | - **Read** or **write** values from a stack frame, using [`#!luau debug.getstack`](./getstack.md) and [`#!luau debug.setstack`](./setstack.md) 18 | - **List** or **retrieve** function prototypes, using [`#!luau debug.getprotos`](./getprotos.md) and [`#!luau debug.getproto`](./getproto.md) 19 | 20 | --- 21 | 22 | ## What can't you do? 23 | 24 | - You cannot access C closures with this library, such as [`#!luau print`](https://create.roblox.com/docs/reference/engine/globals/LuaGlobals#print) 25 | -------------------------------------------------------------------------------- /docs/Debug/getconstant.md: -------------------------------------------------------------------------------- 1 | # `debug.getconstant` 2 | 3 | !!! warning "C closures are not supported" 4 | 5 | This function will throw an error if called on a C closure, such as [`#!luau print`](https://create.roblox.com/docs/reference/engine/globals/LuaGlobals#print), since C closures have no accessible constants. 6 | 7 | `#!luau debug.getconstant` returns the constant at the specified index from a Luau function. If no constant exists at that index, it returns `#!luau nil` instead. 8 | 9 | This is useful when you want to inspect specific constant values (such as strings, numbers, or booleans) without dumping the entire list. 10 | 11 | ```luau 12 | function debug.getconstant(func: (...any) -> (...any) | number, index: number): number | string | boolean | nil 13 | ``` 14 | 15 | ## Parameters 16 | 17 | | Parameter | Description | 18 | |------------------|--------------------------------------------------------------| 19 | | `#!luau func` | The Luau function (or stack level) whose constant to retrieve.| 20 | | `#!luau index` | The position of the desired constant. | 21 | 22 | --- 23 | 24 | ## Examples 25 | 26 | ### Example 1 27 | 28 | ```luau title="Getting a valid constant" linenums="1" 29 | local function dummy_function() 30 | local dummy_string = "foo bar" 31 | string.split(dummy_string, " ") 32 | end 33 | 34 | local result = debug.getconstant(dummy_function, 2) 35 | print(result) -- Output: string 36 | ``` 37 | 38 | ### Example 2 39 | 40 | ```luau title="Getting an out-of-range constant" linenums="1" 41 | local function dummy_function() 42 | local dummy_string = "foo bar" 43 | string.split(dummy_string, " ") 44 | end 45 | 46 | local result = debug.getconstant(dummy_function, 3) 47 | print(result) -- Output: nil 48 | ``` 49 | 50 | ### Example 3 51 | 52 | ```luau title="Calling on a C closure should error" linenums="1" 53 | print(debug.getconstant(print, 1)) -- Should error due to being a C closure 54 | ``` 55 | -------------------------------------------------------------------------------- /docs/Debug/getconstants.md: -------------------------------------------------------------------------------- 1 | # `debug.getconstants` 2 | 3 | !!! warning "C closures are not supported" 4 | 5 | This function will throw an error if called on a C closure, such as [`#!luau print`](https://create.roblox.com/docs/reference/engine/globals/LuaGlobals#print), since C closures have no accessible constants. 6 | 7 | `#!luau debug.getconstants` returns a list of all constants used within a Luau function's bytecode. This includes literal values like numbers, strings, booleans, and `#!luau nil`. 8 | 9 | ```luau 10 | function debug.getconstants(func: (...any) -> (...any) | number): { number | string | boolean | nil } 11 | ``` 12 | 13 | ## Parameters 14 | 15 | | Parameter | Description | 16 | |------------------|--------------------------------------------------------------------| 17 | | `#!luau func` | The Luau function (or stack level) whose constants will be returned.| 18 | 19 | --- 20 | 21 | ## Examples 22 | 23 | ### Example 1 24 | 25 | ```luau title="Retrieving constants from a Luau function" linenums="1" 26 | local function dummy_function() 27 | local dummy_string = "foo bar" 28 | string.split(dummy_string, " ") 29 | end 30 | 31 | local constants = debug.getconstants(dummy_function) 32 | for constant_index, constant in constants do 33 | print(`[{constant_index}]: {constant}`) 34 | end 35 | 36 | -- Output: 37 | -- [1]: "string" 38 | -- [2]: "split" 39 | -- [4]: "foo bar" 40 | -- [5]: " " 41 | ``` 42 | 43 | ### Example 2 44 | 45 | ```luau title="Calling on a C closure should error" linenums="1" 46 | print(debug.getconstants(print)) -- Should error due to being a C closure 47 | ``` 48 | -------------------------------------------------------------------------------- /docs/Debug/getproto.md: -------------------------------------------------------------------------------- 1 | # `debug.getproto` 2 | 3 | !!! warning "C closures are not supported" 4 | 5 | This function will throw an error if called on a C closure, such as [`#!luau print`](https://create.roblox.com/docs/reference/engine/globals/LuaGlobals#print), since C closures do not contain function prototypes. 6 | 7 | !!! info "Inactive protos" 8 | 9 | Protos retrieved without the `activated` should not be callable; this leads to vulnerabilities. 10 | The usage of inactive protos is to retrieve information off of them. 11 | 12 | `#!luau 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 `#!luau activated` parameter is set to `true`. 13 | 14 | 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. 15 | 16 | ```luau 17 | function debug.getproto(func: (...any) -> (...any) | number, index: number, activated: boolean?): (...any) -> (...any) | { (...any) -> (...any) } 18 | ``` 19 | 20 | ## Parameters 21 | 22 | | Parameter | Description | 23 | |---------------------|-----------------------------------------------------------------------------| 24 | | `#!luau func` | The Luau function (or stack level) to extract a proto from. | 25 | | `#!luau index` | The index of the prototype to return. | 26 | | `#!luau activated?` | If `true`, returns a table of currently active functions based on the proto. | 27 | 28 | --- 29 | 30 | ## Examples 31 | 32 | ### Example 1 33 | 34 | ```luau title="Retrieving nested prototypes" linenums="1" 35 | local function dummy_function() 36 | local function dummy_proto_1() 37 | print("Hello") 38 | end 39 | local function dummy_proto_2() 40 | print("Hello2") 41 | end 42 | end 43 | 44 | debug.getproto(dummy_function, 1)() -- Uncallable 45 | debug.getproto(dummy_function, 2)() -- Uncallable 46 | ``` 47 | 48 | ### Example 2 49 | 50 | ```luau title="Retrieving an active function from a proto" linenums="1" 51 | local function dummy_function() 52 | local function dummy_proto() 53 | return "hi" 54 | end 55 | return dummy_proto 56 | end 57 | 58 | local real_proto = dummy_function() 59 | local retrieved_proto = debug.getproto(dummy_function, 1, true)[1] 60 | 61 | print(real_proto == retrieved_proto) -- Output: true 62 | print(retrieved_proto()) -- Output: hi 63 | ``` 64 | -------------------------------------------------------------------------------- /docs/Debug/getprotos.md: -------------------------------------------------------------------------------- 1 | # `debug.getprotos` 2 | 3 | !!! warning "C closures are not supported" 4 | 5 | This function will throw an error if called on a C closure, such as [`#!luau print`](https://create.roblox.com/docs/reference/engine/globals/LuaGlobals#print), since C closures do not contain function prototypes. 6 | 7 | !!! info "Inactive protos" 8 | 9 | Protos retrieved without the `activated` should not be callable; this leads to vulnerabilities. 10 | The usage of inactive protos is to retrieve information off of them. 11 | 12 | `#!luau debug.getprotos` returns all function prototypes defined within the specified Luau function. 13 | 14 | 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. 15 | 16 | ```luau 17 | function debug.getprotos(func: (...any) -> (...any) | number): { (...any) -> (...any) } 18 | ``` 19 | 20 | ## Parameters 21 | 22 | | Parameter | Description | 23 | |------------------|---------------------------------------------------------------| 24 | | `#!luau func` | The Luau function (or stack level) to extract protos from. | 25 | 26 | --- 27 | 28 | ## Example 29 | 30 | ```luau title="Getting nested function prototypes" linenums="1" 31 | local function DummyFunction0() 32 | local function DummyFunction1() end 33 | local function DummyFunction2() end 34 | end 35 | 36 | for index, proto in pairs(debug.getprotos(DummyFunction0)) do 37 | print(index, debug.info(proto, "n")) 38 | end 39 | 40 | -- Output: 41 | -- 1 DummyFunction1 42 | -- 2 DummyFunction2 43 | ``` 44 | -------------------------------------------------------------------------------- /docs/Debug/getstack.md: -------------------------------------------------------------------------------- 1 | # `debug.getstack` 2 | 3 | !!! warning "C closures are not supported" 4 | 5 | This function will throw an error if the stack level points to a C closure, such as `#!luau getstack(0)`. 6 | 7 | `#!luau debug.getstack` retrieves values from the stack at the specified call level. 8 | 9 | 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. 10 | 11 | ```luau 12 | function debug.getstack(level: number, index: number?): any | { any } 13 | ``` 14 | 15 | ## Parameters 16 | 17 | | Parameter | Description | 18 | |-------------------|-------------------------------------------------------------------| 19 | | `#!luau level` | The stack level to inspect. `1` is the current function. | 20 | | `#!luau index?` | The specific slot/index at that stack level to read. | 21 | 22 | --- 23 | 24 | ## Examples 25 | 26 | ### Example 1 27 | 28 | ```luau title="Retrieving multiple values from the stack" linenums="1" 29 | local count = 0 30 | 31 | local function recursive_function() 32 | count += 1 33 | if count > 6 then return end 34 | 35 | local a = 29 36 | local b = true 37 | local c = "Example" 38 | a += 1 39 | b = false 40 | c ..= "s" 41 | 42 | print(debug.getstack(1, count)) 43 | recursive_function() 44 | end 45 | 46 | recursive_function() 47 | -- Output (varies depending on Count): 48 | -- 30 49 | -- false 50 | -- Examples 51 | -- function: 0x... (print) 52 | -- function: 0x... (getstack) 53 | -- etc. 54 | ``` 55 | 56 | ### Example 2 57 | 58 | ```luau title="Retrieving values from the caller's stack" linenums="1" 59 | local function dummy_function() 60 | return "Hello" 61 | end 62 | 63 | local var = 5 64 | var += 1 65 | 66 | (function() 67 | print(debug.getstack(2)[1]()) -- Output: Hello 68 | print(debug.getstack(2)[2]) -- Output: 6 69 | end)() 70 | ``` 71 | -------------------------------------------------------------------------------- /docs/Debug/getupvalue.md: -------------------------------------------------------------------------------- 1 | # `debug.getupvalue` 2 | 3 | !!! warning "C closures are not supported" 4 | 5 | This function will throw an error if called on a C closure, such as [`#!luau print`](https://create.roblox.com/docs/reference/engine/globals/LuaGlobals#print), for security reasons. 6 | 7 | `#!luau 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. 8 | 9 | ```luau 10 | function debug.getupvalue(func: (...any) -> (...any) | number, index: number): any 11 | ``` 12 | 13 | ## Parameters 14 | 15 | | Parameter | Description | 16 | |------------------|--------------------------------------------------------------------| 17 | | `#!luau func` | The Luau function (or stack level) to retrieve an upvalue from. | 18 | | `#!luau index` | The position of the upvalue. | 19 | 20 | --- 21 | 22 | ## Examples 23 | 24 | ### Example 1 25 | 26 | ```luau title="Retrieving a function upvalue" linenums="1" 27 | local UpFunction = function() 28 | print("Hello from up") 29 | end 30 | 31 | local function DummyFunction() 32 | UpFunction() 33 | end 34 | 35 | local Retrieved = debug.getupvalue(DummyFunction, 1) 36 | Retrieved() -- Output: Hello from up 37 | ``` 38 | 39 | ### Example 2 40 | 41 | ```luau title="Invalid index on a function with no upvalues" linenums="1" 42 | local function DummyFunction() end 43 | 44 | debug.getupvalue(DummyFunction, 0) -- Should error 45 | ``` 46 | 47 | ### Example 3 48 | 49 | ```luau title="Calling on a C closure should error" linenums="1" 50 | debug.getupvalue(print, 1) -- Should error due to C closure 51 | ``` 52 | -------------------------------------------------------------------------------- /docs/Debug/getupvalues.md: -------------------------------------------------------------------------------- 1 | # `debug.getupvalues` 2 | 3 | !!! warning "C closures are not supported" 4 | 5 | This function will throw an error if called on a C closure, such as [`#!luau print`](https://create.roblox.com/docs/reference/engine/globals/LuaGlobals#print), for security reasons. 6 | 7 | `#!luau 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. 8 | 9 | If the function has no upvalues, the result will be an empty table. 10 | 11 | ```luau 12 | function debug.getupvalues(func: (...any) -> (...any) | number): { any } 13 | ``` 14 | 15 | ## Parameters 16 | 17 | | Parameter | Description | 18 | |------------------|--------------------------------------------------------------------| 19 | | `#!luau func` | The Luau function (or stack level) to retrieve upvalues from. | 20 | 21 | --- 22 | 23 | ## Examples 24 | 25 | ### Example 1 26 | 27 | ```luau title="Retrieving upvalues from a closure" linenums="1" 28 | local var1 = false 29 | local var2 = "Hi" 30 | 31 | local function dummy_function() 32 | var1 = true 33 | var2 ..= ", hello" 34 | end 35 | 36 | for index, value in pairs(debug.getupvalues(dummy_function)) do 37 | print(index, value) 38 | end 39 | 40 | -- Output: 41 | -- 1 false 42 | -- 2 Hi 43 | ``` 44 | 45 | ### Example 2 46 | 47 | ```luau title="Calling with a function that has no upvalues" linenums="1" 48 | local function dummy_function() 49 | return 123 50 | end 51 | 52 | print(next(debug.getupvalues(dummy_function))) -- Output: nil 53 | ``` 54 | 55 | ### Example 3 56 | 57 | ```luau title="Calling on a C closure should error" linenums="1" 58 | print(debug.getupvalues(print)) -- Should error due to being a C closure 59 | ``` 60 | -------------------------------------------------------------------------------- /docs/Debug/setconstant.md: -------------------------------------------------------------------------------- 1 | # `debug.setconstant` 2 | 3 | !!! warning "C closures are not supported" 4 | 5 | This function will throw an error if called on a C closure, such as [`#!luau print`](https://create.roblox.com/docs/reference/engine/globals/LuaGlobals#print), since C closures have no accessible constants. 6 | 7 | !!! info "Mutable globals" 8 | 9 | If `game`is a mutable global, the constant indexes will be different. 10 | 11 | `#!luau debug.setconstant` modifies a constant at the specified index in a Luau function bytecode. 12 | 13 | This can be used to change hardcoded behavior within functions without modifying their source code - although it requires knowing the correct constant index beforehand. 14 | 15 | ```luau 16 | function debug.setconstant(func: (...any) -> (...any) | number, index: number, value: number | string | boolean | nil): () 17 | ``` 18 | 19 | ## Parameters 20 | 21 | | Parameter | Description | 22 | |------------------|--------------------------------------------------------------| 23 | | `#!luau func` | The Luau function (or stack level) whose constant to modify. | 24 | | `#!luau index` | The position of the constant to change. | 25 | | `#!luau value` | The new constant value to set. | 26 | 27 | --- 28 | 29 | ## Example 30 | 31 | ```luau title="Overwriting a constant string in a function" linenums="1" 32 | local function dummy_function() 33 | print(game.Name) 34 | end 35 | 36 | debug.setconstant(dummy_function, 4, "Players") 37 | 38 | dummy_function() -- Output: Players 39 | ``` 40 | -------------------------------------------------------------------------------- /docs/Debug/setstack.md: -------------------------------------------------------------------------------- 1 | # `debug.setstack` 2 | 3 | !!! warning "C closures are not supported" 4 | 5 | This function will throw an error if the stack level points to a C closure, such as `#!luau setstack(0, 1, 0)`. 6 | 7 | `#!luau debug.setstack` replaces a value in a specified stack frame. 8 | 9 | This allows for powerful manipulation of runtime variables or arguments, particularly useful in advanced debugging or dynamic patching scenarios. 10 | 11 | ```luau 12 | function debug.setstack(level: number, index: number, value: any): () 13 | ``` 14 | 15 | ## Parameters 16 | 17 | | Parameter | Description | 18 | |-------------------|-----------------------------------------------------------------------| 19 | | `#!luau level` | The stack level to target. `1` refers to the current function. | 20 | | `#!luau index` | The index/slot in the stack frame to replace. | 21 | | `#!luau value` | The new value to assign at that stack slot. | 22 | 23 | --- 24 | 25 | ## Examples 26 | 27 | ### Example 1 28 | 29 | ```luau title="Replacing the 'error' function on the stack with our own" linenums="1" 30 | error(debug.setstack(1, 1, function() 31 | return function() 32 | print("Replaced") 33 | end 34 | end))() -- Output: Replaced 35 | ``` 36 | 37 | ### Example 2 38 | 39 | ```luau title="Replacing a numeric local in a parent scope" linenums="1" 40 | local outer_value = 10 41 | 42 | local function inner_function() 43 | outer_value += 9 44 | debug.setstack(2, 1, 100) 45 | end 46 | 47 | inner_function() 48 | print(outer_value) -- Output: 100 49 | ``` 50 | -------------------------------------------------------------------------------- /docs/Debug/setupvalue.md: -------------------------------------------------------------------------------- 1 | # `debug.setupvalue` 2 | 3 | !!! warning "C closures not supported" 4 | 5 | This function will throw an error if called on a C closure, such as [`#!luau print`](https://create.roblox.com/docs/reference/engine/globals/LuaGlobals#print), for security reasons. 6 | 7 | `#!luau debug.setupvalue` replaces an upvalue at the specified index in a Luau function, with a new value. 8 | 9 | This allows for controlled modification of function state, often used in hooking or testing environments. 10 | 11 | ```luau 12 | function debug.setupvalue(func: (...any) -> (...any) | number, index: number, value: any): () 13 | ``` 14 | 15 | ## Parameters 16 | 17 | | Parameter | Description | 18 | |------------------|----------------------------------------------------------------| 19 | | `#!luau func` | The function (or stack level) whose upvalue to replace. | 20 | | `#!luau index` | The index of the upvalue to be replaced. | 21 | | `#!luau value` | The new value to assign to the upvalue. | 22 | 23 | --- 24 | 25 | ## Example 26 | 27 | ```luau title="Replacing a numeric upvalue" linenums="1" 28 | local upvalue = 90 29 | 30 | local function dummy_function() 31 | upvalue += 1 32 | print(upvalue) 33 | end 34 | 35 | dummy_function() -- Output: 91 36 | 37 | debug.setupvalue(dummy_function, 1, 99) 38 | dummy_function() -- Output: 100 39 | ``` 40 | -------------------------------------------------------------------------------- /docs/Drawing/README.md: -------------------------------------------------------------------------------- 1 | # Drawing class 2 | 3 | The `#!luau Drawing` class represents a renderable 2D object that appears on the user's screen. Every specific drawing type (e.g. `Circle`, `Text`, `Line`) inherits from this base and extends it with shape-specific properties. 4 | 5 | Drawing objects are ***not*** instances - they are client-only graphical primitives that do not interact with the 3D world and must be managed manually. 6 | 7 | --- 8 | 9 | ## Constructor 10 | 11 | Creates a new render object of the specified type. These objects render directly onto the game window and do not exist in the [`DataModel`](https://create.roblox.com/docs/reference/engine/classes/DataModel). 12 | 13 | !!! info "Inheritance" 14 | 15 | The returned object inherits from the base `#!luau Drawing` class, and will have specific properties based on its type. 16 | 17 | ```luau 18 | function Drawing.new(type: string): Drawing 19 | ``` 20 | 21 | ## Parameters 22 | 23 | | Parameter | Description | 24 | |---------------|-----------------------------------------------------------------------------| 25 | | `#!luau type` | The type of drawing to create. Must be one of: [`Line`, `Text`, `Image`, `Circle`, `Square`, `Quad`, or `Triangle`](#shape-specific-types). | 26 | 27 | --- 28 | 29 | ## Shared properties 30 | 31 | All drawing object types inherit the following fields: 32 | 33 | | Property | Type | Description | 34 | |--------------------|-----------|-----------------------------------------------------------------------------| 35 | | `#!luau Visible` | `#!luau boolean` | Whether the object is rendered. Defaults to `#!luau false`. | 36 | | `#!luau ZIndex` | `#!luau number` | Render order; higher values appear on top. | 37 | | `#!luau Transparency`| `#!luau number` | Translucency, where `1` is fully transparent and `0` is fully visible. | 38 | | `#!luau Color` | `#!luau Color3` | The color of the drawing. | 39 | | `#!luau __OBJECT_EXISTS` | `#!luau boolean` | Whether the drawing object exists. | 40 | 41 | --- 42 | 43 | ## Methods 44 | 45 | | Method Signature | Description | 46 | |----------------------------------------|---------------------------------------| 47 | | `#!luau Destroy()` | Permanently removes the drawing from view. | 48 | 49 | --- 50 | 51 | ## Shape-specific types 52 | 53 | Each subtype of `Drawing` exposes unique fields that define their visual representation. Below are the supported types: 54 | 55 | ### Line 56 | 57 | | Property | Type | Description | 58 | |----------------|----------|----------------------------------| 59 | | `#!luau From` | `#!luau Vector2`| Start position of the line. | 60 | | `#!luau To` | `#!luau Vector2`| End position of the line. | 61 | | `#!luau Thickness`| `#!luau number` | Width of the line. | 62 | 63 | ### Text 64 | 65 | | Property | Type | Description | 66 | |------------------|----------------|-----------------------------------------------| 67 | | `#!luau Text` | `#!luau string` | The text content to render. | 68 | | `#!luau TextBounds`| `#!luau Vector2` 🔒 | Computed text size (read-only). | 69 | | `#!luau Font` | `#!luau Drawing.Font` | Font to use. | 70 | | `#!luau Size` | `#!luau number` | Size of the text. | 71 | | `#!luau Position` | `#!luau Vector2` | Top-left corner of the text. | 72 | | `#!luau Center` | `#!luau boolean` | Horizontally center the text. | 73 | | `#!luau Outline` | `#!luau boolean` | Whether to draw an outline. | 74 | | `#!luau OutlineColor`| `#!luau Color3` | Outline color. | 75 | 76 | ### Image 77 | 78 | | Property | Type | Description | 79 | |--------------|----------|-----------------------------------------------------| 80 | | `#!luau Data` | `#!luau string` | Raw image byte string (e.g. from [`#!luau readfile`](../Filesystem/readfile.md)). | 81 | | `#!luau Size` | `#!luau Vector2`| Size of the rendered image. | 82 | | `#!luau Position`| `#!luau Vector2`| Top-left corner of the image. | 83 | | `#!luau Rounding`| `#!luau number` | Amount of corner rounding (optional aesthetic). | 84 | 85 | ### Circle 86 | 87 | | Property | Type | Description | 88 | |----------------|-----------|-------------------------------------------------------| 89 | | `#!luau NumSides` | `#!luau number` | Number of sides used to approximate the circle. | 90 | | `#!luau Radius` | `#!luau number` | Radius of the circle. | 91 | | `#!luau Position` | `#!luau Vector2` | Center point of the circle. | 92 | | `#!luau Thickness`| `#!luau number` | Outline thickness (if not filled). | 93 | | `#!luau Filled` | `#!luau boolean` | Whether the circle is filled. | 94 | 95 | ### Square 96 | 97 | | Property | Type | Description | 98 | |----------------|-----------|-------------------------------------------------------| 99 | | `#!luau Size` | `#!luau Vector2` | Size of the rectangle. | 100 | | `#!luau Position` | `#!luau Vector2` | Top-left corner. | 101 | | `#!luau Thickness`| `#!luau number` | Outline thickness (if not filled). | 102 | | `#!luau Filled` | `#!luau boolean` | Whether the square is filled. | 103 | 104 | ### Quad 105 | 106 | | Property | Type | Description | 107 | |----------------|-----------|------------------------------------| 108 | | `#!luau PointA` | `#!luau Vector2` | First point. | 109 | | `#!luau PointB` | `#!luau Vector2` | Second point. | 110 | | `#!luau PointC` | `#!luau Vector2` | Third point. | 111 | | `#!luau PointD` | `#!luau Vector2` | Fourth point. | 112 | | `#!luau Thickness`| `#!luau number` | Outline thickness (if not filled). | 113 | | `#!luau Filled` | `#!luau boolean` | Whether the quad is filled. | 114 | 115 | ### Triangle 116 | 117 | | Property | Type | Description | 118 | |----------------|-----------|------------------------------------| 119 | | `#!luau PointA` | `#!luau Vector2` | First point. | 120 | | `#!luau PointB` | `#!luau Vector2` | Second point. | 121 | | `#!luau PointC` | `#!luau Vector2` | Third point. | 122 | | `#!luau Thickness`| `#!luau number` | Outline thickness (if not filled). | 123 | | `#!luau Filled` | `#!luau boolean` | Whether the triangle is filled. | 124 | 125 | ## Examples 126 | 127 | ### Using the `Destroy` method 128 | 129 | ```luau title="Creating a circle and destroying the drawing object" linenums="1" 130 | local Camera = game.Workspace.CurrentCamera 131 | local Viewport = Camera.ViewportSize 132 | local Position = Vector2.new(Viewport.X / 2, Viewport.Y / 2) 133 | 134 | local circle = Drawing.new("Circle") 135 | circle.Radius = 50 136 | circle.Color = Color3.fromRGB(255, 0, 0) 137 | circle.Filled = true 138 | circle.NumSides = 150 139 | circle.Position = Position 140 | circle.Transparency = 1 141 | circle.Visible = true 142 | 143 | print(circle.__OBJECT_EXISTS) -- Output: true 144 | circle:Destroy() 145 | print(circle.__OBJECT_EXISTS) -- Output: false 146 | ``` 147 | 148 | --- 149 | 150 | ### Drawing an [Image](#image) 151 | 152 | ```luau title="Rendering a centered image" linenums="1" 153 | local Camera = game.Workspace.CurrentCamera 154 | local Viewport = Camera.ViewportSize 155 | local Position = Vector2.new(Viewport.X / 2, Viewport.Y / 2) 156 | local image = Drawing.new("Image") 157 | image.Data = readfile("your_image.png") 158 | image.Size = Vector2.new(455, 155) 159 | image.Visible = true 160 | image.Position = Position 161 | 162 | task.wait(2) 163 | image:Destroy() 164 | ``` 165 | 166 | --- 167 | 168 | ### Using the `#!luau __OBJECT_EXISTS` property 169 | 170 | ```luau title="Rendering a centered image" linenums="1" 171 | local Camera = game.Workspace.CurrentCamera 172 | local Viewport = Camera.ViewportSize 173 | local Position = Vector2.new(Viewport.X / 2, Viewport.Y / 2) 174 | 175 | local circle = Drawing.new("Circle") 176 | circle.Radius = 50 177 | circle.Color = Color3.fromRGB(255, 0, 0) 178 | circle.Filled = true 179 | circle.NumSides = 150 180 | circle.Position = Position 181 | circle.Transparency = 1 182 | circle.Visible = true 183 | 184 | print(circle.__OBJECT_EXISTS) -- Output: true 185 | circle:Destroy() 186 | print(circle.__OBJECT_EXISTS) -- Output: false 187 | ``` 188 | -------------------------------------------------------------------------------- /docs/Drawing/cleardrawcache.md: -------------------------------------------------------------------------------- 1 | # `cleardrawcache` 2 | 3 | `#!luau cleardrawcache` removes **all active drawing objects** created with [`#!luau Drawing.new`](./README.md#constructor). 4 | 5 | ```luau 6 | function cleardrawcache(): () 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |-----------|----------------------------------| 13 | | *(none)* | This function takes no parameters. | 14 | 15 | --- 16 | 17 | ## Example 18 | 19 | ```luau title="Clearing all drawing objects at once" linenums="1" 20 | local camera = game.Workspace.CurrentCamera 21 | local viewport = camera.ViewportSize 22 | local pos = Vector2.new(viewport.X / 2, viewport.Y / 2) 23 | 24 | local circle = Drawing.new("Circle") 25 | circle.Radius = 50 26 | circle.Color = Color3.fromRGB(255, 0, 0) 27 | circle.Filled = true 28 | circle.NumSides = 60 29 | circle.Position = pos 30 | circle.Transparency = 1 31 | circle.Visible = true 32 | 33 | task.defer(cleardrawcache) 34 | 35 | print(circle.__OBJECT_EXISTS) -- Output: true 36 | task.wait() 37 | print(circle.__OBJECT_EXISTS) -- Output: false 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/Drawing/getrenderproperty.md: -------------------------------------------------------------------------------- 1 | # `getrenderproperty` 2 | 3 | `#!luau getrenderproperty` retrieves the value of a property from a [`#!luau Drawing`](./README.md) object. This behaves identically to using `#!luau object[property]`, but is useful when working with dynamic property names or for reflection-like access. 4 | 5 | ```luau 6 | function getrenderproperty(drawing: Drawing, property: string): any 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |------------------|--------------------------------------------------------------| 13 | | `#!luau drawing` | A valid [`#!luau Drawing`](./README.md) object. | 14 | | `#!luau property` | The name of the property to retrieve. | 15 | 16 | --- 17 | 18 | ## Example 19 | 20 | ```luau title="Reading drawing properties" linenums="1" 21 | local circle = Drawing.new("Circle") 22 | circle.Radius = 50 23 | circle.Visible = true 24 | 25 | print(getrenderproperty(circle, "Radius")) -- Output: 50 26 | print(getrenderproperty(circle, "Visible")) -- Output: true 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/Drawing/isrenderobj.md: -------------------------------------------------------------------------------- 1 | # `isrenderobj` 2 | 3 | `#!luau isrenderobj` checks whether a given value is a valid [`#!luau Drawing`](./README.md) object. 4 | 5 | This is useful for validation in functions or modules that work with custom render systems. 6 | 7 | ```luau 8 | function isrenderobj(object: any): boolean 9 | ``` 10 | 11 | ## Parameters 12 | 13 | | Parameter | Description | 14 | |------------------|----------------------------------------| 15 | | `#!luau object` | The value to check for Drawing validity. | 16 | 17 | --- 18 | 19 | ## Example 20 | 21 | ```luau title="Checking if an object is a render object" linenums="1" 22 | local square = Drawing.new("Square") 23 | 24 | print(isrenderobj(square)) -- Output: true 25 | print(isrenderobj(workspace)) -- Output: false 26 | print(isrenderobj("not a draw")) -- Output: false 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/Drawing/setrenderproperty.md: -------------------------------------------------------------------------------- 1 | # `setrenderproperty` 2 | 3 | `#!luau setrenderproperty` assigns a value to a property of a [`#!luau Drawing`](./README.md) object. This behaves identically to `#!luau object[property] = value`, but is useful for dynamic or abstracted property access. 4 | 5 | ```luau 6 | function setrenderproperty(drawing: Drawing, property: string, value: any): () 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |------------------|--------------------------------------------------------------| 13 | | `#!luau drawing` | A valid [`#!luau Drawing`](./README.md) object. | 14 | | `#!luau property` | The name of the property to assign. | 15 | | `#!luau value` | The value to assign to the specified property. | 16 | 17 | --- 18 | 19 | ## Example 20 | 21 | ```luau title="Setting drawing properties" linenums="1" 22 | local circle = Drawing.new("Circle") 23 | 24 | setrenderproperty(circle, "Radius", 50) 25 | setrenderproperty(circle, "Visible", true) 26 | 27 | print(circle.Radius) -- Output: 50 28 | print(circle.Visible) -- Output: true 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/Environment/README.md: -------------------------------------------------------------------------------- 1 | # Environment 2 | 3 | The **Environment** library allows access and inspection to our and Roblox's environment. 4 | 5 | --- 6 | 7 | ## What can you do? 8 | 9 | With the Environment library, you can: 10 | 11 | - **Access and modify executor globals** using [`#!luau getgenv`](./getgenv.md) 12 | - **Modify the game global environment** using [`#!luau getrenv`](./getrenv.md) 13 | - **View collectable and living values** using [`#!luau getgc`](./getgc.md) 14 | - **Filter** garbage-collected values with fine-tuned criteria using [`#!luau filtergc`](./filtergc/README.md) 15 | -------------------------------------------------------------------------------- /docs/Environment/filtergc/FunctionFilterOptions.md: -------------------------------------------------------------------------------- 1 | # Function filter options 2 | 3 | Function filters let you refine what types of Luau functions should be returned when using [`#!luau filtergc`](./README.md) with `#!luau "function"` as the filter type. 4 | 5 | Each key in the filter table specifies a criterion that must be matched by the function for it to be returned. You can use one or multiple fields together to narrow your results. 6 | 7 | --- 8 | 9 | ## Available options 10 | 11 | | Key | Type | Description | Default | 12 | |----------------------|------------------|------------------------------------------------------------------------------------------------------|---------| 13 | | `#!luau Name` | `#!luau string?` | If provided, filters out functions which don't match this name. | `#!luau nil` | 14 | | `#!luau IgnoreExecutor`| `#!luau boolean?` | If `true`, filters out functions that were created inside the executor. | `#!luau true` | 15 | | `#!luau Hash` | `#!luau string?` | Filters by the hash of the function. See [`#!luau getfunctionhash`](../../Closures/getfunctionhash.md). | `#!luau nil` | 16 | | `#!luau Constants` | `#!luau { any }?` | Also includes functions that contain the matching constants in the provided list. | `#!luau nil` | 17 | | `#!luau Upvalues` | `#!luau { any }?` | Also includes functions that contain the matching upvalues in the provided list. | `#!luau nil` | 18 | 19 | --- 20 | 21 | ## Notes 22 | 23 | - These filters work based on narrowing - the more information you provide in the filters, the more accurate the final result. 24 | - If `#!luau IgnoreExecutor` is not explicitly set to `#!luau false`, executor-created functions are skipped by default. 25 | - Filters like `#!luau Constants`, `#!luau Upvalues`, and `#!luau Hash` do not apply to C closures. 26 | 27 | --- 28 | 29 | ## Examples 30 | 31 | !!! info "False negatives may occur" 32 | 33 | Executing these examples multiple times in a short period of time may result in false negatives. 34 | 35 | ### Using `#!luau Name` (returns a `#!luau table` by default) 36 | 37 | ```luau title="Matching a function by name" linenums="1" 38 | local function dummy_function() end 39 | 40 | local retrieved = filtergc("function", { 41 | Name = "dummy_function", 42 | IgnoreExecutor = false 43 | }) 44 | 45 | print(typeof(retrieved)) -- Output: table 46 | print(retrieved[1] == dummy_function) -- Output: true 47 | ``` 48 | 49 | --- 50 | 51 | ### Using `#!luau Name` with `#!luau returnOne = true` 52 | 53 | ```luau title="Single match using returnOne" linenums="1" 54 | local function dummy_function() 55 | end 56 | 57 | local retrieved = filtergc("function", { 58 | Name = "dummy_function", 59 | IgnoreExecutor = false 60 | }, true) 61 | 62 | print(typeof(retrieved)) -- Output: function 63 | print(retrieved == dummy_function) -- Output: true 64 | ``` 65 | 66 | --- 67 | 68 | ### Using `#!luau Hash` 69 | 70 | ```luau title="Matching a function by hash" linenums="1" 71 | local function dummy_function() 72 | return "Hello" 73 | end 74 | 75 | local dummy_function_hash = getfunctionhash(dummy_function) 76 | 77 | local retrieved = filtergc("function", { 78 | Hash = dummy_function_hash, 79 | IgnoreExecutor = false 80 | }, true) 81 | 82 | print(getfunctionhash(retrieved) == dummy_function_hash) -- Output: true 83 | print(retrieved == dummy_function) -- Output: true 84 | ``` 85 | 86 | ### Matching by `#!luau Constants` and `#!luau Upvalues` 87 | 88 | ```luau title="Matching by function constants and upvalues" linenums="1" 89 | local upvalue = 5 90 | 91 | local function dummy_function() 92 | upvalue += 1 93 | print(game.Players.LocalPlayer) 94 | end 95 | 96 | local retrieved = filtergc("function", { 97 | Constants = { "print", "game", "Players", "LocalPlayer", 1 }, 98 | Upvalues = { 5 }, 99 | IgnoreExecutor = false 100 | }, true) 101 | 102 | print(retrieved == dummy_function) -- Output: true 103 | ``` 104 | 105 | ### Type signature for `FunctionFilterOptions` 106 | 107 | ```luau title="" linenums="1" 108 | type FunctionFilterOptions = { 109 | Name: string?, 110 | IgnoreExecutor: boolean?, 111 | Hash: string?, 112 | Constants: { string }?, 113 | Upvalues: { any }? 114 | } 115 | ``` 116 | -------------------------------------------------------------------------------- /docs/Environment/filtergc/README.md: -------------------------------------------------------------------------------- 1 | # `filtergc` 2 | 3 | `#!luau filtergc` allows you to retrieve specific garbage-collected values from Luau's memory, using fine-tuned filters. 4 | 5 | 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 [`#!luau getgc`](../getgc.md), but offers simplicity, efficiency, and more control over what gets returned. 6 | 7 | ```luau 8 | export type AnyFunction = (...any) -> (...any) 9 | export type AnyTable = { [any]: any } 10 | 11 | declare filtergc: 12 | (( filterType: "function", filterOptions: FunctionFilterOptions, returnOne: true) -> AnyFunction? ) & 13 | ((( filterType: "function", filterOptions: FunctionFilterOptions, returnOne: false?) -> ( AnyFunction | { AnyFunction } ) )) & 14 | (( filterType: "table", filterOptions: TableFilterOptions, returnOne: true) -> { AnyTable? } ) & 15 | (( filterType: "table", filterOptions: TableFilterOptions, returnOne: false? ) -> { AnyTable }) 16 | ``` 17 | 18 | --- 19 | 20 | ## Parameters 21 | 22 | | Parameter | Description | 23 | |------------------|-----------------------------------------------------------------------------| 24 | | `#!luau filterType` | The type of value to search for. | 25 | | `#!luau filterOptions` | A set of rules used to match functions or tables. [See below.](#filter-option-types) | 26 | | `#!luau returnOne?` | If `#!luau true`, returns the first match, instead of a table of matches. | 27 | 28 | --- 29 | 30 | ## Filter option types 31 | 32 | Each filter type has its own valid fields: 33 | 34 | - See [Function Filters](./FunctionFilterOptions.md) for matching functions by name, constants, upvalues, and more. 35 | - See [Table Filters](./TableFilterOptions.md) for matching tables by keys, values, metatables, and more. 36 | 37 | --- 38 | 39 | ## Notes 40 | 41 | - Garbage-collected values must still be referenced by a live thread to be found. 42 | - Some filters (like `Constants` or `Hash`) do not apply to C functions. 43 | -------------------------------------------------------------------------------- /docs/Environment/filtergc/TableFilterOptions.md: -------------------------------------------------------------------------------- 1 | # Table filter options 2 | 3 | Table filters define what types of Luau tables should be returned when using [`#!luau filtergc`](./README.md) with `#!luau "table"` as the filter type. 4 | 5 | Each key in the filter table specifies a condition the table must meet in order to be returned. You can use one or multiple fields together to narrow your results. 6 | 7 | --- 8 | 9 | ## Available Options 10 | 11 | | Key | Type | Description | Default | 12 | |----------------------|--------------------|---------------------------------------------------------------------------------------------------|---------------| 13 | | `#!luau Keys` | `#!luau { any }?` | If provided, also includes tables that contain **all** the specified keys. | `#!luau nil` | 14 | | `#!luau Values` | `#!luau { any }?` | If provided, only includes tables that contain **all** the specified values. | `#!luau nil` | 15 | | `#!luau KeyValuePairs` | `#!luau { [any]: any }?` | If provided, only includes tables that contain **all** key-value pairs in this table. | `#!luau nil` | 16 | | `#!luau Metatable` | `#!luau table?` | If provided, only includes tables whose metatable matches the given one. | `#!luau nil` | 17 | 18 | --- 19 | 20 | ## Notes 21 | 22 | - These filters work based on narrowing - the more information you provide in the filters, the more accurate the result. 23 | - If `#!luau Metatable` is used, a raw metatable comparison is performed. 24 | 25 | ## Examples 26 | 27 | !!! info "False negatives may occur" 28 | 29 | Executing these examples multiple times in a short period of time may result in false negatives. 30 | 31 | ### Matching by `#!luau Keys` 32 | 33 | ```luau title="Matching a table by key" linenums="1" 34 | local dummy_table = { ["dummy_key"] = "" } 35 | 36 | local retrieved = filtergc("table", { 37 | Keys = { "dummy_key" }, 38 | }, true) 39 | 40 | print(retrieved == dummy_table) -- Output: true 41 | ``` 42 | 43 | ### Matching by `#!luau KeyValuePairs` 44 | 45 | ```luau title="Matching a table by key-value pairs" linenums="1" 46 | local dummy_table = { ["dummy_key"] = "dummy_value" } 47 | 48 | local retrieved = filtergc("table", { 49 | KeyValuePairs = { ["dummy_key"] = "dummy_value" }, 50 | }, true) 51 | 52 | print(retrieved == dummy_table) -- Output: true 53 | ``` 54 | 55 | ### Matching by `#!luau Metatable` 56 | 57 | ```luau title="Matching a table by metatable" linenums="1" 58 | local dummy_table = setmetatable({}, { __index = getgenv() }) 59 | 60 | local retrieved = filtergc("table", { 61 | Metatable = getmetatable(dummy_table) 62 | }, true) 63 | 64 | print(retrieved == dummy_table) -- Output: true 65 | ``` 66 | 67 | ### Type signature for `TableFilterOptions` 68 | 69 | ```luau title="" linenums="1" 70 | type TableFilterOptions = { 71 | Keys: { [any]: any }?, 72 | Values: { [any]: any }?, 73 | KeyValuePairs: { [any]: any }?, 74 | Metatable: { [any]: any }?, 75 | } 76 | ``` 77 | -------------------------------------------------------------------------------- /docs/Environment/getgc.md: -------------------------------------------------------------------------------- 1 | # `getgc` 2 | 3 | `#!luau getgc` returns a list of **non-dead garbage-collectable values**. These include functions, userdatas, and optionally tables. 4 | 5 | ```luau 6 | export type AnyFunction = (...any) -> (...any) 7 | export type AnyTable = { [any]: any } 8 | 9 | export type userdata = typeof(newproxy()) -- (1) 10 | 11 | declare getgc: 12 | ((includeTables: true) -> { { AnyTable } | AnyFunction | userdata }) & 13 | ((includeTables: false?) -> { AnyFunction }) 14 | ``` 15 | 16 | 1. Note that `#!luau userdata` is not an official Luau type, but we define it here for clarity - because `#!luau getgc` can return them as part of its results. 17 | 18 | ## Parameters 19 | 20 | | Parameter | Description | 21 | |---------------------|-----------------------------------------------------------| 22 | | `#!luau includeTables?` | If `#!luau true`, also includes tables in the returned list. Defaults to `#!luau false`. | 23 | 24 | --- 25 | 26 | ## Examples 27 | 28 | ### Example 1 29 | 30 | ```luau title="Function-only GC scan" linenums="1" 31 | local dummy_table = {} 32 | local function dummy_function() end 33 | task.wait(0.05) -- Step a bit 34 | 35 | for _, value in pairs(getgc()) do 36 | if value == dummy_function then 37 | print(`Found function: {dummy_function}`) 38 | elseif value == dummy_table then 39 | print(`Found table?: {dummy_table}`) -- This shouldn't print 40 | end 41 | end 42 | ``` 43 | 44 | ### Example 2 45 | 46 | ```luau title="Full GC scan including tables" linenums="1" 47 | local dummy_table = {} 48 | local function dummy_function() end 49 | task.wait(0.05) -- Step a bit 50 | 51 | for _, value in pairs(getgc(true)) do 52 | if value == dummy_function then 53 | print(`Found function: {dummy_function}`) -- Should print 54 | elseif value == dummy_table then 55 | print(`Found table: {dummy_table}`) -- Should also print 56 | end 57 | end 58 | ``` 59 | -------------------------------------------------------------------------------- /docs/Environment/getgenv.md: -------------------------------------------------------------------------------- 1 | # `getgenv` 2 | 3 | !!! warning "getgenv polluting" 4 | 5 | Modifications to a thread's global environment should not affect `#!luau getgenv`. 6 | 7 | `#!luau getgenv` returns the **executor's global environment table**, which is shared across all executor-made threads. 8 | 9 | This environment is writable and persistent during the session, making it useful for sharing state or functions across different scripts. 10 | 11 | ```luau 12 | function getgenv(): { any } 13 | ``` 14 | 15 | ## Parameters 16 | 17 | | Parameter | Description | 18 | |-----------|----------------------------------| 19 | | *(none)* | This function takes no parameters. | 20 | 21 | --- 22 | 23 | ## Example 24 | 25 | ```luau title="getgenv shouldn't be affected by the global table/getfenv" linenums="1" 26 | getgenv().dummy_val = "value" 27 | getfenv().dummy_val_2 = 1 28 | 29 | print(dummy_val, getgenv().dummy_val_2) -- Output: value, 1 30 | 31 | getgenv().dummy_val = "value2" 32 | dummy_val = nil 33 | print(dummy_val) -- Output: value2 34 | 35 | ``` 36 | -------------------------------------------------------------------------------- /docs/Environment/getreg.md: -------------------------------------------------------------------------------- 1 | # `getreg` 2 | 3 | `#!luau 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). 4 | 5 | ```luau 6 | function getreg(): { [any]: any } 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |-----------|----------------------------------| 13 | | *(none)* | This function takes no parameters. | 14 | 15 | --- 16 | 17 | ## Example 18 | 19 | ```luau title="Closing a thread via getreg" linenums="1" 20 | local loop_thread = task.spawn(function() 21 | while task.wait(1) do 22 | print("I am still running...") 23 | end 24 | end) 25 | 26 | task.wait(0.2) -- Let the loop run for a bit 27 | 28 | for _, value in pairs(getreg()) do 29 | if value ~= loop_thread then continue end 30 | 31 | print(`Found loop thread: {loop_thread}`) -- Should print 32 | coroutine.close(loop_thread) -- Should close the thread 33 | 34 | break 35 | end 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/Environment/getrenv.md: -------------------------------------------------------------------------------- 1 | # `getrenv` 2 | 3 | !!! warning "Adding `#!luau _G` and `#!luau shared`" 4 | Make sure to properly implement `#!luau _G` and `#!luau shared` into the Roblox environment, as poor implementations will result in detection vectors! 5 | 6 | `#!luau getrenv` returns the **Roblox global environment**, which is used by the entire game. Changes to this environment will affect your executor environment as well. 7 | 8 | ```luau 9 | function getrenv(): { any } 10 | ``` 11 | 12 | ## Parameters 13 | 14 | | Parameter | Description | 15 | |-----------|----------------------------------| 16 | | *(none)* | This function takes no parameters. | 17 | 18 | --- 19 | 20 | ## Example 21 | 22 | ```luau title="Overriding Roblox environment functions" linenums="1" 23 | getrenv().warn = "Hello!" 24 | print(type(warn)) -- Output: string 25 | 26 | getrenv().game = nil 27 | print(game) -- Output: nil 28 | ``` 29 | -------------------------------------------------------------------------------- /docs/Filesystem/README.md: -------------------------------------------------------------------------------- 1 | # Filesystem 2 | 3 | The **Filesystem** library provides access to an executor's virtual file system. It enables reading, writing, creating, and deleting files and folders, as well as utility functions for interacting with content assets. 4 | 5 | This library is especially useful when storing persistent data, managing resources across sessions, or loading runtime content dynamically. 6 | 7 | --- 8 | 9 | ## What can you do? 10 | 11 | With the Filesystem library, you can: 12 | 13 | - **Write** data to a file using [`#!luau writefile`](./writefile.md) 14 | - **Read** file contents with [`#!luau readfile`](./readfile.md) 15 | - **Append** content using [`#!luau appendfile`](./appendfile.md) 16 | - **List** files and folders via [`#!luau listfiles`](./listfiles.md) 17 | - **Delete** files with [`#!luau delfile`](./delfile.md) and folders using [`#!luau delfolder`](./delfolder.md) 18 | - **Check** if a path is a file or folder using [`#!luau isfile`](./isfile.md) or [`#!luau isfolder`](./isfolder.md) 19 | - **Create** folders with [`#!luau makefolder`](./makefolder.md) 20 | - **Dynamically load** code from a file via [`#!luau loadfile`](./loadfile.md) 21 | - **Use** local assets in Roblox via [`#!luau getcustomasset`](./getcustomasset.md), as if it were an uploaded asset 22 | 23 | --- 24 | 25 | ## What can't you do? 26 | 27 | - You cannot access files outside the executor's workspace/sandboxed storage 28 | - You cannot use file IO to interact with the real disk (e.g. `C:/` (Windows), `/Library` (macOS), etc.) 29 | - You cannot escape the executor's `workspace` folder at all. 30 | -------------------------------------------------------------------------------- /docs/Filesystem/appendfile.md: -------------------------------------------------------------------------------- 1 | # `appendfile` 2 | 3 | `#!luau appendfile` appends string content to the end of a file at the specified path. If the file does not exist, it will be created. 4 | 5 | This is useful for logging, accumulating data over time, or extending file contents without overwriting them. 6 | 7 | ```luau 8 | function appendfile(path: string, contents: string): () 9 | ``` 10 | 11 | ## Parameters 12 | 13 | | Parameter | Description | 14 | |--------------------|-----------------------------------------| 15 | | `#!luau path` | The file path to append to. | 16 | | `#!luau contents` | The string content to add to the file. | 17 | 18 | --- 19 | 20 | ## Example 21 | 22 | ```luau title="Appending to a file" linenums="1" 23 | writefile("file4.txt", "print(") 24 | appendfile("file4.txt", "'Hello')") 25 | print(readfile("file4.txt")) -- Output: print('Hello') 26 | ``` 27 | -------------------------------------------------------------------------------- /docs/Filesystem/delfile.md: -------------------------------------------------------------------------------- 1 | # `delfile` 2 | 3 | `#!luau delfile` deletes the file at the specified path if it exists. 4 | 5 | This is useful for cleaning up temporary data or removing no-longer-needed files at runtime. 6 | 7 | ```luau 8 | function delfile(path: string): () 9 | ``` 10 | 11 | ## Parameters 12 | 13 | | Parameter | Description | 14 | |------------------|----------------------------| 15 | | `#!luau path` | The path of the file to delete. | 16 | 17 | --- 18 | 19 | ## Example 20 | 21 | ```luau title="Deleting a file" linenums="1" 22 | writefile("file5.txt", "Hello") 23 | print(isfile("file5.txt")) -- Output: true 24 | delfile("file5.txt") 25 | print(isfile("file5.txt")) -- Output: false 26 | ``` 27 | -------------------------------------------------------------------------------- /docs/Filesystem/delfolder.md: -------------------------------------------------------------------------------- 1 | # `delfolder` 2 | 3 | `#!luau delfolder` deletes the folder at the specified path if it exists. 4 | 5 | ```luau 6 | function delfolder(path: string): () 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |------------------|-------------------------------------| 13 | | `#!luau path` | The path of the folder to delete. | 14 | 15 | --- 16 | 17 | ## Example 18 | 19 | ```luau title="Deleting a folder" linenums="1" 20 | makefolder("folder3") 21 | print(isfolder("folder3")) -- Output: true 22 | delfolder("folder3") 23 | print(isfolder("folder3")) -- Output: false 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/Filesystem/getcustomasset.md: -------------------------------------------------------------------------------- 1 | # `getcustomasset` 2 | 3 | `#!luau getcustomasset` returns a content ID (e.g. `rbxasset://`) that can be used in Roblox APIs for loading audio, meshes, UI images, and other asset types. 4 | 5 | Internally, the file at the given path is copied to the game's content directory and then exposed with a usable asset URL. 6 | 7 | ```luau 8 | function getcustomasset(path: string): string 9 | ``` 10 | 11 | ## Parameters 12 | 13 | | Parameter | Description | 14 | |------------------|--------------------------------------------| 15 | | `#!luau path` | The file path to convert into an asset ID. | 16 | 17 | --- 18 | 19 | ## Example 20 | 21 | ```luau title="Using getcustomasset to load and play a sound in-game" linenums="1" 22 | local encoded = game:HttpGet("https://gitlab.com/sens3/nebunu/-/raw/main/encodedBytecode.txt") 23 | writefile("ExampleSound.mp3", crypt.base64decode(encoded)) 24 | 25 | local asset_id = getcustomasset("ExampleSound.mp3") 26 | 27 | local sound = Instance.new("Sound") 28 | sound.Parent = workspace 29 | sound.SoundId = asset_id 30 | sound.Volume = 0.35 31 | sound:Play() 32 | ``` 33 | -------------------------------------------------------------------------------- /docs/Filesystem/isfile.md: -------------------------------------------------------------------------------- 1 | # `isfile` 2 | 3 | `#!luau isfile` checks whether a given path exists and refers to a file. 4 | 5 | This function is useful when validating input, confirming file existence before reading, or filtering entries returned by [`#!luau listfiles`](./listfiles.md). 6 | 7 | ```luau 8 | function isfile(path: string): boolean 9 | ``` 10 | 11 | ## Parameters 12 | 13 | | Parameter | Description | 14 | |------------------|----------------------------------| 15 | | `#!luau path` | The path to check. | 16 | 17 | --- 18 | 19 | ## Example 20 | 21 | ```luau title="Checking file existence" linenums="1" 22 | print(isfile("nonexistent.txt")) -- Output: false 23 | writefile("file3.txt", "") 24 | print(isfile("file3.txt")) -- Output: true 25 | ``` 26 | -------------------------------------------------------------------------------- /docs/Filesystem/isfolder.md: -------------------------------------------------------------------------------- 1 | # `isfolder` 2 | 3 | `#!luau isfolder` checks whether a given path exists and refers to a folder. 4 | 5 | This is useful when verifying that a directory exists before writing files into it or listing its contents. 6 | 7 | ```luau 8 | function isfolder(path: string): boolean 9 | ``` 10 | 11 | ## Parameters 12 | 13 | | Parameter | Description | 14 | |------------------|----------------------------------| 15 | | `#!luau path` | The path to check. | 16 | 17 | --- 18 | 19 | ## Example 20 | 21 | ```luau title="Checking folder existence" linenums="1" 22 | writefile("file7.txt", "") 23 | makefolder("folder2") 24 | print(isfolder("file7.txt")) -- Output: false 25 | print(isfolder("folder2")) -- Output: true 26 | ``` 27 | -------------------------------------------------------------------------------- /docs/Filesystem/listfiles.md: -------------------------------------------------------------------------------- 1 | # `listfiles` 2 | 3 | !!! info "Relative Paths" 4 | 5 | Please note that paths returned by `#!luau listfiles` are relative to the workspace folder of the executor. 6 | 7 | `#!luau listfiles` returns an array of strings representing all files and folders within the specified directory. 8 | 9 | This can be used to dynamically check which files exist in a folder, etc. 10 | 11 | ```luau 12 | function listfiles(path: string): { string } 13 | ``` 14 | 15 | ## Parameters 16 | 17 | | Parameter | Description | 18 | |------------------|--------------------------------------| 19 | | `#!luau path` | The path to the directory to scan. | 20 | 21 | --- 22 | 23 | ## Example 24 | 25 | ```luau title="Listing files in the root directory" linenums="1" 26 | writefile("file1.txt", "") 27 | writefile("file2.lua", "") 28 | task.wait() 29 | 30 | for _, file in listfiles("") do 31 | if file == "file1.txt" then 32 | print(`Found: {file}`) -- Output: Found: file1.txt 33 | end 34 | if file == "file2.lua" then 35 | print(`Found: {file}`) -- Output: Found: file2.lua 36 | end 37 | end 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/Filesystem/loadfile.md: -------------------------------------------------------------------------------- 1 | # `loadfile` 2 | 3 | `#!luau loadfile` compiles the Luau source code from a file and returns the resulting function (chunk). This chunk runs in the global environment. 4 | 5 | If the file contains syntax errors, an error is thrown - just like [`#!luau loadstring`](https://create.roblox.com/docs/reference/engine/globals/LuaGlobals#loadstring). The error will appear in the console. 6 | 7 | ```luau 8 | function loadfile(path: string): ((A...) -> any | nil, string?) 9 | ``` 10 | 11 | ## Parameters 12 | 13 | | Parameter | Description | 14 | |------------------|-------------------------------------| 15 | | `#!luau path` | The path to the file to be loaded. | 16 | 17 | --- 18 | 19 | ## Examples 20 | 21 | ### Example 1 22 | 23 | ```luau title="Loading and executing a valid file" linenums="1" 24 | writefile("file6.lua", "return 10 + ...") 25 | local chunk = loadfile("file6.lua") 26 | print(chunk(1)) -- Output: 11 27 | ``` 28 | 29 | ### Example 2 30 | 31 | ```luau title="Triggering a syntax error" linenums="1" 32 | writefile("file6.lua", "retrn 10 + ...") 33 | loadfile("file6.lua") -- This will throw an error in the console 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/Filesystem/makefolder.md: -------------------------------------------------------------------------------- 1 | # `makefolder` 2 | 3 | `#!luau makefolder` creates a folder at the specified path if one does not already exist. 4 | 5 | This is useful for organising files into separate directories. 6 | 7 | ```luau 8 | function makefolder(path: string): () 9 | ``` 10 | 11 | ## Parameters 12 | 13 | | Parameter | Description | 14 | |------------------|--------------------------------------| 15 | | `#!luau path` | The folder path to create. | 16 | 17 | --- 18 | 19 | ## Example 20 | 21 | ```luau title="Creating a new folder" linenums="1" 22 | makefolder("test_folder") 23 | print(isfolder("test_folder")) -- Output: true 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/Filesystem/readfile.md: -------------------------------------------------------------------------------- 1 | # `readfile` 2 | 3 | `#!luau readfile` retrieves the contents of a file at the specified path and returns it as a string. 4 | 5 | If the file does not exist or cannot be accessed, the function will **error**. 6 | 7 | ```luau 8 | function readfile(path: string): string 9 | ``` 10 | 11 | ## Parameters 12 | 13 | | Parameter | Description | 14 | |------------------|--------------------------------------| 15 | | `#!luau path` | The file path to read from. | 16 | 17 | --- 18 | 19 | ## Example 20 | 21 | ```luau title="Reading a file" linenums="1" 22 | writefile("file0.txt", "Hello") 23 | print(readfile("file0.txt")) -- Output: Hello 24 | ``` 25 | -------------------------------------------------------------------------------- /docs/Filesystem/writefile.md: -------------------------------------------------------------------------------- 1 | # `writefile` 2 | 3 | `#!luau writefile` writes data to a file at the specified path. If the file already exists, its contents will be overwritten. 4 | 5 | This is one of the primary ways to persist string data within the executor's file sandbox. 6 | 7 | ```luau 8 | function writefile(path: string, data: string): () 9 | ``` 10 | 11 | ## Parameters 12 | 13 | | Parameter | Description | 14 | |------------------|----------------------------------------| 15 | | `#!luau path` | The file path to write to. | 16 | | `#!luau data` | The string data to write into the file.| 17 | 18 | --- 19 | 20 | ## Example 21 | 22 | ```luau title="Basic file writing example" linenums="1" 23 | writefile("file.txt", "Hello world") 24 | print(readfile("file.txt")) -- Output: Hello world 25 | ``` 26 | -------------------------------------------------------------------------------- /docs/Instances/README.md: -------------------------------------------------------------------------------- 1 | # Instances 2 | 3 | The **Instances** library provides direct access to and manipulation of [`Instance`](https://create.roblox.com/docs/reference/engine/classes/Instance) objects in the game world. It includes tools for listing, referencing, and firing Roblox-native interactions. 4 | 5 | These functions are especially useful for inspecting hidden instances, working with UI safely, or simulating player interactions with in-game objects. 6 | 7 | --- 8 | 9 | ## What can you do? 10 | 11 | With the Instances library, you can: 12 | 13 | - **List all objects** tracked by the client using [`#!luau getinstances`](./getinstances.md) 14 | - **List nil-parented objects** using [`#!luau getnilinstances`](./getnilinstances.md) 15 | - **Compare two objects** using [`#!luau compareinstances`](./compareinstances.md) 16 | - **Safely clone instance references** using [`#!luau cloneref`](./cloneref.md) 17 | - **Access hidden UI containers** using [`#!luau gethui`](./gethui.md) 18 | - **Inspect function-based properties** with [`#!luau getcallbackvalue`](./getcallbackvalue.md) 19 | - **Simulate interactions** using [`#!luau fireclickdetector`](./fireclickdetector.md), [`#!luau fireproximityprompt`](./fireproximityprompt.md), and [`#!luau firetouchinterest`](./firetouchinterest.md) 20 | -------------------------------------------------------------------------------- /docs/Instances/cloneref.md: -------------------------------------------------------------------------------- 1 | # `cloneref` 2 | 3 | !!! info "Creates a safe reference to protected instances" 4 | 5 | `#!luau cloneref` returns a reference to an [`#!luau Instance`](https://create.roblox.com/docs/reference/engine/classes/Instance). This can help avoid weak table styled detections. 6 | 7 | `#!luau cloneref` returns a **reference clone** of an [`#!luau Instance`](https://create.roblox.com/docs/reference/engine/classes/Instance). The returned object behaves identically to the original but is not strictly equal (`==`) to it. 8 | 9 | This is commonly used to safely interact with services such as [`#!luau game.CoreGui`](https://create.roblox.com/docs/reference/engine/classes/Players#LocalPlayer), making weak-table style attacks fail. 10 | 11 | ```luau 12 | function cloneref(object: T & Instance): T 13 | ``` 14 | 15 | ## Parameters 16 | 17 | | Parameter | Description | 18 | |---------------|---------------------------------------------------| 19 | | `#!luau object` | The [`#!luau Instance`](https://create.roblox.com/docs/reference/engine/classes/Instance) to clone a safe reference from. | 20 | 21 | --- 22 | 23 | ## Example 24 | 25 | ```luau title="Cloning a safe reference to LocalPlayer" linenums="1" 26 | local players = game:GetService("Players") 27 | 28 | local original = players.LocalPlayer 29 | local clone = cloneref(original) 30 | 31 | print(original == clone) -- Output: false 32 | print(clone.Name) -- Output: Player's name (same as original) 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/Instances/compareinstances.md: -------------------------------------------------------------------------------- 1 | # `compareinstances` 2 | 3 | `#!luau compareinstances` checks if two [`#!luau Instances`](https://create.roblox.com/docs/reference/engine/classes/Instance) are equal. 4 | 5 | This is primarily used for instances which have been [`#!luau cloneref`](./cloneref.md)'d, where the normal equality check with `#!luau ==` fails. 6 | 7 | ```luau 8 | function compareinstances(object1: Instance, object2: Instance): boolean 9 | ``` 10 | 11 | ## Parameters 12 | 13 | | Parameter | Description | 14 | |-----------|----------------------------------| 15 | | `#!luau object1` | This first [`#!luau Instance`](https://create.roblox.com/docs/reference/engine/classes/Instance) to compare. | 16 | | `#!luau object2` | The second [`#!luau Instance`](https://create.roblox.com/docs/reference/engine/classes/Instance) to compare against. | 17 | 18 | --- 19 | 20 | ## Example 21 | 22 | ```luau title="Comparing instances" linenums="1" 23 | print(compareinstances(game, game)) -- true 24 | print(compareinstances(game, workspace)) -- false 25 | print(compareinstances(game, cloneref(game))) -- true 26 | print(game == cloneref(game)) -- false 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/Instances/fireclickdetector.md: -------------------------------------------------------------------------------- 1 | # `fireclickdetector` 2 | 3 | !!! warning "Avoid implementing in Luau" 4 | 5 | This function should **not be implemented** in Luau. Doing so exposes you to easy detection vectors. 6 | 7 | `#!luau fireclickdetector` triggers a [`#!luau ClickDetector`](https://create.roblox.com/docs/reference/engine/classes/ClickDetector) event. By default, it fires the [`#!luau MouseClick`](https://create.roblox.com/docs/reference/engine/classes/ClickDetector#MouseClick) event. 8 | 9 | ```luau 10 | function fireclickdetector(detector: ClickDetector, distance: number?, event: string?): () 11 | ``` 12 | 13 | ## Parameters 14 | 15 | | Parameter | Description | 16 | |------------------|-----------------------------------------------------------------------------| 17 | | `#!luau detector` | The [`#!luau ClickDetector`](https://create.roblox.com/docs/reference/engine/classes/ClickDetector) to trigger.| 18 | | `#!luau distance?` | Distance from which the click is simulated. Defaults to infinite.| 19 | | `#!luau event?` | The event to trigger.| 20 | 21 | --- 22 | 23 | ## Example 24 | 25 | ```luau title="Firing different ClickDetector events" linenums="1" 26 | local click_detector = Instance.new("ClickDetector") 27 | 28 | click_detector.MouseClick:Connect(function(player) 29 | print(`{player.Name} Fired M1`) 30 | end) 31 | 32 | click_detector.RightMouseClick:Connect(function(player) 33 | print(`{player.Name} Fired M2`) 34 | end) 35 | 36 | click_detector.MouseHoverEnter:Connect(function(player) 37 | print(`{player.Name} Fired HoverEnter`) 38 | end) 39 | 40 | click_detector.MouseHoverLeave:Connect(function(player) 41 | print(`{player} Fired HoverLeave`) 42 | end) 43 | 44 | fireclickdetector(click_detector, 0, "MouseClick") -- Output: Player Fired M1 45 | fireclickdetector(click_detector, 0, "RightMouseClick") -- Output: Player Fired M2 46 | fireclickdetector(click_detector, 0, "MouseHoverEnter") -- Output: Player Fired HoverEnter 47 | fireclickdetector(click_detector, 0, "MouseHoverLeave") -- Output: Player Fired HoverLeave 48 | ``` 49 | -------------------------------------------------------------------------------- /docs/Instances/fireproximityprompt.md: -------------------------------------------------------------------------------- 1 | # `fireproximityprompt` 2 | 3 | !!! warning "Avoid implementing in Luau" 4 | 5 | This function should **not be implemented** in Luau. Doing so exposes you to easy detection vectors. 6 | 7 | `#!luau fireproximityprompt` instantly triggers a [`#!luau ProximityPrompt`](https://create.roblox.com/docs/reference/engine/classes/ProximityPrompt), bypassing its [`#!luau HoldDuration`](https://create.roblox.com/docs/reference/engine/classes/ProximityPrompt#HoldDuration) and activation distance. 8 | 9 | ```luau 10 | function fireproximityprompt(prompt: ProximityPrompt): () 11 | ``` 12 | 13 | ## Parameters 14 | 15 | | Parameter | Description | 16 | |-----------------|-----------------------------------------------------------------------------| 17 | | `#!luau prompt` | The [`#!luau ProximityPrompt`](https://create.roblox.com/docs/reference/engine/classes/ProximityPrompt) to trigger. | 18 | 19 | --- 20 | 21 | ## Example 22 | 23 | ```luau title="Triggering a ProximityPrompt manually" linenums="1" 24 | local part = Instance.new("Part", workspace) 25 | local prompt = Instance.new("ProximityPrompt", part) 26 | prompt.ActionText = "Click Me" 27 | 28 | prompt.Triggered:Connect(function(player) 29 | print(player.Name .. " triggered the prompt") 30 | end) 31 | 32 | fireproximityprompt(prompt) -- Output: [YourName] triggered the prompt 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/Instances/firetouchinterest.md: -------------------------------------------------------------------------------- 1 | # `firetouchinterest` 2 | 3 | !!! warning "Avoid implementing in Luau" 4 | 5 | This function should **not be implemented** in Luau. Doing so exposes you to easy detection vectors. 6 | 7 | `#!luau firetouchinterest` simulates a physical touch event between two [`#!luau BasePart`](https://create.roblox.com/docs/reference/engine/classes/BasePart) objects. It can emulate both the start and end of a [`#!luau Touched`](https://create.roblox.com/docs/reference/engine/classes/BasePart#Touched) event. 8 | 9 | ```luau 10 | function firetouchinterest(part1: BasePart, part2: BasePart, toggle: boolean | number): () 11 | ``` 12 | 13 | ## Parameters 14 | 15 | | Parameter | Description | 16 | |----------------|----------------------------------------------------------------------------------------------| 17 | | `#!luau part1` | The initiating [`#!luau BasePart`](https://create.roblox.com/docs/reference/engine/classes/BasePart). | 18 | | `#!luau part2` | The [`#!luau BasePart`](https://create.roblox.com/docs/reference/engine/classes/BasePart) that should be touched. | 19 | | `#!luau toggle` | Whether to simulate touch start or end. `#!luau true` or `#!luau 0` simulates touch; `#!luau false` or `#!luau 1` simulates un-touch. | 20 | 21 | --- 22 | 23 | ## Examples 24 | 25 | ### Example 1 26 | 27 | ```luau title="Simulating a Touched event using 'true/false'" linenums="1" 28 | local dummy_part = Instance.new("Part") 29 | dummy_part.CFrame = CFrame.new(0, -200, 0) 30 | dummy_part.Anchored = true 31 | dummy_part.Parent = workspace 32 | 33 | dummy_part.Touched:Connect(function(part) 34 | print(part.Name .. " touched the dummy part!") 35 | end) 36 | 37 | local player_head = game.Players.LocalPlayer.Character.Head 38 | 39 | firetouchinterest(player_head, dummy_part, true) -- Simulate touch 40 | task.wait(0.5) 41 | firetouchinterest(player_head, dummy_part, false) -- Simulate un-touch 42 | ``` 43 | ### Example 2 44 | 45 | ```luau title="Simulating a Touched event using '0/1'" linenums="1" 46 | local dummy_part = Instance.new("Part") 47 | dummy_part.CFrame = CFrame.new(0, -200, 0) 48 | dummy_part.Anchored = true 49 | dummy_part.Parent = workspace 50 | 51 | dummy_part.Touched:Connect(function(part) 52 | print(part.Name .. " touched the dummy part!") 53 | end) 54 | 55 | local player_head = game.Players.LocalPlayer.Character.Head 56 | 57 | firetouchinterest(player_head, dummy_part, 0) -- Simulate touch 58 | task.wait(0.5) 59 | firetouchinterest(player_head, dummy_part, 1) -- Simulate un-touch 60 | ``` 61 | -------------------------------------------------------------------------------- /docs/Instances/getcallbackvalue.md: -------------------------------------------------------------------------------- 1 | # `getcallbackvalue` 2 | 3 | `#!luau getcallbackvalue` retrieves the **assigned callback property** on an [`#!luau Instance`](https://create.roblox.com/docs/reference/engine/classes/Instance), such as [`#!luau OnInvoke`](https://create.roblox.com/docs/reference/engine/classes/BindableFunction#OnInvoke). 4 | 5 | Normally, these properties are **write-only**, meaning you can assign a function to them but cannot read them back. This function bypasses that limitation and exposes the function directly. 6 | 7 | ```luau 8 | function getcallbackvalue(object: Instance, property: string): any | nil 9 | ``` 10 | 11 | ## Parameters 12 | 13 | | Parameter | Description | 14 | |---------------------|-----------------------------------------------------------------------------| 15 | | `#!luau object` | The [`#!luau Instance`](https://create.roblox.com/docs/reference/engine/classes/Instance) that owns the callback property. | 16 | | `#!luau property` | The name of the callback property to retrieve. | 17 | 18 | --- 19 | 20 | ## Example 21 | 22 | ```luau title="Retrieving a valid callback function, an unset property, and a missing property" linenums="1" 23 | local dummy_bindable = Instance.new("BindableFunction") 24 | local dummy_remote_function = Instance.new("RemoteFunction") 25 | 26 | dummy_bindable.OnInvoke = function() 27 | print("Hello from callback!") 28 | end 29 | 30 | local retrieved = getcallbackvalue(dummy_bindable, "OnInvoke") 31 | retrieved() -- Output: Hello from callback! 32 | 33 | print(getcallbackvalue(dummy_remote_function, "OnClientInvoke")) -- Output: nil 34 | ``` 35 | -------------------------------------------------------------------------------- /docs/Instances/gethui.md: -------------------------------------------------------------------------------- 1 | # `gethui` 2 | 3 | `#!luau gethui` returns a **hidden [`#!luau Instance`](https://create.roblox.com/docs/reference/engine/classes/Instance)** container used for safely storing UI elements. This container is mainly designed to **avoid detections**. 4 | 5 | ```luau 6 | function gethui(): BasePlayerGui | Folder 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |-----------|----------------------------------| 13 | | *(none)* | This function takes no parameters. | 14 | 15 | --- 16 | 17 | ## Example 18 | 19 | ```luau title="Creating undetectable UI in gethui" linenums="1" 20 | local gui = Instance.new("ScreenGui") 21 | gui.Parent = gethui() 22 | gui.Name = "GUI" 23 | 24 | local label = Instance.new("TextLabel") 25 | label.Size = UDim2.fromOffset(200, 50) 26 | label.Text = "Hello from gethui!" 27 | label.Parent = gui 28 | 29 | print(gethui():FindFirstChild(gui)) -- Output: GUI 30 | ``` 31 | -------------------------------------------------------------------------------- /docs/Instances/getinstances.md: -------------------------------------------------------------------------------- 1 | # `getinstances` 2 | 3 | !!! info "Includes all memory-tracked instances" 4 | 5 | `#!luau getinstances` should be able to return [instances](https://create.roblox.com/docs/reference/engine/classes/Instance) outside of [`game`](https://create.roblox.com/docs/reference/engine/classes/DataModel). 6 | 7 | `#!luau getinstances` retrieves **every [`#!luau Instance`](https://create.roblox.com/docs/reference/engine/classes/Instance)** from the registry. Which means that instances that are/were parented to `#!luau nil` will also be returned. 8 | 9 | ```luau 10 | function getinstances(): { Instance } 11 | ``` 12 | 13 | ## Parameters 14 | 15 | | Parameter | Description | 16 | |-----------|----------------------------------| 17 | | *(none)* | This function takes no parameters. | 18 | 19 | --- 20 | 21 | ## Example 22 | 23 | ```luau title="Finding a nil-parented instance" linenums="1" 24 | local dummy_part = Instance.new("Part") 25 | dummy_part.Parent = nil 26 | 27 | for _, instance in pairs(getinstances()) do 28 | if instance == dummy_part then 29 | print("Found the dummy part!") 30 | end 31 | end 32 | ``` 33 | -------------------------------------------------------------------------------- /docs/Instances/getnilinstances.md: -------------------------------------------------------------------------------- 1 | # `getnilinstances` 2 | 3 | `#!luau getnilinstances` returns a list of [`#!luau Instance`](https://create.roblox.com/docs/reference/engine/classes/Instance) objects that are **currently unparented**. These instances exist in memory but are no longer part of the [`#!luau DataModel`](https://create.roblox.com/docs/reference/engine/classes/DataModel) hierarchy. 4 | 5 | ```luau 6 | function getnilinstances(): { Instance } 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |-----------|----------------------------------| 13 | | *(none)* | This function takes no parameters. | 14 | 15 | --- 16 | 17 | ## Example 18 | 19 | ```luau title="Detecting a detached part" linenums="1" 20 | local part = Instance.new("Part") 21 | for _, instance in pairs(getnilinstances()) do 22 | if instance == part then 23 | print("Found our unattached part!") 24 | end 25 | end 26 | ``` 27 | -------------------------------------------------------------------------------- /docs/Metatable/README.md: -------------------------------------------------------------------------------- 1 | # Metatable 2 | 3 | The **Metatable** library enables advanced interaction with [metatables](https://create.roblox.com/docs/luau/metatables) in Luau. It provides direct access to core metamethods and internal table behaviours - including those normally protected or hidden via `#!luau __metatable` locks. 4 | 5 | This library is especially useful when trying to modify or access hidden things within locked Roblox objects. 6 | 7 | --- 8 | 9 | ## What is a metatable? 10 | 11 | A [**metatable**](https://create.roblox.com/docs/luau/metatables) in Luau is a hidden table that can change the behavior of another table. Metatables allow you to define custom behaviors like operator overloading, default values, or interception of table reads and writes using special fields like [`#!luau __index`](https://create.roblox.com/docs/luau/metatables#metamethods) or [`#!luau __newindex`](https://create.roblox.com/docs/luau/metatables#metamethods). 12 | 13 | In Roblox, this is useful for exposing metatables of Roblox Instances so that they can be leveraged for hooking or other modifications. 14 | 15 | --- 16 | 17 | ## What can you do? 18 | 19 | With the Metatable library, you can: 20 | 21 | - **Retrieve** hidden metatables using [`#!luau getrawmetatable`](./getrawmetatable.md) 22 | - **Replace** a table or object's metatable with [`#!luau setrawmetatable`](./setrawmetatable.md) 23 | - **Control** whether a table is locked using [`#!luau setreadonly`](./setreadonly.md) 24 | - **Check** whether a table is locked with [`#!luau isreadonly`](./isreadonly.md) 25 | -------------------------------------------------------------------------------- /docs/Metatable/getrawmetatable.md: -------------------------------------------------------------------------------- 1 | # `getrawmetatable` 2 | 3 | `#!luau getrawmetatable` returns the raw metatable of an object, even if that object has a `#!luau __metatable` field set. 4 | 5 | ```luau 6 | function getrawmetatable(object: { any } | userdata): { [any]: any } | nil 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |------------------|------------------------------------------| 13 | | `#!luau object` | The object whose metatable to retrieve. | 14 | 15 | --- 16 | 17 | ## Examples 18 | 19 | ### Example 1 20 | 21 | ```luau title="Retrieving the metatable of the DataModel" linenums="1" 22 | local mt = getrawmetatable(game) 23 | print(type(mt)) -- Output: table 24 | print(mt.__index(game, "Workspace")) -- Output: Workspace 25 | ``` 26 | 27 | ### Example 2 28 | 29 | ```luau title="Obtaining nil when object has no metatable set" linenums="1" 30 | print(getrawmetatable(newproxy(false))) 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/Metatable/isreadonly.md: -------------------------------------------------------------------------------- 1 | # `isreadonly` 2 | 3 | `#!luau isreadonly` checks whether a table is currently set as **readonly**. 4 | 5 | ```luau 6 | function isreadonly(table: { any }): boolean 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |------------------|-----------------------------------------| 13 | | `#!luau table` | The table to check for readonly status. | 14 | 15 | --- 16 | 17 | ## Example 18 | 19 | ```luau title="Checking if a table is readonly" linenums="1" 20 | print(isreadonly({})) -- Output: false 21 | print(isreadonly(getrawmetatable(game))) -- Output: true 22 | ``` 23 | -------------------------------------------------------------------------------- /docs/Metatable/setrawmetatable.md: -------------------------------------------------------------------------------- 1 | # `setrawmetatable` 2 | 3 | `#!luau setrawmetatable` forcibly sets the metatable of a value, bypassing the `#!luau __metatable` protection field. 4 | 5 | ```luau 6 | function setrawmetatable(object: T & ({ any } | userdata), metatable: { any }): T 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |--------------------|--------------------------------------------------| 13 | | `#!luau object` | The value whose metatable will be overwritten. | 14 | | `#!luau metatable` | The new metatable to assign. | 15 | 16 | --- 17 | 18 | ## Example 19 | 20 | ```luau title="Overriding the metatable of a string" linenums="1" 21 | local dummy_string = "Example" 22 | local string_metatable = setrawmetatable(dummy_string, { 23 | __index = getgenv() 24 | }) 25 | 26 | print(string_metatable) -- Output: Example 27 | print(string_metatable.getgenv) -- Output: function: 0x... 28 | ``` 29 | -------------------------------------------------------------------------------- /docs/Metatable/setreadonly.md: -------------------------------------------------------------------------------- 1 | # `setreadonly` 2 | 3 | `#!luau setreadonly` sets whether a table is **readonly** or **writable**. 4 | 5 | ```luau 6 | function setreadonly(table: { any }, state: boolean): () 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |------------------|----------------------------------------------------------| 13 | | `#!luau table` | The table whose readonly status you want to modify. | 14 | | `#!luau state` | `#!luau true` to lock the table, `#!luau false` to unlock it. | 15 | 16 | --- 17 | 18 | ## Example 19 | 20 | ```luau title="Unlocking a metatable" linenums="1" 21 | local mt = getrawmetatable(game) 22 | mt.Example = "Hello" -- Throws an error 23 | 24 | setreadonly(mt, false) 25 | mt.Example = "Hello" 26 | print(mt.Example) -- Output: Hello 27 | 28 | setreadonly(mt, true) -- Lock back 29 | 30 | ``` 31 | -------------------------------------------------------------------------------- /docs/Miscellaneous/README.md: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | 3 | The **Miscellaneous** library contains functions that do not belong to a specific category. 4 | 5 | --- 6 | 7 | ## What can you do? 8 | 9 | With the Miscellaneous library, you can: 10 | 11 | - **Identify** the current executor and version using [`#!luau identifyexecutor`](./identifyexecutor.md) 12 | - **Send HTTP requests** and receive full responses with [`#!luau request`](./request.md) 13 | 14 | --- 15 | 16 | ## What does [`#!luau request`](./request.md) support? 17 | 18 | The [`#!luau request`](./request.md) function supports a variety of features: 19 | 20 | - Custom HTTP methods (`GET`, `POST`, `PATCH`, `PUT`, `DELETE`) 21 | - Request and response headers 22 | - Request body and cookies 23 | - Built-in executor identification headers, such as `PREFIX-User-Identifier` and `PREFIX-Fingerprint` 24 | 25 | --- 26 | 27 | ## What can't you do? 28 | 29 | - [`#!luau request`](./request.md) is **synchronous** and yields until the server responds - it's not suitable for parallel messaging. 30 | - Some executors may restrict access to external domains (such as the Roblox API for account safety purposes) or block specific methods for security reasons. 31 | - [`#!luau identifyexecutor`](./identifyexecutor.md) should never be relied on as a secure identifier - it's for informational purposes only. 32 | -------------------------------------------------------------------------------- /docs/Miscellaneous/identifyexecutor.md: -------------------------------------------------------------------------------- 1 | # `identifyexecutor` 2 | 3 | `#!luau identifyexecutor` returns the name and version of the currently running executor. 4 | 5 | This function is quite self-explanatory, you use it for logging/debugging purposes, idk - its quite basic. 6 | 7 | The function returns a tuple of: 8 | 9 | 1. `#!luau string` - The name/identifier of the executor. 10 | 2. `#!luau string` - The version string of the executor. 11 | 12 | ```luau 13 | function identifyexecutor(): (string, string) 14 | ``` 15 | 16 | ## Parameters 17 | 18 | | Parameter | Description | 19 | |-----------|--------------------| 20 | | *(none)* | This function takes no parameters. | 21 | 22 | --- 23 | 24 | ## Example 25 | 26 | ```luau title="Getting the current executor and version" linenums="1" 27 | local exec_name, exec_version = identifyexecutor() 28 | print(exec_name, exec_version) -- Output: "YourExploitName 0.0.1" 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/Miscellaneous/request.md: -------------------------------------------------------------------------------- 1 | # `request` 2 | 3 | `#!luau request` sends a [HTTP request](https://en.wikipedia.org/wiki/HTTP) to the given URL using the provided configuration table. It yields until the request is complete and returns a structured response. 4 | 5 | ```luau 6 | type RequestOptions = { 7 | Url: string, 8 | Method: "GET" | "POST" | "PUT" | "PATCH" | "DELETE", 9 | Body: string?, 10 | Headers: { [string]: string }?, 11 | Cookies: { [string]: string }? 12 | } 13 | 14 | type Response = { 15 | Body: string, 16 | StatusCode: number, 17 | StatusMessage: string, 18 | Success: boolean, 19 | Headers: { [string]: string } 20 | } 21 | 22 | function request(options: RequestOptions): Response 23 | ``` 24 | 25 | ## Parameters 26 | 27 | | Parameter | Description | 28 | |-------------------|---------------------------------------------| 29 | | `#!luau options` | A table of fields defining the HTTP request. | 30 | 31 | ### `#!luau RequestOptions` Fields 32 | 33 | | Field | Type | Description | 34 | |---------------|--------------|------------------------------------------------------------| 35 | | `#!luau Url` | `string` | The target URL. | 36 | | `#!luau Method` | `string` | The HTTP [method](https://en.wikipedia.org/wiki/HTTP#Request_methods) (`GET`, `POST`, `PATCH`, or `PUT`). | 37 | | `#!luau Body` | `string?` | (Optional) The request payload. | 38 | | `#!luau Headers` | `{ [string]: string }?` | (Optional) Dictionary of HTTP [headers](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields). | 39 | | `#!luau Cookies` | `{ [string]: string }?` | (Optional) Dictionary of [cookies](https://en.wikipedia.org/wiki/HTTP_cookie). | 40 | 41 | ### `#!luau Response` Fields 42 | 43 | | Field | Type | Description | 44 | |--------------------|------------|------------------------------------------| 45 | | `#!luau Body` | `string` | The returned response body. | 46 | | `#!luau StatusCode` | `number` | The numeric HTTP [status code](https://en.wikipedia.org/wiki/List_of_HTTP_status_codes). | 47 | | `#!luau StatusMessage` | `string` | The human-readable status description. | 48 | | `#!luau Success` | `boolean` | Whether the request was successful. | 49 | | `#!luau Headers` | `{ [string]: string }` | Dictionary of response [headers](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields).| 50 | 51 | ### Automatically added Headers 52 | 53 | Executors will attach this unique header automatically: 54 | 55 | 56 | 57 | 58 | | Header | Description | 59 | |----------------------------|-----------------------------------------------------------------------------| 60 | | `PREFIX-User-Identifier` | Unique user ID that stays consistent across devices for the same user. | 61 | | `PREFIX-Fingerprint` | Hardware-bound identifier (HWID) of the client's machine. | 62 | | [`User-Agent`](https://en.wikipedia.org/wiki/User-Agent_header) | Executor name and version string. | 63 | 64 | --- 65 | 66 | ## Examples 67 | 68 | ### Example 1 69 | 70 | ```luau title="Basic GET request with fingerprint lookup" linenums="1" 71 | local response = request({ 72 | Url = "http://httpbin.org/get", 73 | Method = "GET", 74 | }) 75 | 76 | local decoded = game:GetService("HttpService"):JSONDecode(response.Body) 77 | local retrieved_fingerprint 78 | 79 | for key in pairs(decoded.headers) do 80 | if key:match("Fingerprint") then 81 | retrieved_fingerprint = key 82 | break 83 | end 84 | end 85 | 86 | print(response.StatusCode) -- Output: 200 87 | print(response.Success) -- Output: true 88 | print(retrieved_fingerprint) -- Output: PREFIX-Fingerprint 89 | ``` 90 | 91 | ### Example 2 92 | 93 | ```luau title="Basic POST request with payload" linenums="1" 94 | local response = request({ 95 | Url = "http://httpbin.org/post", 96 | Method = "POST", 97 | Body = "Example" 98 | }) 99 | 100 | print(response.StatusMessage) -- Output: OK 101 | print(response.StatusCode) -- Output: 200 102 | print(game:GetService("HttpService"):JSONDecode(response.Body).data) -- Output: Example 103 | ``` 104 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # sUNC Documentation 2 | 3 | Welcome to the official documentation for **sUNC** - senS' Unified Naming Convention. 4 | 5 | This documentation site serves as the central knowledge base for understanding what sUNC is, how it works, and how to contribute to the project. 6 | 7 | Whether you're an executor developer, a curious tester, or a contributor helping document functions, you're in the right place! 8 | 9 | --- 10 | 11 | ## 📚 Explore the Docs 12 | 13 | - [What is sUNC?](./About/what-is-sunc.md) 14 | - [How sUNC Test Results Work](./About/test-results.md) 15 | - [How to Contribute](./About/contributing.md) 16 | 17 | ## 📜 The script 18 | 19 | ```luau title="The sUNC testing script" linenums="1" 20 | getgenv().sUNCDebug = { 21 | ["printcheckpoints"] = false, 22 | ["delaybetweentests"] = 0 23 | } 24 | 25 | loadstring(game:HttpGet("https://script.sunc.su/"))() -- (1) 26 | ``` 27 | 28 | 1. This loadstring uses [script.sunc.su](https://script.sunc.su/), which is an official mirror of the sUNC script. If the mirror is down or you would like to use the original loadstring, visit [this](https://gitlab.com/sens3/nebunu/-/raw/main/HummingBird8's_sUNC_yes_i_moved_to_gitlab_because_my_github_acc_got_brickedd/sUNCm0m3n7.lua). 29 | 30 | Please note that as of sUNC v2.0, the test now only runs inside of the official testing game. The latest one may be retrieved from [our Discord server](https://discord.gg/FNNfTUpFYv). 31 | 32 | --- 33 | 34 | Thank you for being here. 35 | -------------------------------------------------------------------------------- /docs/Reflection/README.md: -------------------------------------------------------------------------------- 1 | # Reflection 2 | 3 | The **Reflection** library allows access to and manipulation of hidden or non-scriptable properties of [Instances](https://create.roblox.com/docs/reference/engine/classes/Instance) and internal execution context. It is primarily used to bypass standard Luau restrictions in controlled environments. 4 | 5 | --- 6 | 7 | ## What can you do? 8 | 9 | With the Reflection library, you can: 10 | 11 | - **Read** hidden instance properties using [`#!luau gethiddenproperty`](./gethiddenproperty.md) 12 | - **Write** to hidden instance properties with [`#!luau sethiddenproperty`](./sethiddenproperty.md) 13 | - **Toggle** scriptability of properties using [`#!luau setscriptable`](./setscriptable.md) 14 | - **Elevate** thread permissions with [`#!luau setthreadidentity`](./setthreadidentity.md) 15 | - **Query** the current thread's permission level with [`#!luau getthreadidentity`](./getthreadidentity.md) 16 | 17 | These identities are internally refered to as [security context levels](https://github.com/Pseudoreality/Roblox-Identities/), and determine the permissions granted to a thread. 18 | 19 | --- 20 | 21 | ## What can't you do? 22 | 23 | While powerful, the Reflection library carries **detection risks** in sensitive environments: 24 | 25 | - [`#!luau setscriptable`](./setscriptable.md) is detectable by games that check for unusual access. 26 | - Using these methods irresponsibly may break core game logic or introduce unintended side effects. 27 | -------------------------------------------------------------------------------- /docs/Reflection/gethiddenproperty.md: -------------------------------------------------------------------------------- 1 | # `gethiddenproperty` 2 | 3 | !!! warning "Avoid relying on [`#!luau setscriptable`](./setscriptable.md) to implement this function!" 4 | 5 | Some executors implement this function using [`#!luau setscriptable`](./setscriptable.md), which is limited and/or detectable. 6 | 7 | `#!luau gethiddenproperty` retrieves the value of a hidden or non-scriptable property (e.g. `BinaryString`, `SharedString`, `SystemAddress`) from a given [`Instance`](https://create.roblox.com/docs/reference/engine/classes/Instance), even if it would normally throw an error when accessed directly. 8 | 9 | This function also returns whether the accessed property was hidden. 10 | 11 | ```luau 12 | function gethiddenproperty(instance: Instance, property_name: string): (any, boolean) 13 | ``` 14 | 15 | ## Parameters 16 | 17 | | Parameter | Description | 18 | |-----------------------|-------------------------------------------------------| 19 | | `#!luau instance` | The [instance](https://create.roblox.com/docs/reference/engine/classes/Instance) containing the hidden property. | 20 | | `#!luau property_name` | The name of the property to access. | 21 | 22 | --- 23 | 24 | ## Example 25 | 26 | ```luau title="Reading a hidden property" linenums="1" 27 | local part = Instance.new("Part") 28 | 29 | print(gethiddenproperty(part, "Name")) -- Output: Part, false 30 | print(gethiddenproperty(part, "DataCost")) -- Output: 20, true 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/Reflection/getthreadidentity.md: -------------------------------------------------------------------------------- 1 | # `getthreadidentity` 2 | 3 | `#!luau getthreadidentity` retrieves the thread's identity of the running [Luau thread](https://create.roblox.com/docs/reference/engine/libraries/coroutine#running). 4 | 5 | ```luau 6 | function getthreadidentity(): number 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |------------|------------------------------------| 13 | | *(none)* | This function takes no parameters. | 14 | 15 | --- 16 | 17 | ## Example 18 | 19 | ```luau title="Checking thread identity across defer" linenums="1" 20 | task.defer(function() 21 | setthreadidentity(2) 22 | print(getthreadidentity()) -- Output: 2 23 | end) 24 | 25 | setthreadidentity(3) 26 | print(getthreadidentity()) -- Output: 3 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/Reflection/sethiddenproperty.md: -------------------------------------------------------------------------------- 1 | # `sethiddenproperty` 2 | 3 | !!! warning "Avoid relying on [`#!luau setscriptable`](./setscriptable.md) to implement this function" 4 | 5 | Some executors implement this function using [`#!luau setscriptable`](./setscriptable.md), which is limited and/or detectable. 6 | 7 | `#!luau sethiddenproperty` assigns a value to a hidden or non-scriptable property of an [`Instance`](https://create.roblox.com/docs/reference/engine/classes/Instance), even if that property is normally read-only or inaccessible. 8 | 9 | It returns `#!luau true` if the property is hidden and was successfully written to, or `#!luau false` if the property wasn't hidden but was still updated. 10 | 11 | ```luau 12 | function sethiddenproperty(instance: Instance, property_name: string, property_value: any): boolean 13 | ``` 14 | 15 | ## Parameters 16 | 17 | | Parameter | Description | 18 | |-----------------------|--------------------------------------------------------------| 19 | | `#!luau instance` | The [instance](https://create.roblox.com/docs/reference/engine/classes/Instance) that owns the target property. | 20 | | `#!luau property_name` | The name of the property to update. | 21 | | `#!luau property_value` | The new value to assign to the property. | 22 | 23 | --- 24 | 25 | ## Example 26 | 27 | ```luau title="Setting a hidden property value" linenums="1" 28 | local part = Instance.new("Part") 29 | 30 | print(gethiddenproperty(part, "DataCost")) -- Output: 20, true 31 | 32 | sethiddenproperty(part, "DataCost", 100) 33 | 34 | print(gethiddenproperty(part, "DataCost")) -- Output: 100, true 35 | ``` 36 | -------------------------------------------------------------------------------- /docs/Reflection/setscriptable.md: -------------------------------------------------------------------------------- 1 | # `setscriptable` 2 | 3 | !!! warning "Detection risks" 4 | 5 | `#!luau setscriptable` can expose detection vectors. Games may check whether certain properties are unexpectedly accessible, which can lead to detections. 6 | 7 | !!! info "Limited property support" 8 | 9 | Not all hidden properties can be obtained using this function. 10 | 11 | `#!luau setscriptable` toggles the scriptability of a hidden or non-scriptable property on an [`Instance`](https://create.roblox.com/docs/reference/engine/classes/Instance). When a property is made scriptable, it can be accessed or assigned through standard indexing. 12 | 13 | ```luau 14 | function setscriptable(instance: Instance, property_name: string, state: boolean): boolean | nil 15 | ``` 16 | 17 | ## Parameters 18 | 19 | | Parameter | Description | 20 | |-----------------------|----------------------------------------------------------------| 21 | | `#!luau instance` | The [instance](https://create.roblox.com/docs/reference/engine/classes/Instance) that owns the target property. | 22 | | `#!luau property_name` | The name of the property to make scriptable or un-scriptable. | 23 | | `#!luau state` | Whether to enable (`#!luau true`) or disable (`#!luau false`) scriptability. | 24 | 25 | --- 26 | 27 | ## Example 28 | 29 | ```luau title="Temporarily enabling scriptability of a property" linenums="1" 30 | local part = Instance.new("Part") 31 | 32 | setscriptable(part, "BottomParamA", true) 33 | print(part.BottomParamA) -- Output: -0.5 34 | 35 | setscriptable(part, "BottomParamA", false) 36 | print(part.BottomParamA) -- Throws an error 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/Reflection/setthreadidentity.md: -------------------------------------------------------------------------------- 1 | # `setthreadidentity` 2 | 3 | `#!luau setthreadidentity` sets the current [Luau thread](https://create.roblox.com/docs/reference/engine/libraries/coroutine#running) identity and capabilities matching that identity. 4 | 5 | This is commonly used alongside functions like [`#!luau gethiddenproperty`](./gethiddenproperty.md) or [`#!luau getconnections`](../Signals/getconnections.md) which may require elevated access. 6 | 7 | ```luau 8 | function setthreadidentity(id: number): () 9 | ``` 10 | 11 | ## Parameters 12 | 13 | | Parameter | Description | 14 | |-------------------|------------------------------------------------------------------| 15 | | `#!luau id` | The identity level to set the current thread to. | 16 | 17 | --- 18 | 19 | ## Example 20 | 21 | ```luau title="Changing thread identity for privileged access" linenums="1" 22 | setthreadidentity(2) 23 | print(pcall(function() return game.CoreGui end)) -- Output: false (restricted access) 24 | 25 | setthreadidentity(8) 26 | print(pcall(function() return game.CoreGui end)) -- Output: true Instance 27 | ``` 28 | -------------------------------------------------------------------------------- /docs/Scripts/README.md: -------------------------------------------------------------------------------- 1 | # Scripts 2 | 3 | The **Scripts** library provides advanced functions for inspecting and interacting with script objects. It allows you to analyse bytecode, retrieve closures and environments, and simulate the loading or running of scripts. 4 | 5 | --- 6 | 7 | ## What can you do? 8 | 9 | With the Scripts library, you can: 10 | 11 | - **Read compiled bytecode** from scripts using [`#!luau getscriptbytecode`](./getscriptbytecode.md) 12 | - **Get the bytecode hash** of a script using [`#!luau getscripthash`](./getscripthash.md) 13 | - **Create a new closure based off of the script's bytecode** using [`#!luau getscriptclosure`](./getscriptclosure.md) 14 | - **Access script environments** with [`#!luau getsenv`](./getsenv.md) 15 | - **Enumerate script instances** using [`#!luau getscripts`](./getscripts.md) and [`#!luau getrunningscripts`](./getrunningscripts.md) 16 | - **List loaded modules** via [`#!luau getloadedmodules`](./getloadedmodules.md) 17 | - **Determine the current script** executing via [`#!luau getcallingscript`](./getcallingscript.md) 18 | - **Compile and run code at runtime** using [`#!luau loadstring`](./loadstring.md) 19 | -------------------------------------------------------------------------------- /docs/Scripts/getcallingscript.md: -------------------------------------------------------------------------------- 1 | # `getcallingscript` 2 | 3 | !!! info "Notes on `#!luau getcallingscript`" 4 | 5 | If a game script is executing, and `#!luau getcallingscript` is called, it must return the proper [`Script`](https://create.roblox.com/docs/reference/engine/classes/Script), [`LocalScript`](https://create.roblox.com/docs/reference/engine/classes/LocalScript), or [`ModuleScript`](https://create.roblox.com/docs/reference/engine/classes/ModuleScript) - even if the [`#!luau script`](https://create.roblox.com/docs/reference/engine/globals/RobloxGlobals#script) global for said script is set to `#!luau nil`. 6 | 7 | `#!luau getcallingscript` returns the [`#!luau Script`](https://create.roblox.com/docs/reference/engine/classes/Script), [`#!luau LocalScript`](https://create.roblox.com/docs/reference/engine/classes/LocalScript), or [`#!luau ModuleScript`](https://create.roblox.com/docs/reference/engine/classes/ModuleScript) that **triggered the current code execution**. 8 | 9 | ```luau 10 | function getcallingscript(): BaseScript | ModuleScript | nil 11 | ``` 12 | 13 | ## Parameters 14 | 15 | | Parameter | Description | 16 | |-----------|----------------------------------| 17 | | *(none)* | This function takes no parameters. | 18 | 19 | --- 20 | 21 | ## Example 22 | 23 | ```luau title="Detecting the calling script in a hook" linenums="1" 24 | local old; old = hookmetamethod(game, "__index", function(self, key) 25 | if not checkcaller() then 26 | local caller = getcallingscript() 27 | warn("__index access from script:", caller and caller:GetFullName() or "Unknown") 28 | 29 | hookmetamethod(game, "__index", old) -- Restore the original 30 | return old(self, key) 31 | end 32 | 33 | return old(self, key) 34 | end) 35 | 36 | print(getcallingscript()) -- Output: nil, since we called from an executor thread 37 | 38 | ``` 39 | -------------------------------------------------------------------------------- /docs/Scripts/getloadedmodules.md: -------------------------------------------------------------------------------- 1 | # `getloadedmodules` 2 | 3 | !!! warning "Returns only loaded modules" 4 | 5 | This function **only** returns [`ModuleScript`](https://create.roblox.com/docs/reference/engine/classes/ModuleScript) instances that have already been loaded using [`#!luau require`](https://create.roblox.com/docs/reference/engine/globals/LuaGlobals#require). 6 | It does **not** return all [`ModuleScript`](https://create.roblox.com/docs/reference/engine/classes/ModuleScript) objects in the game - for that, use [`#!luau getscripts`](./getscripts.md). 7 | 8 | `#!luau getloadedmodules` returns a list of all [`#!luau ModuleScript`](https://create.roblox.com/docs/reference/engine/classes/ModuleScript) instances that have been **loaded** (e.g. [`#!luau require`'d](https://create.roblox.com/docs/reference/engine/globals/LuaGlobals#require)). 9 | 10 | This includes only modules with completed executions, and **excludes** any modules that errored or haven't been required yet. 11 | 12 | ```luau 13 | function getloadedmodules(): { ModuleScript } 14 | ``` 15 | 16 | ## Parameters 17 | 18 | | Parameter | Description | 19 | |-----------|----------------------------------| 20 | | *(none)* | This function takes no parameters. | 21 | 22 | --- 23 | 24 | ## Example 25 | 26 | ```luau title="Checking if a module has been loaded" linenums="1" 27 | local loaded = Instance.new("ModuleScript") 28 | local not_loaded = Instance.new("ModuleScript") 29 | 30 | pcall(require, loaded) 31 | 32 | for _, module in pairs(getloadedmodules()) do 33 | if module == loaded then 34 | -- The first modulescript was found because it was required in line 4 35 | print("Found loaded module!") 36 | elseif module == notLoaded then 37 | -- The second modulescript should NOT be found because it was never required 38 | print("This should never appear.") 39 | end 40 | end 41 | ``` 42 | -------------------------------------------------------------------------------- /docs/Scripts/getrunningscripts.md: -------------------------------------------------------------------------------- 1 | # `getrunningscripts` 2 | 3 | `#!luau getrunningscripts` returns a list of **all running scripts** in the caller's global state. This includes [`#!luau Script`](https://create.roblox.com/docs/reference/engine/classes/Script), [`#!luau LocalScript`](https://create.roblox.com/docs/reference/engine/classes/LocalScript), and [`#!luau ModuleScript`](https://create.roblox.com/docs/reference/engine/classes/ModuleScript) instances - excluding [`#!luau CoreScripts`](https://robloxapi.github.io/ref/class/CoreScript.html) by default. 4 | 5 | ```luau 6 | function getrunningscripts(): { BaseScript | ModuleScript } 7 | ``` 8 | 9 | ## Parameters 10 | 11 | | Parameter | Description | 12 | |-----------|----------------------------------| 13 | | *(none)* | This function takes no parameters. | 14 | 15 | --- 16 | 17 | ## Example 18 | 19 | ```luau title="Checking for active scripts in the session" linenums="1" 20 | local running = game.Players.LocalPlayer.Character:FindFirstChild("Animate") 21 | local inactive = Instance.new("LocalScript") -- Not running because no bytecode to run 22 | 23 | for _, script in pairs(getrunningscripts()) do 24 | if script == running then 25 | print("Found the running Animate script.") 26 | elseif script == inactive then 27 | print("This should never print.") 28 | print("If this did print, then you have just experienced 1 in a quintillion chance of BITS FLIPPING from radiation. Do you live inside a nuclear reactor?") 29 | end 30 | end 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/Scripts/getscriptbytecode.md: -------------------------------------------------------------------------------- 1 | # `getscriptbytecode` 2 | 3 | !!! info "Notes on `#!luau getscriptbytecode`" 4 | 5 | This function should return `#!luau nil` if the script has no bytecode. This makes it easier to check for absence consistently across executors. 6 | 7 | `#!luau getscriptbytecode` retrieves the bytecode of a [`#!luau LocalScript`](https://create.roblox.com/docs/reference/engine/classes/LocalScript), [`#!luau ModuleScript`](https://create.roblox.com/docs/reference/engine/classes/ModuleScript), and [`#!luau Script`](https://create.roblox.com/docs/reference/engine/classes/Script). 8 | 9 | ```luau 10 | function getscriptbytecode(script: BaseScript | ModuleScript): string | nil 11 | ``` 12 | 13 | ## Parameters 14 | 15 | | Parameter | Description | 16 | |----------------|----------------------------------------------------------| 17 | | `#!luau script` | The script instance to retrieve the bytecode from. | 18 | 19 | --- 20 | 21 | ## Example 22 | 23 | ```luau title="Reading the bytecode of a running script" linenums="1" 24 | local animate = game.Players.LocalPlayer.Character:FindFirstChild("Animate") 25 | 26 | print(getscriptbytecode(animate)) -- Returns bytecode as a string 27 | 28 | print(getscriptbytecode(Instance.new("LocalScript"))) -- Output: nil 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/Scripts/getscriptclosure.md: -------------------------------------------------------------------------------- 1 | # `getscriptclosure` 2 | 3 | !!! info "Closure is compiled from the script's bytecode, not an active one" 4 | 5 | The function returned by `#!luau getscriptclosure` is a **new closure** compiled from the script's bytecode. It is not the function used by the game script, but has identical metadata. This function is usually used to retrieve constants from a script. 6 | 7 | !!! info "Not all scripts have bytecode" 8 | 9 | If the script has no compiled bytecode, this function will return `#!luau nil`. 10 | 11 | `#!luau getscriptclosure` creates and returns a Luau **function closure** from the compiled bytecode of a [`#!luau Script`](https://create.roblox.com/docs/reference/engine/classes/Script), [`#!luau LocalScript`](https://create.roblox.com/docs/reference/engine/classes/LocalScript), or [`#!luau ModuleScript`](https://create.roblox.com/docs/reference/engine/classes/ModuleScript). 12 | 13 | This function is often used to **extract constants or behaviour** from scripts without needing to run them inside the game. 14 | 15 | ```luau 16 | function getscriptclosure(script: BaseScript | ModuleScript): (...any) -> (...any) | nil 17 | ``` 18 | 19 | ## Parameters 20 | 21 | | Parameter | Description | 22 | |----------------|----------------------------------------------------| 23 | | `#!luau script` | The script instance to convert into a function. | 24 | 25 | --- 26 | 27 | ## Example 28 | 29 | ```luau title="Retrieving a script's closure" linenums="1" 30 | local animate = game.Players.LocalPlayer.Character:FindFirstChild("Animate") 31 | 32 | local closure = getscriptclosure(animate) 33 | 34 | print(typeof(closure)) -- Output: function 0x.... 35 | 36 | print(getscriptclosure(Instance.new("LocalScript"))) -- Output: nil 37 | ``` 38 | -------------------------------------------------------------------------------- /docs/Scripts/getscripthash.md: -------------------------------------------------------------------------------- 1 | # `getscripthash` 2 | 3 | !!! info "Do not decrypt or decompress the bytecode" 4 | 5 | The hash must be computed **on the encrypted, compressed bytecode** - not after any modification. 6 | This function should also return `#!luau nil` if the script has no bytecode. 7 | 8 | `#!luau getscripthash` returns a [SHA-384 hash](https://en.wikipedia.org/wiki/SHA-3) in ***hexadecimal format*** of the raw bytecode for a given [`#!luau Script`](https://create.roblox.com/docs/reference/engine/classes/Script), [`#!luau LocalScript`](https://create.roblox.com/docs/reference/engine/classes/LocalScript), or [`#!luau ModuleScript`](https://create.roblox.com/docs/reference/engine/classes/ModuleScript). 9 | 10 | This is useful for **identifying scripts** by their content, especially when checking for known modules or verifying integrity. 11 | 12 | ```luau 13 | function getscripthash(script: BaseScript | ModuleScript): string | nil 14 | ``` 15 | 16 | ## Parameters 17 | 18 | | Parameter | Description | 19 | |----------------|--------------------------------------------------------| 20 | | `#!luau script` | The [BaseScript](https://create.roblox.com/docs/reference/engine/classes/BaseScript) or [ModuleScript](https://create.roblox.com/docs/reference/engine/classes/ModuleScript) instance to hash. | 21 | 22 | --- 23 | 24 | ## Example 25 | 26 | ```luau title="Hashing a live script" linenums="1" 27 | local Animate = game.Players.LocalPlayer.Character:FindFirstChild("Animate") 28 | 29 | print(getscripthash(Animate)) -- Output: 384-bit hash string 30 | 31 | print(getscripthash(Instance.new("LocalScript"))) -- Output: nil 32 | ``` 33 | -------------------------------------------------------------------------------- /docs/Scripts/getscripts.md: -------------------------------------------------------------------------------- 1 | # `getscripts` 2 | 3 | `#!luau getscripts` returns a list of **all [`#!luau Script`](https://create.roblox.com/docs/reference/engine/classes/Script), [`#!luau LocalScript`](https://create.roblox.com/docs/reference/engine/classes/LocalScript), and [`#!luau ModuleScript`](https://create.roblox.com/docs/reference/engine/classes/ModuleScript) instances** present. 4 | 5 | This function excludes [`#!luau CoreScripts`](https://robloxapi.github.io/ref/class/CoreScript.html) by default. 6 | 7 | ```luau 8 | function getscripts(): { BaseScript | ModuleScript } 9 | ``` 10 | 11 | ## Parameters 12 | 13 | | Parameter | Description | 14 | |-----------|----------------------------------| 15 | | *(none)* | This function takes no parameters. | 16 | 17 | --- 18 | 19 | ## Example 20 | 21 | ```luau title="Locating a known script instance" linenums="1" 22 | local dummy_script = Instance.new("LocalScript") 23 | dummy_script.Name = "TestScript" 24 | 25 | for _, script in pairs(getscripts()) do 26 | if script == dummy_script then 27 | print("Found the dummy script!") 28 | end 29 | end 30 | ``` 31 | -------------------------------------------------------------------------------- /docs/Scripts/getsenv.md: -------------------------------------------------------------------------------- 1 | # `getsenv` 2 | 3 | !!! warning "Only works on active scripts" 4 | 5 | This function will throw an error if the script isn't currently running. If the script is running but on a different Lua State (such as on an [Actor](https://create.roblox.com/docs/reference/engine/classes/Actor)), the function will return nil instead. 6 | 7 | `#!luau getsenv` returns the **global environment table** of a given [`#!luau Script`](https://create.roblox.com/docs/reference/engine/classes/Script), [`#!luau LocalScript`](https://create.roblox.com/docs/reference/engine/classes/LocalScript), or [`#!luau ModuleScript`](https://create.roblox.com/docs/reference/engine/classes/ModuleScript). 8 | 9 | This environment contains **all global variables and functions** available to the target script, such as custom-defined functions or state values. 10 | 11 | ```luau 12 | function getsenv(script: BaseScript | ModuleScript): { [any]: any } | nil 13 | ``` 14 | 15 | ## Parameters 16 | 17 | | Parameter | Description | 18 | |----------------|-----------------------------------------------------------------------------| 19 | | `#!luau script` | The script instance whose environment should be retrieved. | 20 | 21 | --- 22 | 23 | ## Example 24 | 25 | ```luau title="Accessing a script's internal environment" linenums="1" 26 | local animate = game.Players.LocalPlayer.Character:FindFirstChild("Animate") 27 | 28 | local env = getsenv(animate) 29 | 30 | print(typeof(env.onSwimming)) -- Output: function 31 | ``` 32 | -------------------------------------------------------------------------------- /docs/Scripts/loadstring.md: -------------------------------------------------------------------------------- 1 | # `loadstring` 2 | 3 | !!! warning "Unsafe by design" 4 | 5 | Compiles the given string, and returns it runnable in a function. The environment must become unsafe after this function is called due to it allowing the modification of globals uncontrollably (see [`#!luau setfenv`](https://create.roblox.com/docs/reference/engine/globals/LuaGlobals#setfenv)/[`#!luau getfenv`](https://create.roblox.com/docs/reference/engine/globals/LuaGlobals#getfenv) documentation). 6 | 7 | !!! info "Should error when compilation fails" 8 | 9 | This function should return `#!luau nil` and an error message if the provided code fails to compile. 10 | 11 | `#!luau loadstring` compiles a string of Luau code and returns it as a runnable function. If the code has errors, `#!luau nil` is returned and an error message is output. 12 | 13 | ```luau 14 | function loadstring(source: string, chunkname: string?): (((A...) -> any) | nil, string?) 15 | ``` 16 | 17 | ## Parameters 18 | 19 | | Parameter | Description | 20 | |---------------------|------------------------------------| 21 | | `#!luau source` | The source code string to compile. | 22 | | `#!luau chunkname?` | Custom chunk name. | 23 | 24 | --- 25 | 26 | ## Examples 27 | 28 | ### Example 1 29 | 30 | ```luau title="Compiling and running source code successfully" linenums="1" 31 | loadstring([[ 32 | placeholder = {"Example"} 33 | ]])() 34 | 35 | print(placeholder[1]) -- Output: Example 36 | ``` 37 | 38 | --- 39 | 40 | ### Example 2 41 | 42 | ```luau title="Using a custom chunk name while also getting an error" linenums="1" 43 | local func, err = loadstring("Example = ", "CustomChunk") 44 | 45 | print(func) -- Output: nil 46 | print(err) -- Output: [string "CustomChunk"]:1: Expected identifier when parsing expression, got 47 | ``` 48 | -------------------------------------------------------------------------------- /docs/Signals/Connection.md: -------------------------------------------------------------------------------- 1 | # The `Connection` object 2 | 3 | !!! info "Notes on the `object`" 4 | 5 | The retrieved connection object will only have the listed methods and fields, since it's a custom object 6 | 7 | A `#!luau Connection` object represents an active link to a signal's callback. These are returned by [`#!luau getconnections`](./getconnections.md) and allow inspection and manipulation over connections/signals. 8 | 9 | --- 10 | 11 | ## Fields 12 | 13 | | Field | Type | Description | 14 | |---------------------|-------------|-----------------------------------------------------------------------------| 15 | | `#!luau Enabled` | `boolean` | Whether the connection is currently active and will respond to events. | 16 | | `#!luau ForeignState` | `boolean` | `#!luau true` if the connection was made from a foreign Luau state (e.g. CoreScript). | 17 | | `#!luau LuaConnection` | `boolean` | `#!luau true` if the connection was created from Luau, not C or foreign code. | 18 | | `#!luau Function` | `(...any) -> (...any)?` | The bound function, or `#!luau nil` if foreign or non-Luau contexts. | 19 | | `#!luau Thread` | `thread?` | The thread that created the connection, or `#!luau nil` in foreign or non-Luau contexts. | 20 | 21 | !!! info "Foreign and C-state behavior" 22 | 23 | If the connection originates from a foreign Lua state or is a C-level connection, `#!luau Function` and `#!luau Thread` will be `#!luau nil` and their `#!luau ForeignState` property will be `#!luau true`. This is due to neither `#!luau Function` or `#!luau Thread` existing on the current Luau VM. 24 | 25 | --- 26 | 27 | ## Methods 28 | 29 | | Method Signature | Description | 30 | |--------------------------------------------|-----------------------------------------------------------------| 31 | | `#!luau Connection:Fire(...: any): ()` | Fires the connected function with given arguments. | 32 | | `#!luau Connection:Defer(...: any): ()` | Defers execution using [`#!luau task.defer`](https://create.roblox.com/docs/reference/engine/libraries/task#defer). | 33 | | `#!luau Connection:Disconnect(): ()` | Disconnects the connection from the signal. | 34 | | `#!luau Connection:Disable(): ()` | Prevents the connection from receiving events. | 35 | | `#!luau Connection:Enable(): ()` | Re-enables a previously disabled connection. | 36 | -------------------------------------------------------------------------------- /docs/Signals/README.md: -------------------------------------------------------------------------------- 1 | # Signals 2 | 3 | The **Signals** library provides functions for inspecting and manipulating [`RBXScriptSignal`](https://create.roblox.com/docs/reference/engine/datatypes/RBXScriptSignal) and [`RBXScriptConnection`](https://create.roblox.com/docs/reference/engine/datatypes/RBXScriptConnection) objects. 4 | 5 | --- 6 | 7 | ## What is a signal? 8 | 9 | A [signal](https://create.roblox.com/docs/reference/engine/datatypes/RBXScriptSignal) in Roblox is an event emitter - an object that can have functions connected to it, which are triggered when something happens. For example, [`Part.Touched`](https://create.roblox.com/docs/reference/engine/classes/BasePart#Touched) is a signal that fires when something touches a part. 10 | 11 | Signals are backed by objects called **connections**, which are instances of an [`RBXScriptConnection`](https://create.roblox.com/docs/reference/engine/datatypes/RBXScriptConnection). 12 | 13 | Exploits will return their own [custom connection object](./Connection.md) when using `#!luau getconnections`. 14 | 15 | --- 16 | 17 | ## What can you do? 18 | 19 | With the Signals library, you can: 20 | 21 | - **Get all connections** attached to a signal using [`#!luau getconnections`](./getconnections.md). 22 | - **Fire** a signal's Luau connections using [`#!luau firesignal`](./firesignal.md). 23 | - **Replicate signals to the server** with [`#!luau replicatesignal`](./replicatesignal.md), if supported by the signal. 24 | 25 | For a list of known replicable signals, click [this](https://rubis.app/view/?scrap=AIOzG1Di7NSLADKE). 26 | -------------------------------------------------------------------------------- /docs/Signals/firesignal.md: -------------------------------------------------------------------------------- 1 | # `firesignal` 2 | 3 | !!! info "Firing mode" 4 | 5 | This function will invoke all the connections of the signal **immediately**, ignoring the [`#!luau Workspace.SignalBehaviour`](https://create.roblox.com/docs/reference/engine/classes/Workspace#SignalBehavior) property. 6 | 7 | `#!luau firesignal` Invokes all Luau [connections](https://create.roblox.com/docs/reference/engine/datatypes/RBXScriptConnection) connected to a given [`#!luau RBXScriptSignal`](https://create.roblox.com/docs/reference/engine/datatypes/RBXScriptSignal). 8 | 9 | ```luau 10 | function firesignal(signal: RBXScriptSignal, ...: any?) 11 | ``` 12 | 13 | ## Parameters 14 | 15 | | Parameter | Description | 16 | |------------------|--------------------------------------------------------| 17 | | `#!luau signal` | The signal whose connections you want to manually fire. | 18 | | `#!luau ...?` | The arguments to pass to the connected functions. | 19 | 20 | --- 21 | 22 | ## Example 23 | 24 | ```luau title="Manually firing a signal with and without arguments" linenums="1" 25 | local part = Instance.new("Part") 26 | 27 | part.ChildAdded:Connect(function(arg1) 28 | print(typeof(arg1)) 29 | end) 30 | 31 | firesignal(part.ChildAdded) -- Output: nil 32 | firesignal(part.ChildAdded, workspace) -- Output: Instance 33 | ``` 34 | -------------------------------------------------------------------------------- /docs/Signals/getconnections.md: -------------------------------------------------------------------------------- 1 | # `getconnections` 2 | 3 | !!! warning "Your game may crash if C connections are not properly supported." 4 | 5 | `#!luau getconnections` retrieves a list of [`Connection`](./Connection.md) objects currently attached to a given [`RBXScriptSignal`](https://create.roblox.com/docs/reference/engine/datatypes/RBXScriptSignal). 6 | 7 | ```luau 8 | function getconnections(signal: RBXScriptSignal): {Connection} 9 | ``` 10 | 11 | ## Parameters 12 | 13 | | Parameter | Description | 14 | |-------------------|-----------------------------------------------| 15 | | `#!luau signal` | The signal to inspect for active connections. | 16 | 17 | --- 18 | 19 | ## Example 20 | 21 | ```luau title="Inspecting and invoking a Luau connection" linenums="1" 22 | local folder = Instance.new("Folder") 23 | folder.ChildAdded:Connect(function() 24 | return "Triggered" 25 | end) 26 | 27 | local connection = getconnections(folder.ChildAdded)[1] -- First connection in the list 28 | print(connection.Function()) -- Output: Triggered 29 | connection:Fire() -- Same as above, Output: Triggered 30 | print(typeof(connection.Thread)) -- Output: thread 31 | ``` 32 | 33 | --- 34 | 35 | ## Example 2 36 | 37 | ```luau title="Accessing a foreign/C connection" linenums="1" 38 | local cconnection = getconnections(game.Players.LocalPlayer.Idled)[1] 39 | print(cconnection.Function) -- Output: nil 40 | print(cconnection.Thread) -- Output: nil 41 | ``` 42 | -------------------------------------------------------------------------------- /docs/Signals/replicatesignal.md: -------------------------------------------------------------------------------- 1 | # `replicatesignal` 2 | 3 | !!! warning "Signal arguments must match" 4 | 5 | Some signals require specific argument structures. If incorrect arguments are passed, an error must be thrown. 6 | 7 | !!! info "Notes on `#!luau replicatesignal`" 8 | 9 | For an accurate result from the examples, test the function in [our game](https://www.roblox.com/games/133609342474444/ROBLOCKS-STOP-PMOING-ME). 10 | 11 | `#!luau replicatesignal` replicates a signal to the server with the provided arguments, if possible. The arguments must also match accordingly to the signal itself. To know a signal's arguments, visit [this](https://robloxapi.github.io/ref/). 12 | 13 | ```luau 14 | function replicatesignal(signal: RBXScriptSignal, ...: any?) 15 | ``` 16 | 17 | ## Parameters 18 | 19 | | Parameter | Description | 20 | |------------------|--------------------------------------------------------| 21 | | `#!luau signal` | The signal to replicate to the server. | 22 | | `#!luau ...?` | Arguments to pass to the signal. | 23 | 24 | --- 25 | 26 | ## Examples 27 | 28 | ### Example 1 29 | 30 | ```luau title="Replicating a ClickDetector interaction" linenums="1" 31 | local detector = workspace.replicatesigmal.ClickDetector 32 | replicatesignal(detector.MouseActionReplicated, game.Players.LocalPlayer, 0) 33 | task.wait(0.1) 34 | 35 | print(game.Players.LocalPlayer:GetAttribute("MouseClickReplicated")) -- Output: true 36 | ``` 37 | 38 | ### Example 2 39 | 40 | ```luau title="Incorrect argument usage" linenums="1" 41 | local ui_frame = game.Players.LocalPlayer.PlayerGui.ScreenGui.Frame 42 | 43 | -- These will throw an error. 44 | replicatesignal(ui_frame.MouseWheelForward) 45 | replicatesignal(ui_frame.MouseWheelForward, 121) 46 | 47 | -- This succeeds 48 | replicatesignal(ui_frame.MouseWheelForward, 121, 214) 49 | task.wait(0.1) 50 | 51 | print(game.Players.LocalPlayer:GetAttribute("MouseWheelForwardReplicated")) -- Output: true 52 | ``` 53 | -------------------------------------------------------------------------------- /docs/WebSocket/README.md: -------------------------------------------------------------------------------- 1 | # WebSocket class 2 | 3 | !!! warning "This is a WebSocket client only, meaning you won't be able to create a server with this library." 4 | 5 | !!! info "The sUNC test explicitly checks for `wss` (secure) support." 6 | 7 | The `#!luau WebSocket` class provides a lightweight interface for establishing and working with WebSocket connections. It allows scripts to **send** and **receive** messages over a persistent connection to a [WebSocket](https://en.wikipedia.org/wiki/WebSocket) server. 8 | 9 | --- 10 | 11 | ## Constructor 12 | 13 | Attempts to create a new connection to the provided URL. The URL must be a valid WebSocket server URL, typically starting with `ws://` (unsecure) or `wss://` (secure). 14 | 15 | ```luau 16 | function WebSocket.connect(url: string): WebSocket 17 | ``` 18 | 19 | ## Parameters 20 | 21 | | Parameter | Description | 22 | |---------------|-----------------------------------------------------------------------------| 23 | | `#!luau url` | A WebSocket URL.| 24 | 25 | --- 26 | 27 | ## Events 28 | 29 | Signals that allow you handle events that occur during the WebSocket's lifetime, such as opening, receiving messages, or closing. 30 | 31 | | Event | Description | 32 | |---------------|-----------------------------------------------------------------------------| 33 | | `#!luau OnMessage(message: string): ()` | Triggered when a message is received over the WebSocket connection.| 34 | | `#!luau OnClose(): ()` | Triggered when the WebSocket connection closes. | 35 | 36 | ## Methods 37 | 38 | | Method | Description | 39 | |---------------|-----------------------------------------------------------------------------| 40 | | `#!luau Send(message: string): ()` | Sends a message over the WebSocket connection. | 41 | | `#!luau Close(): ()` | Closes the WebSocket connection. | 42 | 43 | --- 44 | 45 | ## Examples 46 | 47 | ### Using the `#!luau OnMessage` event, and `#!luau Send` method 48 | 49 | ```luau title="Responding to incoming messages" linenums="1" 50 | local ws = WebSocket.connect("wss://echo.websocket.events") 51 | ws.OnMessage:Connect(function(message) 52 | print(message) 53 | end) 54 | ws:Send("Hello") -- Output: Hello 55 | ``` 56 | 57 | --- 58 | 59 | ### Using the `#!luau OnClose` event, and `#!luau Close` method 60 | 61 | ```luau title="Receive a closing message and catch it via OnClose" linenums="1" 62 | local ws = WebSocket.connect("wss://echo.websocket.events") 63 | ws.OnClose:Connect(function() 64 | print("Closed") 65 | end) 66 | ws:Close() -- Output: Closed 67 | ``` 68 | -------------------------------------------------------------------------------- /docs/assets/dancing-alienchik.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sUNC-Utilities/docs.sunc.su/789f3e7dff1943484e533b70419fddc6ad1ad050/docs/assets/dancing-alienchik.webp -------------------------------------------------------------------------------- /docs/assets/sUNC_FlatSquare.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sUNC-Utilities/docs.sunc.su/789f3e7dff1943484e533b70419fddc6ad1ad050/docs/assets/sUNC_FlatSquare.png -------------------------------------------------------------------------------- /docs/assets/sUNC_Full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sUNC-Utilities/docs.sunc.su/789f3e7dff1943484e533b70419fddc6ad1ad050/docs/assets/sUNC_Full.png -------------------------------------------------------------------------------- /docs/stylesheets/extra.css: -------------------------------------------------------------------------------- 1 | /* light theme */ 2 | :root > * { 3 | --copyright-accent-colour: #606060; 4 | } 5 | 6 | [data-md-color-scheme="sUNC_Light"] { 7 | --md-primary-fg-color: #bc79ff; 8 | --md-primary-fg-color--light: hsla(265, 78%, 85%, 1); 9 | --md-primary-fg-color--dark: hsla(265, 78%, 65%, 1); 10 | --md-primary-bg-color: hsla(0, 0%, 8%, 1); 11 | --md-primary-bg-color--light: hsla(0, 0%, 15%, 1); 12 | 13 | --md-accent-fg-color: hsla(230, 100%, 75%, 1); 14 | --md-accent-fg-color--transparent: hsla(230, 100%, 75%, 0.1); 15 | --md-accent-bg-color: hsla(0, 0%, 12%, 1); 16 | --md-accent-bg-color--light: hsla(0, 0%, 18%, 1); 17 | 18 | --md-code-fg-color: #2a2a2e; 19 | --md-code-bg-color: #f8f8fc; 20 | --md-code-hl-color: #dcd6f0; 21 | --md-code-hl-color--light: rgba(189, 154, 244, 0.15); 22 | 23 | --md-code-hl-number-color: #b3004b; 24 | --md-code-hl-special-color: #8e44ad; 25 | --md-code-hl-function-color: #8e6dfc; 26 | --md-code-hl-constant-color: #4b5cfa; 27 | --md-code-hl-keyword-color: #5271ff; 28 | --md-code-hl-string-color: #008f53; 29 | --md-code-hl-name-color: #2a2a2e; 30 | --md-code-hl-operator-color: #666; 31 | --md-code-hl-punctuation-color: #888; 32 | --md-code-hl-comment-color: #aaa; 33 | --md-code-hl-generic-color: #b06f00; 34 | --md-code-hl-variable-color: #914747; 35 | } 36 | 37 | /* dark theme */ 38 | [data-md-color-scheme="slate"] { 39 | --md-primary-fg-color: #a35ee9; 40 | --md-primary-fg-color--light: #d6c3f8; 41 | --md-primary-fg-color--dark: #9c77d2; 42 | /* --md-primary-bg-color: #121212; */ 43 | --md-primary-bg-color--light: rgba(18, 18, 18, 0.7); 44 | 45 | --md-accent-fg-color: #bd9af4; 46 | --md-accent-fg-color--transparent: rgba(189, 154, 244, 0.1); 47 | /* --md-accent-bg-color: #121212; */ 48 | --md-accent-bg-color--light: rgba(18, 18, 18, 0.7); 49 | 50 | --md-code-fg-color: #e8e6f2; 51 | --md-code-bg-color: #1a1a1d; 52 | --md-code-hl-color: #3a2e4f; 53 | --md-code-hl-color--light: rgba(189, 154, 244, 0.1); 54 | 55 | --md-code-hl-number-color: #f38ba8; 56 | --md-code-hl-special-color: #cba6f7; 57 | --md-code-hl-function-color: #bd9af4; 58 | --md-code-hl-constant-color: #cdd6f4; 59 | --md-code-hl-keyword-color: #94e2d5; 60 | --md-code-hl-string-color: #a6e3a1; 61 | --md-code-hl-name-color: #e8e6f2; 62 | --md-code-hl-operator-color: #cdd6f4; 63 | --md-code-hl-punctuation-color: #b4befe; 64 | --md-code-hl-comment-color: #6c7086; 65 | --md-code-hl-generic-color: #fab387; 66 | --md-code-hl-variable-color: #f2cdcd; 67 | } 68 | 69 | .md-nav__title { 70 | display: none !important; 71 | } 72 | 73 | .md-nav__link { 74 | position: relative; 75 | color: inherit; 76 | } 77 | 78 | .md-nav__item--section > .md-nav__link { 79 | border-bottom: 1px solid rgba(255, 255, 255, 0.068); 80 | padding-bottom: 0.3rem; 81 | margin-bottom: 0.1rem; 82 | } 83 | 84 | .md-nav__link.md-nav__link--active { 85 | padding-left: 0.09rem; 86 | color: var(--md-primary-fg-color); 87 | } 88 | 89 | .md-nav__link.md-nav__link--active:not(:has(.md-nav__icon.md-icon))::before { 90 | content: ""; 91 | position: absolute; 92 | left: 0%; 93 | top: 50%; 94 | transform: translateY(-50%); 95 | height: 60%; 96 | width: 4px; 97 | background: var(--md-primary-fg-color); 98 | border-radius: 2px; 99 | opacity: 0; 100 | animation: navHighlight 0.3s ease forwards, 101 | navIdlePulseBar 3s ease-in-out infinite; 102 | } 103 | 104 | @keyframes navIdlePulseBar { 105 | 0%, 106 | 100% { 107 | transform: translateY(-50%) scaleY(1); 108 | } 109 | 50% { 110 | transform: translateY(-50%) scaleY(1.2); 111 | } 112 | } 113 | 114 | @keyframes navHighlight { 115 | from { 116 | opacity: 0; 117 | left: -0.9rem; 118 | } 119 | to { 120 | opacity: 1; 121 | left: -0.4rem; 122 | } 123 | } 124 | 125 | .md-grid { 126 | max-width: 1500px; 127 | } 128 | -------------------------------------------------------------------------------- /docs/stylesheets/extra.js: -------------------------------------------------------------------------------- 1 | function sleep(ms) { 2 | return new Promise(resolve => setTimeout(resolve, ms)); 3 | } 4 | 5 | document.addEventListener('mouseout', function (e) { 6 | const link = e.target.closest('.md-nav__link'); 7 | const elements = document.querySelectorAll('.md-ellipsis'); 8 | elements.forEach(element => { 9 | if (element.textContent.trim() === "Filtergc") { 10 | element.textContent = "filtergc" 11 | } 12 | }) 13 | if (link && !link.contains(e.relatedTarget)) { 14 | link.blur(); 15 | } 16 | }); 17 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: sUNC Documentation 2 | site_url: https://docs.sunc.su 3 | 4 | repo_name: sUNC-Utilities/docs.sunc.su 5 | repo_url: https://github.com/sUNC-Utilities/docs.sunc.su 6 | edit_uri: edit/main/docs 7 | 8 | plugins: 9 | - search 10 | - git-revision-date-localized: 11 | type: timeago 12 | fallback_to_build_date: true 13 | enabled: true 14 | 15 | markdown_extensions: 16 | - pymdownx.highlight: 17 | anchor_linenums: true 18 | line_spans: __span 19 | pygments_lang_class: true 20 | - pymdownx.superfences: 21 | 22 | - pymdownx.inlinehilite 23 | - pymdownx.snippets 24 | - pymdownx.superfences 25 | - pymdownx.details 26 | - admonition 27 | 28 | theme: 29 | logo: assets/sUNC_Full.png 30 | favicon: assets/sUNC_FlatSquare.png 31 | 32 | icon: 33 | repo: fontawesome/brands/github 34 | edit: material/pencil 35 | view: material/eye 36 | 37 | language: en 38 | 39 | features: 40 | - navigation.instant 41 | # - navigation.instant.prefetch # experimental, prefetches content on link hover. might be unnecessary data usage 42 | - navigation.instant.progress 43 | #- navigation.instant.preview # please check this functionality 44 | - navigation.tracking 45 | # - navigation.tabs 46 | # - navigation.tabs.sticky 47 | - navigation.sections 48 | - navigation.expand 49 | - navigation.path 50 | - navigation.indexes # allows you to provide an index file for each section 51 | - navigation.top 52 | - navigation.footer 53 | # - navigation.prune 54 | 55 | - toc.follow 56 | 57 | - search.suggest 58 | #- search.highlight 59 | 60 | - content.action.edit 61 | - content.action.view 62 | 63 | - content.code.copy 64 | - content.code.select 65 | - content.code.annotate 66 | 67 | custom_dir: overrides 68 | 69 | name: material 70 | font: 71 | text: Nunito Sans 72 | code: JetBrains Mono 73 | 74 | palette: 75 | - media: "(prefers-color-scheme)" 76 | 77 | toggle: 78 | icon: material/brightness-auto 79 | name: Switch to Early Bird mode 80 | 81 | - media: "(prefers-color-scheme: light)" 82 | scheme: sUNC_Light 83 | 84 | toggle: 85 | icon: material/weather-sunny 86 | name: Switch to Night Owl mode 87 | 88 | - media: "(prefers-color-scheme: dark)" 89 | scheme: slate 90 | 91 | toggle: 92 | icon: material/weather-night 93 | name: Switch to automatic mode 94 | 95 | extra_css: 96 | - stylesheets/extra.css 97 | 98 | extra_javascript: 99 | - stylesheets/extra.js 100 | 101 | extra: 102 | generator: false 103 | 104 | analytics: 105 | provider: custom 106 | 107 | social: 108 | - icon: fontawesome/solid/globe 109 | link: https://sunc.su/ 110 | 111 | - icon: fontawesome/solid/bookmark 112 | link: https://numelon.fandom.com/sUNC 113 | 114 | - icon: fontawesome/brands/github 115 | link: https://github.com/sUNC-Utilities/docs.sunc.su 116 | 117 | - icon: fontawesome/brands/discord 118 | link: https://discord.gg/FNNfTUpFYv 119 | -------------------------------------------------------------------------------- /overrides/partials/copyright.html: -------------------------------------------------------------------------------- 1 |

2 | © 2025 sUNC - All Rights Reserved. 3 |
4 | This documentation is the rightful work of generous sUNC contributors and maintainers, who strive to keep everything 5 | clear, accurate, and helpful. 6 |

7 | 8 |

9 | This domain and documentation site are the result of a collaboration between sUNC and the Numelon 10 | Bespoke service by Numelon Ltd. - a company incorporated in 12 | England and Wales 13 | under No. 14 | 15801378. 15 |

16 | 17 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 102 | 103 | -------------------------------------------------------------------------------- /overrides/partials/integrations/analytics/custom.html: -------------------------------------------------------------------------------- 1 | 2 | 4 | -------------------------------------------------------------------------------- /parser/docExtractor.lua: -------------------------------------------------------------------------------- 1 | return function(markdown) 2 | local lines = {} 3 | for line in markdown:gmatch("[^\r\n]+") do 4 | table.insert(lines, line) 5 | end 6 | 7 | local result = { 8 | title = nil, 9 | description = nil, 10 | signature = nil, 11 | parameters = {} 12 | } 13 | 14 | local current = "header" 15 | local insideCodeblock = false 16 | local codeblockLanguage = nil 17 | local insideAdmonition = false 18 | local descriptionCaptured = false 19 | 20 | for i = 1, #lines do 21 | local line = lines[i] 22 | 23 | if line:match("^!!!") then 24 | insideAdmonition = true 25 | goto continue 26 | elseif insideAdmonition then 27 | if line:match("^%s*$") or not line:match("^%s") then 28 | insideAdmonition = false 29 | else 30 | goto continue 31 | end 32 | end 33 | 34 | if line:match("^## Parameters") then 35 | current = "parameters" 36 | elseif line:match("^```") then 37 | if not insideCodeblock then 38 | insideCodeblock = true 39 | codeblockLanguage = line:match("^```(%w+)") 40 | else 41 | insideCodeblock = false 42 | codeblockLanguage = nil 43 | end 44 | elseif line:match("^# ") and current == "header" then 45 | result.title = line:match("^#%s+`(.-)`") or line:match("^#%s+(.-)$") 46 | elseif current == "header" and not descriptionCaptured and line:match("%S") then 47 | result.description = line 48 | descriptionCaptured = true 49 | elseif insideCodeblock and codeblockLanguage == "luau" and not result.signature then 50 | result.signature = line 51 | elseif current == "parameters" and line:match("|") then 52 | local param, desc = line:match("|%s*`.-luau%s+(.-)`%s*|%s*(.-)%s*|") 53 | if param and desc then 54 | result.parameters[param] = desc 55 | end 56 | end 57 | 58 | ::continue:: 59 | end 60 | 61 | return result 62 | end 63 | -------------------------------------------------------------------------------- /parser/efficientArray.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | This is obviously a very rough and quick implementation, and does not handle any clashes at all 3 | 4 | Richy-Z@GitHub, https://richy.lol 5 | ]] 6 | 7 | return function(arr) 8 | local constructed = {} 9 | 10 | for i, v in pairs(arr) do 11 | constructed[v] = true 12 | end 13 | 14 | return setmetatable(constructed, { 15 | __newindex = function() 16 | error("Addition of new items is not permitted") 17 | end, 18 | 19 | __index = function(tebel, key) 20 | if key == "contains" then 21 | return function(_, k) 22 | return constructed[k] or false 23 | end 24 | end 25 | end 26 | }) 27 | end 28 | -------------------------------------------------------------------------------- /parser/exclusions.lua: -------------------------------------------------------------------------------- 1 | local arr = require("efficientArray") 2 | 3 | return arr { 4 | "About", 5 | "assets", 6 | "stylesheets", 7 | "built-info", 8 | "CNAME", -- not required (file, not folder) 9 | "README.md" -- not required (file, not folder) 10 | } 11 | -------------------------------------------------------------------------------- /parser/indexExtractor.lua: -------------------------------------------------------------------------------- 1 | return function(markdown) 2 | local lines = {} 3 | for line in markdown:gmatch("[^\r\n]+") do 4 | table.insert(lines, line) 5 | end 6 | 7 | local constructed = {} 8 | local insideBlock = false 9 | local collect = false 10 | 11 | for i = 1, #lines do 12 | local line = lines[i] 13 | 14 | if line:match("^!!!") then 15 | insideBlock = true 16 | elseif insideBlock and (line:match("^%s*$") or not line:match("^%s")) then 17 | insideBlock = false 18 | end 19 | 20 | if not collect then 21 | if line:match("^# ") then 22 | -- found main header so skip mkdocs block if present 23 | local j = i + 1 24 | while j <= #lines do 25 | local next_line = lines[j] 26 | if next_line:match("^!!!") then 27 | insideBlock = true 28 | j = j + 1 29 | -- skip the mkdocs block properly 30 | while j <= #lines do 31 | local block_line = lines[j] 32 | if block_line:match("^%s*$") or not block_line:match("^%s") then 33 | insideBlock = false 34 | break 35 | end 36 | j = j + 1 37 | end 38 | elseif next_line:match("%S") then 39 | collect = true 40 | i = j - 1 41 | break 42 | end 43 | j = j + 1 44 | end 45 | end 46 | elseif not insideBlock then 47 | if line:match("^%-%-%-$") or line:match("^## ") then 48 | break 49 | end 50 | table.insert(constructed, line) 51 | end 52 | end 53 | 54 | return table.concat(constructed, "\n") 55 | end 56 | -------------------------------------------------------------------------------- /parser/install.sh: -------------------------------------------------------------------------------- 1 | sudo apt update 2 | sudo apt install -y curl 3 | sudo apt install -y openssl 4 | 5 | curl -L https://github.com/luvit/lit/raw/master/get-lit.sh | sh 6 | 7 | sudo mv lit /usr/local/bin/ 8 | sudo mv luvi /usr/local/bin/ 9 | sudo mv luvit /usr/local/bin/ 10 | 11 | lit install -------------------------------------------------------------------------------- /parser/main.lua: -------------------------------------------------------------------------------- 1 | local fs = require("coro-fs") 2 | local json = require("json") 3 | 4 | local exclusions = require("exclusions") 5 | 6 | local extractIndex = require("indexExtractor") 7 | local extractDoc = require("docExtractor") 8 | 9 | local tree = {} 10 | for item in fs.scandir("../docs") do 11 | if item.type == "directory" and not exclusions:contains(item.name) then 12 | local library = {} 13 | 14 | for func in fs.scandir("../docs/" .. item.name) do 15 | if func.type ~= "directory" then 16 | library[func.name:gsub(".md", "")] = fs.readFile(("../docs/%s/%s"):format(item.name, func.name)) 17 | end 18 | end 19 | 20 | tree[item.name] = library 21 | end 22 | end 23 | 24 | local function clean(md) 25 | md = md:gsub("%*%*(.-)%*%*", "%1") --bold 26 | md = md:gsub("%*(.-)%*", "%1") -- italic 27 | md = md:gsub("__(.-)__", "%1") -- underline 28 | md = md:gsub("_(.-)_", "%1") -- italic again but with underscores 29 | md = md:gsub("`(.-)`", "%1") -- inline code 30 | md = md:gsub("%[(.-)%]%b()", "%1") -- markdown links 31 | 32 | return md 33 | end 34 | 35 | local function normaliseSnippets(md) 36 | return md:gsub("`#!luau%s+(.-)`", "`%1`") 37 | end 38 | 39 | local function normaliseUrls(md, libname) 40 | -- "../x/y.md" -> "https://docs.sunc.su/x/y" 41 | md = md:gsub("%.%.%/(.-)%.md", "https://docs.sunc.su/%1") 42 | -- "./x.md" with "https://docs.sunc.su//x" 43 | md = md:gsub("%./(.-)%README.md", "https://docs.sunc.su/" .. libname .. "/%1") 44 | md = md:gsub("%./(.-)%.md", "https://docs.sunc.su/" .. libname .. "/%1") 45 | 46 | return md 47 | end 48 | 49 | --[[ 50 | functions to be cautious of (due to unique doc format) when parsing: 51 | WebSocket library 52 | Connection object under Signals lib 53 | request() function 54 | filtergc() 55 | 56 | uhh more i forgor 57 | ]] 58 | 59 | local bot = {} 60 | for libname, library in pairs(tree) do 61 | bot[libname] = {} 62 | 63 | for func, doc in pairs(library) do 64 | if func == "README" then 65 | local description = extractIndex(doc) 66 | bot[libname]._description = normaliseUrls(normaliseSnippets(description), libname) 67 | bot[libname]._link = "https://docs.sunc.su/" .. libname 68 | elseif func == "WebSocket" then 69 | -- do nothing, we will parse this separately later 70 | elseif libname == "Signals" and func == "Connection" then 71 | -- also do nothing, will parse this later 72 | else 73 | local a = extractDoc(doc) 74 | 75 | a.description = normaliseUrls(normaliseSnippets(a.description), libname) 76 | 77 | --a.description = normaliseSnippets(extractIndex(doc)) 78 | 79 | for param, desc in pairs(a.parameters) do 80 | a.parameters[param] = normaliseUrls(normaliseSnippets(desc), libname) 81 | end 82 | 83 | a.link = string.format("https://docs.sunc.su/%s/%s", libname, func) 84 | 85 | bot[libname][func] = a 86 | end 87 | end 88 | end 89 | 90 | fs.mkdirp("../docs/built-info") 91 | 92 | local bot_json = json.encode(bot, { indent = true }) 93 | fs.writeFile("../docs/built-info/bot.json", bot_json) 94 | 95 | local viewer = {} 96 | 97 | for libname, lib in pairs(bot) do 98 | for k, func in pairs(lib) do 99 | if k ~= "_description" and k ~= "_link" then 100 | viewer[func.title or ""] = clean(func.description or "") 101 | end 102 | end 103 | end 104 | 105 | viewer[""] = nil 106 | 107 | local viewer_json = json.encode(viewer, { indent = true }) 108 | fs.writeFile("../docs/built-info/viewer.json", viewer_json) 109 | -------------------------------------------------------------------------------- /parser/package.lua: -------------------------------------------------------------------------------- 1 | return { 2 | private = true, 3 | name = "Richy-Z/sUNC-documentation-parser", 4 | version = "2.0.1", 5 | description = "A parser for the docs.sunc.su GitHub repository", 6 | tags = { "docs.sunc.su", "documentation", "parser", "sUNC" }, 7 | license = "MIT", 8 | author = { name = "Richard Ziupsnys", email = "hello@richy.lol" }, 9 | homepage = "https://github.com/sUNC-Utilities/docs.sunc.su/tree/main/parser", 10 | dependencies = { 11 | "luvit/json", 12 | "creationix/coro-fs" 13 | }, 14 | files = { 15 | "!*" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | mkdocs-material 2 | mkdocs-git-revision-date-localized-plugin 3 | pygments --------------------------------------------------------------------------------