⚡ SCRIPT EXECUTION - modedp/script-ware-documentation GitHub Wiki

Script Execution Engine

✨Execution, made interesting.

All of Script-Ware's platforms are supercharged by its incredible script execution engine, developed by multiple veteran developers over a long course of time. It is one of the best Lua engines available on the market and it is absolutely optimised and featured to provide a smooth running experience.

Script-Ware allows for fully unrestricted and secure script execution on the client.

What makes Script-Ware so good?

We'll be evidently diving into every part of what you can achieve using our awesome execution engine, but the following awesome features are what Script-Ware comes with:

  • We have implemented 150+ viable (proprietary) custom implementations to our script environment, allowing for an incredible amount of scalability.
  • This means that our environment has been extended to offer compatibility for extremely popular scripts alongside providing a capability to develop extraordinarily advanced scripts.
  • Furthermore, Script-Ware has extremely special features that allow for insane script efficiency, such as the bitstream library
  • Script-Ware is extremely regulated and organised to handle stress and to prevent unexpected crashes during it's execution process.
  • Everything is documented (goes without saying)! We've taken pride in ensuring you are absolutely aware of what every single thing means in your product.

Let's begin the documentation for our script engine.

The Script Environment

What does Script-Ware have that is different?

Our script identity

All scripts are provided with a script identity which details their permissions - what they can and cannot do. These are set to restrict generic scripts to performing malicious activity by abusing APIs.

Unlike generic scripts, Script-Ware runs scripts at a script identity level of 8 (which was previously 6 or 7, hence the term "Level 7" - Script-Ware is always a step ahead 😎). Scripts running at this level allow for complete access to every API and have scot-free access to every permission.

You can test this by quickly running the following script in Script-Ware: printidentity()

8EP78QgrXN6DhrSUyDE-__image

If you run this same script within an in-game script/localscript - it will usually have an identity of 2.

With Script-Ware's elevated script identity, you can receive elevated access to perform things such like being able to place GUI's within game:GetService("CoreGui") - a place where the client will typically never have access to thus making it far safer to use.

However, even better is our gethui function, of which provides you a GUI container that is even harder to access than CoreGui - completely sliding past any and all anti-cheats.

Every single platform we have supported will have an elevated script identity to eight. Utilise this.


With this information understood, we can start diving into the vast functionality Script-Ware offers.

The Script-Ware API

This section will display all the documentation for every Script-Ware implemented, custom, function.

Although the vast majority of these functions are on every Script-Ware platform, some anomalies may lie where-by a function is not actively supported by a certain Script-Ware platform. Be advised, we know! We will eventually implement said functions across all platforms.

However, some of these functions cannot be created on macOS due to restrictions and differences between both operating systems.


Reference

void naturally refers to a function that does not return anything.

[type] refers to an optional parameter, one that does not need to have anything passed to it.

any refers to it taking any type of datatype within its argument.

Multiple declarations for a function indicate that they are the same functions (typically for compatibility)

Script-Ware Functions

These functions are typically special to Script-Ware in the sense that they provide information about Script-Ware or load scripts via Script-Ware.

⚠️ Some of these are only available on certain platforms!


Get Executor Name

string getexecutorname()
string identifyexecutor()

Simply returns "ScriptWare" to signal the identity of the executor that is running the script.


Import Script From Script Catalogue

void import(int scriptnumber)

Executes the script from the script catalogue as if you were running it from the executor. To get a script's id, refer to the script link: https://dashboard.script-ware.com/catalogue?scriptID=18, in this case 18 is the script number and can be executed by being passed to import.


Is Our Closure

bool isourclosure(function f)
bool isexecutorclosure(function f)

Returns true of the function passed is a Script-Ware function, returns false otherwise.


Script-Ware Execute

<void> executescript(union<string, number> script, <table?> settings)

Executes "script" as if it was being run from the Script-Ware editor. If "script" is a number, it will import the script id from the catalogue.

image

Create Script Global:

image

Mode:

image


Print to Output

void outputprint(int type, string message)

Prints "message" to the Script-Ware Output Page using type.

image

They will appear as "SCRIPT INFO", "SCRIPT WARN" & "SCRIPT ERROR" in the output page respectively.

Environment Functions

These functions allow you to read into environments (and instances).

All Script-Ware platforms support these functions!


Loadstring

union loadstring(string chunk, [string chunk_name])

Attempts to load "chunk", returns a valid function is successful. You can set an optional chunk name via "chunk_name".


Get Identity

number getidentity()
number getthreadidentity()
number getthreadcontext()

Returns the identity for the current thread.


Get Script From Thread

Instance getscriptfromthread(thread t)

Returns the script from thread even if the script does "script = nil"


Get Hidden UI

instance gethui()

Returns a holder made for GUI's to be parented in. It hides children from FindFirstChild attacks and does not fire game.DescendantAdded.


Get Global Environment

table getgenv()

Returns the Script-Ware environment


Get Game Environment

table getrenv()

Returns the global game environment

Get Registry

table getreg()

Returns the Lua registry.


Get Garbage Collection

table getgc(bool include_tables)

Returns the garbage collector table.


Get Script Environment

table getsenv(LocalScript/ModuleScript script)

Returns the environment of "script".


Get Instances

table<instance> getinstances()

Returns every single instance in the client.


Get Nil Instances

table<instance> getnilinstances()

Returns every instance in the game that is parented to nil.


Get Connections

table<Connections> getconnections(Connections signal)

Get a list of active connections to the provided signal.


Get Hidden Property

variant gethiddenproperty(instance object, string property)

Returns the hidden "property" from "object". Not all internal types are pushable to Lua, we currently support "BinaryString, SharedString and SystemAddress". If SystemAddress is pushed it returns a table like so: "{Address = x, Port = x}"


Set Hidden Property

void sethiddenproperty(Instance object, string property, variant value)

Set's "object"'s hidden "property" value to "value".


Set Hidden

bool sethidden(Instance, string property, bool value)

Sets whether a property is hidden or not using value. Returns old visibility status.


Is Hidden Property

bool ishiddenproperty(Instance object, string property)

Returns true if property is hidden, false is the property isn't hidden, nil if the property doesn't exist.


Get Properties

table getproperties(Instance object)

Returns a array of property names on said object.


Get Hidden Properties

table gethiddenproperties(Instance object)

Returns a array of hidden property names on said object.


Get Script Bytecode

string getscriptbytecode(Instance script)
string dumpstring(Instance script)

Gets the Luau bytecode of a script, useless if you don't know what you're doing. Using the Bitstream library is recommended if you plan to do any parsing, it has built in LEB128.


Get Script Hash

string getscripthash(Instance script)

Gets the hashed bytecode of the specified "script" and returns it. This is useful for comparing game scripts to see if the developers have changed their scripts.


Get Loaded Modules

table getloadedmodules(bool filter)

Returns all ModuleScripts loaded in the game. If "filter" is false it will not filter our core items.

