mirror of
https://github.com/ppy/osu.git
synced 2025-03-05 11:43:01 +08:00
Merge pull request #14929 from peppy/gameplay-state
Replace `GameplayBeatmap` with `GameplayState`
This commit is contained in:
commit
aa1bfc16d2
@ -4,13 +4,11 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Testing;
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Rulesets.Objects;
|
using osu.Game.Rulesets.Objects;
|
||||||
using osu.Game.Rulesets.Objects.Types;
|
using osu.Game.Rulesets.Objects.Types;
|
||||||
using osu.Game.Rulesets.Osu.Mods;
|
using osu.Game.Rulesets.Osu.Mods;
|
||||||
using osu.Game.Rulesets.Osu.Objects;
|
using osu.Game.Rulesets.Osu.Objects;
|
||||||
using osu.Game.Screens.Play;
|
|
||||||
using osuTK;
|
using osuTK;
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
namespace osu.Game.Rulesets.Osu.Tests.Mods
|
||||||
@ -122,7 +120,7 @@ namespace osu.Game.Rulesets.Osu.Tests.Mods
|
|||||||
private bool checkSomeHit() => Player.ScoreProcessor.JudgedHits >= 4;
|
private bool checkSomeHit() => Player.ScoreProcessor.JudgedHits >= 4;
|
||||||
|
|
||||||
private bool objectWithIncreasedVisibilityHasIndex(int index)
|
private bool objectWithIncreasedVisibilityHasIndex(int index)
|
||||||
=> Player.Mods.Value.OfType<TestOsuModHidden>().Single().FirstObject == Player.ChildrenOfType<GameplayBeatmap>().Single().HitObjects[index];
|
=> Player.Mods.Value.OfType<TestOsuModHidden>().Single().FirstObject == Player.GameplayState.Beatmap.HitObjects[index];
|
||||||
|
|
||||||
private class TestOsuModHidden : OsuModHidden
|
private class TestOsuModHidden : OsuModHidden
|
||||||
{
|
{
|
||||||
|
@ -17,6 +17,7 @@ using osu.Framework.Testing.Input;
|
|||||||
using osu.Framework.Utils;
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Audio;
|
using osu.Game.Audio;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Rulesets.Osu.Skinning;
|
using osu.Game.Rulesets.Osu.Skinning;
|
||||||
using osu.Game.Rulesets.Osu.UI.Cursor;
|
using osu.Game.Rulesets.Osu.UI.Cursor;
|
||||||
using osu.Game.Screens.Play;
|
using osu.Game.Screens.Play;
|
||||||
@ -29,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
public class TestSceneGameplayCursor : OsuSkinnableTestScene
|
public class TestSceneGameplayCursor : OsuSkinnableTestScene
|
||||||
{
|
{
|
||||||
[Cached]
|
[Cached]
|
||||||
private GameplayBeatmap gameplayBeatmap;
|
private GameplayState gameplayState;
|
||||||
|
|
||||||
private OsuCursorContainer lastContainer;
|
private OsuCursorContainer lastContainer;
|
||||||
|
|
||||||
@ -40,7 +41,8 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
|
|
||||||
public TestSceneGameplayCursor()
|
public TestSceneGameplayCursor()
|
||||||
{
|
{
|
||||||
gameplayBeatmap = new GameplayBeatmap(CreateBeatmap(new OsuRuleset().RulesetInfo));
|
var ruleset = new OsuRuleset();
|
||||||
|
gameplayState = new GameplayState(CreateBeatmap(ruleset.RulesetInfo), ruleset, Array.Empty<Mod>());
|
||||||
|
|
||||||
AddStep("change background colour", () =>
|
AddStep("change background colour", () =>
|
||||||
{
|
{
|
||||||
@ -57,7 +59,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
AddSliderStep("circle size", 0f, 10f, 0f, val =>
|
AddSliderStep("circle size", 0f, 10f, 0f, val =>
|
||||||
{
|
{
|
||||||
config.SetValue(OsuSetting.AutoCursorSize, true);
|
config.SetValue(OsuSetting.AutoCursorSize, true);
|
||||||
gameplayBeatmap.BeatmapInfo.BaseDifficulty.CircleSize = val;
|
gameplayState.Beatmap.BeatmapInfo.BaseDifficulty.CircleSize = val;
|
||||||
Scheduler.AddOnce(() => loadContent(false));
|
Scheduler.AddOnce(() => loadContent(false));
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -73,7 +75,7 @@ namespace osu.Game.Rulesets.Osu.Tests
|
|||||||
public void TestSizing(int circleSize, float userScale)
|
public void TestSizing(int circleSize, float userScale)
|
||||||
{
|
{
|
||||||
AddStep($"set user scale to {userScale}", () => config.SetValue(OsuSetting.GameplayCursorSize, userScale));
|
AddStep($"set user scale to {userScale}", () => config.SetValue(OsuSetting.GameplayCursorSize, userScale));
|
||||||
AddStep($"adjust cs to {circleSize}", () => gameplayBeatmap.BeatmapInfo.BaseDifficulty.CircleSize = circleSize);
|
AddStep($"adjust cs to {circleSize}", () => gameplayState.Beatmap.BeatmapInfo.BaseDifficulty.CircleSize = circleSize);
|
||||||
AddStep("turn on autosizing", () => config.SetValue(OsuSetting.AutoCursorSize, true));
|
AddStep("turn on autosizing", () => config.SetValue(OsuSetting.AutoCursorSize, true));
|
||||||
|
|
||||||
AddStep("load content", () => loadContent());
|
AddStep("load content", () => loadContent());
|
||||||
|
@ -37,7 +37,7 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
private OsuPlayfield playfield { get; set; }
|
private OsuPlayfield playfield { get; set; }
|
||||||
|
|
||||||
[Resolved(canBeNull: true)]
|
[Resolved(canBeNull: true)]
|
||||||
private GameplayBeatmap gameplayBeatmap { get; set; }
|
private GameplayState gameplayState { get; set; }
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(ISkinSource skin, OsuColour colours)
|
private void load(ISkinSource skin, OsuColour colours)
|
||||||
@ -75,12 +75,12 @@ namespace osu.Game.Rulesets.Osu.Skinning.Legacy
|
|||||||
|
|
||||||
protected override void Update()
|
protected override void Update()
|
||||||
{
|
{
|
||||||
if (playfield == null || gameplayBeatmap == null) return;
|
if (playfield == null || gameplayState == null) return;
|
||||||
|
|
||||||
DrawableHitObject kiaiHitObject = null;
|
DrawableHitObject kiaiHitObject = null;
|
||||||
|
|
||||||
// Check whether currently in a kiai section first. This is only done as an optimisation to avoid enumerating AliveObjects when not necessary.
|
// Check whether currently in a kiai section first. This is only done as an optimisation to avoid enumerating AliveObjects when not necessary.
|
||||||
if (gameplayBeatmap.ControlPointInfo.EffectPointAt(Time.Current).KiaiMode)
|
if (gameplayState.Beatmap.ControlPointInfo.EffectPointAt(Time.Current).KiaiMode)
|
||||||
kiaiHitObject = playfield.HitObjectContainer.AliveObjects.FirstOrDefault(isTracking);
|
kiaiHitObject = playfield.HitObjectContainer.AliveObjects.FirstOrDefault(isTracking);
|
||||||
|
|
||||||
kiaiSpewer.Active.Value = kiaiHitObject != null;
|
kiaiSpewer.Active.Value = kiaiHitObject != null;
|
||||||
|
@ -52,7 +52,7 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Resolved(canBeNull: true)]
|
[Resolved(canBeNull: true)]
|
||||||
private GameplayBeatmap beatmap { get; set; }
|
private GameplayState state { get; set; }
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private OsuConfigManager config { get; set; }
|
private OsuConfigManager config { get; set; }
|
||||||
@ -96,10 +96,10 @@ namespace osu.Game.Rulesets.Osu.UI.Cursor
|
|||||||
{
|
{
|
||||||
float scale = userCursorScale.Value;
|
float scale = userCursorScale.Value;
|
||||||
|
|
||||||
if (autoCursorScale.Value && beatmap != null)
|
if (autoCursorScale.Value && state != null)
|
||||||
{
|
{
|
||||||
// if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier.
|
// if we have a beatmap available, let's get its circle size to figure out an automatic cursor scale modifier.
|
||||||
scale *= GetScaleForCircleSize(beatmap.BeatmapInfo.BaseDifficulty.CircleSize);
|
scale *= GetScaleForCircleSize(state.Beatmap.BeatmapInfo.BaseDifficulty.CircleSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
cursorScale.Value = scale;
|
cursorScale.Value = scale;
|
||||||
|
@ -25,10 +25,10 @@ namespace osu.Game.Rulesets.Taiko.Skinning.Legacy
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader(true)]
|
||||||
private void load(GameplayBeatmap gameplayBeatmap)
|
private void load(GameplayState gameplayState)
|
||||||
{
|
{
|
||||||
if (gameplayBeatmap != null)
|
if (gameplayState != null)
|
||||||
((IBindable<JudgementResult>)LastResult).BindTo(gameplayBeatmap.LastJudgementResult);
|
((IBindable<JudgementResult>)LastResult).BindTo(gameplayState.LastJudgementResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool passing;
|
private bool passing;
|
||||||
|
@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader(true)]
|
[BackgroundDependencyLoader(true)]
|
||||||
private void load(TextureStore textures, GameplayBeatmap gameplayBeatmap)
|
private void load(TextureStore textures, GameplayState gameplayState)
|
||||||
{
|
{
|
||||||
InternalChildren = new[]
|
InternalChildren = new[]
|
||||||
{
|
{
|
||||||
@ -49,8 +49,8 @@ namespace osu.Game.Rulesets.Taiko.UI
|
|||||||
animations[TaikoMascotAnimationState.Fail] = new TaikoMascotAnimation(TaikoMascotAnimationState.Fail),
|
animations[TaikoMascotAnimationState.Fail] = new TaikoMascotAnimation(TaikoMascotAnimationState.Fail),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (gameplayBeatmap != null)
|
if (gameplayState != null)
|
||||||
((IBindable<JudgementResult>)LastResult).BindTo(gameplayBeatmap.LastJudgementResult);
|
((IBindable<JudgementResult>)LastResult).BindTo(gameplayState.LastJudgementResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void LoadComplete()
|
protected override void LoadComplete()
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
@ -17,6 +18,8 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Replays;
|
using osu.Game.Replays;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Rulesets.Replays;
|
using osu.Game.Rulesets.Replays;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
@ -38,7 +41,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
private TestReplayRecorder recorder;
|
private TestReplayRecorder recorder;
|
||||||
|
|
||||||
[Cached]
|
[Cached]
|
||||||
private GameplayBeatmap gameplayBeatmap = new GameplayBeatmap(new Beatmap());
|
private GameplayState gameplayState = new GameplayState(new Beatmap(), new OsuRuleset(), Array.Empty<Mod>());
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp() => Schedule(() =>
|
public void SetUp() => Schedule(() =>
|
||||||
@ -57,7 +60,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
Recorder = recorder = new TestReplayRecorder(new Score
|
Recorder = recorder = new TestReplayRecorder(new Score
|
||||||
{
|
{
|
||||||
Replay = replay,
|
Replay = replay,
|
||||||
ScoreInfo = { Beatmap = gameplayBeatmap.BeatmapInfo }
|
ScoreInfo = { Beatmap = gameplayState.Beatmap.BeatmapInfo }
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
ScreenSpaceToGamefield = pos => recordingManager.ToLocalSpace(pos),
|
ScreenSpaceToGamefield = pos => recordingManager.ToLocalSpace(pos),
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -13,6 +14,8 @@ using osu.Game.Beatmaps;
|
|||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Replays;
|
using osu.Game.Replays;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Rulesets.Replays;
|
using osu.Game.Rulesets.Replays;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
using osu.Game.Scoring;
|
using osu.Game.Scoring;
|
||||||
@ -30,7 +33,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
private readonly TestRulesetInputManager recordingManager;
|
private readonly TestRulesetInputManager recordingManager;
|
||||||
|
|
||||||
[Cached]
|
[Cached]
|
||||||
private GameplayBeatmap gameplayBeatmap = new GameplayBeatmap(new Beatmap());
|
private GameplayState gameplayState = new GameplayState(new Beatmap(), new OsuRuleset(), Array.Empty<Mod>());
|
||||||
|
|
||||||
public TestSceneReplayRecording()
|
public TestSceneReplayRecording()
|
||||||
{
|
{
|
||||||
@ -48,7 +51,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
Recorder = new TestReplayRecorder(new Score
|
Recorder = new TestReplayRecorder(new Score
|
||||||
{
|
{
|
||||||
Replay = replay,
|
Replay = replay,
|
||||||
ScoreInfo = { Beatmap = gameplayBeatmap.BeatmapInfo }
|
ScoreInfo = { Beatmap = gameplayState.Beatmap.BeatmapInfo }
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
ScreenSpaceToGamefield = pos => recordingManager.ToLocalSpace(pos)
|
ScreenSpaceToGamefield = pos => recordingManager.ToLocalSpace(pos)
|
||||||
|
@ -25,6 +25,8 @@ using osu.Game.Online.Spectator;
|
|||||||
using osu.Game.Replays;
|
using osu.Game.Replays;
|
||||||
using osu.Game.Replays.Legacy;
|
using osu.Game.Replays.Legacy;
|
||||||
using osu.Game.Rulesets;
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
using osu.Game.Rulesets.Replays;
|
using osu.Game.Rulesets.Replays;
|
||||||
using osu.Game.Rulesets.Replays.Types;
|
using osu.Game.Rulesets.Replays.Types;
|
||||||
using osu.Game.Rulesets.UI;
|
using osu.Game.Rulesets.UI;
|
||||||
@ -62,7 +64,7 @@ namespace osu.Game.Tests.Visual.Gameplay
|
|||||||
private SpectatorClient spectatorClient { get; set; }
|
private SpectatorClient spectatorClient { get; set; }
|
||||||
|
|
||||||
[Cached]
|
[Cached]
|
||||||
private GameplayBeatmap gameplayBeatmap = new GameplayBeatmap(new Beatmap());
|
private GameplayState gameplayState = new GameplayState(new Beatmap(), new OsuRuleset(), Array.Empty<Mod>());
|
||||||
|
|
||||||
[SetUp]
|
[SetUp]
|
||||||
public void SetUp() => Schedule(() =>
|
public void SetUp() => Schedule(() =>
|
||||||
|
@ -134,7 +134,7 @@ namespace osu.Game.Online.Spectator
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BeginPlaying(GameplayBeatmap beatmap, Score score)
|
public void BeginPlaying(GameplayState state, Score score)
|
||||||
{
|
{
|
||||||
Debug.Assert(ThreadSafety.IsUpdateThread);
|
Debug.Assert(ThreadSafety.IsUpdateThread);
|
||||||
|
|
||||||
@ -148,7 +148,7 @@ namespace osu.Game.Online.Spectator
|
|||||||
currentState.RulesetID = score.ScoreInfo.RulesetID;
|
currentState.RulesetID = score.ScoreInfo.RulesetID;
|
||||||
currentState.Mods = score.ScoreInfo.Mods.Select(m => new APIMod(m)).ToArray();
|
currentState.Mods = score.ScoreInfo.Mods.Select(m => new APIMod(m)).ToArray();
|
||||||
|
|
||||||
currentBeatmap = beatmap.PlayableBeatmap;
|
currentBeatmap = state.Beatmap;
|
||||||
currentScore = score;
|
currentScore = score;
|
||||||
|
|
||||||
BeginPlayingInternal(currentState);
|
BeginPlayingInternal(currentState);
|
||||||
|
@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
private SpectatorClient spectatorClient { get; set; }
|
private SpectatorClient spectatorClient { get; set; }
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private GameplayBeatmap gameplayBeatmap { get; set; }
|
private GameplayState gameplayState { get; set; }
|
||||||
|
|
||||||
protected ReplayRecorder(Score target)
|
protected ReplayRecorder(Score target)
|
||||||
{
|
{
|
||||||
@ -49,7 +49,7 @@ namespace osu.Game.Rulesets.UI
|
|||||||
|
|
||||||
inputManager = GetContainingInputManager();
|
inputManager = GetContainingInputManager();
|
||||||
|
|
||||||
spectatorClient?.BeginPlaying(gameplayBeatmap, target);
|
spectatorClient?.BeginPlaying(gameplayState, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool isDisposing)
|
protected override void Dispose(bool isDisposing)
|
||||||
|
@ -213,8 +213,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void StartGameplay(int userId, GameplayState gameplayState)
|
protected override void StartGameplay(int userId, SpectatorGameplayState spectatorGameplayState)
|
||||||
=> instances.Single(i => i.UserId == userId).LoadScore(gameplayState.Score);
|
=> instances.Single(i => i.UserId == userId).LoadScore(spectatorGameplayState.Score);
|
||||||
|
|
||||||
protected override void EndGameplay(int userId)
|
protected override void EndGameplay(int userId)
|
||||||
{
|
{
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
||||||
// See the LICENCE file in the repository root for full licence text.
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using osu.Framework.Bindables;
|
|
||||||
using osu.Framework.Graphics;
|
|
||||||
using osu.Game.Beatmaps;
|
|
||||||
using osu.Game.Beatmaps.ControlPoints;
|
|
||||||
using osu.Game.Beatmaps.Timing;
|
|
||||||
using osu.Game.Rulesets.Judgements;
|
|
||||||
using osu.Game.Rulesets.Objects;
|
|
||||||
|
|
||||||
namespace osu.Game.Screens.Play
|
|
||||||
{
|
|
||||||
public class GameplayBeatmap : Component, IBeatmap
|
|
||||||
{
|
|
||||||
public readonly IBeatmap PlayableBeatmap;
|
|
||||||
|
|
||||||
public GameplayBeatmap(IBeatmap playableBeatmap)
|
|
||||||
{
|
|
||||||
PlayableBeatmap = playableBeatmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BeatmapInfo BeatmapInfo
|
|
||||||
{
|
|
||||||
get => PlayableBeatmap.BeatmapInfo;
|
|
||||||
set => PlayableBeatmap.BeatmapInfo = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BeatmapMetadata Metadata => PlayableBeatmap.Metadata;
|
|
||||||
|
|
||||||
public ControlPointInfo ControlPointInfo
|
|
||||||
{
|
|
||||||
get => PlayableBeatmap.ControlPointInfo;
|
|
||||||
set => PlayableBeatmap.ControlPointInfo = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<BreakPeriod> Breaks => PlayableBeatmap.Breaks;
|
|
||||||
|
|
||||||
public double TotalBreakTime => PlayableBeatmap.TotalBreakTime;
|
|
||||||
|
|
||||||
public IReadOnlyList<HitObject> HitObjects => PlayableBeatmap.HitObjects;
|
|
||||||
|
|
||||||
public IEnumerable<BeatmapStatistic> GetStatistics() => PlayableBeatmap.GetStatistics();
|
|
||||||
|
|
||||||
public double GetMostCommonBeatLength() => PlayableBeatmap.GetMostCommonBeatLength();
|
|
||||||
|
|
||||||
public IBeatmap Clone() => PlayableBeatmap.Clone();
|
|
||||||
|
|
||||||
private readonly Bindable<JudgementResult> lastJudgementResult = new Bindable<JudgementResult>();
|
|
||||||
|
|
||||||
public IBindable<JudgementResult> LastJudgementResult => lastJudgementResult;
|
|
||||||
|
|
||||||
public void ApplyResult(JudgementResult result) => lastJudgementResult.Value = result;
|
|
||||||
}
|
|
||||||
}
|
|
55
osu.Game/Screens/Play/GameplayState.cs
Normal file
55
osu.Game/Screens/Play/GameplayState.cs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||||
|
// See the LICENCE file in the repository root for full licence text.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using osu.Framework.Bindables;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Judgements;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.Play
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The state of an active gameplay session, generally constructed and exposed by <see cref="Player"/>.
|
||||||
|
/// </summary>
|
||||||
|
public class GameplayState
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The final post-convert post-mod-application beatmap.
|
||||||
|
/// </summary>
|
||||||
|
public readonly IBeatmap Beatmap;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ruleset used in gameplay.
|
||||||
|
/// </summary>
|
||||||
|
public readonly Ruleset Ruleset;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The mods applied to the gameplay.
|
||||||
|
/// </summary>
|
||||||
|
public IReadOnlyList<Mod> Mods;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A bindable tracking the last judgement result applied to any hit object.
|
||||||
|
/// </summary>
|
||||||
|
public IBindable<JudgementResult> LastJudgementResult => lastJudgementResult;
|
||||||
|
|
||||||
|
private readonly Bindable<JudgementResult> lastJudgementResult = new Bindable<JudgementResult>();
|
||||||
|
|
||||||
|
public GameplayState(IBeatmap beatmap, Ruleset ruleset, IReadOnlyList<Mod> mods)
|
||||||
|
{
|
||||||
|
Beatmap = beatmap;
|
||||||
|
Ruleset = ruleset;
|
||||||
|
Mods = mods;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies the score change of a <see cref="JudgementResult"/> to this <see cref="GameplayState"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="result">The <see cref="JudgementResult"/> to apply.</param>
|
||||||
|
public void ApplyResult(JudgementResult result) => lastJudgementResult.Value = result;
|
||||||
|
}
|
||||||
|
}
|
@ -93,9 +93,9 @@ namespace osu.Game.Screens.Play
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private SpectatorClient spectatorClient { get; set; }
|
private SpectatorClient spectatorClient { get; set; }
|
||||||
|
|
||||||
protected Ruleset GameplayRuleset { get; private set; }
|
public GameplayState GameplayState { get; private set; }
|
||||||
|
|
||||||
protected GameplayBeatmap GameplayBeatmap { get; private set; }
|
private Ruleset ruleset;
|
||||||
|
|
||||||
private Sample sampleRestart;
|
private Sample sampleRestart;
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
// ensure the score is in a consistent state with the current player.
|
// ensure the score is in a consistent state with the current player.
|
||||||
Score.ScoreInfo.Beatmap = Beatmap.Value.BeatmapInfo;
|
Score.ScoreInfo.Beatmap = Beatmap.Value.BeatmapInfo;
|
||||||
Score.ScoreInfo.Ruleset = GameplayRuleset.RulesetInfo;
|
Score.ScoreInfo.Ruleset = ruleset.RulesetInfo;
|
||||||
Score.ScoreInfo.Mods = Mods.Value.ToArray();
|
Score.ScoreInfo.Mods = Mods.Value.ToArray();
|
||||||
|
|
||||||
PrepareReplay();
|
PrepareReplay();
|
||||||
@ -206,16 +206,16 @@ namespace osu.Game.Screens.Play
|
|||||||
if (game is OsuGame osuGame)
|
if (game is OsuGame osuGame)
|
||||||
LocalUserPlaying.BindTo(osuGame.LocalUserPlaying);
|
LocalUserPlaying.BindTo(osuGame.LocalUserPlaying);
|
||||||
|
|
||||||
DrawableRuleset = GameplayRuleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value);
|
DrawableRuleset = ruleset.CreateDrawableRulesetWith(playableBeatmap, Mods.Value);
|
||||||
dependencies.CacheAs(DrawableRuleset);
|
dependencies.CacheAs(DrawableRuleset);
|
||||||
|
|
||||||
ScoreProcessor = GameplayRuleset.CreateScoreProcessor();
|
ScoreProcessor = ruleset.CreateScoreProcessor();
|
||||||
ScoreProcessor.ApplyBeatmap(playableBeatmap);
|
ScoreProcessor.ApplyBeatmap(playableBeatmap);
|
||||||
ScoreProcessor.Mods.BindTo(Mods);
|
ScoreProcessor.Mods.BindTo(Mods);
|
||||||
|
|
||||||
dependencies.CacheAs(ScoreProcessor);
|
dependencies.CacheAs(ScoreProcessor);
|
||||||
|
|
||||||
HealthProcessor = GameplayRuleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime);
|
HealthProcessor = ruleset.CreateHealthProcessor(playableBeatmap.HitObjects[0].StartTime);
|
||||||
HealthProcessor.ApplyBeatmap(playableBeatmap);
|
HealthProcessor.ApplyBeatmap(playableBeatmap);
|
||||||
|
|
||||||
dependencies.CacheAs(HealthProcessor);
|
dependencies.CacheAs(HealthProcessor);
|
||||||
@ -225,12 +225,11 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
InternalChild = GameplayClockContainer = CreateGameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime);
|
InternalChild = GameplayClockContainer = CreateGameplayClockContainer(Beatmap.Value, DrawableRuleset.GameplayStartTime);
|
||||||
|
|
||||||
AddInternal(GameplayBeatmap = new GameplayBeatmap(playableBeatmap));
|
dependencies.CacheAs(GameplayState = new GameplayState(playableBeatmap, ruleset, Mods.Value));
|
||||||
|
|
||||||
AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer));
|
AddInternal(screenSuspension = new ScreenSuspensionHandler(GameplayClockContainer));
|
||||||
|
|
||||||
dependencies.CacheAs(GameplayBeatmap);
|
var rulesetSkinProvider = new RulesetSkinProvidingContainer(ruleset, playableBeatmap, Beatmap.Value.Skin);
|
||||||
|
|
||||||
var rulesetSkinProvider = new RulesetSkinProvidingContainer(GameplayRuleset, playableBeatmap, Beatmap.Value.Skin);
|
|
||||||
|
|
||||||
// load the skinning hierarchy first.
|
// load the skinning hierarchy first.
|
||||||
// this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources.
|
// this is intentionally done in two stages to ensure things are in a loaded state before exposing the ruleset to skin sources.
|
||||||
@ -280,7 +279,7 @@ namespace osu.Game.Screens.Play
|
|||||||
{
|
{
|
||||||
HealthProcessor.ApplyResult(r);
|
HealthProcessor.ApplyResult(r);
|
||||||
ScoreProcessor.ApplyResult(r);
|
ScoreProcessor.ApplyResult(r);
|
||||||
GameplayBeatmap.ApplyResult(r);
|
GameplayState.ApplyResult(r);
|
||||||
};
|
};
|
||||||
|
|
||||||
DrawableRuleset.RevertResult += r =>
|
DrawableRuleset.RevertResult += r =>
|
||||||
@ -478,17 +477,17 @@ namespace osu.Game.Screens.Play
|
|||||||
throw new InvalidOperationException("Beatmap was not loaded");
|
throw new InvalidOperationException("Beatmap was not loaded");
|
||||||
|
|
||||||
var rulesetInfo = Ruleset.Value ?? Beatmap.Value.BeatmapInfo.Ruleset;
|
var rulesetInfo = Ruleset.Value ?? Beatmap.Value.BeatmapInfo.Ruleset;
|
||||||
GameplayRuleset = rulesetInfo.CreateInstance();
|
ruleset = rulesetInfo.CreateInstance();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
playable = Beatmap.Value.GetPlayableBeatmap(GameplayRuleset.RulesetInfo, Mods.Value);
|
playable = Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, Mods.Value);
|
||||||
}
|
}
|
||||||
catch (BeatmapInvalidForRulesetException)
|
catch (BeatmapInvalidForRulesetException)
|
||||||
{
|
{
|
||||||
// A playable beatmap may not be creatable with the user's preferred ruleset, so try using the beatmap's default ruleset
|
// A playable beatmap may not be creatable with the user's preferred ruleset, so try using the beatmap's default ruleset
|
||||||
rulesetInfo = Beatmap.Value.BeatmapInfo.Ruleset;
|
rulesetInfo = Beatmap.Value.BeatmapInfo.Ruleset;
|
||||||
GameplayRuleset = rulesetInfo.CreateInstance();
|
ruleset = rulesetInfo.CreateInstance();
|
||||||
|
|
||||||
playable = Beatmap.Value.GetPlayableBeatmap(rulesetInfo, Mods.Value);
|
playable = Beatmap.Value.GetPlayableBeatmap(rulesetInfo, Mods.Value);
|
||||||
}
|
}
|
||||||
@ -1010,7 +1009,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
using (var stream = new MemoryStream())
|
using (var stream = new MemoryStream())
|
||||||
{
|
{
|
||||||
new LegacyScoreEncoder(score, GameplayBeatmap.PlayableBeatmap).Encode(stream);
|
new LegacyScoreEncoder(score, GameplayState.Beatmap).Encode(stream);
|
||||||
replayReader = new LegacyByteArrayReader(stream.ToArray(), "replay.osr");
|
replayReader = new LegacyByteArrayReader(stream.ToArray(), "replay.osr");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ namespace osu.Game.Screens.Play
|
|||||||
DrawableRuleset?.SetReplayScore(Score);
|
DrawableRuleset?.SetReplayScore(Score);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override Score CreateScore() => createScore(GameplayBeatmap.PlayableBeatmap, Mods.Value);
|
protected override Score CreateScore() => createScore(GameplayState.Beatmap, Mods.Value);
|
||||||
|
|
||||||
// Don't re-import replay scores as they're already present in the database.
|
// Don't re-import replay scores as they're already present in the database.
|
||||||
protected override Task ImportScore(Score score) => Task.CompletedTask;
|
protected override Task ImportScore(Score score) => Task.CompletedTask;
|
||||||
@ -78,7 +78,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
void keyboardSeek(int direction)
|
void keyboardSeek(int direction)
|
||||||
{
|
{
|
||||||
double target = Math.Clamp(GameplayClockContainer.CurrentTime + direction * keyboard_seek_amount, 0, GameplayBeatmap.HitObjects.Last().GetEndTime());
|
double target = Math.Clamp(GameplayClockContainer.CurrentTime + direction * keyboard_seek_amount, 0, GameplayState.Beatmap.HitObjects.Last().GetEndTime());
|
||||||
|
|
||||||
Seek(target);
|
Seek(target);
|
||||||
}
|
}
|
||||||
|
@ -56,7 +56,7 @@ namespace osu.Game.Screens.Play
|
|||||||
/// The player's immediate online gameplay state.
|
/// The player's immediate online gameplay state.
|
||||||
/// This doesn't always reflect the gameplay state being watched.
|
/// This doesn't always reflect the gameplay state being watched.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private GameplayState immediateGameplayState;
|
private SpectatorGameplayState immediateSpectatorGameplayState;
|
||||||
|
|
||||||
private GetBeatmapSetRequest onlineBeatmapRequest;
|
private GetBeatmapSetRequest onlineBeatmapRequest;
|
||||||
|
|
||||||
@ -146,7 +146,7 @@ namespace osu.Game.Screens.Play
|
|||||||
Width = 250,
|
Width = 250,
|
||||||
Anchor = Anchor.Centre,
|
Anchor = Anchor.Centre,
|
||||||
Origin = Anchor.Centre,
|
Origin = Anchor.Centre,
|
||||||
Action = () => scheduleStart(immediateGameplayState),
|
Action = () => scheduleStart(immediateSpectatorGameplayState),
|
||||||
Enabled = { Value = false }
|
Enabled = { Value = false }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,18 +167,18 @@ namespace osu.Game.Screens.Play
|
|||||||
showBeatmapPanel(spectatorState);
|
showBeatmapPanel(spectatorState);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void StartGameplay(int userId, GameplayState gameplayState)
|
protected override void StartGameplay(int userId, SpectatorGameplayState spectatorGameplayState)
|
||||||
{
|
{
|
||||||
immediateGameplayState = gameplayState;
|
immediateSpectatorGameplayState = spectatorGameplayState;
|
||||||
watchButton.Enabled.Value = true;
|
watchButton.Enabled.Value = true;
|
||||||
|
|
||||||
scheduleStart(gameplayState);
|
scheduleStart(spectatorGameplayState);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void EndGameplay(int userId)
|
protected override void EndGameplay(int userId)
|
||||||
{
|
{
|
||||||
scheduledStart?.Cancel();
|
scheduledStart?.Cancel();
|
||||||
immediateGameplayState = null;
|
immediateSpectatorGameplayState = null;
|
||||||
watchButton.Enabled.Value = false;
|
watchButton.Enabled.Value = false;
|
||||||
|
|
||||||
clearDisplay();
|
clearDisplay();
|
||||||
@ -194,7 +194,7 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
private ScheduledDelegate scheduledStart;
|
private ScheduledDelegate scheduledStart;
|
||||||
|
|
||||||
private void scheduleStart(GameplayState gameplayState)
|
private void scheduleStart(SpectatorGameplayState spectatorGameplayState)
|
||||||
{
|
{
|
||||||
// This function may be called multiple times in quick succession once the screen becomes current again.
|
// This function may be called multiple times in quick succession once the screen becomes current again.
|
||||||
scheduledStart?.Cancel();
|
scheduledStart?.Cancel();
|
||||||
@ -203,15 +203,15 @@ namespace osu.Game.Screens.Play
|
|||||||
if (this.IsCurrentScreen())
|
if (this.IsCurrentScreen())
|
||||||
start();
|
start();
|
||||||
else
|
else
|
||||||
scheduleStart(gameplayState);
|
scheduleStart(spectatorGameplayState);
|
||||||
});
|
});
|
||||||
|
|
||||||
void start()
|
void start()
|
||||||
{
|
{
|
||||||
Beatmap.Value = gameplayState.Beatmap;
|
Beatmap.Value = spectatorGameplayState.Beatmap;
|
||||||
Ruleset.Value = gameplayState.Ruleset.RulesetInfo;
|
Ruleset.Value = spectatorGameplayState.Ruleset.RulesetInfo;
|
||||||
|
|
||||||
this.Push(new SpectatorPlayerLoader(gameplayState.Score, () => new SoloSpectatorPlayer(gameplayState.Score)));
|
this.Push(new SpectatorPlayerLoader(spectatorGameplayState.Score, () => new SoloSpectatorPlayer(spectatorGameplayState.Score)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,8 +66,8 @@ namespace osu.Game.Screens.Play
|
|||||||
|
|
||||||
foreach (var frame in bundle.Frames)
|
foreach (var frame in bundle.Frames)
|
||||||
{
|
{
|
||||||
IConvertibleReplayFrame convertibleFrame = GameplayRuleset.CreateConvertibleReplayFrame();
|
IConvertibleReplayFrame convertibleFrame = GameplayState.Ruleset.CreateConvertibleReplayFrame();
|
||||||
convertibleFrame.FromLegacy(frame, GameplayBeatmap.PlayableBeatmap);
|
convertibleFrame.FromLegacy(frame, GameplayState.Beatmap);
|
||||||
|
|
||||||
var convertedFrame = (ReplayFrame)convertibleFrame;
|
var convertedFrame = (ReplayFrame)convertibleFrame;
|
||||||
convertedFrame.Time = frame.Time;
|
convertedFrame.Time = frame.Time;
|
||||||
|
@ -8,9 +8,9 @@ using osu.Game.Scoring;
|
|||||||
namespace osu.Game.Screens.Spectate
|
namespace osu.Game.Screens.Spectate
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The gameplay state of a spectated user. This class is immutable.
|
/// An immutable spectator gameplay state.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GameplayState
|
public class SpectatorGameplayState
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The score which the user is playing.
|
/// The score which the user is playing.
|
||||||
@ -27,7 +27,7 @@ namespace osu.Game.Screens.Spectate
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly WorkingBeatmap Beatmap;
|
public readonly WorkingBeatmap Beatmap;
|
||||||
|
|
||||||
public GameplayState(Score score, Ruleset ruleset, WorkingBeatmap beatmap)
|
public SpectatorGameplayState(Score score, Ruleset ruleset, WorkingBeatmap beatmap)
|
||||||
{
|
{
|
||||||
Score = score;
|
Score = score;
|
||||||
Ruleset = ruleset;
|
Ruleset = ruleset;
|
@ -43,7 +43,7 @@ namespace osu.Game.Screens.Spectate
|
|||||||
private readonly IBindableDictionary<int, SpectatorState> playingUserStates = new BindableDictionary<int, SpectatorState>();
|
private readonly IBindableDictionary<int, SpectatorState> playingUserStates = new BindableDictionary<int, SpectatorState>();
|
||||||
|
|
||||||
private readonly Dictionary<int, User> userMap = new Dictionary<int, User>();
|
private readonly Dictionary<int, User> userMap = new Dictionary<int, User>();
|
||||||
private readonly Dictionary<int, GameplayState> gameplayStates = new Dictionary<int, GameplayState>();
|
private readonly Dictionary<int, SpectatorGameplayState> gameplayStates = new Dictionary<int, SpectatorGameplayState>();
|
||||||
|
|
||||||
private IBindable<WeakReference<BeatmapSetInfo>> managerUpdated;
|
private IBindable<WeakReference<BeatmapSetInfo>> managerUpdated;
|
||||||
|
|
||||||
@ -173,7 +173,7 @@ namespace osu.Game.Screens.Spectate
|
|||||||
Replay = new Replay { HasReceivedAllFrames = false },
|
Replay = new Replay { HasReceivedAllFrames = false },
|
||||||
};
|
};
|
||||||
|
|
||||||
var gameplayState = new GameplayState(score, resolvedRuleset, beatmaps.GetWorkingBeatmap(resolvedBeatmap));
|
var gameplayState = new SpectatorGameplayState(score, resolvedRuleset, beatmaps.GetWorkingBeatmap(resolvedBeatmap));
|
||||||
|
|
||||||
gameplayStates[userId] = gameplayState;
|
gameplayStates[userId] = gameplayState;
|
||||||
Schedule(() => StartGameplay(userId, gameplayState));
|
Schedule(() => StartGameplay(userId, gameplayState));
|
||||||
@ -190,8 +190,8 @@ namespace osu.Game.Screens.Spectate
|
|||||||
/// Starts gameplay for a user.
|
/// Starts gameplay for a user.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="userId">The user to start gameplay for.</param>
|
/// <param name="userId">The user to start gameplay for.</param>
|
||||||
/// <param name="gameplayState">The gameplay state.</param>
|
/// <param name="spectatorGameplayState">The gameplay state.</param>
|
||||||
protected abstract void StartGameplay(int userId, [NotNull] GameplayState gameplayState);
|
protected abstract void StartGameplay(int userId, [NotNull] SpectatorGameplayState spectatorGameplayState);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Ends gameplay for a user.
|
/// Ends gameplay for a user.
|
||||||
|
@ -84,7 +84,7 @@ namespace osu.Game.Tests.Visual
|
|||||||
|
|
||||||
if (autoplayMod != null)
|
if (autoplayMod != null)
|
||||||
{
|
{
|
||||||
DrawableRuleset?.SetReplayScore(autoplayMod.CreateReplayScore(GameplayBeatmap.PlayableBeatmap, Mods.Value));
|
DrawableRuleset?.SetReplayScore(autoplayMod.CreateReplayScore(GameplayState.Beatmap, Mods.Value));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user