mirror of
https://github.com/osukey/osukey.git
synced 2025-08-04 15:16:38 +09:00
Merge branch 'master' into no-gameplay-clock-gameplay-offset
This commit is contained in:
@ -69,8 +69,9 @@ namespace osu.Game.Database
|
||||
/// 21 2022-07-27 Migrate collections to realm (BeatmapCollection).
|
||||
/// 22 2022-07-31 Added ModPreset.
|
||||
/// 23 2022-08-01 Added LastLocalUpdate to BeatmapInfo.
|
||||
/// 24 2022-08-22 Added MaximumStatistics to ScoreInfo.
|
||||
/// </summary>
|
||||
private const int schema_version = 23;
|
||||
private const int schema_version = 24;
|
||||
|
||||
/// <summary>
|
||||
/// Lock object which is held during <see cref="BlockAllOperations"/> sections, blocking realm retrieval during blocking periods.
|
||||
|
@ -74,6 +74,9 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
[JsonProperty("statistics")]
|
||||
public Dictionary<HitResult, int> Statistics { get; set; } = new Dictionary<HitResult, int>();
|
||||
|
||||
[JsonProperty("maximum_statistics")]
|
||||
public Dictionary<HitResult, int> MaximumStatistics { get; set; } = new Dictionary<HitResult, int>();
|
||||
|
||||
#region osu-web API additions (not stored to database).
|
||||
|
||||
[JsonProperty("id")]
|
||||
@ -153,6 +156,7 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
MaxCombo = MaxCombo,
|
||||
Rank = Rank,
|
||||
Statistics = Statistics,
|
||||
MaximumStatistics = MaximumStatistics,
|
||||
Date = EndedAt,
|
||||
Hash = HasReplay ? "online" : string.Empty, // TODO: temporary?
|
||||
Mods = mods,
|
||||
@ -174,6 +178,7 @@ namespace osu.Game.Online.API.Requests.Responses
|
||||
Passed = score.Passed,
|
||||
Mods = score.APIMods,
|
||||
Statistics = score.Statistics.Where(kvp => kvp.Value != 0).ToDictionary(kvp => kvp.Key, kvp => kvp.Value),
|
||||
MaximumStatistics = score.MaximumStatistics.Where(kvp => kvp.Value != 0).ToDictionary(kvp => kvp.Key, kvp => kvp.Value),
|
||||
};
|
||||
|
||||
public long OnlineID => ID ?? -1;
|
||||
|
@ -1,27 +1,27 @@
|
||||
// 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;
|
||||
using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Framework.Platform;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Chat;
|
||||
using osu.Game.Overlays.Dialog;
|
||||
|
||||
namespace osu.Game.Online.Chat
|
||||
{
|
||||
public class ExternalLinkOpener : Component
|
||||
{
|
||||
[Resolved]
|
||||
private GameHost host { get; set; }
|
||||
private GameHost host { get; set; } = null!;
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private IDialogOverlay dialogOverlay { get; set; }
|
||||
private IDialogOverlay? dialogOverlay { get; set; }
|
||||
|
||||
private Bindable<bool> externalLinkWarning;
|
||||
private Bindable<bool> externalLinkWarning = null!;
|
||||
|
||||
[BackgroundDependencyLoader(true)]
|
||||
private void load(OsuConfigManager config)
|
||||
@ -31,10 +31,39 @@ namespace osu.Game.Online.Chat
|
||||
|
||||
public void OpenUrlExternally(string url, bool bypassWarning = false)
|
||||
{
|
||||
if (!bypassWarning && externalLinkWarning.Value)
|
||||
dialogOverlay.Push(new ExternalLinkDialog(url, () => host.OpenUrlExternally(url)));
|
||||
if (!bypassWarning && externalLinkWarning.Value && dialogOverlay != null)
|
||||
dialogOverlay.Push(new ExternalLinkDialog(url, () => host.OpenUrlExternally(url), () => host.GetClipboard()?.SetText(url)));
|
||||
else
|
||||
host.OpenUrlExternally(url);
|
||||
}
|
||||
|
||||
public class ExternalLinkDialog : PopupDialog
|
||||
{
|
||||
public ExternalLinkDialog(string url, Action openExternalLinkAction, Action copyExternalLinkAction)
|
||||
{
|
||||
HeaderText = "Just checking...";
|
||||
BodyText = $"You are about to leave osu! and open the following link in a web browser:\n\n{url}";
|
||||
|
||||
Icon = FontAwesome.Solid.ExclamationTriangle;
|
||||
|
||||
Buttons = new PopupDialogButton[]
|
||||
{
|
||||
new PopupDialogOkButton
|
||||
{
|
||||
Text = @"Yes. Go for it.",
|
||||
Action = openExternalLinkAction
|
||||
},
|
||||
new PopupDialogCancelButton
|
||||
{
|
||||
Text = @"Copy URL to the clipboard instead.",
|
||||
Action = copyExternalLinkAction
|
||||
},
|
||||
new PopupDialogCancelButton
|
||||
{
|
||||
Text = @"No! Abort mission!"
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,35 +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.
|
||||
|
||||
#nullable disable
|
||||
|
||||
using System;
|
||||
using osu.Framework.Graphics.Sprites;
|
||||
using osu.Game.Overlays.Dialog;
|
||||
|
||||
namespace osu.Game.Overlays.Chat
|
||||
{
|
||||
public class ExternalLinkDialog : PopupDialog
|
||||
{
|
||||
public ExternalLinkDialog(string url, Action openExternalLinkAction)
|
||||
{
|
||||
HeaderText = "Just checking...";
|
||||
BodyText = $"You are about to leave osu! and open the following link in a web browser:\n\n{url}";
|
||||
|
||||
Icon = FontAwesome.Solid.ExclamationTriangle;
|
||||
|
||||
Buttons = new PopupDialogButton[]
|
||||
{
|
||||
new PopupDialogOkButton
|
||||
{
|
||||
Text = @"Yes. Go for it.",
|
||||
Action = openExternalLinkAction
|
||||
},
|
||||
new PopupDialogCancelButton
|
||||
{
|
||||
Text = @"No! Abort mission!"
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@ -128,8 +128,7 @@ namespace osu.Game.Rulesets.Scoring
|
||||
private bool beatmapApplied;
|
||||
|
||||
private readonly Dictionary<HitResult, int> scoreResultCounts = new Dictionary<HitResult, int>();
|
||||
|
||||
private Dictionary<HitResult, int>? maximumResultCounts;
|
||||
private readonly Dictionary<HitResult, int> maximumResultCounts = new Dictionary<HitResult, int>();
|
||||
|
||||
private readonly List<HitEvent> hitEvents = new List<HitEvent>();
|
||||
private HitObject? lastHitObject;
|
||||
@ -405,8 +404,6 @@ namespace osu.Game.Rulesets.Scoring
|
||||
return ScoreRank.D;
|
||||
}
|
||||
|
||||
public int GetStatistic(HitResult result) => scoreResultCounts.GetValueOrDefault(result);
|
||||
|
||||
/// <summary>
|
||||
/// Resets this ScoreProcessor to a default state.
|
||||
/// </summary>
|
||||
@ -421,7 +418,9 @@ namespace osu.Game.Rulesets.Scoring
|
||||
if (storeResults)
|
||||
{
|
||||
maximumScoringValues = currentScoringValues;
|
||||
maximumResultCounts = new Dictionary<HitResult, int>(scoreResultCounts);
|
||||
|
||||
maximumResultCounts.Clear();
|
||||
maximumResultCounts.AddRange(scoreResultCounts);
|
||||
}
|
||||
|
||||
scoreResultCounts.Clear();
|
||||
@ -449,7 +448,10 @@ namespace osu.Game.Rulesets.Scoring
|
||||
score.HitEvents = hitEvents;
|
||||
|
||||
foreach (var result in HitResultExtensions.ALL_TYPES)
|
||||
score.Statistics[result] = GetStatistic(result);
|
||||
score.Statistics[result] = scoreResultCounts.GetValueOrDefault(result);
|
||||
|
||||
foreach (var result in HitResultExtensions.ALL_TYPES)
|
||||
score.MaximumStatistics[result] = maximumResultCounts.GetValueOrDefault(result);
|
||||
|
||||
// Populate total score after everything else.
|
||||
score.TotalScore = (long)Math.Round(ComputeFinalScore(ScoringMode.Standardised, score));
|
||||
|
@ -73,6 +73,9 @@ namespace osu.Game.Scoring
|
||||
|
||||
if (string.IsNullOrEmpty(model.StatisticsJson))
|
||||
model.StatisticsJson = JsonConvert.SerializeObject(model.Statistics);
|
||||
|
||||
if (string.IsNullOrEmpty(model.MaximumStatisticsJson))
|
||||
model.MaximumStatisticsJson = JsonConvert.SerializeObject(model.MaximumStatistics);
|
||||
}
|
||||
|
||||
protected override void PostImport(ScoreInfo model, Realm realm, bool batchImport)
|
||||
|
@ -63,6 +63,9 @@ namespace osu.Game.Scoring
|
||||
[MapTo("Statistics")]
|
||||
public string StatisticsJson { get; set; } = string.Empty;
|
||||
|
||||
[MapTo("MaximumStatistics")]
|
||||
public string MaximumStatisticsJson { get; set; } = string.Empty;
|
||||
|
||||
public ScoreInfo(BeatmapInfo? beatmap = null, RulesetInfo? ruleset = null, RealmUser? realmUser = null)
|
||||
{
|
||||
Ruleset = ruleset ?? new RulesetInfo();
|
||||
@ -133,6 +136,7 @@ namespace osu.Game.Scoring
|
||||
var clone = (ScoreInfo)this.Detach().MemberwiseClone();
|
||||
|
||||
clone.Statistics = new Dictionary<HitResult, int>(clone.Statistics);
|
||||
clone.MaximumStatistics = new Dictionary<HitResult, int>(clone.MaximumStatistics);
|
||||
clone.RealmUser = new RealmUser
|
||||
{
|
||||
OnlineID = RealmUser.OnlineID,
|
||||
@ -181,6 +185,24 @@ namespace osu.Game.Scoring
|
||||
set => statistics = value;
|
||||
}
|
||||
|
||||
private Dictionary<HitResult, int>? maximumStatistics;
|
||||
|
||||
[Ignored]
|
||||
public Dictionary<HitResult, int> MaximumStatistics
|
||||
{
|
||||
get
|
||||
{
|
||||
if (maximumStatistics != null)
|
||||
return maximumStatistics;
|
||||
|
||||
if (!string.IsNullOrEmpty(MaximumStatisticsJson))
|
||||
maximumStatistics = JsonConvert.DeserializeObject<Dictionary<HitResult, int>>(MaximumStatisticsJson);
|
||||
|
||||
return maximumStatistics ??= new Dictionary<HitResult, int>();
|
||||
}
|
||||
set => maximumStatistics = value;
|
||||
}
|
||||
|
||||
private Mod[]? mods;
|
||||
|
||||
[Ignored]
|
||||
|
@ -55,8 +55,6 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
match &= !criteria.Artist.HasFilter || criteria.Artist.Matches(BeatmapInfo.Metadata.Artist) ||
|
||||
criteria.Artist.Matches(BeatmapInfo.Metadata.ArtistUnicode);
|
||||
|
||||
match &= criteria.Sort != SortMode.DateRanked || BeatmapInfo.BeatmapSet?.DateRanked != null;
|
||||
|
||||
match &= !criteria.UserStarDifficulty.HasFilter || criteria.UserStarDifficulty.IsInRange(BeatmapInfo.StarRating);
|
||||
|
||||
if (match && criteria.SearchTerms.Length > 0)
|
||||
|
@ -99,6 +99,13 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
|
||||
case SortMode.Difficulty:
|
||||
return compareUsingAggregateMax(otherSet, b => b.StarRating);
|
||||
|
||||
case SortMode.DateSubmitted:
|
||||
// Beatmaps which have no submitted date should already be filtered away in this mode.
|
||||
if (BeatmapSet.DateSubmitted == null || otherSet.BeatmapSet.DateSubmitted == null)
|
||||
return 0;
|
||||
|
||||
return otherSet.BeatmapSet.DateSubmitted.Value.CompareTo(BeatmapSet.DateSubmitted.Value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,7 +129,12 @@ namespace osu.Game.Screens.Select.Carousel
|
||||
public override void Filter(FilterCriteria criteria)
|
||||
{
|
||||
base.Filter(criteria);
|
||||
Filtered.Value = Items.All(i => i.Filtered.Value);
|
||||
bool match = Items.All(i => i.Filtered.Value);
|
||||
|
||||
match &= criteria.Sort != SortMode.DateRanked || BeatmapSet?.DateRanked != null;
|
||||
match &= criteria.Sort != SortMode.DateSubmitted || BeatmapSet?.DateSubmitted != null;
|
||||
|
||||
Filtered.Value = match;
|
||||
}
|
||||
|
||||
public override string ToString() => BeatmapSet.ToString();
|
||||
|
@ -20,6 +20,9 @@ namespace osu.Game.Screens.Select.Filter
|
||||
[LocalisableDescription(typeof(SortStrings), nameof(SortStrings.ArtistTracksBpm))]
|
||||
BPM,
|
||||
|
||||
[Description("Date Submitted")]
|
||||
DateSubmitted,
|
||||
|
||||
[Description("Date Added")]
|
||||
DateAdded,
|
||||
|
||||
|
Reference in New Issue
Block a user