Metatable Functions

Functions related to metatable manipulation. ✅ All Script-Ware platforms support these functions!


Get Raw Metatable

table getrawmetatable(union obj)

Returns the metatable value of "obj", bypassing the __metatable field.


Set Raw Metatable

void setrawmetatable(union obj, table newmetatable)

Set's the metatable of "obj" to "newmetatable".


Set Read-Only

void setreadonly(table tab, bool state)

Set's the read-only state of "tab" to "state" - setting whether it can be written to or not.


Is Read-Only

bool isreadonly(table tab)

Returns the read-only state of "tab".


Is Writable

bool iswritable(table tab)

Returns if "tab" is writable (not read-only).


Make Writable

void makewritable(table tab)

Makes "tab" writable (sets the read-only status to false).


Make Read-Only

void makereadonly(table tab)

Makes tab read-only (sets the read-only status to true).

Closure Functions

Referring to closure manipulation.

All Script-Ware platforms support these functions!

Get Script Closure

function getscriptclosure(Instance script)

Returns a new copy of the script's closure.


New CClosure

function newcclosure(function f)

Returns a wrapped CClosure of "f".


Hook Function

function hookfunction(function old, function hook)

Hooks the function specified in "old" - replacing it with "hook".


Check Caller

bool checkcaller()

Returns if the current function is being called by Script-Ware or not.


Get Calling Script

instance<union> getcallingscript()

Returns the script that called the function. Even gets scripts that call "script = nil"

NOTE: Script-Ware created functions will always return nil.


Is Lua Closure

bool islclosure(function f)

Returns whether "f" is a Lua closure.


Is C Closure

bool iscclosure(function f)

Returns whether "f" is a CClosure


Check Closure

bool checkclosure(function f)

Returns whether "f" is a closure created by Script-Ware.

Instance Saving Functions

Instance Saving Functions ⚠️ Some of these are only available on certain platforms!


Set Studio Clipboard

void setrbxclipboard(string data)

Sets the studio clipboard to data allowing the data to be pasted inside of studio.

The data must be in a valid xml/binary model format or it will not work.

Example:

saveinstance(object,"clipboard.rbxm")
setrbxclipboard(readfile("clipboard.rbxm"))

Get PhysicalConfigData

variant getpcd(instance obj)

Returns content of the PhysicalConfigData of "obj".

NOTE: It is not recommended you use this, just do gethiddenproperty(obj, "PhysicalConfigData") instead. This function exists for compatibility and ease of use, however, it is deprecated.


Save Instance

void saveinstance(tuple<Instance,Array> obj, string filename, table options)

Allows you to serialize instances into model/place files allowing you to inspect them in studio.

If "obj" is an instance it serializes into a model file, if it is "game" it will be written to a place file. (as in .rblx if its in binary mode)

"filename" is the name of the file it will write to.

If "obj" is a table then it will serialize the instances of the numerical indices of the table into a model file.

Options

image

Network Functions

Functions that refer to network ownership manipulation. ✅ All Script-Ware platforms support these functions!


Is Network Owner

bool isnetworkowner(instance part)

Returns true if you are the current network owner of "part".


Set Simulation Radius

void setsimulationradius(int simulationradius)

Sets your physical simulation radius to "simulationradius"


Get Simulation Radius

int getsimulationradius()

Returns the current set physical simulation radius of the LocalPlayer.

Input Functions

These functions are related to inputting mouse activity and key activity into the window process through Lua. ✅ All Script-Ware platforms support these functions!


Is Active

function isrbxactive(): boolean

Returns true is the main window is in focus.

This must return true for any of the other functions to work.

This doesn't mean you must call it, but the main window must be in focus for the other functions to work.


Keyboard

function keypress(key: number)

Performs a keypress with the provided key - you can read on keys available here.

function keyrelease(key: number)

Performs a key release with the provided key.


Mouse Clicking

Left Button

function mouse1click()

Stimulates a full left mouse click (press and release).

function mouse1press()

Stimulates a left mouse press (button is pressed but not released).

function mouse1release()

Stimulates a left mouse release (button is released after being pressed).

Right Button

function mouse2click()

Stimulates a full right mouse click (press and release).

function mouse2press()

Stimulates a right mouse press (button is pressed but not released).

function mouse2release()

Stimulates a right mouse release (button is released after being pressed).


Mouse Movement

function mousescroll(pixels: number)

Scrolls the mouse wheel by "pixels".

function mousemoverel(x: number, y: number)

Moves the mouse relative to the current mouse position by coordinates "x" and "y".

function mousemoveabs(x: number, y: number)

Moves the mouse to the coordinates "x" and "y" from the top left of the main window.


Example

local player = game.Players.LocalPlayer 
local camera = workspace.CurrentCamera
local m = player:GetMouse()

while wait(1) do
    local pos = camera:WorldToScreenPoint(player.Character.Head.Position)
    mousemoverel(pos.X - m.X, pos.Y - m.Y) --moves the camera to the position of the LocalPlayers head.
end

Filesystem Functions

These functions allow for the manipulation and analysis of files in respective locations.

⚠️ Some of these are only available on certain platforms!

Files can only be written to the workspace folder.

Don't be afraid of potentially malicious scripts that could install malware or flood your folders. Only the workspace folder can have files programatically created, deleted and written to.


Read Dialog

function readdialog(title: string, filter: string): tuple<bool, string>

aZBcahEok2zDYWnvEJQh4_2021-02-07_15-56-16

Result of dialog call

Opens a read file dialog with title and filter.

See for docs on filter: https://docs.microsoft.com/en-us/windows/win32/api/commdlg/ns-commdlg-openfilenamea

This allows for the user to select a file anywhere on their computer. If the user selects a file true is return with the file data. If the user doesn't select a file then false is return a long with nil.

Note: Both writedialog and readdialog are async. They will not hang the process.


Write Dialog

function writedialog(title: string, filter: string, data: string): bool

Makes a write file dialog with title and filter.

When a user selects a file data is written to selected file and true is returned.

Use cases: Saving lists of data(ex. sound logs, chat logs, remote logs, etc.), Saving images directly out of the game.


Read File

function readfile(path: string): string

Reads the content of the file located in "path" and returns it. This function provides descriptive errors to notify you if there has been a problem during this process.


Write File

function writefile(path: string, content: string, usecontentfolder: bool?): string

Writes a file in "path" with the data specified in "content". If "usecontentfolder" is set to true it will write to the content folder rather than workspace.


Append File

function appendfile(path: string, content: string)

Appends "content" to the file located in "path".


Load File

function loadfile(path: string): variant

Loads content of file located in "path" as a chunk and returns a valid function if successful.


Do File

function dofile(path: string)

Attempts to load and execute the file located in "path".


List Files

function listfiles(folder: string): table<string>

Returns a table of all the files located in "folder" (a path to the folder).


Is Folder

function isfolder(path: string): bool

Returns true if "path" leads to a folder.


