Maui — Packing Modules as Executable Luau Scripts

Maui Logo

Maui

Roblox Studio Plugin for Packing Modules as Executable Luau Scripts

Roblox Marketplace GitHub Releases Latte Softworks Discord Latte Softworks Twitter


About

Put short, Maui is the full idea of Roblox model/object serialization and script packing put together. This allows developers to use any of the tooling or libraries they wish, all in one packaged script! You could use a workflow with VSCode, Aftman, Rojo, Wally, Roblox-TS, Tarmac, Darklua, etc… Or just good ol’ Roblox Studio! If it’s built down to a Roblox model, you can build it into a script with Maui.

It’s very general purpose, and will pack almost any model you throw at it. Any class, any property, any attribute, and any Lua DataType. As long as it’s configured properly in the API dump and is a Lua-accessable DataType, it’ll build!

Maui is built with LuaEncode, another general-purpose project of mine that was a direct component of this. It will handle any Lua/Roblox-Lua DataType, and even supports vanilla Lua 5.1! If it weren’t for making LuaEncode, Maui wouldn’t be possible.

Also…

The first thing you may be wondering if you clicked on the “Get it on Roblox” button before reading this is probably something along the lines of “Why is this a paid plugin?”. Well, it is and it isn’t. Let me explain.

The plugin, and all of its source code, will always be 100% free (as-in freedom) & open source, under the MIT License. You can download & build from source on the GitHub repository (if you’re worried about security or whatnot), or install a pre-built version directly from the releases page. We also provide the plugin on Roblox’s Developer Marketplace for ~250 Robux, if you want to support us, or just want automatic updates. With a self/pre-built version of the plugin, you’re responsible for keeping it up-to-date in your plugins folder.


Why the Name?

The name of this project was originally going to be “Eclipse”, however, it turned out to be a very generic and overused name, used by multiple other Lua (Roblox) projects. (“Lua” means “Moon”, yeah…) Roblox’s built-in scripting language is named “Luau”, which is a type of traditional party/feast in Hawaiian culture. “Maui” is one of the largest islands in Hawaii, with Luau parties throughout the year. Hence, a non-generic name!


Installation

  • Installation via Roblox Marketplace

    You can purchase the plugin directly here. Remember, you can get the plugin for free directly from GitHub, but you are responsable for maintaining the build on your local machine.

    From there, just “Install” the plugin in Studio from Roblox like normal!

  • Installation via GitHub Releases

    Goto the latest release on the GitHub repository, and download whichever file suites best. (*.rbxm is faster to load, and *.rbxmx is more readable.)

    Do note, pre-built versions of Maui are always minified with Darklua, a Lua formatter. It is not obfuscation, just minification.

    If you don’t know where your specific local-plugins folder is, in Studio, goto the “Plugins” tab via the ribbon-bar, and on the left there should be a “Plugins Folder” button, opening that will prompt the local plugins folder, where you will place the plugin in.

    Where the plugins folder is

  • Building from Source

    We provide a build.sh script, however it will only work with a POSIX-compliant shell. You need everything in aftman.toml installed, preferably with Aftman.

    The following instructions are just for building Maui as quickly as possible, in-case you can’t use build.sh.

    • Clone the Repository (Recursively! We have submodules in use)

      git clone https://github.com/latte-soft/maui.git --recursive && cd maui
      
    • Install Packages w/ Wally

      wally install
      
    • Build Model w/ Rojo

      rojo build -o Maui.rbxm
      

      And you’re done! You can place the built model file into your plugins folder


Usage

In a new/existing Studio place, go to the “Plugins” tab from the ribbon-menu, and you’ll see a button similar to this:

Maui in plugins tab

Upon toggle, you should automatically see the widget, which from there has more instructions in the console! It is always completely synced with your Studio’s color palette theme, with Fusion components similar to Studio’s look & feel.

What the widget's GUI looks like

From there, just select an object, and click “Build”! Due to LuaEncode’s EXTREMELY fast speeds and optimization, Maui usually only takes a few milliseconds to create the output.

After the script is built, Maui should open the output script’s editor window, and Maui will store information logs in the internal console.

Widget gui console output

From there, you’re done! You can run it in a script utility, another script, place it into obfuscation, etc… It’s 100% portable, and will work in almost any Roblox environment!

Remember, because it literally packs a Roblox model, you need to have at least 1 LocalScript (client context) or Script (server context) to actually initialize what you want. You can configure this to ignore context like Script.Disabled or running a script in the wrong context in the project format. By default, if you provide a MainModule, Maui will return the value from it with the exact same behavior as requiring a module by ID on Roblox.


