1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-06 18:37:27 +08:00
Commit Graph

4032 Commits

Author SHA1 Message Date
Salman Ahmed
835898dd30 Introduce DistancedHitObjectComposer and supersede OsuToolboxComposite 2022-04-28 06:44:50 +03:00
Salman Ahmed
59cf3ff50f Move distancing methods from IPositionSnapProvider to IDistanceSnapProvider 2022-04-28 05:48:45 +03:00
Salman Ahmed
cccc9d7d39 Rename method to better reflect what it's doing 2022-04-27 00:03:48 +03:00
Salman Ahmed
31f64b1381 Fix HealthProcessor fail conditions not handling multiple invocations 2022-04-26 23:27:03 +03:00
Salman Ahmed
7d32490198 Change score accuracy grading logic to be inclusive 2022-04-26 04:55:27 +03:00
Salman Ahmed
8ed39009fd Encapsulate distance spacing control handling to a "distance toolbox composite"
Encapsulated in a way which can allow further extensibility for the
right-side area of toolboxes.
2022-04-24 08:33:03 +03:00
Salman Ahmed
70a93c0e7e Move DistanceSpacingMultiplier bindable to its own IDistanceSnapProvider interface 2022-04-24 08:33:00 +03:00
Salman Ahmed
4f8f27a58b Merge branch 'master' into osu-distance-spacing 2022-04-24 05:23:30 +03:00
Dean Herbert
9c68b3edc5 Merge branch 'master' into fix-spectator-seeks 2022-04-13 12:33:41 +09:00
Bartłomiej Dach
6630b38c08
Make all ModRateAdjust implementations incompatible with each other 2022-04-07 22:38:46 +02:00
Dean Herbert
a3695c7e97
Merge branch 'master' into fix-spectator-seeks 2022-04-06 12:58:43 +09:00
Dan Balasescu
40b6f3ff0a Rename method to CalculateAllLegacyCombinations() 2022-03-31 15:09:06 +09:00
Dan Balasescu
32e55e7d78 Merge branch 'master' into osu-diff-calc-max-combo 2022-03-31 15:08:08 +09:00
Dean Herbert
e0d434b89f Remove unused using statement 2022-03-31 11:34:32 +09:00
Dean Herbert
0cac935939 Shorten class name of ModCreatedReplayUser 2022-03-31 11:34:23 +09:00
Dean Herbert
2c1ccc7d36
Update obsolete message to match targeted developers' use case
Co-authored-by: Salman Ahmed <frenzibyte@gmail.com>
2022-03-31 11:33:26 +09:00
Dean Herbert
234bec45cc Remove unnecessary logging 2022-03-31 11:32:00 +09:00
Salman Ahmed
6874cdf0c8 Remove unnecessary public prefix in interface method 2022-03-31 01:50:46 +03:00
Bartłomiej Dach
83bae81095
Fill out ICreateReplayData xmldocs 2022-03-30 22:04:54 +02:00
Bartłomiej Dach
9621a7f9cb
Merge branch 'master' into fix-autoplay-mod-user-id 2022-03-30 21:41:45 +02:00
Salman Ahmed
8d4356f23b Mark "autoplay" and "cinema" mods as mutually exclusive 2022-03-29 17:26:02 +03:00
Salman Ahmed
9a09c97457 Fix "Barrel Roll" tooltip not limiting decimal places for spin speed 2022-03-29 16:11:44 +03:00
Dean Herbert
ea9495eb74 Update all existing calls to extension method with correct fallback handling 2022-03-29 16:51:30 +09:00
Dean Herbert
7d716adf39 Create new ICreateReplayData interface and obsolete ICreateReplay 2022-03-29 16:51:30 +09:00
Dean Herbert
3fc8c23fe4 Remove unnecessary SetReplayScore call in ModCinema 2022-03-29 16:51:30 +09:00
Dean Herbert
327477d050 Remove unnecessary SetReplayScore call in ModCinema 2022-03-29 16:50:05 +09:00
Dean Herbert
6f529cf7a4 Merge branch 'master' into fix-spectator-seeks 2022-03-24 14:24:20 +09:00
Salman Ahmed
6cd67928ab Simplify documentation of ModUsage 2022-03-23 15:48:52 +03:00
Salman Ahmed
b218046fa2 Remove redundant line from mod usage 2022-03-23 15:38:48 +03:00
Dean Herbert
c079a9cd32 Add comment regarding equality check importance in LegacyHitSampleInfo 2022-03-23 20:18:44 +09:00
Dean Herbert
997c091a8d Revert "Remove IsLayered from LegacyHitSampleInfo comparison"
This reverts commit 4523393208.
2022-03-23 20:15:17 +09:00
Dean Herbert
2ea9e5245c Revert "Remove IsLayered from GetHasCode implementation"
This reverts commit 16ee6b5fc7.
2022-03-23 20:15:13 +09:00
Dan Balasescu
36772ec652
Merge pull request #17356 from apollo-dw/strict-tracking
Implement "Strict Tracking" mod in osu!
2022-03-22 07:32:36 +09:00
Salman Ahmed
5f878ed82b Delegate IsPlayable to the obsoleted UserPlayable by default
Handles consumers who still haven't updated to use `IsPlayable` yet.
2022-03-20 16:07:09 +03:00
Salman Ahmed
add9f3ec91 Rename multiplayer mod usages to make more sense 2022-03-20 13:12:24 +03:00
Salman Ahmed
820a672940 Reword xmldoc to make more sense 2022-03-20 06:37:08 +03:00
Salman Ahmed
70e943fbcc ModUsage.Solo -> ModUsage.User 2022-03-20 06:36:51 +03:00
apollo-dw
149cfd338d Use new mod-related object types for Strict Tracking 2022-03-19 18:29:44 +00:00
Salman Ahmed
8078a8c1f8 Simplify IncreasesCombo/BreaksCombo helper method implementation 2022-03-18 17:18:42 +03:00
Salman Ahmed
5ec2d86c09 Update ScoreProcessor to use new defined helper methods 2022-03-18 15:22:53 +03:00
Salman Ahmed
fc576b1369 Separate increase/break combo helper methods from AffectsCombo 2022-03-18 15:22:01 +03:00
Dean Herbert
0988c2b0fa Move DrawableRuleset binding to LoadComplete to avoid exceptions on InputManager access 2022-03-18 15:28:48 +09:00
Salman Ahmed
f2248ecc08 Update usages to use IsPlayable instead 2022-03-18 02:11:18 +03:00
Salman Ahmed
51e5dd7d0e Introduce IsPlayable(...) and obsolete UserPlayable 2022-03-18 02:08:30 +03:00
Salman Ahmed
d90f21e140
Reword mod documentation
Co-authored-by: Bartłomiej Dach <dach.bartlomiej@gmail.com>
2022-03-18 00:13:40 +03:00
Salman Ahmed
b3ac544d65 Revert "Consider UnknownMod to be "playable in multiplayer""
This reverts commit 07e9f3780a.
2022-03-17 06:31:51 +03:00
Salman Ahmed
07e9f3780a Consider UnknownMod to be "playable in multiplayer" 2022-03-17 05:15:48 +03:00
Salman Ahmed
187059a37f Replace hardcoded overrides with the newly introduced Mod properties 2022-03-17 03:51:27 +03:00
Salman Ahmed
d90a334853 Introduce multiplayer playability and free mod validity in Mod 2022-03-17 03:48:56 +03:00
Dan Balasescu
d80830b415
Merge pull request #17226 from peppy/skin-component-settings
Allow skin components to have settings
2022-03-16 17:12:11 +09:00
Dean Herbert
1814a325d8 Move GetSettingUnderlyingValue to a SettingSource extension method 2022-03-15 14:54:00 +09:00
Dean Herbert
6fb06d69cc
Merge branch 'master' into pp-counter-alloc-reduction 2022-03-15 13:31:57 +09:00
Dean Herbert
deb4aeb4b2
Merge pull request #17242 from smoogipoo/performance-calculator-cleanup
Restructure PerformanceCalculator to not require ScoreInfo argument
2022-03-15 13:31:34 +09:00
Dan Balasescu
3a6d254d1f Add safeguards around incorrect ruleset sources 2022-03-15 09:20:32 +09:00
Dan Balasescu
e79bed8fbe Merge branch 'master' into skin-component-settings 2022-03-14 18:54:27 +09:00
Dean Herbert
16ee6b5fc7 Remove IsLayered from GetHasCode implementation 2022-03-14 18:12:04 +09:00
Dean Herbert
39d95aa8cf Add automatic preloading of sample pools at a Playfield level 2022-03-14 17:19:48 +09:00
Dean Herbert
4523393208 Remove IsLayered from LegacyHitSampleInfo comparison
The equality of samples is generally used to compare the sample
equality, not its full properties. For instance, we don't compare
`Volume` in the base implementation.