Is File

function isfile(path: string): bool

Returns true if "path" leads to a file.


Make Folder

function makefolder(path: string)

Creates a new folder at "path".


Delete Folder

function delfolder(path: string)

Deletes the folder located at "path". Errors if no folder was located.


Delete File

function delfile(path: string)

Deletes the file located at "path". Errors if no folder was located.

Profile Functions

Alas! There is no more need to utilise chunky and often easily (accidentally) deleted folders within workspace to store user data to then utilise it later on. Using Script-Ware's novel profile functions, this makes this far cleaner.

You are able to create multiple profiles under one setting, making it especially nice to organise certain areas of your script.

This should be cross software (provided other products follow this guideline).

Settings are written to the App Data folder, under a new "ExecutorProfiles" folder.

Setting is the parent for the profiles, it is the folder that holds the profile.

Profile is the actual data holder, it is a file (file.profile) of which is under Setting

⚠️ These functions are only available on Windows!


Write Profile

function writeprofile(setting: string, profile: string, data: string)

Creates a new folder named "setting", and within the setting a new "profile" is made named profile containing "data" as its content. If the setting already exists, the profile is just made within it.


Get Profile

function getprofile(setting: string, profile: string)
function readprofile(setting: string, profile: string)

Reads the "content" of the existing "profile" and returns the content.


Delete Setting

function: deletestring(setting: string)

Deletes an entire setting, including profiles within the setting.


Delete Profile

function deleteprofile(setting: string, profile: string)

Deletes the specified profile located within the specified setting.


Get Setting Profiles

function getsettingprofiles(setting: string): table

Returns all profiles under specified setting in a table.


Is Setting

function issetting(setting: string): bool

Returns whether or not the specified setting exists.


Is Profile

function isprofile(setting: string, profile: string): bool

Returns whether the profile exists within the specified setting


Example

local DefaultSettings = {
    MaxHealth = 100,
    Health = 50,
}

local function EncodeJson(x)
    return game:GetService("HttpService"):JSONEncode(x)
end

local function DecodeJson(x)
    return game:GetService("HttpService"):JSONDecode(x)
end

local Settings

if not isprofile("MyEpicSettings", "Profile1") then
    writeprofile("MyEpicSettings", "Profile1", EncodeJson(DefaultSettings))
    Settings = DefaultSettings
else
    Settings = DecodeJson(getprofile("MyEpicSettings", "Profile1"))
end

print("Health", Settings.Health)
print("Max Health", Settings.MaxHealth)

Console Functions

Script-Ware allows for the user to generate a console of which can be printed to, coloured, used to log, error & more. This can be useful for safely debugging a script.

⚠️ These functions are only available on Windows!


Start Console

function consolecreate()
function rconsolecreate()

Opens a console without any text inside of it. A default console title will be set.


Printing to Console

function consoleprint(message: string, colour: string?)
function rconsoleprint(message: string, colour: string?)

Prints "message" to the console and takes an optional colour argument. If none is given, the default will be white.

image

NOTES:

"u(colour)" will underline the message.

"b(colour)" will bold the message.


Set the console title

function consolesettitle(title: string)
function rconsolesettitle(title: string)

Set the console's title to "title".


Console Input

function consoleinput(): string
function rconsoleinput(): string

Allows the user to enter something in the console, and returns what they have entered.


Clear Console

function consoleclear()
function rconsoleclear()

Clears the console out entirely (all prints are gone).


Destroy Console

function rconsoledestroy()
function consoledestroy()

Puts the console away, when re-shown - the previous data will remain.

Miscellaneous Functions

These are functions that do not fit into a specific category.

⚠️ Some of these are only available on certain platforms!


getcallbackvalue

function getcallbackvalue(inst: Instance, callbackname: string)

Gets the callback function of the given callback on the given instance.

Example:

local RemoteFunc = Instance.new("RemoteFunction")
RemoteFunc.OnInvoke = function() print("hi") end

print(RemoteFunc.OnInvoke) --> fails
print(getcallbackvalue(RemoteFunc, "OnInvoke")) --> function 0xDEADBEEF

Clipboard

Set Clipboard

function setclipboard(text: string)
function toclipboard(text: string)

Sets the users studio clipboard to "text".


Get Custom Asset

function getcustomasset(filename: string, preventcache: bool?): string

Makes a custom content-id from filename allowing you to load your own content from the workspace folder. if "preventcache" is enabled, it will force the content to not cache allowing it to be reloaded.

Get Custom Asset Example

-- Custom Asset Image Displayer "Creates a simple GUI which loads images from a URL inputted."

local function loadCustomAsset(url,filename,reusable)
    local data = game:HttpGet(url)
    writefile(filename,data)
    
    return getcustomasset(filename,reusable)
end

local gui = Instance.new("ScreenGui")
local label = Instance.new("ImageLabel",gui)
label.Size = UDim2.new(0,500,0,500)
local textBox = Instance.new("TextBox",label)
textBox.Size = UDim2.new(1,0,0,25)
textBox.Position = UDim2.new(0,0,1,-25)
textBox.FocusLost:Connect(function(enter)
    if enter then
        label.Image = loadCustomAsset(textBox.Text,"displayImage.png",true)
        textBox.Text = ""
    end
end)
gui.Parent = game:GetService("Players").LocalPlayer.PlayerGui

Clone Ref

function cloneref(data: userdata): userdata

This takes a userdata and copies it.


Message Box

function messagebox(text: string, caption: string, flags: int): int

Creates a message box that appears from the game, it returns the user's input. This is ran async.

Flags

image

It returns an integer of which reflects the following events:

Responses

image


String Compression

function compress_string(text: string, algorithm: string): string

Compresses "text" using the compression "algorithm" specified in the next argument - returns the compressed string.


Algorithms

image

String Decompression

function decompress_string(text: string, algorithm: string, lz4size: int?): string

Decompresses "text" using the supported compression "algorithm" specified (being the ones above), this also optionally takes the "lz4size". Returns the decompressed string.

Lz4 Compress

function lz4compress(text: string): string

Compresses "text" using only the lz4 compression algorithm - returns the result.

Lz4 Decompress

function lz4decompress(text: string, size: int): string

Decompresses "text" using only the lz4 compression algorithm, takes the size as the second parameter - returns the result.


Set Fast Flag

function setfflag(fflag: string, value: string)

Sets FFlag "flag" to "value".


Set Script Identity

function setidentity(identity: number)

Sets the current thread's identity to "identity".


Queue on teleport

function queue_on_teleport(script: string)

Executes "script" upon successful teleport.


Set Namecall Method

function setnamecallmethod(method: string)

Sets current namecall method to new namecall "method". Assumes the function is called in a metamethod hook.


Get Namecall Method

function getnamecallmethod(): string

Returns the current namecall method. Assumes the function is called in a metamethod hook.


Set Parent Internal

function setparentinternal(object: Instance, newparent: Instance)

