1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 13:22:55 +08:00

Merge branch 'master' into multiplayer-local-beatmap-query

This commit is contained in:
Dan Balasescu 2021-12-12 16:37:41 +09:00 committed by GitHub
commit bf3abb2455
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
47 changed files with 133 additions and 115 deletions

View File

@ -27,10 +27,10 @@
]
},
"ppy.localisationanalyser.tools": {
"version": "2021.725.0",
"version": "2021.1210.0",
"commands": [
"localisation"
]
}
}
}
}

View File

@ -52,7 +52,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.1203.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.1207.0" />
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.1210.0" />
</ItemGroup>
<ItemGroup Label="Transitive Dependencies">
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->

View File

@ -1022,7 +1022,7 @@ namespace osu.Game.Tests.Beatmaps.IO
{
return ImportScoreTest.LoadScoreIntoOsu(osu, new ScoreInfo
{
OnlineScoreID = 2,
OnlineID = 2,
BeatmapInfo = beatmapInfo,
BeatmapInfoID = beatmapInfo.ID
}, new ImportScoreTest.TestArchiveReader());

View File

@ -809,7 +809,7 @@ namespace osu.Game.Tests.Database
// TODO: reimplement when we have score support in realm.
// return ImportScoreTest.LoadScoreIntoOsu(osu, new ScoreInfo
// {
// OnlineScoreID = 2,
// OnlineID = 2,
// Beatmap = beatmap,
// BeatmapInfoID = beatmap.ID
// }, new ImportScoreTest.TestArchiveReader());

View File

@ -40,7 +40,7 @@ namespace osu.Game.Tests.Scores.IO
Combo = 250,
User = new APIUser { Username = "Test user" },
Date = DateTimeOffset.Now,
OnlineScoreID = 12345,
OnlineID = 12345,
};
var imported = await LoadScoreIntoOsu(osu, toImport);
@ -52,7 +52,7 @@ namespace osu.Game.Tests.Scores.IO
Assert.AreEqual(toImport.Combo, imported.Combo);
Assert.AreEqual(toImport.User.Username, imported.User.Username);
Assert.AreEqual(toImport.Date, imported.Date);
Assert.AreEqual(toImport.OnlineScoreID, imported.OnlineScoreID);
Assert.AreEqual(toImport.OnlineID, imported.OnlineID);
}
finally
{
@ -163,12 +163,12 @@ namespace osu.Game.Tests.Scores.IO
{
var osu = LoadOsuIntoHost(host, true);
await LoadScoreIntoOsu(osu, new ScoreInfo { OnlineScoreID = 2 }, new TestArchiveReader());
await LoadScoreIntoOsu(osu, new ScoreInfo { OnlineID = 2 }, new TestArchiveReader());
var scoreManager = osu.Dependencies.Get<ScoreManager>();
// Note: A new score reference is used here since the import process mutates the original object to set an ID
Assert.That(scoreManager.IsAvailableLocally(new ScoreInfo { OnlineScoreID = 2 }));
Assert.That(scoreManager.IsAvailableLocally(new ScoreInfo { OnlineID = 2 }));
}
finally
{

View File

@ -44,24 +44,6 @@ namespace osu.Game.Tests.Scores.IO
Assert.That(score1, Is.EqualTo(score2));
}
[Test]
public void TestNonMatchingByHash()
{
ScoreInfo score1 = new ScoreInfo { Hash = "a" };
ScoreInfo score2 = new ScoreInfo { Hash = "b" };
Assert.That(score1, Is.Not.EqualTo(score2));
}
[Test]
public void TestMatchingByHash()
{
ScoreInfo score1 = new ScoreInfo { Hash = "a" };
ScoreInfo score2 = new ScoreInfo { Hash = "a" };
Assert.That(score1, Is.EqualTo(score2));
}
[Test]
public void TestNonMatchingByNull()
{

View File

@ -9,6 +9,7 @@ using osu.Framework.Screens;
using osu.Framework.Testing;
using osu.Game.Beatmaps;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Screens.Backgrounds;
using osu.Game.Screens.Edit;
@ -44,6 +45,7 @@ namespace osu.Game.Tests.Visual.Editing
protected override void LoadEditor()
{
Beatmap.Value = beatmaps.GetWorkingBeatmap(importedBeatmapSet.Beatmaps.First(b => b.RulesetID == 0));
SelectedMods.Value = new[] { new ModCinema() };
base.LoadEditor();
}
@ -67,6 +69,7 @@ namespace osu.Game.Tests.Visual.Editing
var background = this.ChildrenOfType<BackgroundScreenBeatmap>().Single();
return background.Colour == Color4.DarkGray && background.BlurAmount.Value == 0;
});
AddAssert("no mods selected", () => SelectedMods.Value.Count == 0);
}
[Test]