Having `IsLayered` here breaks actual usages of equality, ie. for
pooling purposes.
2022-03-14 17:19:48 +09:00
Dean Herbert
8676a2587c Add the ability for HitObjects to specify auxiliary samples 2022-03-14 17:19:48 +09:00
Dan Balasescu
028750936c Apply review suggestions 2022-03-14 17:10:37 +09:00
Dan Balasescu
3fff7f4b7e Require ScoreProcessor to receive ruleset 2022-03-14 15:51:10 +09:00
Dan Balasescu
9cc7f70872 Nullable annotate classes 2022-03-14 15:38:00 +09:00
Dan Balasescu
4a3e3aba65 Restructure PerformanceCalculator to not require ScoreInfo argument 2022-03-14 14:25:28 +09:00
Dean Herbert
8d1ee28e67 Add settings modification UI to skin editor 2022-03-13 17:03:25 +09:00
Dean Herbert
db5c2c15dc
Merge pull request #17164 from smoogipoo/scoreprocessor-rework
Rework ScoreProcessor score calculation methods to fix various issues
2022-03-10 16:48:58 +09:00
Dan Balasescu
13a4058efd
Merge pull request #17191 from peppy/fix-mod-conversion-exceptions
Change `ToMod` to return an `UnknownMod` rather than throw if a mod isn't available
2022-03-10 16:20:50 +09:00
Dan Balasescu
cf91353009 Merge branch 'master' into scoreprocessor-rework 2022-03-10 16:14:28 +09:00
Dean Herbert
eaef27595c Also mark UnknownMod as not user-playable 2022-03-10 15:33:50 +09:00
Dan Balasescu
c36badab4b Add per-ruleset score multipliers for classic scoring 2022-03-10 10:26:09 +09:00
Dean Herbert
94ff6a338f
Merge branch 'master' into scoreprocessor-rework 2022-03-09 23:04:18 +09:00
Dean Herbert
02f44d7061 Merge branch 'master' into fix-mod-conversion-exceptions 2022-03-09 18:07:42 +09:00
Dean Herbert
0267aed846 Change ToMod to return an UnknownMod rather than throw if a mod isn't available
As seen by this kind of crash, having the `.ToMod` method throw can be
very problematic and also hidden (as it is used inside of models in
places where exceptions are not expected to occur).