Internally sets the parent property of "object" to "newparent". This does not trigger any events or anything, this includes it not being to any children lists. If you want that behavior use this along with addchildinternal.


Add Child Internal

function addchildinternal(parent: Instance, child: Instance)

Adds a child to an instance without firing any signals (thwarts event-based detection)


Remove Child Internal

function removechildinternal(parent: Instance, child: Instance)

Remove a child in an instance without firing any signals. NOTE: You must have a reference to the child in the parent in order to delete it.


Fire Proximity Prompt

function fireproximityprompt(proximity: Instance)

Triggers the Proximity Prompt that was passed to "proximity". This is replicated to the server!


Fire Click Detector

function fireclickdetector(detector: Instance, distance: number?, flag: string?)

Fires a Click Detector with the given distance provided, if none is provided, the distanced clicked is defaulted to 0. The different flags to fire the event with are as follows:

image

If no flag is provided, the function defaults to "MouseClick".

Fire Click Detector Example

local ClickDetector = game:GetService("Workspace").MyPart.ClickDetector

fireclickdetector(ClickDetector, 50, "RightMouseClick")
-- Fires the Click detector at a 50 stud range and fires the ClickDetector.RightMouseClick:Connect() signal

NOTE: The click detector will not fire if "ClickDetector.MaxActivationDistance" is greater than the distance provided.


Fire Touch Interest

function firetouchinterest(o1: Instance, o2: Instance, begin: number?)

If "begin" is 0, it begins the touch; if 1, it ends the touch.


Fire Signal

function firesignal(event: RBXScriptSignal)

Fires all signals attached to "event"


Set Proximity Prompt Duration

function setproximitypromptduration(proximity: obj, duration: number)

Sets the duration of the proximity prompt to duration.


Get Proximity Prompt Duration

function getproximitypromptduration(proximity: obj): number

Returns the current proximity prompt duration.


GetObjects

function game:GetObjects(url: string): table

A full custom implementation of GetObjects, this returns all objects whereas the common implementation (often just an alias for the LoadLocalAsset function) merely returns the first asset.

Other Functions

This is an extension to miscellaneous functions, functions that also do not fall under certain criteria.

All Script-Ware platforms support these functions!


Request

function http.request(options: table): table
function request(options: table): table

Creates an HTTP request using the conventionally made "options".

Script-Ware Headers

image

Request Fields

image

Response Fields

image

Libraries

Script-Ware comes equipped with many of its own, viable, libraries which contain various functions that fit the library names.

These libraries are:

  • Drawing Library
  • Cache Library
  • Bit Library
  • Websocket Library
  • Debug Library
  • Crypt Library

We will discuss these libraries and what content they contain - alongside providing examples for them.

Cache Library

⚠️ These functions are only available on Windows!


Invalidate Cache

void cache.invalidate(Instance obj)

Invalidates instance "obj" in the cache.


Replace Cache

void cache.replace(Instance oldguy, Instance newhire)

Replaces the "oldguy" in the cache with the "newhire".


Is Cached

bool cache.iscached(Instance obj)

Returns true if instance "obj" is cached.

Bit Library

These functions are here for compatibility, since, these functions are naturally supported. See here.

All Script-Ware platforms support these functions!


Bit Functions

Or

int bit.bor(int x, int y)

Returns bitwise or of "x" and "y".


And

int bit.band(int x, int y)

Returns bitwise and of "x" and "y".


Not

int bit.banot(int x)

Returns bitwise not of "x".


Xor

int bit.bxor(int x, int y)

Returns bitwise xor of "x" and "y".


Add

int bit.badd(int x, int y)

Performs binary addition on "x" and "y", returns the answer.


Subtract

int bit.bdsub(int x, int y)

Performs binary subtraction on "x" and "y", returns the answer.


Divide

int bit.bdiv(int x, int y)

Performs binary divison on "x" and "y", returns the answer.


Multiply

int bit.bmul(int x, int y)

Performs binary multiplication on "x" and "y", returns the answer.


Swap

int bit.bswap(int x)

Swaps the bytes of "x" and returns it.


Left Shift

int bit.blshift(int x, int y)

Returns the result of a logical bitwise left-shift of "x" by the bits provided by "y".


Right Shift

int bit.brshift(int x, int y)

Returns the result of a logical bitwise right-shift of "x" by the bits provided by "y".


To Bit

int bit.btobit(int x, int y)

Returns "x" represented as a binary number.


To Hex

int bit.btohex(int x, int y)

Returns "x" represented in hexadecimal.

Debug Library

Re-implementation of the Lua debug library, with added additions.

All Script-Ware platforms support these functions!


Get Constants

function debug.getconstants(f: (function | number)): table

Returns the constants in function/level "f".


Get Constant

function debug.getconstant(f: (function | number), idx: number): table

Returns the constant "idx" from function/level "f".


Set Constant

function debug.setconstant(f: (function | number), idx: number, obj: any): table

Sets constant "idx" from function/level "idx" to "val". NOTE: The new object MUST be of the same type as the old.


Get UpValues

function debug.getupvalues(f: (function | number)): table

Returns upvalues in function/level "f".


Get UpValue

function debug.getupvalue(f: (function | number), idx: number): table

Returns upvalue "idx" in function/level "f".


Set UpValue

function debug.setupvalue(f: (function | number), idx:number, obj: any): table

Sets upvalue "idx" in function/level "f" to "val".


Get Protos

function debug.getprotos(f: (function | number)): table

Returns protos in function/level "f".


Get Proto

function debug.getproto(f: (function | number), idx: number, active: boolean?): (function | table)

Returns proto "idx" in function/level "f".


Set Proto

function debug.setproto(variant f, int idx, function replacement)

Sets proto "f" at idx with "function" replacement at level/function "f".


Get Stack

function debug.getstack(level: number, idx: number): any

Returns register "idx" in the stack located at "level".


Set Stack

function debug.setstack(level: number, idx: number, obj: any)

Sets register "idx" in the stack located at "level" to "val".


Get Info

function debug.getinfo(f: (function | number)): table

Returns information about function/level "f".

Drawing Library

All Script-Ware platforms support these functions!


Create Render Object

userdata Drawing.new(string class)
userdata createrenderobj(string class)

Creates and returns a new draw object of type "class"


Is Render Object

bool isrenderobj(userdata object)

Checks if "object" is a draw object.


Set Render Property

Sets a draw object's "property" to given "value" NOTE: "setrenderproperty" is a draw object's "__newindex"


Get Render Property (typo)

variant getrenderproperty(userdata drawobject, string property)

Returns a draw object's "property" NOTE: "getrenderproperty" is a draw object's "__index"


Clear Draw Cache

void cleardrawcache()

Clears all objects from the internal draw object list NOTE: this invalidates any references to pre-existing draw objects


Properties by Example

