1
0
mirror of https://github.com/ppy/osu.git synced 2025-01-27 01:02:54 +08:00

Fix mods not being serialised correctly in ScoreInfo

This commit is contained in:
smoogipoo 2021-04-12 19:50:24 +09:00
parent e8c248f2b2
commit d2d7f77430
2 changed files with 57 additions and 25 deletions

View File

@ -11,7 +11,10 @@ using osu.Game.Online.API;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
namespace osu.Game.Tests.Online namespace osu.Game.Tests.Online
{ {
@ -84,6 +87,36 @@ namespace osu.Game.Tests.Online
Assert.That(converted?.OverallDifficulty.Value, Is.EqualTo(11)); Assert.That(converted?.OverallDifficulty.Value, Is.EqualTo(11));
} }
[Test]
public void TestDeserialiseScoreInfoWithEmptyMods()
{
var score = new ScoreInfo { Ruleset = new OsuRuleset().RulesetInfo };
var deserialised = JsonConvert.DeserializeObject<ScoreInfo>(JsonConvert.SerializeObject(score));
if (deserialised != null)
deserialised.Ruleset = new OsuRuleset().RulesetInfo;
Assert.That(deserialised?.Mods.Length, Is.Zero);
}
[Test]
public void TestDeserialiseScoreInfoWithCustomModSetting()
{
var score = new ScoreInfo
{
Ruleset = new OsuRuleset().RulesetInfo,
Mods = new Mod[] { new OsuModDoubleTime { SpeedChange = { Value = 2 } } }
};
var deserialised = JsonConvert.DeserializeObject<ScoreInfo>(JsonConvert.SerializeObject(score));
if (deserialised != null)
deserialised.Ruleset = new OsuRuleset().RulesetInfo;
Assert.That(((OsuModDoubleTime)deserialised?.Mods[0])?.SpeedChange.Value, Is.EqualTo(2));
}
private class TestRuleset : Ruleset private class TestRuleset : Ruleset
{ {
public override IEnumerable<Mod> GetModsFor(ModType type) => new Mod[] public override IEnumerable<Mod> GetModsFor(ModType type) => new Mod[]

View File

@ -10,6 +10,7 @@ using Newtonsoft.Json.Converters;
using osu.Framework.Extensions; using osu.Framework.Extensions;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.Online.API;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
@ -55,9 +56,10 @@ namespace osu.Game.Scoring
[JsonIgnore] [JsonIgnore]
public virtual RulesetInfo Ruleset { get; set; } public virtual RulesetInfo Ruleset { get; set; }
private APIMod[] localAPIMods;
private Mod[] mods; private Mod[] mods;
[JsonProperty("mods")] [JsonIgnore]
[NotMapped] [NotMapped]
public Mod[] Mods public Mod[] Mods
{ {
@ -66,45 +68,50 @@ namespace osu.Game.Scoring
if (mods != null) if (mods != null)
return mods; return mods;
if (modsJson == null) if (apiMods == null)
return Array.Empty<Mod>(); return Array.Empty<Mod>();
return getModsFromRuleset(JsonConvert.DeserializeObject<DeserializedMod[]>(modsJson)); var rulesetInstance = Ruleset.CreateInstance();
return apiMods.Select(m => m.ToMod(rulesetInstance)).ToArray();
} }
set set
{ {
modsJson = null; localAPIMods = null;
mods = value; mods = value;
} }
} }
private Mod[] getModsFromRuleset(DeserializedMod[] mods) => Ruleset.CreateInstance().GetAllMods().Where(mod => mods.Any(d => d.Acronym == mod.Acronym)).ToArray(); // Used for API serialisation/deserialisation.
[JsonProperty("mods")]
private string modsJson; private APIMod[] apiMods
[JsonIgnore]
[Column("Mods")]
public string ModsJson
{ {
get get
{ {
if (modsJson != null) if (localAPIMods != null)
return modsJson; return localAPIMods;
if (mods == null) if (mods == null)
return null; return Array.Empty<APIMod>();
return modsJson = JsonConvert.SerializeObject(mods.Select(m => new DeserializedMod { Acronym = m.Acronym })); return localAPIMods = mods.Select(m => new APIMod(m)).ToArray();
} }
set set
{ {
modsJson = value; localAPIMods = value;
// we potentially can't update this yet due to Ruleset being late-bound, so instead update on read as necessary. // We potentially can't update this yet due to Ruleset being late-bound, so instead update on read as necessary.
mods = null; mods = null;
} }
} }
// Used for database serialisation/deserialisation.
[Column("Mods")]
private string modsString
{
get => JsonConvert.SerializeObject(apiMods);
set => apiMods = JsonConvert.DeserializeObject<APIMod[]>(value);
}
[NotMapped] [NotMapped]
[JsonProperty("user")] [JsonProperty("user")]
public User User { get; set; } public User User { get; set; }
@ -251,14 +258,6 @@ namespace osu.Game.Scoring
} }
} }
[Serializable]
protected class DeserializedMod : IMod
{
public string Acronym { get; set; }
public bool Equals(IMod other) => Acronym == other?.Acronym;
}
public override string ToString() => $"{User} playing {Beatmap}"; public override string ToString() => $"{User} playing {Beatmap}";
public bool Equals(ScoreInfo other) public bool Equals(ScoreInfo other)