Given there are tens of usages of this method, returning a placeholder
mod seems like a better idea than outright throwing.

```
 An unhandled has occurred.
 System.InvalidOperationException:
There is no mod in the ruleset (osu) matching the acronym AS.
 at osu.Game.Online.API.APIMod.ToMod(Ruleset ruleset) in /Users/dean/Projects/osu/osu.Game/Online/API/APIMod.cs:line 54
 at osu.Game.Scoring.ScoreInfo.<get_Mods>b__117_0(APIMod m) in /Users/dean/Projects/osu/osu.Game/Scoring/ScoreInfo.cs:line 193
 at System.Linq.Enumerable.SelectArrayIterator`2.ToArray()
 at osu.Game.Scoring.ScoreInfo.get_Mods() in /Users/dean/Projects/osu/osu.Game/Scoring/ScoreInfo.cs:line 193
 at osu.Game.Screens.Select.Leaderboards.BeatmapLeaderboard.<>c.<subscribeToLocalScores>b__40_2(ScoreInfo s) in /Users/dean/Projects/osu/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs:line 199
 at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
 at osu.Game.Database.RealmObjectExtensions.Detach[T](IEnumerable`1 items) in /Users/dean/Projects/osu/osu.Game/Database/RealmObjectExtensions.cs:line 180
 at osu.Game.Screens.Select.Leaderboards.BeatmapLeaderboard.<>c__DisplayClass40_0.<subscribeToLocalScores>g__localScoresChanged|1(IRealmCollection`1 sender, ChangeSet changes, Exception exception) in /Users/dean/Projects/osu/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs:line