circle = Drawing.new('Circle');
circle.Radius = 50;
circle.Color = Color3.fromRGB(255, 255, 255);
circle.Filled = false;
circle.NumSides = 32; -- Circles aren't drawn perfectly; more "sides" = more lag
circle.Position = Vector2.new(20, 20); -- pixels offset from top right
circle.Transparency = 0.9;

square = Drawing.new('Square');
square.Position = Vector2.new(20, 20);
square.Size = Vector2.new(20, 20); -- pixels offset from .Position
square.Thickness = 2;
square.Color = Color3.fromRGB(255, 255, 255);
square.Filled = true;
square.Transparency = 0.9;

line = Drawing.new('Line');
line.PointA = Vector2.new(20, 20); -- origin
line.PointB = Vector2.new(50, 50); -- destination
line.Color = Color3.new(.33, .66, .99);
line.Thickness = 1;
line.Transparency = 0.9;

text = Drawing.new('Text');
text.Text = '𝘚𝘤𝘳𝘪𝘱𝘵-𝘞𝘢𝘳𝘦';
text.Color = Color3.new(1, 1, 1); -- white text
text.OutlineColor = Color3.new(0, 0, 0); -- black outline
text.Center = true; -- center text
text.Outline = true;
text.Position = Vector2.new(100, 100);
text.Size = 20; -- font size
text.Font = Drawing.Fonts.Monospace; -- 'UI', 'System', 'Plex', 'Monospace'
text.Transparency = 0.9;

image = Drawing.new('Image'); -- todo: look into how images are actually rendered
image.Color = Color3.new(0, 0, 0);
image.Rounding = 3;
image.Size = Vector2.new(256, 256);
image.Position = Vector2.new(100, 100);
image.Transparency = 0.9;

quad = Drawing.new('Quad');
quad.Color = Color3.new(.1, .2, .3);
quad.Filled = false;
quad.Thickness = 2;
quad.Point1 = Vector2.new(100, 0);
quad.Point2 = Vector2.new(50, 50);
quad.Point3 = Vector2.new(0, 100);
quad.Point4 = Vector2.new(100, 100);
quad.Transparency = 0.69;

triangle = Drawing.new('Triangle'); 
triangle.PointA = Vector2.new(50, 0);
triangle.PointB = Vector2.new(0, 50);
triangle.PointC = Vector2.new(100, 50);
triangle.Thickness = 3;
triangle.Color = Color3.new(1, 0, 0);
triangle.Filled = true;
triangle.Transparency = 1.0;

-- don't forget to clean up after yourself!

for obj in next, {circle, square, line, text, image, quad, triangle} do
    obj:Destroy(); -- or :Remove()
end

Crypt Library

Script-Ware allows for high level encryption and string encoding through it's crypt library, featuring many methods of performing functions.

⚠️ Some of these are only available on certain platforms! RSA is currently only on Windows platforms.


AES Encryption

Encryption

function crypt.encrypt(data: string, key: string, nonce: string?): string

"data" is encrypted and returned in Base64 encoding via AES-CTR encryption using the "key" and a "nonce" that is otherwise automatically generated. The key and IV are assumed to be encoded in Base64.

Decryption

function crypt.decrypt(data: string, key: string, nonce: string?): string

"data" is decrypted using the "key" and a "nonce" that is otherwise used by the automatically generated previous nonce. The key and IV are assumed to be encoded in Base64.

Custom Encryption

function crypt.custom_encrypt(data: string, key: string, nonce: string, ciphermode: string): string

Encrypts "data" using the same arguments as in the normal encrypt function, but allows for you to specify your own cipher mode. The following are the compatible ones:

image

Custom Decryption

function crypt.custom_decrypt(data: string, key: string, nonce: string, ciphermode: string): string

Decrypts "data" using the same arguments as in the normal decrypt function, but allows for you to specify your own cipher mode. The same ones as shown above.

Generate Encryption Key

function crypt.generatekey(): string

Returns a 256 bit, Base64 encoded, encryption key. You can use this key for the encryption process.

Generate Bytes

function crypt.generatebytes(bytes: number?): string

Generates randomly generated, base64 encoded, "bytes" in length bytes. If the "bytes" is not passed, it generates 16 bytes. This is typically used for the nonce/IV.


RSA Encryption

Script-Ware V2 is the first to properly support asymmetric encryption, you can now secure stuff using two keys, a public (encryption) and a private (decryption) via the RSA algorithm.

OAEP padding is used alongside the encryption, meaning that encrypted results will appear completely different every time but can still be decrypted fine.

If the key is invalid, or the data being given for decryption is not in-line with the private key, an error will be thrown.

XML, PEM, DER & even JWK encryption key formats are accepted. Furthermore, encrypted data is returned base64 encoded. Decryption data is taken base64 encoded. Just like AES.

Encryption

function crypt.asym_encrypt(plain_text: string, public_key: string): string

Returns encrypted "plain_text" using the public RSA key "public_key".

Decryption

function crypt.asym_decrypt(cipher_text: string, private_key: string): string

Returns decrypted "cipher_text" using the private RSA key "private_key"

Generate Keys

function crypt.asym_generatekey(): string

Returns a keypair in XML format which looks like this:

PUBLICKEY: <RSAPublicKey><Modulus>yLWaMsvl+0F4W4wzGqacD5WFANtH88Xs5M0bPizkjPdc4PopRtnMfTKX55JDB/EkXWxVZU3Xvcx3a41EQtJ4Bb8IT2mZALKAHJzFEJxRyL6C5IIWK1pia40aO6oLcZCpn8uS08sR/2rWzVF8u2UED08LvwSMsRaUFPwjrcj0aDTpdv8dI7YQOu2Qwqgjov0w3h5EPeoQIMXGlP8LbBJ6WcoI8s3vq4Nn2XvYRgcahQ6Pf24V35gi6joPKk09UERJDwAOsMLMFb1LClI0MG7N9O/k0INu7lNYH40YDlaztMvD/X6A7jRkinjwOoFeQeT20+zcwdGFyzfxXhHMlxa0qQ==</Modulus><Exponent>AQAB</Exponent></RSAPublicKey>

