local Params = {
RepoURL = "https://raw.githubusercontent.com/luau/SynSaveInstance/main/",
SSI = "saveinstance",
}
local synsaveinstance = loadstring(game:HttpGet(Params.RepoURL .. Params.SSI .. ".luau", true), Params.SSI)()
local Options = {} -- All Options can be found here https://github.com/luau/UniversalSynSaveInstance/blob/main/saveinstance.lua#L772
synsaveinstance(Options)
Or shortly USSI, a project aimed at resurrecting saveinstance function from Synapse X Source 2019 & Other Executor Source leaks .
Reason: Many Executors fail miserably at providing good user experience when it comes to tinkering with saving instances.
- Credits are appreciated 💖
- Do NOT claim you wrote this
- Do NOT forget to include the License
https://discord.com/invite/wx4ThpAsmw / https://discord.gg/wx4ThpAsmw
-
!!! Custom fallback Decompiler for ModuleScripts using require and then iterating through it, gathering all info about functions using getupvals/getprotos/getconsts, converting all DataTypes using tostring or Descriptors, and then perhaps converting to JSON. (Make use of op-codes from Dex?) !!!
-
Check out varios Leaked Executors (Especially their Init / Lua scripts) to expand knowledge on the whole subject of saveinstance
-
Look into adding support for Binary Format Output (rbxl/rbxm)
- Users can already convert to Binary Format by
- Open the File
- Click on top left "FILE" text and select "Save to File As"
- Make Sure rbxl/rbxm format is selected (not XML!)
- Click Save
- .RBXL files are similar to .RBXLX files but are saved in Binary format, which helps reduce the file size.
- ! Check out Rojo Rbx Dom Binary & Roblox Format Specifications Binary for more documentation about the Binary File Format!
- ! Also see buffer, bit32 libraries as well as pack/unpack from the string library for more information on how you can implement something like this!
- ! Rbx-Binary-Format
- Users can already convert to Binary Format by
-
Add custom decompiler in case executor doesn't have one but has getscriptbytecode (UMF)
-
Add custom timeout logic for decompiler instead of relying on executor to have one
- Using threads & coroutines.
-
Add
continue
where needed -
Add Documentation similar to KRNL Docs or Synapse X Docs / Synapse X Docs Old
-
Merge SharedStrings and sharedstrings tables
-
Add fallback function for appendfile (whether through storing current xml as string or with use of readfile)Removed Appendfile entirely -
Add getproperties as fallback for specialinfo
-
Add Redirects to some special (in a bad way 😡) values, more info @
PropertyPatches v1PropertyPatches v2+PropertyPatches v3, otherwise they will fallback to default when file is opened- Not all though, test each & see if it carries over or not (when file is opened)..
- All current redirects: Here
-
Add more Fixes for Errors that can pop up during opening process
-
Add Optional tags support
-
Add readbinarystring or readbinarystringpropertyvalue/readbspval/getbspval (elysian) as fallback for gethiddenproperty
-
Add table.clone instead {} in some cases if possible
-
Avoid scanning for default values of properties if those properties won't get serialized anyway (e.g. don't have a Descriptor)
-
Add --!native tag just in case
-
Find default values of binarystring properties (MaximumADHD might have a clue)
- LOOK INTO Instance:IsPropertyModified & Instance:ResetPropertyToDefault
-
Auto-Detect DataTypes/ValueType Categories of Properties (CFrame, UDim2 so on)Full API Dump Solves this ? -
Bring said DataType serializer into an outside function
-
Bypass NotCreatable by hardcoding links/references/indexes to said ClassesShould be Solved by IsPropertyModified- Example: Terrain class can be indexed by doing workspace.Terrain but is NotCreatable
-
Check if table.concat is actually the fastest way as compared to other alternatives (IT'S NOT)
-
Do
clean-up in inheritor &(API Dumps solve this, illogical) automatically assume the top-most class that owns the property, while also cleaning up said property from classes that inherit from it- This will be only be needed if we try to implement our own scanning for hidden properties in which case a lot of duplicates might arise that need to be tracked down to instance they all inherit from & cleaned up respectively
-
Fix indexes being mixed up after table.remove shifting
-
Hidden properties
-
Scan for themFull API Dump Solves this -
Scan game & map instances in format {ClassName = {Instance1, Instance2} }, if none found then attempt to create proper Replica for themFull API Dump Solves this
- This will help with getting many ValueTypes accurately, especially BinaryStrings vs strings
-
Inherit them properly & do the clean-upFull API Dump Solves this -
Tell whether ValueType is string or BinaryStringFull API Dump Solves this
-
-
Support for Model files:
- rbxmx (xml)
- rbxm (binary)
-
Possibly convert to non-Name tables & use instance references instead (Perhaps make a config Bool Toggle for this, false by default), ex. DecompileIgnore = {game.CoreGui}Add too much complexity for now- This will allow for more flexibility of saveinstancing
-
Remove Useless tables & functions of specialinfoRepurposed -
Implement Luau Syntax (important for performance!):
- Compound Operators
- Avoid using
next
,ipairs
&pairs
- [BENCHMARK] Interpolated strings instead of concat
- [BENCHMARK]
next,
and numerical loops on both lua & luau to decide which and where to use - Type-checking (😩🙀)
-
local maxValue = if a > b then a else b
expressions - print(
Bob has {count} apple(s)!
) expressions - Floor division
-
Speed things up as much as possible
- Requires benchmarks
- Requires looking at other scripts of ours that are aimed at speed & performance
-
Support for NotScriptable Properties
- Requires gethiddenproperty support
-
Support for as many KRNL-like saveinstance Options & UNC:
- Change mode to invalid mode like "custom" if you only want to save ExtraInstances
- Decompile (! This takes priority over OPTIONS.noscripts if set !)
- DecompileIgnore
- DecompileTimeout (! This takes priority over OPTIONS.timeout if set !)
- ExtraInstances
- FilePath
- IgnoreDefaultProps
- IsolateStarterPlayer
- NilInstances
- Object (for .rbxmx files)
- RemovePlayerCharacters
- SavePlayers
- ShowStatus
- Add Drawing Library support for ShowStatus
[-] IsolatePlayerGuiUse IsolateLocalPlayer instead- Callback
- Clipboard/CopyToClipboard
- Binary (rbxl/rbxm)
-
Support for as many Executors as possible (🤢🤮)
-
Use getspecialinfo fallback function carefully as it's hardcodedUseless because there's no way to tell if the Property Values of those instances are default or not- LOOK INTO Instance:IsPropertyModified & Instance:ResetPropertyToDefault
-
Isolators must clear
-
Store all functions outside that are used during saveinstancing for sake of performance
-
Remove buffersize, savebuffer & so on for sake of performance by concatenating strings to total string then writing it to file (no extra steps like table.concat)table.concat proved faster in the case of huge amount of concatenations- Test table.concat vs string ..= with a full buffer (this benchmark differs per usecase)
-
Make sure BinaryStrings are compared to Defaults properly (aka in same format)
-
Add Option to restart saveinstance from the point that it crashed on
-
Check out DataType Exceptions
-
Add README Similar to current Synapse
-
Ignore all properties of instances that aren't Local or Module Scripts except Name if mode is set to "scripts"
-
Maybe modes should do more than just affecting the list of instances to save, like changing IgnoreDefaultProperties to false if mode is "full" for example
-
Add Support for SharedStrings
- Fun fact: SharedStrings can also be used for ValueTypes that aren't
SharedString
, this behavior is not documented anywhere but makes sense (Could create issues though, due to potential ValueType mix-up). By replacing<BinaryString name="Tags">Base64EncodedValue</BinaryString>
with<SharedString name="Tags">UniqueIdentifierForSharedString</SharedString>
& putting<SharedString md5="UniqueIdentifierForSharedString">Base64EncodedValue</SharedString>
into SharedStrings container you can achieve this amazing behaviour. This should be only enabled using an optional setting
Only known to work with (probably because both are base64 encoded):
- BinaryString
- Fun fact: SharedStrings can also be used for ValueTypes that aren't
-
Add Lua & Luau versions instead of merged (WARNING: LUAU WILL ALWAYS BE MORE UPDATED THAN LUA VERSION - IDC & CBA SIMPLY, lua version exists just for sake of old & bad executors, ask devs of your executors to support luau as its latest & greatest)
-
Add Support for multiple Instances to be saved as a model
-
Do something about devs renaming Services therefore bypassing Ignore lists (CoreGui/CorePackages are not affected)
- LOOK INTO Instance:IsPropertyModified & Instance:ResetPropertyToDefault
-
Fix Player's Characters not being visible (must Refresh MeshId)
- "https://assetdelivery.roblox.com/v1/asset/?id=" Could cause issues too (needs testing)
- Perhaps add a possible FIX script to README
-
Be able to exclude / blacklist any mentions of certain string in other strings
- Example: You wish to blacklist your player's name from appearing in any property value
- Default options like IsolateSomething might also use / influence this
-
Force disable ParticleEmitters in case something like IgnorePropertiesOfNotScriptsOnScriptsMode is enabled (they stack in one place and create huge lag)
-
Be able to specify which special properties you want saved (to avoid saving all)
This document is based largely on the efforts of @Anaminus & @Dekkonot, authors of the Roblox Format Specifications. Additional resources include:
- Syngp Synapse X Source code 2019 for base saveinstance code (extended by @mblouka & @Acrillis)
- Rojo Rbx Dom Xml for being a fallback documentation in case something wasn't clear in the Roblox Format Specifications
- Roblox File Format for a list of redirects of old/deprecated xml properties that still use the old tag values
- Roblox Client Tracker for an extended & close to full JSON Api Dump (with hidden properties & default values)
*** View source code of this file for more credits