-
-
Notifications
You must be signed in to change notification settings - Fork 1
Migrating from v1 to v2
This wiki page contains directions for upgrading from v1 to v2.
The <MapInfo>.maxScore
method has been removed as it requires a Beatmap
instance to be able to function. Therefore, it makes sense to put this method in the Beatmap
instance itself.
In v2, the equivalent method is <Beatmap>.maxDroidScore
.
- <MapInfo>.maxScore()
+ <Beatmap>.maxDroidScore()
The return values of <MapInfo>.showStatistics
for some options have been changed.
Option Value | v1 | v2 |
---|---|---|
0 | Returns map title and mods used if defined | Returns map title and mods used if defined |
1 | Returns song source and map download link to beatmap mirrors | Returns song source and map download link to beatmap mirrors |
2 | Returns CS, AR, OD, HP | Returns circle, slider, and spinner count |
3 | Returns BPM, map length, max combo | Returns CS, AR, OD, HP, and max score statistics for droid |
4 | Returns last update date and map status | Returns CS, AR, OD, HP, and max score statistics for PC |
5 | Returns favorite count and play count | Returns BPM, map length, and max combo |
6 | N/A | Returns last update date and map status |
7 | N/A | Returns favorite count and play count |
The <MapInfo>.getInformation
method now returns null
as opposed to a blank instance in one of these cases:
- The beatmap is not found
- The beatmap is not an osu!standard beatmap
Additionally, the method now expects two parameters as opposed to an object. The first parameter is the beatmap ID or hash. The second parameter is a download beatmap flag (indicating whether you want to download the beatmap or not).
- MapInfo.getInformation({
- beatmapID: 901854,
- file: true,
- })
+ MapInfo.getInformation(901854, true);
This method has been changed to return void
instead of its instance.
The <MapInfo>.map
getter has been renamed to <MapInfo>.beatmap
. Additionally, it no longer returns a deep copy of the original Beatmap
instance.
The use cases of a deep-cloned instance are rare, and it introduced an overhead. Users who expect the getter to return a deep-cloned instance must perform the deep clone operation by themselves using Utils.deepCopy
.
The Beatmap
class has been rewritten to be able to store all informations necessary to encode an .osu
file instead of only storing informations necessary for difficulty calculation.
Some old fields that have been moved are as follows:
-
ar
,cs
,od
,hp
,sv
, andtickRate
have been moved todifficulty
-
artist
,artistUnicode
,beatmapId
,beatmapSetId
,creator
,title
, andtitleUnicode
have been moved tometadata
-
circles
,sliders
,spinners
,sliderEnds
,sliderRepeatPoints
, andsliderTicks
have been moved tohitObjects
-
objects
has been moved tohitObjects.objects
- Directly adding hitobjects to the array is no longer supported. Use the
add
method to maintain the sorting order of hitobjects. - Use the
hitObjects.removeAt
method to remove a hitobject at a certain index.
- Directly adding hitobjects to the array is no longer supported. Use the
-
timingPoints
has been moved tocontrolPoints.timing
-
difficultyTimingPoints
has been moved tocontrolPoints.difficulty
-
difficultyControlPointAt
has been moved tocontrolPoints.difficulty.controlPointAt
-
timingControlPointAt
has been moved tocontrolPoints.timing.controlPointAt
Directly adding hitobjects and timing points to respective arrays are no longer supported.
To do this in v2, use the hitObjects.add
or controlPoints.<ControlPointManager>.add
method. The method will maintain the sorting order of hitobjects or timing points.
To remove a hitobject or timing point at an index, use the hitObjects.removeAt
or controlPoints.<ControlPointManager>.removeAt
method.
For timing points, you can use the controlPoints.<ControlPointManager>.remove
method to remove a timing point. This method will check for the equality of a timing point and remove the first timing point found in the array. Like the add
method, this will maintain the sorting order of hitobjects or timing points.
In v2, when adding a timing point, the timing point may not be added if the correct state is already present at the timing point's time.
Some slider object-related classes and fields have been renamed:
-
HeadCircle
-->SliderHead
-
RepeatPoint
-->SliderRepeat
-
TailCircle
-->SliderTail
-
<Slider>.headCircle
--><Slider>.head
-
<Slider>.tailCircle
--><Slider>.tail
-
<Slider>.repeatPoints
--><Slider>.repeats
To avoid confusion with the new beatmap encoder, the Parser
class in v1 has been renamed to BeatmapDecoder
in v2. Similarly, the <Parser>.parse
method has been renamed to <BeatmapDecoder>.decode
.
The droid CS scale when converting droid CS to standard CS in MapStats
has been capped to 0.001, preventing incredibly high CS from breaking difficulty calculations and making behavior inline with the game.
To keep naming convention inline with performance calculators, these classes have been renamed:
-
StarRating
-->DifficultyCalculator
-
DroidStarRating
-->DroidDifficultyCalculator
-
OsuStarRating
-->OsuDifficultyCalculator
From this point onwards, these classes will be referred to their new name.
In v1, you need to pass in a map
property to <DifficultyCalculator>.calculate
parameter object.
In v2, this has been moved to the constructor.
- new DroidStarRating().calculate({ map: beatmap });
+ new DroidDifficultyCalculator(beatmap).calculate();
Uses full name to make the field clearer. Additionally, this field is now read-only.
This has been handled internally as it doesn't make sense to have it as a required parameter.
In v1, you need to pass in a stars
property to <PerformanceCalculator>.calculate
parameter object.
In v2, this has been moved to the constructor.
- new DroidPerformanceCalculator().calculate({ stars: diffCalc });
+ new DroidPerformanceCalculator(diffCalc).calculate();
Uses full name to make the field clearer. Additionally, this field is now read-only.
In v1, cursor data movement is stored as an array of CursorData
s. Each CursorData
contains a time, x position, y position, and movement ID data in an array respectively. This process is rather complicated and often a waste of resource when you want to find connections between a cursor occurrence and another.
In v2, this has been simplified. Each CursorData
contains an occurrences
field, which contains all cursor occurrences of the cursor instance. Each cursor occurrence contains the time, position, and the movement ID of the occurrence.
Below is the difference in accessing a cursor occurrence in v1 compared to v2:
const firstCursorData = replayAnalyzer.data.cursorMovement[0];
- const index = 0;
- console.log(firstCursorData.time[0]);
- console.log(firstCursorData.x[0]);
- console.log(firstCursorData.y[0]);
- console.log(firstCursorData.id[0]);
+ const occurrence = firstCursorData.occurrences[0];
+ console.log(occurrence.time);
+ console.log(occurrence.position.x);
+ console.log(occurrence.position.y);
+ console.log(occurrence.id);
Uses full name to make the field clearer.
To keep naming convention inline with performance calculators, these classes have been renamed:
-
StarRating
-->DifficultyCalculator
-
DroidStarRating
-->DroidDifficultyCalculator
-
OsuStarRating
-->OsuDifficultyCalculator
From this point onwards, these classes will be referred to their new name.
In v1, you need to pass in a map
property to <DifficultyCalculator>.calculate
parameter object.
In v2, this has been moved to the constructor.
- new DroidStarRating().calculate({ map: beatmap });
+ new DroidDifficultyCalculator(beatmap).calculate();
Uses full name to make the field clearer. Additionally, this field is now read-only.
This has been handled internally as it doesn't make sense to have it as a required parameter.
In v1, you need to pass in a stars
property to <PerformanceCalculator>.calculate
parameter object.
In v2, this has been moved to the constructor.
- new DroidPerformanceCalculator().calculate({ stars: diffCalc });
+ new DroidPerformanceCalculator(diffCalc).calculate();
Uses full name to make the field clearer. Additionally, this field is now read-only.
Since maximum score calculations have been moved to Beatmap
level, it is now convenient to add another maximum score calculation method that calculates for osu!standard instead of osu!droid.
This method accepts an array of Mod
s as opposed to a MapStats
instance like in <Beatmap>.maxDroidScore
.
The new beatmap decoder (BeatmapDecoder
) can now decode an entire .osu
file (including storyboard, using StoryboardDecoder
which also supports .osb
files).
With this, the Beatmap
class has been restructured with respect to .osu
file contents (i.e. <Beatmap>.editor
, <Beatmap>.general
, etc) to be able to serve these additions nicely.
Each ControlPoint
classes now have an isRedundant
method to check whether a timing point will cause a meaningful change when added to the list of current timing points.
Now that a beatmap and storyboard decoder exist, it is possible to make a beatmap and storyboard encoder.
Keep in mind that equality with the original file is not guaranteed, especially if the beatmap or storyboard's format version is older than 14.
The MathUtils
class now has static methods to convert angles from radians to degrees and vice versa.
The Beatmap
class now has a getter that will return the most common beat length in the beatmap. This can be used to calculate BPM with the following formula: 60000 / <Beatmap>.mostCommonBeatLength
.
The DroidHitWindow
and OsuHitWindow
classes now have static methods that can convert a judgement hit window value to its respective OD value.
DroidHitWindow.hitWindow300ToOD(10);
DroidHitWindow.hitWindow100ToOD(10);
DroidHitWindow.hitWindow50ToOD(10);
OsuHitWindow.hitWindow300ToOD(10);
OsuHitWindow.hitWindow100ToOD(10);
OsuHitWindow.hitWindow50ToOD(10);
The ModHidden
class now have static fade multipliers.
This is used in difficulty calculation in MBMasher's FL opacity change.
You can now specify options in ModUtil
parsing methods to determine the behavior of the parser. For example, you can set the parser to ignore duplicate and incompatible mods. By default, the parser will do both operations to keep the behavior consistent with v1.
ModUtil.pcStringToMods("HDHR", {
checkDuplicate: false,
checkIncompatible: false,
});
In v1, there is no way to narrow the type of <MapInfo>.map
without checking for the value of the field.
In v2, the MapInfo.getInformation
method will automatically narrow the type of <MapInfo>.map
depending on whether you downloaded the beatmap file.
let beatmapInfo = await MapInfo.getInformation(901854);
console.log(beatmapInfo.map); // type is `Beatmap`
beatmapInfo = await MapInfo.getInformation(901854, false);
console.log(beatmapInfo.map); // type is `null`
Unfortunately, type-narrowing with promises is not supported. Therefore, the <MapInfo>.hasDownloadedBeatmap
method has been added to allow manual type-narrowing.
This method shouldn't be protected in the first place albeit it's in an abstract class.
This skill attempts to quantify the skill required to read every object in a beatmap.
This is required to port MBMasher's FL opacity change.
This method is used to calculate a hitobject's opacity at a given time. This is required to port MBMasher's FL opacity change.
In the same way as osu!lazer does it.
In the same way as osu!lazer does it.
In the same way as osu!lazer does it, however it excludes hitobjects that overlap with each other.
This feature is still in beta. However, there are too many cases to consider, hence I decided to stop here for now.
Penalty for more three-finger usage should be more harsh.
This method shouldn't be protected in the first place albeit it's in an abstract class.
This skill attempts to quantify the skill required to read every object in a beatmap.
This is required to port MBMasher's FL opacity change.
This method is used to calculate a hitobject's opacity at a given time. This is required to port MBMasher's FL opacity change.
In the same way as osu!lazer does it.
In the same way as osu!lazer does it.
In the same way as osu!lazer does it, however in droid it excludes hitobjects that overlap with each other.
In the same way as osu!lazer does it.
Small circles in droid have always been underrated. This is because it is still based on PC small circle bonus, which will never be hit unless the Small Circle (SC) mod is used.
This rework aims to solve that problem while buffing smaller circles as they inch towards 0 radius.
The introduction of droid visual skill has solved numerous problems, however one problem that became noticeable is that using HR in some beatmaps can cause the final pp value to be lower than NM due to the skill being based mainly on note density. This is especially noticeable when a beatmap is set at OD 10 in NM.
In beatmaps that specialize in low AR reading, this is reasonable, however it doesn't make sense for beatmaps that don't do so. Therefore, in order to help alleviate this problem, a small bonus is given for AR value between 9.5 and 10.
In very old beatmaps, AR is equal to OD. Therefore, the beatmap decoder has been adjusted to account for this. However, the check uses the bang operator (!
), which converts 0 to a truthy value. As a result, the beatmap's AR is assigned as its OD.
The tap star rating when calculating with the Relax mod should be 0.
The tap star rating when calculating with the Relax mod should be 0.