PRIVATEKEY: <RSAKeyValue>
	<Modulus>yLWaMsvl+0F4W4wzGqacD5WFANtH88Xs5M0bPizkjPdc4PopRtnMfTKX55JDB/EkXWxVZU3Xvcx3a41EQtJ4Bb8IT2mZALKAHJzFEJxRyL6C5IIWK1pia40aO6oLcZCpn8uS08sR/2rWzVF8u2UED08LvwSMsRaUFPwjrcj0aDTpdv8dI7YQOu2Qwqgjov0w3h5EPeoQIMXGlP8LbBJ6WcoI8s3vq4Nn2XvYRgcahQ6Pf24V35gi6joPKk09UERJDwAOsMLMFb1LClI0MG7N9O/k0INu7lNYH40YDlaztMvD/X6A7jRkinjwOoFeQeT20+zcwdGFyzfxXhHMlxa0qQ==</Modulus>
	<Exponent>AQAB</Exponent>
	<D>YYIQksMKTQGmlltLbJQq10tdnWfq0dyDVTjsFk27D10Ra189dGVVejF9KQyeshoN/7Ek351sxZGzJrYvxoL3ulrvj50Orw8JPF1RQ9udw/gCIT+tw4waqoOXjgrzmk2cirxc7bYHXV4rUv5WqbfOvB076KYuL853TKaeMsyhKIpHvuGBiM5fYxVR1tUMGFqaZFktXvYUSBDUKSxIkWl5sEK+OYX7KuvO813GZMFuraWR29fevSqyAvnk1sgMTZxPui+oPqnnJvMiQErlLTK3MWRviYKHtkM4UHVBQ/wGDtlR0c4Y7Dq7CouPnZiqM7nrmbV9+wAcAUHq1OCylRQIAQ==</D>
	<P>2ZBiSsD45Uermt6nH+oEbQPAyH1JY0Rskd6idFt76wpCPoldW5+BBX4gFd36e3LBi47WM5g6dLyMvflW1AHqoOQjJ2vs+vqs6KaV7qpN7Ebvc3e6suz9I9vh4SRx3kN2q5jl/wTLQyWfMp0Bbej2meE2xx5ndn484X9gjTBQ2ak=</P>
	<Q>7CryRb1U23+z3sf50aS0RT2IE3FJ8u6fn1Qo+POkY3nqjkJUT4C5h9sr8+pQaC29rJXDMXHdQb9c3akcqLtdpGqlDQpU6et0RO8ZdOfUMEY142KPjpQNKwdHydnb4Fi5v5O80gIU4WG1vgYm7LOw1bwZihWSai3TF5kxyWS94wE=</Q>
	<DP>Orju3tBxHamXluiL4WBPq4D80uCGI2X/i+u0m4Vp0Ann0WtQKH/H2kytqllM128k8F8wT6LB/Go77rbTCcwuoRiSqHxH7YIlk3ILO+z5tVF8JgVl/g9bUAd0U0l79ortB+nwAkIv/sKz0nxwO1NK5EPWfi4lrOTr182CqPkmiWk=</DP>
	<DQ>Ks9+K3Yus7tqd6/4cTBSHVsSF7Qpm4f2F4PCCZ7g5cdr5W3QqrjC6QWp6gVHnhrsjyR2xbfGS+zMgMHvGAce6ncKhFqjGeQ8p2JQUwjTRgz0J8vuCgJ8gJhJQyXi3cA3q6q0R71o25JCx7eFxtKr85KtboKKkATOhzCV/dPtOAE=</DQ>
	<InverseQ>tTHkUX+TPJ98y+RwsMWTKuXU0cswIyvBlbrvGi9ENt8pS18TspAfYWDt48Ajw4fJirnK3MqKuQumxiTVsdJK2A70H/rSpyax7VwWiKxO+8Zns2R5TpI1E9aEkcBnHBEQu9cbPXU09lRFZs7f4AReU3jkBZGXJueGMmBKtQH4Ku4=</InverseQ>
</RSAKeyValue>

Don't use this function for your encryption/decryption code!

You can then use this to perform encryption. These keys are not special, they are generic RSA keys in XML encoding - feel free to use your own generated keys in any supported encoding.

This function is strictly only to generate keys, don't pass this function to the encrypt or decrypt function. It won't work!


Base64 Encoding

Base64 Encode

function crypt.base64encode(data: any): string

"data" is base64 encoded and returned.

Base64 Decode

function crypt.base64decode(data: any): string

"data" is base64 decoded and returned.


Hash

Hash String

function crypt.hash(data: string, algorithm: string?): string

"data" is hashed via the algorithm. Defaulted to SHA256.

image

Wow, what a plethora of cool algorithms!


Examples

AES Example

local generated_key = crypt.generatekey()
local generated_nonce = crypt.generatebytes()

local encrypted = crypt.encrypt("hello, world!", generated_key, generated_nonce)

print(encrypted) --encrypted "hello, world!"

local decrypted = crypt.decrypt(encrypted, generated_key, generated_nonce)

print(decrypted) --decrypted encrypted "hello, world!"

RSA Example

local RSA_Public = "<RSAPublicKey><Modulus>yLWaMsvl+0F4W4wzGqacD5WFANtH88Xs5M0bPizkjPdc4PopRtnMfTKX55JDB/EkXWxVZU3Xvcx3a41EQtJ4Bb8IT2mZALKAHJzFEJxRyL6C5IIWK1pia40aO6oLcZCpn8uS08sR/2rWzVF8u2UED08LvwSMsRaUFPwjrcj0aDTpdv8dI7YQOu2Qwqgjov0w3h5EPeoQIMXGlP8LbBJ6WcoI8s3vq4Nn2XvYRgcahQ6Pf24V35gi6joPKk09UERJDwAOsMLMFb1LClI0MG7N9O/k0INu7lNYH40YDlaztMvD/X6A7jRkinjwOoFeQeT20+zcwdGFyzfxXhHMlxa0qQ==</Modulus><Exponent>AQAB</Exponent></RSAPublicKey>"
local RSA_Private = "<RSAKeyValue><Modulus>yLWaMsvl+0F4W4wzGqacD5WFANtH88Xs5M0bPizkjPdc4PopRtnMfTKX55JDB/EkXWxVZU3Xvcx3a41EQtJ4Bb8IT2mZALKAHJzFEJxRyL6C5IIWK1pia40aO6oLcZCpn8uS08sR/2rWzVF8u2UED08LvwSMsRaUFPwjrcj0aDTpdv8dI7YQOu2Qwqgjov0w3h5EPeoQIMXGlP8LbBJ6WcoI8s3vq4Nn2XvYRgcahQ6Pf24V35gi6joPKk09UERJDwAOsMLMFb1LClI0MG7N9O/k0INu7lNYH40YDlaztMvD/X6A7jRkinjwOoFeQeT20+zcwdGFyzfxXhHMlxa0qQ==</Modulus><Exponent>AQAB</Exponent><D>YYIQksMKTQGmlltLbJQq10tdnWfq0dyDVTjsFk27D10Ra189dGVVejF9KQyeshoN/7Ek351sxZGzJrYvxoL3ulrvj50Orw8JPF1RQ9udw/gCIT+tw4waqoOXjgrzmk2cirxc7bYHXV4rUv5WqbfOvB076KYuL853TKaeMsyhKIpHvuGBiM5fYxVR1tUMGFqaZFktXvYUSBDUKSxIkWl5sEK+OYX7KuvO813GZMFuraWR29fevSqyAvnk1sgMTZxPui+oPqnnJvMiQErlLTK3MWRviYKHtkM4UHVBQ/wGDtlR0c4Y7Dq7CouPnZiqM7nrmbV9+wAcAUHq1OCylRQIAQ==</D><P>2ZBiSsD45Uermt6nH+oEbQPAyH1JY0Rskd6idFt76wpCPoldW5+BBX4gFd36e3LBi47WM5g6dLyMvflW1AHqoOQjJ2vs+vqs6KaV7qpN7Ebvc3e6suz9I9vh4SRx3kN2q5jl/wTLQyWfMp0Bbej2meE2xx5ndn484X9gjTBQ2ak=</P><Q>7CryRb1U23+z3sf50aS0RT2IE3FJ8u6fn1Qo+POkY3nqjkJUT4C5h9sr8+pQaC29rJXDMXHdQb9c3akcqLtdpGqlDQpU6et0RO8ZdOfUMEY142KPjpQNKwdHydnb4Fi5v5O80gIU4WG1vgYm7LOw1bwZihWSai3TF5kxyWS94wE=</Q><DP>Orju3tBxHamXluiL4WBPq4D80uCGI2X/i+u0m4Vp0Ann0WtQKH/H2kytqllM128k8F8wT6LB/Go77rbTCcwuoRiSqHxH7YIlk3ILO+z5tVF8JgVl/g9bUAd0U0l79ortB+nwAkIv/sKz0nxwO1NK5EPWfi4lrOTr182CqPkmiWk=</DP><DQ>Ks9+K3Yus7tqd6/4cTBSHVsSF7Qpm4f2F4PCCZ7g5cdr5W3QqrjC6QWp6gVHnhrsjyR2xbfGS+zMgMHvGAce6ncKhFqjGeQ8p2JQUwjTRgz0J8vuCgJ8gJhJQyXi3cA3q6q0R71o25JCx7eFxtKr85KtboKKkATOhzCV/dPtOAE=</DQ><InverseQ>tTHkUX+TPJ98y+RwsMWTKuXU0cswIyvBlbrvGi9ENt8pS18TspAfYWDt48Ajw4fJirnK3MqKuQumxiTVsdJK2A70H/rSpyax7VwWiKxO+8Zns2R5TpI1E9aEkcBnHBEQu9cbPXU09lRFZs7f4AReU3jkBZGXJueGMmBKtQH4Ku4=</InverseQ></RSAKeyValue>"