View File

@ -164,7 +164,7 @@ namespace osu.Game.Tests.Visual.Gameplay
private ScoreInfo getScoreInfo(bool replayAvailable)
{
return new APIScoreInfo
return new APIScore
{
OnlineID = 2553163309,
RulesetID = 0,

View File

@ -33,7 +33,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
BeatmapInfo = beatmapInfo,
User = new APIUser { Username = "Test user" },
Date = DateTimeOffset.Now,
OnlineScoreID = 12345,
OnlineID = 12345,
Ruleset = rulesetInfo,
};

View File

@ -37,7 +37,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
BeatmapInfo = beatmapInfo,
User = new APIUser { Username = "Test user" },
Date = DateTimeOffset.Now,
OnlineScoreID = 12345,
OnlineID = 12345,
Ruleset = rulesetInfo,
};

View File

@ -128,7 +128,7 @@ namespace osu.Game.Tests.Visual.Navigation
imported = Game.ScoreManager.Import(new ScoreInfo
{
Hash = Guid.NewGuid().ToString(),
OnlineScoreID = i,
OnlineID = i,
BeatmapInfo = beatmap.Beatmaps.First(),
Ruleset = ruleset ?? new OsuRuleset().RulesetInfo
}).Result.Value;

View File

@ -47,9 +47,9 @@ namespace osu.Game.Tests.Visual.Online
var allScores = new APIScoresCollection
{
Scores = new List<APIScoreInfo>
Scores = new List<APIScore>
{
new APIScoreInfo
new APIScore
{
User = new APIUser
{
@ -74,7 +74,7 @@ namespace osu.Game.Tests.Visual.Online
TotalScore = 1234567890,
Accuracy = 1,
},
new APIScoreInfo
new APIScore
{
User = new APIUser
{
@ -98,7 +98,7 @@ namespace osu.Game.Tests.Visual.Online
TotalScore = 1234789,
Accuracy = 0.9997,
},
new APIScoreInfo
new APIScore
{
User = new APIUser
{
@ -121,7 +121,7 @@ namespace osu.Game.Tests.Visual.Online
TotalScore = 12345678,
Accuracy = 0.9854,
},
new APIScoreInfo
new APIScore
{
User = new APIUser
{
@ -143,7 +143,7 @@ namespace osu.Game.Tests.Visual.Online
TotalScore = 1234567,
Accuracy = 0.8765,
},
new APIScoreInfo
new APIScore
{
User = new APIUser
{
@ -166,7 +166,7 @@ namespace osu.Game.Tests.Visual.Online
var myBestScore = new APIScoreWithPosition
{
Score = new APIScoreInfo
Score = new APIScore
{
User = new APIUser
{
@ -189,7 +189,7 @@ namespace osu.Game.Tests.Visual.Online
var myBestScoreWithNullPosition = new APIScoreWithPosition
{
Score = new APIScoreInfo
Score = new APIScore
{
User = new APIUser
{
@ -212,9 +212,9 @@ namespace osu.Game.Tests.Visual.Online
var oneScore = new APIScoresCollection
{
Scores = new List<APIScoreInfo>
Scores = new List<APIScore>
{
new APIScoreInfo
new APIScore
{
User = new APIUser
{

View File

@ -19,7 +19,7 @@ namespace osu.Game.Tests.Visual.Online
{
public TestSceneUserProfileScores()
{
var firstScore = new APIScoreInfo
var firstScore = new APIScore
{
PP = 1047.21,
Rank = ScoreRank.SH,
@ -42,7 +42,7 @@ namespace osu.Game.Tests.Visual.Online
Accuracy = 0.9813
};
var secondScore = new APIScoreInfo
var secondScore = new APIScore
{
PP = 134.32,
Rank = ScoreRank.A,
@ -64,7 +64,7 @@ namespace osu.Game.Tests.Visual.Online
Accuracy = 0.998546
};
var thirdScore = new APIScoreInfo
var thirdScore = new APIScore
{
PP = 96.83,
Rank = ScoreRank.S,
@ -81,7 +81,7 @@ namespace osu.Game.Tests.Visual.Online
Accuracy = 0.9726
};
var noPPScore = new APIScoreInfo
var noPPScore = new APIScore
{
Rank = ScoreRank.B,
Beatmap = new APIBeatmap

View File

@ -30,6 +30,7 @@ namespace osu.Game.Tests.Visual.Playlists
private const int scores_per_result = 10;
private TestResultsScreen resultsScreen;
private int currentScoreId;
private bool requestComplete;
private int totalCount;
@ -37,7 +38,7 @@ namespace osu.Game.Tests.Visual.Playlists
[SetUp]
public void Setup() => Schedule(() =>
{
currentScoreId = 0;
currentScoreId = 1;
requestComplete = false;
totalCount = 0;
bindHandler();
@ -50,13 +51,13 @@ namespace osu.Game.Tests.Visual.Playlists
AddStep("bind user score info handler", () =>
{
userScore = new TestScoreInfo(new OsuRuleset().RulesetInfo) { OnlineScoreID = currentScoreId++ };
userScore = new TestScoreInfo(new OsuRuleset().RulesetInfo) { OnlineID = currentScoreId++ };
bindHandler(userScore: userScore);
});
createResults(() => userScore);
AddAssert("user score selected", () => this.ChildrenOfType<ScorePanel>().Single(p => p.Score.OnlineScoreID == userScore.OnlineScoreID).State == PanelState.Expanded);
AddAssert("user score selected", () => this.ChildrenOfType<ScorePanel>().Single(p => p.Score.OnlineID == userScore.OnlineID).State == PanelState.Expanded);
}
[Test]
@ -74,14 +75,14 @@ namespace osu.Game.Tests.Visual.Playlists
AddStep("bind user score info handler", () =>
{
userScore = new TestScoreInfo(new OsuRuleset().RulesetInfo) { OnlineScoreID = currentScoreId++ };
userScore = new TestScoreInfo(new OsuRuleset().RulesetInfo) { OnlineID = currentScoreId++ };
bindHandler(true, userScore);
});
createResults(() => userScore);
AddAssert("more than 1 panel displayed", () => this.ChildrenOfType<ScorePanel>().Count() > 1);
AddAssert("user score selected", () => this.ChildrenOfType<ScorePanel>().Single(p => p.Score.OnlineScoreID == userScore.OnlineScoreID).State == PanelState.Expanded);
AddAssert("user score selected", () => this.ChildrenOfType<ScorePanel>().Single(p => p.Score.OnlineID == userScore.OnlineID).State == PanelState.Expanded);
}
[Test]
@ -123,7 +124,7 @@ namespace osu.Game.Tests.Visual.Playlists
AddStep("bind user score info handler", () =>
{
userScore = new TestScoreInfo(new OsuRuleset().RulesetInfo) { OnlineScoreID = currentScoreId++ };
userScore = new TestScoreInfo(new OsuRuleset().RulesetInfo) { OnlineID = currentScoreId++ };
bindHandler(userScore: userScore);
});
@ -230,7 +231,7 @@ namespace osu.Game.Tests.Visual.Playlists
{
var multiplayerUserScore = new MultiplayerScore
{
ID = (int)(userScore.OnlineScoreID ?? currentScoreId++),
ID = (int)(userScore.OnlineID > 0 ? userScore.OnlineID : currentScoreId++),
Accuracy = userScore.Accuracy,
EndedAt = userScore.Date,
Passed = userScore.Passed,

View File

@ -159,8 +159,8 @@ namespace osu.Game.Tests.Visual.Ranking
var firstScore = new TestScoreInfo(new OsuRuleset().RulesetInfo);
var secondScore = new TestScoreInfo(new OsuRuleset().RulesetInfo);
firstScore.User.Username = "A";
secondScore.User.Username = "B";
firstScore.UserString = "A";
secondScore.UserString = "B";
createListStep(() => new ScorePanelList());

View File

@ -91,7 +91,7 @@ namespace osu.Game.Tests.Visual.UserInterface
{
var score = new ScoreInfo
{
OnlineScoreID = i,
OnlineID = i,
BeatmapInfo = beatmapInfo,
BeatmapInfoID = beatmapInfo.ID,
Accuracy = RNG.NextDouble(),
@ -163,7 +163,7 @@ namespace osu.Game.Tests.Visual.UserInterface
});
AddUntilStep("wait for fetch", () => leaderboard.Scores != null);
AddUntilStep("score removed from leaderboard", () => leaderboard.Scores.All(s => s.OnlineScoreID != scoreBeingDeleted.OnlineScoreID));
AddUntilStep("score removed from leaderboard", () => leaderboard.Scores.All(s => s.OnlineID != scoreBeingDeleted.OnlineID));
}
[Test]
@ -171,7 +171,7 @@ namespace osu.Game.Tests.Visual.UserInterface
{
AddStep("delete top score", () => scoreManager.Delete(importedScores[0]));
AddUntilStep("wait for fetch", () => leaderboard.Scores != null);
AddUntilStep("score removed from leaderboard", () => leaderboard.Scores.All(s => s.OnlineScoreID != importedScores[0].OnlineScoreID));
AddUntilStep("score removed from leaderboard", () => leaderboard.Scores.All(s => s.OnlineID != importedScores[0].OnlineID));
}
}
}

View File

@ -147,7 +147,7 @@ namespace osu.Game.Database
modelBuilder.Entity<BeatmapInfo>().HasOne(b => b.BaseDifficulty);
modelBuilder.Entity<ScoreInfo>().HasIndex(b => b.OnlineScoreID).IsUnique();
modelBuilder.Entity<ScoreInfo>().HasIndex(b => b.OnlineID).IsUnique();
}
private class OsuDbLoggerFactory : ILoggerFactory

View File

@ -104,6 +104,14 @@ namespace osu.Game.Extensions
/// <returns>Whether online IDs match. If either instance is missing an online ID, this will return false.</returns>
public static bool MatchesOnlineID(this APIUser? instance, APIUser? other) => matchesOnlineID(instance, other);
/// <summary>
/// Check whether the online ID of two <see cref="IScoreInfo"/>s match.
/// </summary>
/// <param name="instance">The instance to compare.</param>
/// <param name="other">The other instance to compare against.</param>
/// <returns>Whether online IDs match. If either instance is missing an online ID, this will return false.</returns>
public static bool MatchesOnlineID(this IScoreInfo? instance, IScoreInfo? other) => matchesOnlineID(instance, other);
private static bool matchesOnlineID(this IHasOnlineID<long>? instance, IHasOnlineID<long>? other)
{
if (instance == null || other == null)

View File

@ -8,7 +8,7 @@ using osu.Game.Rulesets;
namespace osu.Game.Online.API.Requests
{
public class GetUserScoresRequest : PaginatedAPIRequest<List<APIScoreInfo>>
public class GetUserScoresRequest : PaginatedAPIRequest<List<APIScore>>
{
private readonly long userId;
private readonly ScoreType type;

View File

@ -13,10 +13,11 @@ using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Scoring;
using osu.Game.Scoring.Legacy;
using osu.Game.Users;
namespace osu.Game.Online.API.Requests.Responses
{
public class APIScoreInfo : IScoreInfo
public class APIScore : IScoreInfo
{
[JsonProperty(@"score")]
public long TotalScore { get; set; }
@ -101,7 +102,7 @@ namespace osu.Game.Online.API.Requests.Responses
BeatmapInfo = beatmap,
User = User,
Accuracy = Accuracy,
OnlineScoreID = OnlineID,
OnlineID = OnlineID,
Date = Date,
PP = PP,
RulesetID = RulesetID,
@ -150,6 +151,11 @@ namespace osu.Game.Online.API.Requests.Responses
public IRulesetInfo Ruleset => new RulesetInfo { OnlineID = RulesetID };
IEnumerable<INamedFileUsage> IHasNamedFiles.Files => throw new NotImplementedException();
#region Implementation of IScoreInfo
IBeatmapInfo IScoreInfo.Beatmap => Beatmap;
IUser IScoreInfo.User => User;
#endregion
}
}

View File

@ -14,7 +14,7 @@ namespace osu.Game.Online.API.Requests.Responses
public int? Position;
[JsonProperty(@"score")]
public APIScoreInfo Score;
public APIScore Score;
public ScoreInfo CreateScoreInfo(RulesetStore rulesets, BeatmapInfo beatmap = null)
{

View File

@ -9,7 +9,7 @@ namespace osu.Game.Online.API.Requests.Responses
public class APIScoresCollection
{
[JsonProperty(@"scores")]
public List<APIScoreInfo> Scores;
public List<APIScore> Scores;
[JsonProperty(@"userScore")]
public APIScoreWithPosition UserScore;

View File

@ -111,7 +111,7 @@ namespace osu.Game.Online.Leaderboards
background = new Box
{
RelativeSizeAxes = Axes.Both,
Colour = user.Id == api.LocalUser.Value.Id && allowHighlight ? colour.Green : Color4.Black,
Colour = user.OnlineID == api.LocalUser.Value.Id && allowHighlight ? colour.Green : Color4.Black,
Alpha = background_alpha,
},
},

View File

@ -69,7 +69,7 @@ namespace osu.Game.Online.Rooms
var scoreInfo = new ScoreInfo
{
OnlineScoreID = ID,
OnlineID = ID,
TotalScore = TotalScore,
MaxCombo = MaxCombo,
BeatmapInfo = beatmap,

View File

@ -3,6 +3,7 @@
using System;
using osu.Framework.Allocation;
using osu.Game.Extensions;
using osu.Game.Online.API;
using osu.Game.Scoring;
@ -35,7 +36,7 @@ namespace osu.Game.Online
var scoreInfo = new ScoreInfo
{
ID = TrackedItem.ID,
OnlineScoreID = TrackedItem.OnlineScoreID
OnlineID = TrackedItem.OnlineID
};
if (Manager.IsAvailableLocally(scoreInfo))
@ -113,7 +114,7 @@ namespace osu.Game.Online
UpdateState(DownloadState.NotDownloaded);
});
private bool checkEquality(IScoreInfo x, IScoreInfo y) => x.OnlineID == y.OnlineID;
private bool checkEquality(IScoreInfo x, IScoreInfo y) => x.MatchesOnlineID(y);
#region Disposal

View File

@ -16,7 +16,7 @@ namespace osu.Game.Online.Solo
{
/// <summary>
/// A class specifically for sending scores to the API during score submission.
/// This is used instead of <see cref="APIScoreInfo"/> due to marginally different serialisation naming requirements.
/// This is used instead of <see cref="APIScore"/> due to marginally different serialisation naming requirements.
/// </summary>
[Serializable]
public class SubmittableScore

View File

@ -487,8 +487,8 @@ namespace osu.Game
// to ensure all the required data for presenting a replay are present.
ScoreInfo databasedScoreInfo = null;
if (score.OnlineScoreID != null)
databasedScoreInfo = ScoreManager.Query(s => s.OnlineScoreID == score.OnlineScoreID);
if (score.OnlineID > 0)
databasedScoreInfo = ScoreManager.Query(s => s.OnlineID == score.OnlineID);
databasedScoreInfo ??= ScoreManager.Query(s => s.Hash == score.Hash);

View File

@ -94,7 +94,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
topScoresContainer.Add(new DrawableTopScore(topScore));
if (userScoreInfo != null && userScoreInfo.OnlineScoreID != topScore.OnlineScoreID)
if (userScoreInfo != null && userScoreInfo.OnlineID != topScore.OnlineID)
topScoresContainer.Add(new DrawableTopScore(userScoreInfo, userScore.Position));
}), TaskContinuationOptions.OnlyOnRanToCompletion);
});

View File

@ -28,7 +28,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
private const float performance_background_shear = 0.45f;
protected readonly APIScoreInfo Score;
protected readonly APIScore Score;
[Resolved]
private OsuColour colours { get; set; }
@ -36,7 +36,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
[Resolved]
private OverlayColourProvider colourProvider { get; set; }
public DrawableProfileScore(APIScoreInfo score)
public DrawableProfileScore(APIScore score)
{
Score = score;

View File

@ -16,7 +16,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
{
private readonly double weight;
public DrawableProfileWeightedScore(APIScoreInfo score, double weight)
public DrawableProfileWeightedScore(APIScore score, double weight)
: base(score)
{
this.weight = weight;

View File

@ -15,7 +15,7 @@ using APIUser = osu.Game.Online.API.Requests.Responses.APIUser;
namespace osu.Game.Overlays.Profile.Sections.Ranks
{
public class PaginatedScoreContainer : PaginatedProfileSubsection<APIScoreInfo>
public class PaginatedScoreContainer : PaginatedProfileSubsection<APIScore>
{
private readonly ScoreType type;
@ -51,7 +51,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
}
}
protected override void OnItemsReceived(List<APIScoreInfo> items)
protected override void OnItemsReceived(List<APIScore> items)
{
if (VisiblePages == 0)
drawableItemIndex = 0;
@ -59,12 +59,12 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
base.OnItemsReceived(items);
}
protected override APIRequest<List<APIScoreInfo>> CreateRequest() =>
protected override APIRequest<List<APIScore>> CreateRequest() =>
new GetUserScoresRequest(User.Value.Id, type, VisiblePages++, ItemsPerPage);
private int drawableItemIndex;
protected override Drawable CreateDrawableItem(APIScoreInfo model)
protected override Drawable CreateDrawableItem(APIScore model)
{
switch (type)
{

View File

@ -4,14 +4,14 @@
using System;
using osu.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Online.API.Requests.Responses;
using osu.Game.Rulesets;
using osu.Game.Users;
namespace osu.Game.Scoring
{
public interface IScoreInfo : IHasOnlineID<long>, IHasNamedFiles
{
APIUser User { get; }
IUser User { get; }
long TotalScore { get; }

View File

@ -80,12 +80,9 @@ namespace osu.Game.Scoring.Legacy
byte[] compressedReplay = sr.ReadByteArray();
if (version >= 20140721)
scoreInfo.OnlineScoreID = sr.ReadInt64();
scoreInfo.OnlineID = sr.ReadInt64();
else if (version >= 20121008)
scoreInfo.OnlineScoreID = sr.ReadInt32();
if (scoreInfo.OnlineScoreID <= 0)
scoreInfo.OnlineScoreID = null;
scoreInfo.OnlineID = sr.ReadInt32();
if (compressedReplay?.Length > 0)
{

View File

@ -14,6 +14,7 @@ using osu.Game.Online.API.Requests.Responses;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Users;
using osu.Game.Utils;
namespace osu.Game.Scoring
@ -136,7 +137,14 @@ namespace osu.Game.Scoring
[Column("Beatmap")]
public BeatmapInfo BeatmapInfo { get; set; }
public long? OnlineScoreID { get; set; }
private long? onlineID;
[Column("OnlineScoreID")]
public long? OnlineID
{
get => onlineID;
set => onlineID = value > 0 ? value : null;
}
public DateTimeOffset Date { get; set; }
@ -231,24 +239,18 @@ namespace osu.Game.Scoring
public bool Equals(ScoreInfo other)
{
if (other == null)
return false;
if (ReferenceEquals(this, other)) return true;
if (other == null) return false;
if (ID != 0 && other.ID != 0)
return ID == other.ID;
if (OnlineScoreID.HasValue && other.OnlineScoreID.HasValue)
return OnlineScoreID == other.OnlineScoreID;
if (!string.IsNullOrEmpty(Hash) && !string.IsNullOrEmpty(other.Hash))
return Hash == other.Hash;
return ReferenceEquals(this, other);
return false;
}
#region Implementation of IHasOnlineID
public long OnlineID => OnlineScoreID ?? -1;
long IHasOnlineID<long>.OnlineID => OnlineID ?? -1;
#endregion
@ -256,6 +258,7 @@ namespace osu.Game.Scoring
IBeatmapInfo IScoreInfo.Beatmap => BeatmapInfo;
IRulesetInfo IScoreInfo.Ruleset => Ruleset;
IUser IScoreInfo.User => User;
bool IScoreInfo.HasReplay => Files.Any();
#endregion

View File

@ -71,7 +71,7 @@ namespace osu.Game.Scoring
return scores.Select((score, index) => (score, totalScore: totalScores[index]))
.OrderByDescending(g => g.totalScore)
.ThenBy(g => g.score.OnlineScoreID)
.ThenBy(g => g.score.OnlineID)
.Select(g => g.score)
.ToArray();
}

View File

@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.
using osu.Game.Database;
using osu.Game.Extensions;
using osu.Game.Online.API;
using osu.Game.Online.API.Requests;
@ -17,6 +18,6 @@ namespace osu.Game.Scoring
protected override ArchiveDownloadRequest<IScoreInfo> CreateDownloadRequest(IScoreInfo score, bool minimiseDownload) => new DownloadReplayRequest(score);
public override ArchiveDownloadRequest<IScoreInfo> GetExistingDownload(IScoreInfo model)
=> CurrentDownloads.Find(r => r.Model.OnlineID == model.OnlineID);
=> CurrentDownloads.Find(r => r.Model.MatchesOnlineID(model));
}
}

View File

@ -66,6 +66,6 @@ namespace osu.Game.Scoring
protected override bool CheckLocalAvailability(ScoreInfo model, IQueryable<ScoreInfo> items)
=> base.CheckLocalAvailability(model, items)
|| (model.OnlineScoreID != null && items.Any(i => i.OnlineScoreID == model.OnlineScoreID));
|| (model.OnlineID > 0 && items.Any(i => i.OnlineID == model.OnlineID));
}
}

View File

@ -1,6 +1,7 @@
// 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 JetBrains.Annotations;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
@ -9,6 +10,7 @@ using osu.Framework.Screens;
using osu.Framework.Threading;
using osu.Game.Beatmaps;
using osu.Game.Graphics.UserInterface;
using osu.Game.Rulesets.Mods;
using osu.Game.Screens.Menu;
using osu.Game.Screens.Play;
@ -53,6 +55,14 @@ namespace osu.Game.Screens.Edit
});
}
protected override void LoadComplete()
{
base.LoadComplete();
// will be restored via lease, see `DisallowExternalBeatmapRulesetChanges`.
Mods.Value = Array.Empty<Mod>();
}
protected virtual Editor CreateEditor() => new Editor(this);
protected override void LogoArriving(OsuLogo logo, bool resuming)

View File

@ -7,6 +7,7 @@ using System.Diagnostics;
using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Framework.Development;
using osu.Framework.Graphics;
using osu.Framework.Logging;
using osu.Game.Online.API;
@ -107,6 +108,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
public void AddOrUpdateRoom(Room room)
{
Debug.Assert(ThreadSafety.IsUpdateThread);
Debug.Assert(room.RoomID.Value != null);
if (ignoredRooms.Contains(room.RoomID.Value.Value))
@ -136,12 +138,16 @@ namespace osu.Game.Screens.OnlinePlay.Components
public void RemoveRoom(Room room)
{
Debug.Assert(ThreadSafety.IsUpdateThread);
rooms.Remove(room);
notifyRoomsUpdated();
}
public void ClearRooms()
{
Debug.Assert(ThreadSafety.IsUpdateThread);
rooms.Clear();
notifyRoomsUpdated();
}

View File

@ -186,12 +186,12 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
Schedule(() =>
{
// Prefer selecting the local user's score, or otherwise default to the first visible score.
SelectedScore.Value = scoreInfos.FirstOrDefault(s => s.User.Id == api.LocalUser.Value.Id) ?? scoreInfos.FirstOrDefault();
SelectedScore.Value = scoreInfos.FirstOrDefault(s => s.User.OnlineID == api.LocalUser.Value.Id) ?? scoreInfos.FirstOrDefault();
});
}
// Invoke callback to add the scores. Exclude the user's current score which was added previously.
callback.Invoke(scoreInfos.Where(s => s.OnlineScoreID != Score?.OnlineScoreID));
callback.Invoke(scoreInfos.Where(s => s.OnlineID != Score?.OnlineID));
hideLoadingSpinners(pivot);
}));

View File

@ -1031,13 +1031,13 @@ namespace osu.Game.Screens.Play
//
// Until we better define the server-side logic behind this, let's not store the online ID to avoid potential unique constraint
// conflicts across various systems (ie. solo and multiplayer).
long? onlineScoreId = score.ScoreInfo.OnlineScoreID;
score.ScoreInfo.OnlineScoreID = null;
long? onlineScoreId = score.ScoreInfo.OnlineID;
score.ScoreInfo.OnlineID = -1;
await scoreManager.Import(score.ScoreInfo, replayReader).ConfigureAwait(false);
// ... And restore the online ID for other processes to handle correctly (e.g. de-duplication for the results screen).
score.ScoreInfo.OnlineScoreID = onlineScoreId;
score.ScoreInfo.OnlineID = onlineScoreId;
}
/// <summary>

View File

@ -54,7 +54,7 @@ namespace osu.Game.Screens.Play
private void userSentFrames(int userId, FrameDataBundle bundle)
{
if (userId != score.ScoreInfo.User.Id)
if (userId != score.ScoreInfo.User.OnlineID)
return;
if (!LoadedBeatmapSuccessfully)

View File

@ -156,7 +156,7 @@ namespace osu.Game.Screens.Play
request.Success += s =>
{
score.ScoreInfo.OnlineScoreID = s.ID;
score.ScoreInfo.OnlineID = s.ID;
score.ScoreInfo.Position = s.Position;
scoreSubmissionSource.SetResult(true);

View File

@ -341,7 +341,7 @@ namespace osu.Game.Screens.Ranking
private IEnumerable<ScorePanelTrackingContainer> applySorting(IEnumerable<Drawable> drawables) => drawables.OfType<ScorePanelTrackingContainer>()
.OrderByDescending(GetLayoutPosition)
.ThenBy(s => s.Panel.Score.OnlineScoreID);
.ThenBy(s => s.Panel.Score.OnlineID);
}
private class Scroll : OsuScrollContainer

View File

@ -31,7 +31,7 @@ namespace osu.Game.Screens.Ranking
return null;
getScoreRequest = new GetScoresRequest(Score.BeatmapInfo, Score.Ruleset);
getScoreRequest.Success += r => scoresCallback?.Invoke(r.Scores.Where(s => s.OnlineID != Score.OnlineScoreID).Select(s => s.CreateScoreInfo(rulesets, Beatmap.Value.BeatmapInfo)));
getScoreRequest.Success += r => scoresCallback?.Invoke(r.Scores.Where(s => s.OnlineID != Score.OnlineID).Select(s => s.CreateScoreInfo(rulesets, Beatmap.Value.BeatmapInfo)));
return getScoreRequest;
}

View File

@ -20,7 +20,7 @@
<ItemGroup Label="Package References">
<PackageReference Include="AutoMapper" Version="10.1.1" />
<PackageReference Include="DiffPlex" Version="1.7.0" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.38" />
<PackageReference Include="HtmlAgilityPack" Version="1.11.39" />
<PackageReference Include="Humanizer" Version="2.13.14" />
<PackageReference Include="MessagePack" Version="2.3.85" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="5.0.11" />
@ -31,15 +31,15 @@
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="5.0.0" />
<PackageReference Include="Microsoft.NETCore.Targets" Version="3.1.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="ppy.LocalisationAnalyser" Version="2021.725.0">
<PackageReference Include="ppy.LocalisationAnalyser" Version="2021.1210.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Realm" Version="10.7.1" />
<PackageReference Include="ppy.osu.Framework" Version="2021.1207.0" />
<PackageReference Include="ppy.osu.Framework" Version="2021.1210.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.1203.0" />
<PackageReference Include="Sentry" Version="3.11.1" />
<PackageReference Include="SharpCompress" Version="0.30.0" />
<PackageReference Include="Sentry" Version="3.12.1" />
<PackageReference Include="SharpCompress" Version="0.30.1" />
<PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="System.ComponentModel.Annotations" Version="5.0.0" />
<PackageReference Include="TagLibSharp" Version="2.2.0" />

View File

@ -60,7 +60,7 @@
<Reference Include="System.Net.Http" />
</ItemGroup>
<ItemGroup Label="Package References">
<PackageReference Include="ppy.osu.Framework.iOS" Version="2021.1207.0" />
<PackageReference Include="ppy.osu.Framework.iOS" Version="2021.1210.0" />
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.1203.0" />
</ItemGroup>
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
@ -83,7 +83,7 @@
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="ppy.osu.Framework" Version="2021.1207.0" />
<PackageReference Include="ppy.osu.Framework" Version="2021.1210.0" />
<PackageReference Include="SharpCompress" Version="0.30.0" />
<PackageReference Include="NUnit" Version="3.13.2" />
<PackageReference Include="SharpRaven" Version="2.4.0" />