Provides a few tools that will (hopefully) aid in the ability to modify/replace/create custom songs
Please note that this tutorial has yet to be fully ironed out, nor does this work for entirely custom songs.
Instead, I will guide you through the process of:
- Adding your "own" custom song (referred to as level) to .assets
- Adding this song to existing collections in .assets
- Recompiling this .assets file
- Profit
Before we can even start, please make sure you have access to the sharedassets17.assets.split*
files. These files can be found in the assets\bin\Data
folder of the beat saber apk. Next, please clone/download this repo, as well as download the zip from the releases page.
Also make sure you have python >= 3 on your computer. You can check your version of python by doing python --version
.
I would also recommend moving all of the sharedassets17.assets.split*
files out of the apk directory to somewhere more useful/easier to access, as well as making backups.
- First off, we want to turn our several
.split
files into one, big.assets
file. We can do this via the following python command:python splitter.py "path/to/sharedassets17.assets.split" 1
. This will create asharedassets17.assets
file in the directorypath/to/
. - Next, we want to make our
.assets
file legible. We can do this by converting only pieces of information that we care about to JSON, via the following command:python replacer.py "path/to/sharedassets17.assets" --json-out "LegibleData"
. This will create a directory calledLegibleData
in the directory that you were in when you ran that command. Inside this directory contains 3 subfolders:
LevelCollections
LevelPacks
SongLevels
It is important to NOT delete or rename these directories, as it looks for exactly these names. Inside each of these directories, there are .json files for each object under each directory.
- We can edit these .json files however we prefer, however, make sure that you increase the size of your arrays when you add or remove elements.
- Now that we have our legible data, let us create our own level to add to a collection. You can do this by copy-pasting an existing level from the
SongLevels
folder, or by usingMyOwnCustomNameY.json
from the .zip from the releases page. - Do NOT save this new .json file in the
LegibleData
directory, or theSongLevels
directory! Save it somewhere else, it will appear once you have added it successfully. - A Custom Object must have two JSON keys:
Metadata
Data
Metadata
must be a dictionary with at least two items:
ByteSize
: The size of the file in bytes. This is tricky to calculate (this step will be automated in the future)TypeID
: The type ID of the object. The type ID of a level is15
.
Data
must be a dictionary containing a raw .json from LegibleData
. It must contain at least the following 4 values:
GameObject
: A dict that represents an object pointer. Must contain at least two keys:FileID
andPathID
Enabled
: A uint32 that represents the enabled state of the object.MonoScript
: A dict that represents an object pointer. Must contain at least two keys:FileID
andPathID
Name
: An aligned_string that represents the name of the object.
If you copied over an existing level to make your own, rejoice! You won't have to find all of those annoying parameters...
Otherwise, get searching for MonoScript.PathID
(which represents the script in charge of this object)
- After creating your custom object (or copying it and changing a few things) make sure that your
ByteSize
is correct (to do this, I usually copy over an existing level that has a knownByteSize
and then make changes and carefully count how many bytes I have added/removed.) - Now we are ready to add the custom object to our
.assets
file! Run the following command:python replacer.py "path/to/sharedassets17.assets" --json-out "LegibleData" --add-object "myCustomObject.json"
If all goes well (and you gave your custom object a unique name) you should see your custom song appear in theSongLevels
folder. Nicely done! - Now let's add it to a collection. Find the
ExtrasLevelCollection.json
and increase the size of the array and add a new element. Refer to your custom object in theLegibleData
folder in order to find yourPathID
. - Now we can build everything back! Run the following command:
python replacer.py "path/to/sharedassets17.assets" --json-in "LegibleData" --output "sharedassets17.assets.split" --add-object "myCustomSong.json"
. You will find manysharedassets17.assets.split*
files in the directory that you ran this command in, which you can now copy over to the .apk. - Repackage and sign the apk, install it, and enjoy viewing your new song! (Even if it already exists under a different name...)