local encrypted = asym_encrypt("hello, world!", RSA_Public)
local decrypted(asym_decrypt(encrypted, RSA_Private))
-- two keys!

Websocket Library

⚠️ These functions are only available on Windows!


Connect

function WebSocket.connect(url: string): object

Attempts to connect to the "url" provided.


Methods

Send

function WebSocket:Send(msg: string)

Sends the provided message "msg" to the server.

Close

function WebSocket:Close()

Closes the opened connection.


Events

On Message

signal WebSocket.OnMessage

This event is fired when a message is sent from the server.

On Close

signal WebSocket.OnClose

This event is fired when the WebSocket is closed, by either the "WebSocket:Close" method or by the server.


Example

local socket = WebSocket.connect("ws://localhost:8126/foo")

socket.OnClose:Connect(function() print'closed' end)
socket.OnMessage:Connect(function(msg)
    print(msg)
end)

socket:Send("Hello")

Script Disassembler (The only reason I made this wiki)

The Script-Ware Disassember is a new advancement in script analysis. This utility is useful for examining scripts that may have anti-decompile methods, or for learning purposes.


function disassemble(bytecode: string): string

The disassembler takes bytecode as a string returned from getscriptbytecode or your own.


Example

local bytecode = getscriptbytecode(script_instance)
writefile("myBytecode.txt", disassemble(bytecode))

Output Documentation

How to read the disassembler's output

Source and disassembly examples

Lua

for i = 1, 10 do 
	print(string.format("%i, Hi!", i))
end
print("High Five!")

Luau

 [000] VARARGINIT  0  0  0
 [001] LOADNUMBER  2  1
 [002] LOADNUMBER  0 10
 [003] LOADNUMBER  1  1
 [004] FORPREP  0  9 ; jump to 13
 [005] LOADMULTIK  3  1 ; multi-index(1): print
 [007] LOADMULTIK  4  4 ; multi-index(2): string.format
 [009] LOADK  5  5 ; K(Bx): %i, Hi!
 [010] MOVE  6  2
 [011] CALL  4  3  0
 [012] CALL  3  0  1
 [013] FORLOOP  0 -9 ; jump to 4
 [014] LOADMULTIK  0  1 ; multi-index(1): print
 [016] LOADK  1  6 ; K(Bx): High Five!
 [017] CALL  0  2  1
 [018] RETURN  0  1  0

In Lua and Luau, there is a fixed size stack that has 2 to 250 values. You can see that here in the maxstacksize field:

TOhEDZucZGH1uba9v8X_7_image

In this case, 7 values on the stack will ever be used at the same time.

As far as instructions are concerned, Lua stack is not a traditional push/pop style stack; instead, the number of values needed, and where every one of them are used is predetermined at compile time, and used as necessary by instructions.

Here's an example of how the stack is used to store and retrieve values:

lAZJo0vNNOv2WHyM3oWWK_image

The first instruction, LOADMULTIK, loads the function print into register 0, the second instruction loads the constant "High Five!" which is in constant index 6 into register 1, and then comes the CALL instruction.

The CALL instruction's arguments are 0, 2 and 1. What do these mean?

Like with many instructions, the first argument (this is called argument A) are used as a base register reference to then operate with offsets. In this case, the CALL instruction's base is 0, which is where the stored "print" function is (you can always expect the first argument to have the function being called.) But where does the 2nd and 3rd argument (called argument B and C, respectively) come from? Well that's easy: take argument B and subtract it by 1 (that's the number of arguments passed to the function) and take argument C and subtract it by 1 (that's the number of values returned.) You can indeed see that B - 1 == 1, which we only pass 1 argument "High Five!" and expect no returns (0 values returned.)

As one more explanation, take a CALL instruction with the base of 6, and it is calling with 3 arguments and 2 returns. You can expect the format to be "CALL 6 4 3", with the arguments being in 7, 8 and 9 (as an offset from 6.) A visualization would be "local a, b = func(c, d, e)".

How can I read a for loop?

For loops work like CALL instructions in how they work with a base location on the stack. You can see this in action in this example:

4myHaIWp6tuGv9IRa-3Ui_image

You can see that FORPREP's base is 0, where the values of the for loop are stored for usage. Base + 0 is the limit, base + 1 is the iteration, and base + 2 is the starting number.

But, you're probably wondering what the 2nd argument is. That is called the jump offset.

What is a jump offset?

A jump offset is a number that is added with the current program counter (called PC) to specify a relative location/destination.

You can see off to the side the locations of instructions:

zK3Hs7BB3OKjuSkhsgHm4_image

These are important for the VM to keep track of so instructions know their way around with relative locations. You can see the disassembler add the offset automatically, showing you where the instructions go "FORPREP 0 9 ; jump to 13" such the current PC (which is 4) is added to the offset (which is 9) to be 13. At position 13, you can see the FORLOOP instruction, which checks if the condition of the for loop has been met, else jump back to the beginning of the loop and run another iteration.

