New version of the Rhythia Map format
For those that aren’t aware, if a word ends with / (for example, Insane/), then that means it is a folder
As the last version of .rhym, it will be formatted in a folder. This takes inspiration from osu, quaver, Beat Saber, etc.
Again, .rhym is just the compressed version of the map. It is just a zip, but with the filename extension renamed. So if a file is called Map.rhym, you can just rename it to and it will work COMPLETELY the same!
If I do any global caching for songs and videos and whatnot, it is to speed up parsing logically! To add on to this, difficulties no longer have their own folders (BY DEFAULT). BUT, users can still make their own folders if they would like! This gives mappers more creativity and more organization, which is completely up to the mapper. So an aspire map can have an assets/ folder if they would like, or a massive training map pack can have respective song folders. For example, “BlueZenith/”, “Kamikaze/”, or “Dangerous_Slot/”, anything you desire!
This enables mappers to have more freedom with how their map is structured. If it is of a user’s concern on map scanning parsing times, there will be tools available to automatically optimize parsing speeds! (Optimizer Tool that gets rid of all folders, and moves it all in the global folder to speed up parsing)
READ THIS HEADS UP!!
Anything used by a difficulty will be defined in the metadata.json!! I am moving from separate folders and metadata.jsons and object.jsons to a singular metadata.json to keep parsing fast, and making objects BINARY!! BoooOOoooo... (.rhyo) Don’t get scared... It will be WAAAY easier to interpret compared to SSPMv2! Just a reminder this also includes events, so events and note objects will be in the same file! (For example BPM events, modchart events such as moving notes around, etc etc.)
-Designed solely by fog! :)
.rhym/Map ID/Folder Name Example
Example #1
121 - Haxagon_Example_こんにちは/
Example #2
MapID - MapCreator_Artist_Title/
Folder Format Example (Default/Barebones)
1 - fog_Example_こんにちは1/
- cover.png
- song.mp3
- metadata.json
- TASUKETE.rhyo
Folder Format Example #2
121 - Haxagon_Example_こんにちは/
- assets/
- cover.png
- differentSong.mp3
- example_konnichiwa.mp3
- metadata.json
- Hard.rhyo
- Insane.rhyo
- DifferentSong.rhyo
Folder Format Example #3
13 - fogsaturate_Example_こんにちは2/
- Hard/
- hard.rhyo
- Insane/
- insane.json
- crazier_cover_to_show_this_diff_is_harder!!!.png
- Artist_DifferentSong/
- differentSong.mp3
- DifferentSong.json
- Differentvideo.mp4
- differentcover.png
- example_konnichiwa.mp3
- metadata.json
- globalcover.png
- globalvideo.mp4
metadata.json Key Legend
// ANYTHING WITH A ? NEXT TO THE TYPE IS OPTIONAL
// GLOBAL SECTION
version: int
artist: string
romanizedArtist: string? // romanized = multi-language characters into english alphabet
title: string
romanizedTitle: string?
colorset: string[]?
coverPath: string?
audioPath: string
videoPath: string?
difficulties: difficulty[]
// DIFFICULTY SECTION
// ANYTHING THAT IS THE SAME AS GLOBAL IS OPTIONAL,
// AND WILL DEFAULT TO GLOBAL IF NOT OVERWRITTEN!!!
rhyoPath: string
difficultyName: string
mappers: mapper[] // mapper: string, id: int?
artist: string?
romanizedArtist: string?
title: string?
romanizedTitle: string?
colorset: string[]?
coverPath: string?
audioPath: string?
videoPath: string?
Mapset's metadata.json Example #1 (barebones example)
{
"version":1,
"artist":"テスト",
"romanizedArtist":"Tesuto",
"title":"こんにちは",
"romanizedTitle":"Konnichiwa",
"colorset": ["0000ff"], // this can optionally have a #, for example ["#0000FF"]
"coverPath": "cover.png",
"audioPath": "audio.mp3",
"videoPath": "video.mp4",
"difficulties":[
{
"rhyoPath": "TASUKETE.rhyo",
"difficultyName": "TASUKETE?!?",
"mappers": [{ "name": "fogsaturate", "id": 1 }]
}
],
}
.rhyo Documentation (STILL MASSIVELY W.I.P)
This format is written in binary, which is done to conserve as MUCH file space as possible.
This couldn’t have done without the help of kermeet, so thanks to him for assisting me with this!
Order of .rhyo:
General Object Metadata → Event List → Note Object List
Let’s get started!
Event List
To be written
Note Object List
This format will be slightly hard to understand, but it will all piece together. I will provide numerous explanations at the end
We will be manipulating a SINGULAR BYTE to define a note. So in other words, we will be using bit masks to compress as much information for a note as possible!
Before we get into it, I will be using the word “nibble” a lot. What this means is 4 bits of a byte. So take 00010101 for example. The left nibble is 0001, and the right is 0101
Just a disclaimer, this format will be USING DELTA TIME! This means the milliseconds of an object will be subtracted from the last object. If it is the first object, then it will start out at 0.
The order of notes will go like this
Flag Byte/Note Position → Note Position Float (When applicable) → Time Delta
0000 0000
We will be focusing on the left 4 bits for the flag section, or in other words, the Left Nibble.
Flag Bits for Left Nibble (1111 0000)
Bits for Right Nibble (0000 1111)
Right Nibble Key Legend