Skip to content

Commit f414dd7

Browse files
authored
Merge pull request #34880 from minetoblend/fix/editor-player-crash
Fix crash when trying to test map in the editor
2 parents 69bcef8 + 4ed72ef commit f414dd7

File tree

1 file changed

+41
-21
lines changed

1 file changed

+41
-21
lines changed

osu.Game/Screens/Edit/GameplayTest/EditorPlayer.cs

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,25 @@ protected override GameplayClockContainer CreateGameplayClockContainer(WorkingBe
5555
return masterGameplayClockContainer;
5656
}
5757

58+
protected override void LoadAsyncComplete()
59+
{
60+
base.LoadAsyncComplete();
61+
62+
if (!LoadedBeatmapSuccessfully)
63+
return;
64+
65+
// This hack needs to be called to install its hooks before drawable hit objects get the chance to run update logic,
66+
// because it will not work otherwise due to being too late (various effects of the objects getting missed will have already taken place).
67+
preventMissOnPreviousHitObjects();
68+
}
69+
5870
protected override void LoadComplete()
5971
{
6072
base.LoadComplete();
6173

74+
// this will notify components such as the skin's combo counter, which needs to happen on the update thread
75+
// and therefore can't happen alongside `preventMissOnPreviousHitObjects()` in `LoadAsyncComplete()`
6276
markPreviousObjectsHit();
63-
markVisibleDrawableObjectsHit();
6477

6578
ScoreProcessor.HasCompleted.BindValueChanged(completed =>
6679
{
@@ -111,38 +124,45 @@ static IEnumerable<HitObject> enumerateHitObjects(IEnumerable<HitObject> hitObje
111124
}
112125
}
113126

114-
private void markVisibleDrawableObjectsHit()
127+
private void preventMissOnPreviousHitObjects()
115128
{
116-
if (!DrawableRuleset.Playfield.IsLoaded)
129+
void preventMiss(HitObject hitObject)
117130
{
118-
Schedule(markVisibleDrawableObjectsHit);
119-
return;
131+
var drawableObject = DrawableRuleset.Playfield.HitObjectContainer
132+
.AliveObjects
133+
.SingleOrDefault(it => it.HitObject == hitObject);
134+
135+
if (drawableObject != null)
136+
preventMissOnDrawable(drawableObject);
120137
}
121138

122-
foreach (var drawableObject in enumerateDrawableObjects(DrawableRuleset.Playfield.AllHitObjects, editorState.Time))
139+
void preventMissOnDrawable(DrawableHitObject drawableObject)
123140
{
124-
if (drawableObject.Entry == null)
125-
continue;
141+
foreach (var nested in drawableObject.NestedHitObjects)
142+
preventMissOnDrawable(nested);
126143

127-
var result = drawableObject.CreateResult(drawableObject.HitObject.Judgement);
128-
result.Type = result.Judgement.MaxResult;
129-
drawableObject.Entry.Result = result;
144+
if (drawableObject.Entry != null && drawableObject.HitObject.GetEndTime() < editorState.Time)
145+
{
146+
var result = drawableObject.CreateResult(drawableObject.HitObject.Judgement);
147+
result.Type = result.Judgement.MaxResult;
148+
drawableObject.Entry.Result = result;
149+
}
130150
}
131151

132-
static IEnumerable<DrawableHitObject> enumerateDrawableObjects(IEnumerable<DrawableHitObject> drawableObjects, double cutoffTime)
152+
void removeListener()
133153
{
134-
foreach (var drawableObject in drawableObjects)
154+
if (!DrawableRuleset.Playfield.IsLoaded)
135155
{
136-
foreach (var nested in enumerateDrawableObjects(drawableObject.NestedHitObjects, cutoffTime))
137-
{
138-
if (nested.HitObject.GetEndTime() < cutoffTime)
139-
yield return nested;
140-
}
141-
142-
if (drawableObject.HitObject.GetEndTime() < cutoffTime)
143-
yield return drawableObject;
156+
Schedule(removeListener);
157+
return;
144158
}
159+
160+
DrawableRuleset.Playfield.HitObjectUsageBegan -= preventMiss;
145161
}
162+
163+
DrawableRuleset.Playfield.HitObjectUsageBegan += preventMiss;
164+
165+
Schedule(removeListener);
146166
}
147167

148168
protected override void PrepareReplay()

0 commit comments

Comments
 (0)