Now that you know the basics of how to read the disassembly, let's dive into more advanced topics.

A closer look at compound globals

Luau has a unique feature that we call multi-index table retreival (or compound globals.) This allows much faster grabbing of values nested in multiple tables compared to vanilla Lua.

Source: "print(a.b.c)"

Luau

[000] VARARGINIT  0  0  0
[001] LOADMULTIK  0  1 ; multi-index(1): print
[003] LOADMULTIK  1  5 ; multi-index(3): a.b.c
[005] CALL  0  2  1
[006] RETURN  0  1  0

Text

[1] getglobal  0   0        ; print
[2] getglobal  1   1        ; a
[3] gettable   1   1   258  ; "b"
[4] gettable   1   1   259  ; "c"
[5] call       0   2   1  
[6] return     0   1    

As you can see in the comparison, Luau combines one GETGLOBAL and up to two GETTABLE operations after that, into a single instruction. Which means Luau will not be able to combine past 2 levels deep into a table efficiently, thus concluding a.b.c.d.e.f will not generate 2 LOADMULTIK's; instead, it generates one LOADMULTIK and 3 (three) GETTABLEK instructions.

What are fastcalls?

In Luau, fastcalls are a great optimization. ROBLOX keeps a hardcoded list of function pointers that are indexed directly by argument A, in which these functions are specially chosen and generated to work in this fashion (the fastcall version of math.sqrt is NOT the same as the normal function.) In order for fastcalls to work, the normal version of the call must exist in the code. The reason for this is because of something called dynamic deoptimization.

Dynamic deoptimization and fastcalls

Fastcalls alone are a powerful tool, indeed; however, they are not compliant with the Lua 5.1 backwards compatibility promise. Since special functions exist simply for the sake of being able to be fastcalled, using functions like getfenv or setfenv on or in the environment causes the environment to dynamically deoptimized such that fastcalls will no longer work and run the slower, normal code instead.

Here's an example of this in action:

Luau

[000] VARARGINIT  0  0  0
[001] LOADMULTIK  0  1 ; multi-index(1): print
[003] LOADNUMBER  3 90
[004] MONOFCALL 22  3  2 ; jump to 6 ; fastcalling 'math.rad'
[005] LOADMULTIK  2  4 ; multi-index(2): math.rad
[007] CALL  2  2  0
[008] MONOFCALL 24  0  2 ; jump to 10 ; fastcalling 'math.sin'
[009] LOADMULTIK  1  6 ; multi-index(2): math.sin
[011] CALL  1  0  0
[012] CALL  0  0  1
[013] RETURN  0  1  0

Text

[01] getglobal  0   0        ; print
[02] getglobal  1   1        ; math
[03] gettable   1   1   258  ; "sin"
[04] getglobal  2   1        ; math
[05] gettable   2   2   259  ; "rad"
[06] loadk      3   4        ; 90
[07] call       2   2   0  
[08] call       1   0   0  
[09] call       0   0   1  
[10] return     0   1      

You can see the special MONOFCALL instructions jumping with argument C (being 2, for both.) This is a conditional jump that will happen only if the environment is optimized. If the jump does not happen, you can see that it will run the code necessary for a non-optimized call. Fastcalling instructions always point to and/or jump to their respective CALL instruction, because these instructions require values in the normal CALL. This means that fastcalls will not work if the unoptimized version of the code does not exist.

Script Decompiler

Script-Ware comes with the premium capability of accessing the content of in-game Local and Module scripts. It does this through decompiling the scripts data and providing you with a readable output.

You can optionally specify to decompile all available scripts when you save a game in its entirety through using SaveInstance.

Script-Ware's current decompiler is in Beta. There are more improvements we have planned to make, stay tuned!

⚠️ Only the Windows platform supports decompilation! macOS compatibility will be added soon.


Decompile

string decompile(LocalScript/ModuleScript script)

Returns the decompiled "script".

If decompilation fails, it will return an error message


Disassembler (NEW)

string disassemble(string bytecode)

This provides you diassembled bytecode which you can utilise to very nicely analyse script content. This bypasses every single anti-decompile procedure that exists.

This is an entirely new dynamic that scripters will have to get used to, but it is a powerful tool for script developers, game developers, and more.

In order to pass "bytecode", use the getscriptbytecode function of which returns the scripts Luau bytecode. This is shown in the below example.

Example

writefile("My Script.txt", disassemble(getscriptbytecode(game.Lighting.EpicScript)))

This creates a file in the workspace folder with the diassembled content you can now read through.

Reporting Crashes/Bugs

Although we try our best to make Script-Ware the most versatile and stable script execution product on the market, it is inevitable that we will encounter problems, bugs, glitches, and what have you. If you encounter one, we are more than happy to fix it.

This goes for our scripting engine, our scripting environment, our interface, and more.

Did you know?

Script-Ware is the top product for resolving bugs and problems! We have an amazing track record of resolving something 48 hours after it has been reported, with some exceptions.


How to report a crash (for Windows)

When Script-Ware crashes it will pop up with a notepad file that has some information on who to send the file to as well as what looks like complete garbage data (which is the crash data that we will use to diagnose this crash).

ccWUq9sVw2vqYgVOzWN4k_image

You should then head to https://dashboard.script-ware.com/report-crash to report this crash properly, the rest of the details are available there. You'll then receive an email letting you know that your problem is being looked into.

You leaving this file as-is and continuing will just mean your crash will never be resolved! Please make sure you report crashes you get so we can get crashes fixed.


How to report a bug (for everyone)

Script-Ware has a new bug report form in the support section of the site! You can easily discuss your bug and give us screenshots and information so that we can resolve the problem for you.

This section is accessible here: https://dashboard.script-ware.com/report-bug

Please ensure you provide us with as much information as possible, including how to reproduce your bug so that we can fix it for you.


Reporting serious vulnerabilities with any Script-Ware software

Script-Ware will absolutely accept any serious vulnerabilities that are discovered within its software. This goes for all of our platforms.

Depending on the severity of the vulnerability, you are also entitled to a cash reward for reporting the vulnerability. An example of a vulnerability we would pay cash for is a detection method on injection, a way to bypass or mess with our authentication, a way to grab our environment, and similar vulnerabilities.

Vulnerabilities like these are best privately reported to an official developer such as AzuLX or Modulus through Discord or other (private/direct) means. When reported and resolved you will be given a cash reward which can range upwards of hundreds of dollars.

Alternatively, you may send an email to this email address: [email protected] - explaining how to get in contact with you for a one-to-one discussion regarding your found vulnerability. Thank you.

Your reward is void if you decide to release a vulnerability to the public!

Severe vulnerabilities like this can potentially harm our large userbase (as well as other, similar, products). You helping us means we can protect our userbase as well as provide you with a reward for helping us out.

⚠️ **GitHub.com Fallback** ⚠️