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

Merge pull request #12378 from smoogipoo/fix-score-serialisation

Fix mods not being serialised correctly in ScoreInfo
This commit is contained in:
Dean Herbert 2021-04-12 21:54:24 +09:00 committed by GitHub
commit 3fd3f36895
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 65 additions and 31 deletions

View File

@ -11,7 +11,10 @@ using osu.Game.Online.API;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
namespace osu.Game.Tests.Online
{
@ -84,6 +87,36 @@ namespace osu.Game.Tests.Online
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
{
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.Game.Beatmaps;
using osu.Game.Database;
using osu.Game.Online.API;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
@ -55,9 +56,10 @@ namespace osu.Game.Scoring
[JsonIgnore]
public virtual RulesetInfo Ruleset { get; set; }
private APIMod[] localAPIMods;
private Mod[] mods;
[JsonProperty("mods")]
[JsonIgnore]
[NotMapped]
public Mod[] Mods
{
@ -66,43 +68,50 @@ namespace osu.Game.Scoring
if (mods != null)
return mods;
if (modsJson == null)
if (localAPIMods == null)
return Array.Empty<Mod>();
return getModsFromRuleset(JsonConvert.DeserializeObject<DeserializedMod[]>(modsJson));
var rulesetInstance = Ruleset.CreateInstance();
return apiMods.Select(m => m.ToMod(rulesetInstance)).ToArray();
}
set
{
modsJson = null;
localAPIMods = null;
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")]
[NotMapped]
private APIMod[] apiMods
{
get
{
if (localAPIMods != null)
return localAPIMods;
private string modsJson;
if (mods == null)
return Array.Empty<APIMod>();
return localAPIMods = mods.Select(m => new APIMod(m)).ToArray();
}
set
{
localAPIMods = value;
// We potentially can't update this yet due to Ruleset being late-bound, so instead update on read as necessary.
mods = null;
}
}
// Used for database serialisation/deserialisation.
[JsonIgnore]
[Column("Mods")]
public string ModsJson
{
get
{
if (modsJson != null)
return modsJson;
if (mods == null)
return null;
return modsJson = JsonConvert.SerializeObject(mods.Select(m => new DeserializedMod { Acronym = m.Acronym }));
}
set
{
modsJson = value;
// we potentially can't update this yet due to Ruleset being late-bound, so instead update on read as necessary.
mods = null;
}
get => JsonConvert.SerializeObject(apiMods);
set => apiMods = JsonConvert.DeserializeObject<APIMod[]>(value);
}
[NotMapped]
@ -251,14 +260,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 bool Equals(ScoreInfo other)