The maui Script Global

In all Maui script closures, a “maui” global is pushed into the environment. You could use it in a script like so:

if maui then -- Then the script is running under Maui's environment!
    print(maui.Version)
end

Here’s the current API reference:

  • Get Version

    <string> maui.Version
    

    Returns a constant of the version of Maui the script was built with.

  • Get Real Script Object

    <Instance: LuaSourceContainer> maui.GetScript(<void>)
    

    Returns the REAL script global from the closure that’s currently running.

  • Get Shared Environment Table

    <table> maui.GetShared(<void>)
    

    Returns a “shared” table for ALL closures in a Maui-generated script, so you don’t need to the real _G or shared.


The .maui Project Format

This is really meant for more advanced projects/modules you’re packing, and right now there really isn’t much outside of minification options.

You can place a module named “.maui” under the model you’re building, and Maui will expect the return to be a table of options. Here’s a Lua template for this:

return {
    FormatVersion = 1, -- Isn't necessary in the project file, but just for future proofing the format incase we ever change anything

    -- All output options
    Output = {
        Directory = "return script.Parent", -- A string/function/instance (supports all) denoting/returning a specific output path in the DataModel, and a string of the filename
        ScriptName = "MauiGeneratedScript", -- The actual name of the output script object, e.g. "SomeScript"
        ScriptType = "LocalScript", -- Accepts "LocalScript", "Script", and "ModuleScript"

        MinifyTable = false, -- If the codegen table itself (made from LuaEncode) is to be minified
        UseMinifiedLoader = true -- Use the pre-minified LoadModule script in the codegen, which is always predefined and not useful for debugging
    },

    -- "Flags" to be respected at runtime
    Flags = {
        ContextualExecution = true, -- If client/server context should be checked at runtime, and ignores LuaSourceContainer.Disabled (e.g. LocalScripts only run on the client, Scripts only run on the server)
        ReturnMainModule = true -- **If applicable**, return the contents of a "MainModule"-named ModuleScript from the root of the model. This behaves exactly like Roblox's MainModule system
    },

    -- Property wl/bl overrides
    Properties = {
        Whitelist = {}, -- [ClassName] = {PropertyName, ...}
        Blacklist = {} --  ^^^
    }
}

You can also use Rojo’s JSON module feature (if you’re using Rojo) to store this module in JSON, which would obviously be a file named “.maui.json”:

{
    "FormatVersion": 1,

    "Output": {
        "Directory": "return script.Parent",
        "ScriptName": "MauiGeneratedScript",
        "ScriptType": "LocalScript",

        "MinifyTable": false,
        "UseMinifiedLoader": true
    },

    "Flags": {
        "ContextualExecution": true,
        "ReturnMainModule": true
    },

    "Properties": {
        "Whitelist": {},
        "Blacklist": {}
    }
}

Still keep in mind, you need to include this file in your *.project.json file, if you’re using Rojo.


Contributing

For now, there really isn’t any specific contribution instructions to follow. We’re still working on our public Luau style-guide, so if you have an idea/implementation of something, show us your idea through an issue or pull-request!


License

This project, and all related files/documents, are licensed under the MIT License. You should have recieved a copy of LICENSE.txt in this program.

README social link icons by @csqrl

18 Likes

Very good plugin, helpful and works like a charm, one of the best plugins that came out of lattesoft.

This is going to make my life much much easier, thanks for sharing!

Not sure what I can say about the developer group, they’re also active in the exploiting community. (this resource was also posted on V3rmillion and they’ve also released exploits like place crashers before)

But when looking at the product, it looks like a clever method to ease CI/CD pipelines for example. Maui is impressively quick compared to other solutions. Thanks for the contribution!

2 Likes

Just because of what the product is itself, it made sense to have that community be a target audience. It mainly solves issues for certain larger developers over there, and it was more or less just to show that it exists

(Currently outside of our control, that’s why we’re releasing more here!) Our community consists of ~95%> of people from that general community, so that’s where the resource was initially spread.

We plan to release other similar-style general purpose, FOSS products for normal developers in the coming future, shifting our userbase overall, and eventually leaving the other forum as a whole.

Also, I plan to add better automation to the plugin in the future, utilizing Rojo’s 2-way-sync API to place output in a specific location over rojo serve, which would make this quite useful with CI.

4 Likes