209
 at Realms.RealmCollectionBase`1.Realms.INotifiable<Realms.NotifiableObjectHandleBase.CollectionChangeSet>.NotifyCallbacks(Nullable`1 changes, Nullable`1 exception)
 at Realms.NotifiableObjectHandleBase.NotifyObjectChanged(IntPtr managedHandle, IntPtr changes, IntPtr exception)
```
2022-03-09 17:57:55 +09:00
Dean Herbert
8bb07f83cd
Merge pull request #17054 from hlysine/mod-adaptive-speed
Implement Adaptive Speed mod
2022-03-09 17:56:34 +09:00
Dan Balasescu
6fd8b4d891 Safeguard method against invalid invocation 2022-03-08 22:30:44 +09:00
Dan Balasescu
f1c40bd9ed Rework GetScore() method signatures + implementations
Rename legacy-facing overload to mention as much
2022-03-08 22:30:44 +09:00
Dan Balasescu
a8e99f1a95 Calculate classic score using total basic hitobject count 2022-03-08 21:49:41 +09:00
Dan Balasescu
5b6b8d1fa9 Remove GetStandardisedScore() proxy method 2022-03-08 21:49:41 +09:00
Dan Balasescu
6654977a7b Add GetScore() overload with total hitobject count 2022-03-08 21:49:41 +09:00
Dan Balasescu
2c382bd1d9 Rename GetImmediateScore() as overload of GetScore() 2022-03-08 21:49:40 +09:00
Dan Balasescu
a352a140bc
Merge pull request #17157 from peppy/fix-statistics-json-serialisation
Fix incorrect serialisation of submitted scores
2022-03-08 20:20:31 +09:00
Dan Balasescu
a172fc6cb8 Add IsBasic() and IsTick() extensions on HitResult 2022-03-08 18:19:12 +09:00
Dean Herbert
589a40ca2d Add EnumMember naming to HitResult to allow for correct json serialisation 2022-03-08 17:58:37 +09:00
Henry Lin
8b8b54b58f Scale rate adjustments based on hit timing consistency and tweak some related numbers 2022-03-05 21:48:57 +08:00
Henry Lin
76d257fbe4
Merge branch 'master' into mod-adaptive-speed 2022-03-04 15:16:37 +08:00
Henry Lin
f72c9a1f41 Cap speed change per hit and apply a speed decrease on miss 2022-03-04 11:48:48 +08:00
Henry Lin
b66af7edf4 Rename approximatedRates to ratesForRewinding and update xmldoc 2022-03-04 11:03:57 +08:00
Bartłomiej Dach
fcefd3c725
Fix slightly wrong references in xmldocs 2022-03-03 17:39:55 +01:00
Bartłomiej Dach
3797871aa0
Add extended documentation of adaptive speed mod machinations 2022-03-03 17:25:49 +01:00
Bartłomiej Dach
ffaf5b729f
Move and reword docs of allowable rate range constants 2022-03-03 17:07:43 +01:00
Henry Lin
464be6e64c Only call IUpdatableByPlayfield.Update if the playfield isn't nested 2022-03-03 14:37:39 +08:00
Henry Lin
4ce2044e4c Reorder members 2022-03-03 13:09:41 +08:00
Henry Lin
9c2aa51194 Rename applyPitchAdjustment to adjustPitchChanged 2022-03-03 13:07:30 +08:00
Henry Lin
ae71dcceeb Convert comments to xmldoc 2022-03-03 13:03:53 +08:00
Henry Lin
09254407fe Interpolate speed change using IUpdatableByPlayfield 2022-03-03 12:09:36 +08:00
Henry Lin
51258dbab4 Use binary search in ApplyToBeatmap 2022-03-03 11:21:20 +08:00
Henry Lin
95a40c5dc5 Remove pointless comment 2022-03-03 10:43:30 +08:00
Henry Lin
ff7f65de27 Extract duplicated conditionals 2022-03-03 10:43:04 +08:00
Henry Lin
55737226a3 Use Enumerable.Repeat 2022-03-03 10:18:36 +08:00
Henry Lin
d335a2229f Tweak average_count 2022-03-02 21:07:57 +08:00
Henry Lin
17bc714297 Allow the mod to properly react to nested hit objects 2022-03-02 20:48:57 +08:00
Henry Lin
6caecf79a0 Use smooth speed change 2022-03-02 20:08:05 +08:00
Henry Lin
c6934b4bce Improve adaptive speed algorithm and add rewind support 2022-03-02 10:35:03 +08:00
Henry Lin
783f43ccfb Add initial rate setting 2022-03-02 09:57:52 +08:00
Henry Lin
c9b205afeb Add adaptive speed mod 2022-03-02 09:57:52 +08:00
Dean Herbert
7215f3f66b Fix CalculateAverageHitError throwing if there are zero HitEvents 2022-03-01 18:44:15 +09:00
Dean Herbert
159db38f8a Add missing xmldoc 2022-02-28 19:14:43 +09:00
Dean Herbert
a41e1c80f1 Show hit error on results screen
Leading up to implementation of "local offset", this feels like a good
thing to have visible first and foremost.
2022-02-28 19:11:06 +09:00
Dan Balasescu
3a03833912
Merge pull request #16890 from peppy/beatmap-decoder-ruleset-store
Fix `LegacyBeatmapDecoder` not populating correct rulesets
2022-02-25 19:03:43 +09:00
Bartłomiej Dach
d8fa443ea0
Extract default mod switch measurements to constants
For use later when specific sizes/scales of the mod switches are
desired.
2022-02-22 23:22:11 +01:00
Dan Balasescu
bedd07d2e4 Add remark about usage of CalculateAll() 2022-02-22 18:12:55 +09:00
Bartłomiej Dach
cfc41a0a36
Implement small mod switch 2022-02-22 00:26:35 +01:00
Bartłomiej Dach
5186693dad
Implement tiny mod switch 2022-02-22 00:26:35 +01:00
Dan Balasescu
c466d6df94 Ensure to not multiply by 0 2022-02-21 17:19:35 +09:00
Dan Balasescu
c3b365cf6b Scale classic score by hitobject count 2022-02-21 13:31:03 +09:00
Dan Balasescu
567da9214e Merge branch 'master' into osu-diff-calc-max-combo 2022-02-18 18:35:24 +09:00
Dan Balasescu
3945cd24eb wip 2022-02-17 21:14:49 +09:00
Dean Herbert
7307e68e9c Revert "Merge pull request #16889 from smoogipoo/remove-mod-multiplier"
This reverts commit 252b945d3b, reversing
changes made to a1b39a96cf.
2022-02-17 13:26:12 +09:00
Dean Herbert
23933fc881 Update xmldoc to mention that multipliers are not applied anywhere 2022-02-16 17:32:22 +09:00
Dean Herbert
5ffd3ff82a Add xmldoc and allow constructing an AssemblyRulesetStore with a directory path 2022-02-16 17:25:16 +09:00
Dean Herbert
d0efecfc9c Add RulesetStore for use where realm is not present (ie. other projects) 2022-02-16 17:13:54 +09:00
Dean Herbert
7a69de0060 Split out realm portion of RulesetStore 2022-02-16 17:13:31 +09:00
Dan Balasescu
4c1413e0c7 No longer require Mod implementation 2022-02-16 16:36:02 +09:00
Dan Balasescu
5dd9771c5f Remove mod multipliers from being applied to scores 2022-02-16 16:27:27 +09:00
Dan Balasescu
84e82ef5e4 Add XMLDocs to difficulty attribute properties 2022-02-16 14:09:19 +09:00
Salman Ahmed
0992bec2c8 Change "distance spacing" multipler type to double
Avoids losing precision on initial load, causing an unnecessary
hash change in `EditorChangeHandler`.

