mirror of
https://github.com/ppy/osu.git
synced 2024-11-11 14:17:26 +08:00
Merge branch 'master' into precise-rotation-2
This commit is contained in:
commit
a78c03bd5b
@ -85,7 +85,7 @@ namespace osu.Desktop
|
||||
}
|
||||
}
|
||||
|
||||
using (DesktopGameHost host = Host.GetSuitableDesktopHost(gameName, new HostOptions { BindIPC = true }))
|
||||
using (DesktopGameHost host = Host.GetSuitableDesktopHost(gameName, new HostOptions { BindIPC = !tournamentClient }))
|
||||
{
|
||||
if (!host.IsPrimaryInstance)
|
||||
{
|
||||
|
@ -14,7 +14,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Skills
|
||||
{
|
||||
private const double individual_decay_base = 0.125;
|
||||
private const double overall_decay_base = 0.30;
|
||||
private const double release_threshold = 24;
|
||||
private const double release_threshold = 30;
|
||||
|
||||
protected override double SkillMultiplier => 1;
|
||||
protected override double StrainDecayBase => 1;
|
||||
@ -50,10 +50,13 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Skills
|
||||
for (int i = 0; i < endTimes.Length; ++i)
|
||||
{
|
||||
// The current note is overlapped if a previous note or end is overlapping the current note body
|
||||
isOverlapping |= Precision.DefinitelyBigger(endTimes[i], startTime, 1) && Precision.DefinitelyBigger(endTime, endTimes[i], 1);
|
||||
isOverlapping |= Precision.DefinitelyBigger(endTimes[i], startTime, 1) &&
|
||||
Precision.DefinitelyBigger(endTime, endTimes[i], 1) &&
|
||||
Precision.DefinitelyBigger(startTime, startTimes[i], 1);
|
||||
|
||||
// We give a slight bonus to everything if something is held meanwhile
|
||||
if (Precision.DefinitelyBigger(endTimes[i], endTime, 1))
|
||||
if (Precision.DefinitelyBigger(endTimes[i], endTime, 1) &&
|
||||
Precision.DefinitelyBigger(startTime, startTimes[i], 1))
|
||||
holdFactor = 1.25;
|
||||
|
||||
closestEndTime = Math.Min(closestEndTime, Math.Abs(endTime - endTimes[i]));
|
||||
@ -70,7 +73,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty.Skills
|
||||
// 0.0 +--------+-+---------------> Release Difference / ms
|
||||
// release_threshold
|
||||
if (isOverlapping)
|
||||
holdAddition = 1 / (1 + Math.Exp(0.5 * (release_threshold - closestEndTime)));
|
||||
holdAddition = 1 / (1 + Math.Exp(0.27 * (release_threshold - closestEndTime)));
|
||||
|
||||
// Decay and increase individualStrains in own column
|
||||
individualStrains[column] = applyDecay(individualStrains[column], startTime - startTimes[column], individual_decay_base);
|
||||
|
@ -139,7 +139,6 @@ namespace osu.Game.Rulesets.Taiko.Beatmaps
|
||||
StartTime = obj.StartTime,
|
||||
Samples = obj.Samples,
|
||||
Duration = taikoDuration,
|
||||
SliderVelocity = obj is IHasSliderVelocity velocityData ? velocityData.SliderVelocity : 1
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
|
||||
using osu.Game.Rulesets.Objects.Types;
|
||||
using System.Threading;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Beatmaps.ControlPoints;
|
||||
using osu.Game.Beatmaps.Formats;
|
||||
@ -14,7 +13,7 @@ using osuTK;
|
||||
|
||||
namespace osu.Game.Rulesets.Taiko.Objects
|
||||
{
|
||||
public class DrumRoll : TaikoStrongableHitObject, IHasPath, IHasSliderVelocity
|
||||
public class DrumRoll : TaikoStrongableHitObject, IHasPath
|
||||
{
|
||||
/// <summary>
|
||||
/// Drum roll distance that results in a duration of 1 speed-adjusted beat length.
|
||||
@ -34,19 +33,6 @@ namespace osu.Game.Rulesets.Taiko.Objects
|
||||
/// </summary>
|
||||
public double Velocity { get; private set; }
|
||||
|
||||
public BindableNumber<double> SliderVelocityBindable { get; } = new BindableDouble(1)
|
||||
{
|
||||
Precision = 0.01,
|
||||
MinValue = 0.1,
|
||||
MaxValue = 10
|
||||
};
|
||||
|
||||
public double SliderVelocity
|
||||
{
|
||||
get => SliderVelocityBindable.Value;
|
||||
set => SliderVelocityBindable.Value = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Numer of ticks per beat length.
|
||||
/// </summary>
|
||||
@ -63,8 +49,9 @@ namespace osu.Game.Rulesets.Taiko.Objects
|
||||
base.ApplyDefaultsToSelf(controlPointInfo, difficulty);
|
||||
|
||||
TimingControlPoint timingPoint = controlPointInfo.TimingPointAt(StartTime);
|
||||
EffectControlPoint effectPoint = controlPointInfo.EffectPointAt(StartTime);
|
||||
|
||||
double scoringDistance = base_distance * difficulty.SliderMultiplier * SliderVelocity;
|
||||
double scoringDistance = base_distance * difficulty.SliderMultiplier * effectPoint.ScrollSpeed;
|
||||
Velocity = scoringDistance / timingPoint.BeatLength;
|
||||
|
||||
TickRate = difficulty.SliderTickRate == 3 ? 3 : 4;
|
||||
|
@ -49,6 +49,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
LoadComponentAsync(leaderboard = new MultiSpectatorLeaderboard(clocks.Keys.Select(id => new MultiplayerRoomUser(id)).ToArray())
|
||||
{
|
||||
Anchor = Anchor.Centre,
|
||||
Origin = Anchor.Centre,
|
||||
Expanded = { Value = true }
|
||||
}, Add);
|
||||
});
|
||||
|
@ -79,6 +79,19 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
AddWaitStep("wait a bit", 20);
|
||||
}
|
||||
|
||||
[TestCase(2)]
|
||||
[TestCase(16)]
|
||||
public void TestTeams(int count)
|
||||
{
|
||||
int[] userIds = getPlayerIds(count);
|
||||
|
||||
start(userIds, teams: true);
|
||||
loadSpectateScreen();
|
||||
|
||||
sendFrames(userIds, 1000);
|
||||
AddWaitStep("wait a bit", 20);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestMultipleStartRequests()
|
||||
{
|
||||
@ -450,16 +463,18 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
||||
|
||||
private void start(int userId, int? beatmapId = null) => start(new[] { userId }, beatmapId);
|
||||
|
||||
private void start(int[] userIds, int? beatmapId = null, APIMod[]? mods = null)
|
||||
private void start(int[] userIds, int? beatmapId = null, APIMod[]? mods = null, bool teams = false)
|
||||
{
|
||||
AddStep("start play", () =>
|
||||
{
|
||||
foreach (int id in userIds)
|
||||
for (int i = 0; i < userIds.Length; i++)
|
||||
{
|
||||
int id = userIds[i];
|
||||
var user = new MultiplayerRoomUser(id)
|
||||
{
|
||||
User = new APIUser { Id = id },
|
||||
Mods = mods ?? Array.Empty<APIMod>(),
|
||||
MatchState = teams ? new TeamVersusUserState { TeamID = i % 2 } : null,
|
||||
};
|
||||
|
||||
OnlinePlayDependencies.MultiplayerClient.AddUser(user, true);
|
||||
|
@ -4,6 +4,7 @@
|
||||
using NUnit.Framework;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Testing;
|
||||
using osu.Game.Beatmaps.Legacy;
|
||||
using osu.Game.Tests.Visual;
|
||||
using osu.Game.Tournament.Components;
|
||||
@ -17,11 +18,11 @@ namespace osu.Game.Tournament.Tests.Components
|
||||
[Cached]
|
||||
private readonly LadderInfo ladder = new LadderInfo();
|
||||
|
||||
[Test]
|
||||
public void TestSongBar()
|
||||
{
|
||||
SongBar songBar = null!;
|
||||
private SongBar songBar = null!;
|
||||
|
||||
[SetUpSteps]
|
||||
public void SetUpSteps()
|
||||
{
|
||||
AddStep("create bar", () => Child = songBar = new SongBar
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
@ -29,7 +30,11 @@ namespace osu.Game.Tournament.Tests.Components
|
||||
Origin = Anchor.Centre
|
||||
});
|
||||
AddUntilStep("wait for loaded", () => songBar.IsLoaded);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TestSongBar()
|
||||
{
|
||||
AddStep("set beatmap", () =>
|
||||
{
|
||||
var beatmap = CreateAPIBeatmap(Ruleset.Value);
|
||||
|
@ -14,7 +14,6 @@ using osu.Game.Extensions;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Tournament.Models;
|
||||
using osuTK;
|
||||
using osuTK.Graphics;
|
||||
|
||||
@ -22,14 +21,14 @@ namespace osu.Game.Tournament.Components
|
||||
{
|
||||
public partial class SongBar : CompositeDrawable
|
||||
{
|
||||
private TournamentBeatmap? beatmap;
|
||||
private IBeatmapInfo? beatmap;
|
||||
|
||||
public const float HEIGHT = 145 / 2f;
|
||||
|
||||
[Resolved]
|
||||
private IBindable<RulesetInfo> ruleset { get; set; } = null!;
|
||||
|
||||
public TournamentBeatmap? Beatmap
|
||||
public IBeatmapInfo? Beatmap
|
||||
{
|
||||
set
|
||||
{
|
||||
@ -37,7 +36,7 @@ namespace osu.Game.Tournament.Components
|
||||
return;
|
||||
|
||||
beatmap = value;
|
||||
update();
|
||||
refreshContent();
|
||||
}
|
||||
}
|
||||
|
||||
@ -49,7 +48,7 @@ namespace osu.Game.Tournament.Components
|
||||
set
|
||||
{
|
||||
mods = value;
|
||||
update();
|
||||
refreshContent();
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,19 +70,25 @@ namespace osu.Game.Tournament.Components
|
||||
protected override bool ComputeIsMaskedAway(RectangleF maskingBounds) => false;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
private void load(OsuColour colours)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
Masking = true;
|
||||
CornerRadius = 5;
|
||||
|
||||
InternalChildren = new Drawable[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Colour = colours.Gray3,
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
},
|
||||
flow = new FillFlowContainer
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
AutoSizeAxes = Axes.Y,
|
||||
LayoutDuration = 500,
|
||||
LayoutEasing = Easing.OutQuint,
|
||||
Direction = FillDirection.Full,
|
||||
Anchor = Anchor.BottomRight,
|
||||
Origin = Anchor.BottomRight,
|
||||
@ -93,7 +98,7 @@ namespace osu.Game.Tournament.Components
|
||||
Expanded = true;
|
||||
}
|
||||
|
||||
private void update()
|
||||
private void refreshContent()
|
||||
{
|
||||
if (beatmap == null)
|
||||
{
|
||||
@ -229,7 +234,7 @@ namespace osu.Game.Tournament.Components
|
||||
}
|
||||
}
|
||||
},
|
||||
new TournamentBeatmapPanel(beatmap)
|
||||
new UnmaskedTournamentBeatmapPanel(beatmap)
|
||||
{
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Width = 0.5f,
|
||||
@ -272,4 +277,18 @@ namespace osu.Game.Tournament.Components
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal partial class UnmaskedTournamentBeatmapPanel : TournamentBeatmapPanel
|
||||
{
|
||||
public UnmaskedTournamentBeatmapPanel(IBeatmapInfo? beatmap, string mod = "")
|
||||
: base(beatmap, mod)
|
||||
{
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load()
|
||||
{
|
||||
Masking = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ namespace osu.Game.Tournament.Components
|
||||
{
|
||||
public partial class TournamentBeatmapPanel : CompositeDrawable
|
||||
{
|
||||
public readonly TournamentBeatmap? Beatmap;
|
||||
public readonly IBeatmapInfo? Beatmap;
|
||||
|
||||
private readonly string mod;
|
||||
|
||||
@ -30,7 +30,7 @@ namespace osu.Game.Tournament.Components
|
||||
|
||||
private Box flash = null!;
|
||||
|
||||
public TournamentBeatmapPanel(TournamentBeatmap? beatmap, string mod = "")
|
||||
public TournamentBeatmapPanel(IBeatmapInfo? beatmap, string mod = "")
|
||||
{
|
||||
Beatmap = beatmap;
|
||||
this.mod = mod;
|
||||
@ -58,7 +58,7 @@ namespace osu.Game.Tournament.Components
|
||||
{
|
||||
RelativeSizeAxes = Axes.Both,
|
||||
Colour = OsuColour.Gray(0.5f),
|
||||
OnlineInfo = Beatmap,
|
||||
OnlineInfo = (Beatmap as IBeatmapSetOnlineInfo),
|
||||
},
|
||||
new FillFlowContainer
|
||||
{
|
||||
|
@ -14,7 +14,7 @@ namespace osu.Game.Tournament.IPC
|
||||
public Bindable<LegacyMods> Mods { get; } = new Bindable<LegacyMods>();
|
||||
public Bindable<TourneyState> State { get; } = new Bindable<TourneyState>();
|
||||
public Bindable<string> ChatChannel { get; } = new Bindable<string>();
|
||||
public BindableInt Score1 { get; } = new BindableInt();
|
||||
public BindableInt Score2 { get; } = new BindableInt();
|
||||
public BindableLong Score1 { get; } = new BindableLong();
|
||||
public BindableLong Score2 { get; } = new BindableLong();
|
||||
}
|
||||
}
|
||||
|
@ -1,181 +1,19 @@
|
||||
// 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;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Graphics.Shapes;
|
||||
using osu.Game.Graphics;
|
||||
using osu.Game.Graphics.Sprites;
|
||||
using osu.Game.Graphics.UserInterface;
|
||||
using osu.Game.Screens.Play.HUD;
|
||||
using osu.Game.Tournament.IPC;
|
||||
using osuTK;
|
||||
|
||||
namespace osu.Game.Tournament.Screens.Gameplay.Components
|
||||
{
|
||||
// TODO: Update to derive from osu-side class?
|
||||
public partial class TournamentMatchScoreDisplay : CompositeDrawable
|
||||
public partial class TournamentMatchScoreDisplay : MatchScoreDisplay
|
||||
{
|
||||
private const float bar_height = 18;
|
||||
|
||||
private readonly BindableInt score1 = new BindableInt();
|
||||
private readonly BindableInt score2 = new BindableInt();
|
||||
|
||||
private readonly MatchScoreCounter score1Text;
|
||||
private readonly MatchScoreCounter score2Text;
|
||||
|
||||
private readonly MatchScoreDiffCounter scoreDiffText;
|
||||
|
||||
private readonly Drawable score1Bar;
|
||||
private readonly Drawable score2Bar;
|
||||
|
||||
public TournamentMatchScoreDisplay()
|
||||
{
|
||||
RelativeSizeAxes = Axes.X;
|
||||
AutoSizeAxes = Axes.Y;
|
||||
|
||||
InternalChildren = new[]
|
||||
{
|
||||
new Box
|
||||
{
|
||||
Name = "top bar red (static)",
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = bar_height / 4,
|
||||
Width = 0.5f,
|
||||
Colour = TournamentGame.COLOUR_RED,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopRight
|
||||
},
|
||||
new Box
|
||||
{
|
||||
Name = "top bar blue (static)",
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = bar_height / 4,
|
||||
Width = 0.5f,
|
||||
Colour = TournamentGame.COLOUR_BLUE,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopLeft
|
||||
},
|
||||
score1Bar = new Box
|
||||
{
|
||||
Name = "top bar red",
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = bar_height,
|
||||
Width = 0,
|
||||
Colour = TournamentGame.COLOUR_RED,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopRight
|
||||
},
|
||||
score1Text = new MatchScoreCounter
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre
|
||||
},
|
||||
score2Bar = new Box
|
||||
{
|
||||
Name = "top bar blue",
|
||||
RelativeSizeAxes = Axes.X,
|
||||
Height = bar_height,
|
||||
Width = 0,
|
||||
Colour = TournamentGame.COLOUR_BLUE,
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopLeft
|
||||
},
|
||||
score2Text = new MatchScoreCounter
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Origin = Anchor.TopCentre
|
||||
},
|
||||
scoreDiffText = new MatchScoreDiffCounter
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Margin = new MarginPadding
|
||||
{
|
||||
Top = bar_height / 4,
|
||||
Horizontal = 8
|
||||
},
|
||||
Alpha = 0
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(MatchIPCInfo ipc)
|
||||
{
|
||||
score1.BindValueChanged(_ => updateScores());
|
||||
score1.BindTo(ipc.Score1);
|
||||
|
||||
score2.BindValueChanged(_ => updateScores());
|
||||
score2.BindTo(ipc.Score2);
|
||||
}
|
||||
|
||||
private void updateScores()
|
||||
{
|
||||
score1Text.Current.Value = score1.Value;
|
||||
score2Text.Current.Value = score2.Value;
|
||||
|
||||
var winningText = score1.Value > score2.Value ? score1Text : score2Text;
|
||||
var losingText = score1.Value <= score2.Value ? score1Text : score2Text;
|
||||
|
||||
winningText.Winning = true;
|
||||
losingText.Winning = false;
|
||||
|
||||
var winningBar = score1.Value > score2.Value ? score1Bar : score2Bar;
|
||||
var losingBar = score1.Value <= score2.Value ? score1Bar : score2Bar;
|
||||
|
||||
int diff = Math.Max(score1.Value, score2.Value) - Math.Min(score1.Value, score2.Value);
|
||||
|
||||
losingBar.ResizeWidthTo(0, 400, Easing.OutQuint);
|
||||
winningBar.ResizeWidthTo(Math.Min(0.4f, MathF.Pow(diff / 1500000f, 0.5f) / 2), 400, Easing.OutQuint);
|
||||
|
||||
scoreDiffText.Alpha = diff != 0 ? 1 : 0;
|
||||
scoreDiffText.Current.Value = -diff;
|
||||
scoreDiffText.Origin = score1.Value > score2.Value ? Anchor.TopLeft : Anchor.TopRight;
|
||||
}
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
{
|
||||
base.UpdateAfterChildren();
|
||||
score1Text.X = -Math.Max(5 + score1Text.DrawWidth / 2, score1Bar.DrawWidth);
|
||||
score2Text.X = Math.Max(5 + score2Text.DrawWidth / 2, score2Bar.DrawWidth);
|
||||
}
|
||||
|
||||
private partial class MatchScoreCounter : CommaSeparatedScoreCounter
|
||||
{
|
||||
private OsuSpriteText displayedSpriteText = null!;
|
||||
|
||||
public MatchScoreCounter()
|
||||
{
|
||||
Margin = new MarginPadding { Top = bar_height, Horizontal = 10 };
|
||||
}
|
||||
|
||||
public bool Winning
|
||||
{
|
||||
set => updateFont(value);
|
||||
}
|
||||
|
||||
protected override OsuSpriteText CreateSpriteText() => base.CreateSpriteText().With(s =>
|
||||
{
|
||||
displayedSpriteText = s;
|
||||
displayedSpriteText.Spacing = new Vector2(-6);
|
||||
updateFont(false);
|
||||
});
|
||||
|
||||
private void updateFont(bool winning)
|
||||
=> displayedSpriteText.Font = winning
|
||||
? OsuFont.Torus.With(weight: FontWeight.Bold, size: 50, fixedWidth: true)
|
||||
: OsuFont.Torus.With(weight: FontWeight.Regular, size: 40, fixedWidth: true);
|
||||
}
|
||||
|
||||
private partial class MatchScoreDiffCounter : CommaSeparatedScoreCounter
|
||||
{
|
||||
protected override OsuSpriteText CreateSpriteText() => base.CreateSpriteText().With(s =>
|
||||
{
|
||||
s.Spacing = new Vector2(-2);
|
||||
s.Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: bar_height, fixedWidth: true);
|
||||
});
|
||||
Team1Score.BindTo(ipc.Score1);
|
||||
Team2Score.BindTo(ipc.Score2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Timing;
|
||||
using osu.Game.Screens.Play;
|
||||
|
||||
@ -59,6 +60,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Spectate
|
||||
|
||||
public bool Seek(double position)
|
||||
{
|
||||
Logger.Log($"{nameof(SpectatorPlayerClock)} seeked to {position}");
|
||||
CurrentTime = position;
|
||||
return true;
|
||||
}
|
||||
|
@ -160,6 +160,21 @@ namespace osu.Game.Screens.Play
|
||||
|
||||
Seek(StartTime);
|
||||
|
||||
// This is a workaround for the fact that DecoupleableInterpolatingFramedClock doesn't seek the source
|
||||
// if the source is not IsRunning. (see https://github.com/ppy/osu-framework/blob/2102638056dfcf85d21b4d85266d53b5dd018767/osu.Framework/Timing/DecoupleableInterpolatingFramedClock.cs#L209-L210)
|
||||
// I hope to remove this once we knock some sense into clocks in general.
|
||||
//
|
||||
// Without this seek, the multiplayer spectator start sequence breaks:
|
||||
// - Individual clients' clocks are never updated to their expected time
|
||||
// - The sync manager thinks they are running behind
|
||||
// - Gameplay doesn't start when it should (until a timeout occurs because nothing is happening for 10+ seconds)
|
||||
//
|
||||
// In addition, we use `CurrentTime` for this seek instead of `StartTime` as the above seek may have applied inherent
|
||||
// offsets which need to be accounted for (ie. FramedBeatmapClock.TotalAppliedOffset).
|
||||
//
|
||||
// See https://github.com/ppy/osu/pull/24451/files/87fee001c786b29db34063ef3350e9a9f024d3ab#diff-28ca02979641e2d98a15fe5d5e806f56acf60ac100258a059fa72503b6cc54e8.
|
||||
(SourceClock as IAdjustableClock)?.Seek(CurrentTime);
|
||||
|
||||
if (!wasPaused || startClock)
|
||||
Start();
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
// 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.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
@ -24,11 +22,13 @@ namespace osu.Game.Screens.Play.HUD
|
||||
public BindableLong Team1Score = new BindableLong();
|
||||
public BindableLong Team2Score = new BindableLong();
|
||||
|
||||
protected MatchScoreCounter Score1Text;
|
||||
protected MatchScoreCounter Score2Text;
|
||||
protected MatchScoreCounter Score1Text = null!;
|
||||
protected MatchScoreCounter Score2Text = null!;
|
||||
|
||||
private Drawable score1Bar;
|
||||
private Drawable score2Bar;
|
||||
private Drawable score1Bar = null!;
|
||||
private Drawable score2Bar = null!;
|
||||
|
||||
private MatchScoreDiffCounter scoreDiffText = null!;
|
||||
|
||||
[BackgroundDependencyLoader]
|
||||
private void load(OsuColour colours)
|
||||
@ -98,6 +98,16 @@ namespace osu.Game.Screens.Play.HUD
|
||||
},
|
||||
}
|
||||
},
|
||||
scoreDiffText = new MatchScoreDiffCounter
|
||||
{
|
||||
Anchor = Anchor.TopCentre,
|
||||
Margin = new MarginPadding
|
||||
{
|
||||
Top = bar_height / 4,
|
||||
Horizontal = 8
|
||||
},
|
||||
Alpha = 0
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@ -139,6 +149,10 @@ namespace osu.Game.Screens.Play.HUD
|
||||
|
||||
losingBar.ResizeWidthTo(0, 400, Easing.OutQuint);
|
||||
winningBar.ResizeWidthTo(Math.Min(0.4f, MathF.Pow(diff / 1500000f, 0.5f) / 2), 400, Easing.OutQuint);
|
||||
|
||||
scoreDiffText.Alpha = diff != 0 ? 1 : 0;
|
||||
scoreDiffText.Current.Value = -diff;
|
||||
scoreDiffText.Origin = Team1Score.Value > Team2Score.Value ? Anchor.TopLeft : Anchor.TopRight;
|
||||
}
|
||||
|
||||
protected override void UpdateAfterChildren()
|
||||
@ -150,7 +164,7 @@ namespace osu.Game.Screens.Play.HUD
|
||||
|
||||
protected partial class MatchScoreCounter : CommaSeparatedScoreCounter
|
||||
{
|
||||
private OsuSpriteText displayedSpriteText;
|
||||
private OsuSpriteText displayedSpriteText = null!;
|
||||
|
||||
public MatchScoreCounter()
|
||||
{
|
||||
@ -174,5 +188,14 @@ namespace osu.Game.Screens.Play.HUD
|
||||
? OsuFont.Torus.With(weight: FontWeight.Bold, size: font_size, fixedWidth: true)
|
||||
: OsuFont.Torus.With(weight: FontWeight.Regular, size: font_size * 0.8f, fixedWidth: true);
|
||||
}
|
||||
|
||||
private partial class MatchScoreDiffCounter : CommaSeparatedScoreCounter
|
||||
{
|
||||
protected override OsuSpriteText CreateSpriteText() => base.CreateSpriteText().With(s =>
|
||||
{
|
||||
s.Spacing = new Vector2(-2);
|
||||
s.Font = OsuFont.Torus.With(weight: FontWeight.Regular, size: bar_height, fixedWidth: true);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,7 +124,12 @@ namespace osu.Game.Tests.Visual.Spectator
|
||||
if (frames.Count == 0)
|
||||
return;
|
||||
|
||||
var bundle = new FrameDataBundle(new ScoreInfo { Combo = currentFrameIndex }, new ScoreProcessor(rulesetStore.GetRuleset(0)!.CreateInstance()), frames.ToArray());
|
||||
var bundle = new FrameDataBundle(new ScoreInfo
|
||||
{
|
||||
Combo = currentFrameIndex,
|
||||
TotalScore = (long)(currentFrameIndex * 123478 * RNG.NextDouble(0.99, 1.01)),
|
||||
Accuracy = RNG.NextDouble(0.98, 1),
|
||||
}, new ScoreProcessor(rulesetStore.GetRuleset(0)!.CreateInstance()), frames.ToArray());
|
||||
((ISpectatorClient)this).UserSentFrames(userId, bundle);
|
||||
|
||||
frames.Clear();
|
||||
|
Loading…
Reference in New Issue
Block a user