Resolves test failures in `TestSceneEditorChangeStates`
(https://github.com/ppy/osu/runs/5192493482?check_suite_focus=true).
2022-02-16 03:28:12 +03:00
Salman Ahmed
868dcd20f5 Remove e.ShiftPressed handling for now
Broken on macOS, will be handled differently later on as discussed.
2022-02-15 02:21:53 +03:00
Salman Ahmed
528dc03b8c Expose distance spacing in IPositionSnapProvider for updating distance grid
Alternate method is to expose a `SnapDistancesChanged` event in
`IPositionSnapProvider` instead, but I chose this way as an analogue to
`IBeatSnapProvider.BeatDivisor`, which might even make sense to be
exposed as `BindableBeatDivisor` instead of caching that separately.
2022-02-15 02:21:53 +03:00
Salman Ahmed
19ee05c232 Add "distance spacing" multiplier for osu! ruleset
While osu!catch also implements a distance snap grid, it doesn't rely on
`GetBeatSnapDistanceAt` (unlike osu!), therefore it can't have the
"distance spacing" multiplier yet.
2022-02-15 02:21:53 +03:00
Dean Herbert
b9d9fc56af Move files to UI namespace 2022-02-14 17:51:39 +09:00
Salman Ahmed
92e22c57a7 Introduce private APIRuleset for online ID equality comparison 2022-02-11 08:27:01 +03:00
Salman Ahmed
26839f6ad8 Consider OnlineIDs during ruleset equality if available
Required for `APIBeatmap`s, which provide `Ruleset` instances with `OnlineID` available only.

Also consistent with the comparer implementation.
2022-02-11 04:26:58 +03:00
Salman Ahmed
1b729e891d Update pointless CompareTo implementation once again 2022-02-11 04:17:30 +03:00
Salman Ahmed
9574bc1382 Allow IRulesetInfos of same type to be comparable
At first I was planning on making `CompareTo` implemented at
`IRulesetInfo` itself and shared across classes, but turns out it only
implements it explicitly and not allow direct `IRulesetInfo.Equals`
calls.

It messed with my head enough that I decided to just let each class have
its own implementation and only allow same type.
2022-02-11 04:03:23 +03:00
Dan Balasescu
ebd105422f Remove unused using 2022-02-10 14:22:08 +09:00
Dan Balasescu
f7fb7825cc Simplify disposal 2022-02-10 14:21:51 +09:00
Dan Balasescu
a3896a8ebd Remove allowance of null dependency 2022-02-10 14:21:50 +09:00
Dan Balasescu
45b3f472ab Merge branch 'master' into spectator-state-rework 2022-02-08 19:51:50 +09:00
Henry Lin
56c90a21ce Add a todo 2022-02-06 11:22:12 +08:00
Henry Lin
f78c853bc7 Calculate max combo locally in PerformanceBreakdownCalculator 2022-02-06 10:59:53 +08:00
Henry Lin
0b1fef38af Use the playable beatmap provided in CreateStatisticsForScore 2022-02-05 21:36:34 +08:00
Henry Lin
f29301cd1e
Merge branch 'master' into display-performance-attributes 2022-02-05 16:59:46 +08:00
Dan Balasescu
483977d5c8 Merge branch 'master' into spectator-state-rework 2022-02-03 19:59:07 +09:00
Bartłomiej Dach
82f9ad63f5
Fix flashlight size multiplier printing with too many decimal digits 2022-02-02 20:41:25 +01:00
Salman Ahmed
074a691635 Set keyboard step to 0.1 for difficulty adjust sliders 2022-02-02 17:43:08 +03:00
Dan Balasescu
6d3bc005ea Merge branch 'master' into spectator-state-rework 2022-02-02 18:57:04 +09:00
Dean Herbert
0c5da9370a Fix rulesets potentially being marked Available even when methods are missing
Came up when running the game after the recent breaking changes
(https://github.com/ppy/osu/pull/16722), where two template rulesets I
had loaded were erroring on startup but still being marked as available,
allowing them to crash the game on attempting to initiate relpay logic.

These cases are already handled for first-time ruleset loading via the
`GetTypes()` enumeration in `RulesetStore.addRuleset`, but when
consistency checking already present rulesets the only runtime
validation being done was `ruleset.CreateInstance()`, which does not
handle missing types or methods.
2022-02-02 14:52:01 +09:00
Henry Lin
b06128ffa5 Rename "Final PP" to "Achieved PP" 2022-02-01 22:26:55 +08:00
Dan Balasescu
41007169f7 Give SpectatorState a user state 2022-02-01 21:51:05 +09:00
Dean Herbert
0f83f77d2b Add xmldoc for new ResetFromReplayFrame method 2022-02-01 16:52:53 +09:00
Dan Balasescu
0641264a11 Merge branch 'master' into spectator-consistency-frames 2022-02-01 14:35:30 +09:00