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

Merge pull request #3784 from smoogipoo/scoredatabase

Add a ScoreManager + score-related tables to the database
This commit is contained in:
Dean Herbert 2018-11-30 18:23:26 +09:00 committed by GitHub
commit f517f98ae7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
148 changed files with 1773 additions and 599 deletions

View File

@ -5,20 +5,17 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Catch.Replays;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring; using osu.Game.Scoring;
using osu.Game.Users; using osu.Game.Users;
namespace osu.Game.Rulesets.Catch.Mods namespace osu.Game.Rulesets.Catch.Mods
{ {
public class CatchModAutoplay : ModAutoplay<CatchHitObject> public class CatchModAutoplay : ModAutoplay<CatchHitObject>
{ {
protected override Score CreateReplayScore(Beatmap<CatchHitObject> beatmap) protected override Score CreateReplayScore(Beatmap<CatchHitObject> beatmap) => new Score
{ {
return new Score ScoreInfo = new ScoreInfo { User = new User { Username = "osu!salad!" } },
{ Replay = new CatchAutoGenerator(beatmap).Generate(),
User = new User { Username = "osu!salad!" }, };
Replay = new CatchAutoGenerator(beatmap).Generate(),
};
}
} }
} }

View File

@ -5,6 +5,7 @@ using System;
using System.Linq; using System.Linq;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Replays;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Catch.UI;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;

View File

@ -4,6 +4,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using osu.Framework.Input.StateChanges; using osu.Framework.Input.StateChanges;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
using osu.Game.Replays;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;
namespace osu.Game.Rulesets.Catch.Replays namespace osu.Game.Rulesets.Catch.Replays

View File

@ -2,9 +2,9 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Replays.Legacy;
using osu.Game.Rulesets.Catch.UI; using osu.Game.Rulesets.Catch.UI;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Replays.Legacy;
using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Replays.Types;
namespace osu.Game.Rulesets.Catch.Replays namespace osu.Game.Rulesets.Catch.Replays

View File

@ -5,12 +5,12 @@ using osu.Framework.Input;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Input.Handlers; using osu.Game.Input.Handlers;
using osu.Game.Replays;
using osu.Game.Rulesets.Catch.Objects; using osu.Game.Rulesets.Catch.Objects;
using osu.Game.Rulesets.Catch.Objects.Drawable; using osu.Game.Rulesets.Catch.Objects.Drawable;
using osu.Game.Rulesets.Catch.Replays; using osu.Game.Rulesets.Catch.Replays;
using osu.Game.Rulesets.Catch.Scoring; using osu.Game.Rulesets.Catch.Scoring;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling;

View File

@ -8,6 +8,7 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
namespace osu.Game.Rulesets.Mania.Difficulty namespace osu.Game.Rulesets.Mania.Difficulty
{ {
@ -27,7 +28,7 @@ namespace osu.Game.Rulesets.Mania.Difficulty
private int countMeh; private int countMeh;
private int countMiss; private int countMiss;
public ManiaPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, Score score) public ManiaPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo score)
: base(ruleset, beatmap, score) : base(ruleset, beatmap, score)
{ {
} }

View File

@ -24,7 +24,7 @@ using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Configuration;
using osu.Game.Rulesets.Mania.Difficulty; using osu.Game.Rulesets.Mania.Difficulty;
using osu.Game.Rulesets.Mania.Edit; using osu.Game.Rulesets.Mania.Edit;
using osu.Game.Rulesets.Scoring; using osu.Game.Scoring;
namespace osu.Game.Rulesets.Mania namespace osu.Game.Rulesets.Mania
{ {
@ -32,7 +32,7 @@ namespace osu.Game.Rulesets.Mania
{ {
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new ManiaRulesetContainer(this, beatmap); public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap) => new ManiaRulesetContainer(this, beatmap);
public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap); public override IBeatmapConverter CreateBeatmapConverter(IBeatmap beatmap) => new ManiaBeatmapConverter(beatmap);
public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, Score score) => new ManiaPerformanceCalculator(this, beatmap, score); public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new ManiaPerformanceCalculator(this, beatmap, score);
public override HitObjectComposer CreateHitObjectComposer() => new ManiaHitObjectComposer(this); public override HitObjectComposer CreateHitObjectComposer() => new ManiaHitObjectComposer(this);

View File

@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public abstract class ManiaKeyMod : Mod, IApplicableToBeatmapConverter public abstract class ManiaKeyMod : Mod, IApplicableToBeatmapConverter
{ {
public override string ShortenedName => Name; public override string Acronym => Name;
public abstract int KeyCount { get; } public abstract int KeyCount { get; }
public override ModType Type => ModType.Conversion; public override ModType Type => ModType.Conversion;
public override double ScoreMultiplier => 1; // TODO: Implement the mania key mod score multiplier public override double ScoreMultiplier => 1; // TODO: Implement the mania key mod score multiplier

View File

@ -6,20 +6,17 @@ using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Mania.Replays; using osu.Game.Rulesets.Mania.Replays;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring; using osu.Game.Scoring;
using osu.Game.Users; using osu.Game.Users;
namespace osu.Game.Rulesets.Mania.Mods namespace osu.Game.Rulesets.Mania.Mods
{ {
public class ManiaModAutoplay : ModAutoplay<ManiaHitObject> public class ManiaModAutoplay : ModAutoplay<ManiaHitObject>
{ {
protected override Score CreateReplayScore(Beatmap<ManiaHitObject> beatmap) protected override Score CreateReplayScore(Beatmap<ManiaHitObject> beatmap) => new Score
{ {
return new Score ScoreInfo = new ScoreInfo { User = new User { Username = "osu!topus!" } },
{ Replay = new ManiaAutoGenerator((ManiaBeatmap)beatmap).Generate(),
User = new User { Username = "osu!topus!" }, };
Replay = new ManiaAutoGenerator((ManiaBeatmap)beatmap).Generate(),
};
}
} }
} }

View File

@ -12,7 +12,7 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModDualStages : Mod, IPlayfieldTypeMod, IApplicableToBeatmapConverter, IApplicableToBeatmap<ManiaHitObject> public class ManiaModDualStages : Mod, IPlayfieldTypeMod, IApplicableToBeatmapConverter, IApplicableToBeatmap<ManiaHitObject>
{ {
public override string Name => "Dual Stages"; public override string Name => "Dual Stages";
public override string ShortenedName => "DS"; public override string Acronym => "DS";
public override string Description => @"Double the stages, double the fun!"; public override string Description => @"Double the stages, double the fun!";
public override ModType Type => ModType.Conversion; public override ModType Type => ModType.Conversion;
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;

View File

@ -11,7 +11,7 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModFadeIn : Mod public class ManiaModFadeIn : Mod
{ {
public override string Name => "Fade In"; public override string Name => "Fade In";
public override string ShortenedName => "FI"; public override string Acronym => "FI";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden; public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden;
public override ModType Type => ModType.DifficultyIncrease; public override ModType Type => ModType.DifficultyIncrease;
public override string Description => @"Keys appear out of nowhere!"; public override string Description => @"Keys appear out of nowhere!";

View File

@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public override int KeyCount => 1; public override int KeyCount => 1;
public override string Name => "One Key"; public override string Name => "One Key";
public override string ShortenedName => "1K"; public override string Acronym => "1K";
public override string Description => @"Play with one key."; public override string Description => @"Play with one key.";
} }
} }

View File

@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public override int KeyCount => 2; public override int KeyCount => 2;
public override string Name => "Two Keys"; public override string Name => "Two Keys";
public override string ShortenedName => "2K"; public override string Acronym => "2K";
public override string Description => @"Play with two keys."; public override string Description => @"Play with two keys.";
} }
} }

View File

@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public override int KeyCount => 3; public override int KeyCount => 3;
public override string Name => "Three Keys"; public override string Name => "Three Keys";
public override string ShortenedName => "3K"; public override string Acronym => "3K";
public override string Description => @"Play with three keys."; public override string Description => @"Play with three keys.";
} }
} }

View File

@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public override int KeyCount => 4; public override int KeyCount => 4;
public override string Name => "Four Keys"; public override string Name => "Four Keys";
public override string ShortenedName => "4K"; public override string Acronym => "4K";
public override string Description => @"Play with four keys."; public override string Description => @"Play with four keys.";
} }
} }

View File

@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public override int KeyCount => 5; public override int KeyCount => 5;
public override string Name => "Five Keys"; public override string Name => "Five Keys";
public override string ShortenedName => "5K"; public override string Acronym => "5K";
public override string Description => @"Play with five keys."; public override string Description => @"Play with five keys.";
} }
} }

View File

@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public override int KeyCount => 6; public override int KeyCount => 6;
public override string Name => "Six Keys"; public override string Name => "Six Keys";
public override string ShortenedName => "6K"; public override string Acronym => "6K";
public override string Description => @"Play with six keys."; public override string Description => @"Play with six keys.";
} }
} }

View File

@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public override int KeyCount => 7; public override int KeyCount => 7;
public override string Name => "Seven Keys"; public override string Name => "Seven Keys";
public override string ShortenedName => "7K"; public override string Acronym => "7K";
public override string Description => @"Play with seven keys."; public override string Description => @"Play with seven keys.";
} }
} }

View File

@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public override int KeyCount => 8; public override int KeyCount => 8;
public override string Name => "Eight Keys"; public override string Name => "Eight Keys";
public override string ShortenedName => "8K"; public override string Acronym => "8K";
public override string Description => @"Play with eight keys."; public override string Description => @"Play with eight keys.";
} }
} }

View File

@ -7,7 +7,7 @@ namespace osu.Game.Rulesets.Mania.Mods
{ {
public override int KeyCount => 9; public override int KeyCount => 9;
public override string Name => "Nine Keys"; public override string Name => "Nine Keys";
public override string ShortenedName => "9K"; public override string Acronym => "9K";
public override string Description => @"Play with nine keys."; public override string Description => @"Play with nine keys.";
} }
} }

View File

@ -13,7 +13,7 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModMirror : Mod, IApplicableToRulesetContainer<ManiaHitObject> public class ManiaModMirror : Mod, IApplicableToRulesetContainer<ManiaHitObject>
{ {
public override string Name => "Mirror"; public override string Name => "Mirror";
public override string ShortenedName => "MR"; public override string Acronym => "MR";
public override ModType Type => ModType.Conversion; public override ModType Type => ModType.Conversion;
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;
public override bool Ranked => true; public override bool Ranked => true;

View File

@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModRandom : Mod, IApplicableToRulesetContainer<ManiaHitObject> public class ManiaModRandom : Mod, IApplicableToRulesetContainer<ManiaHitObject>
{ {
public override string Name => "Random"; public override string Name => "Random";
public override string ShortenedName => "RD"; public override string Acronym => "RD";
public override ModType Type => ModType.Conversion; public override ModType Type => ModType.Conversion;
public override FontAwesome Icon => FontAwesome.fa_osu_dice; public override FontAwesome Icon => FontAwesome.fa_osu_dice;
public override string Description => @"Shuffle around the keys!"; public override string Description => @"Shuffle around the keys!";

View File

@ -3,6 +3,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Game.Replays;
using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Objects; using osu.Game.Rulesets.Mania.Objects;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;

View File

@ -4,6 +4,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Input.StateChanges; using osu.Framework.Input.StateChanges;
using osu.Game.Replays;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;
namespace osu.Game.Rulesets.Mania.Replays namespace osu.Game.Rulesets.Mania.Replays

View File

@ -3,9 +3,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Replays.Legacy;
using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Replays.Legacy;
using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Replays.Types;
namespace osu.Game.Rulesets.Mania.Replays namespace osu.Game.Rulesets.Mania.Replays

View File

@ -12,6 +12,7 @@ using osu.Framework.MathUtils;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Beatmaps.ControlPoints; using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Input.Handlers; using osu.Game.Input.Handlers;
using osu.Game.Replays;
using osu.Game.Rulesets.Mania.Beatmaps; using osu.Game.Rulesets.Mania.Beatmaps;
using osu.Game.Rulesets.Mania.Configuration; using osu.Game.Rulesets.Mania.Configuration;
using osu.Game.Rulesets.Mania.Mods; using osu.Game.Rulesets.Mania.Mods;
@ -21,7 +22,6 @@ using osu.Game.Rulesets.Mania.Replays;
using osu.Game.Rulesets.Mania.Scoring; using osu.Game.Rulesets.Mania.Scoring;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling;

View File

@ -10,6 +10,7 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Mods; using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
namespace osu.Game.Rulesets.Osu.Difficulty namespace osu.Game.Rulesets.Osu.Difficulty
{ {
@ -29,7 +30,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
private int countMeh; private int countMeh;
private int countMiss; private int countMiss;
public OsuPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, Score score) public OsuPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo score)
: base(ruleset, beatmap, score) : base(ruleset, beatmap, score)
{ {
countHitCircles = Beatmap.HitObjects.Count(h => h is HitCircle); countHitCircles = Beatmap.HitObjects.Count(h => h is HitCircle);

View File

@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Osu.Mods
public class OsuModAutopilot : Mod public class OsuModAutopilot : Mod
{ {
public override string Name => "Autopilot"; public override string Name => "Autopilot";
public override string ShortenedName => "AP"; public override string Acronym => "AP";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_autopilot; public override FontAwesome Icon => FontAwesome.fa_osu_mod_autopilot;
public override ModType Type => ModType.Automation; public override ModType Type => ModType.Automation;
public override string Description => @"Automatic cursor movement - just follow the rhythm."; public override string Description => @"Automatic cursor movement - just follow the rhythm.";

View File

@ -7,7 +7,7 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Osu.Replays;
using osu.Game.Rulesets.Scoring; using osu.Game.Scoring;
namespace osu.Game.Rulesets.Osu.Mods namespace osu.Game.Rulesets.Osu.Mods
{ {
@ -15,12 +15,9 @@ namespace osu.Game.Rulesets.Osu.Mods
{ {
public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).Append(typeof(OsuModSpunOut)).ToArray(); public override Type[] IncompatibleMods => base.IncompatibleMods.Append(typeof(OsuModAutopilot)).Append(typeof(OsuModSpunOut)).ToArray();
protected override Score CreateReplayScore(Beatmap<OsuHitObject> beatmap) protected override Score CreateReplayScore(Beatmap<OsuHitObject> beatmap) => new Score
{ {
return new Score Replay = new OsuAutoGenerator(beatmap).Generate()
{ };
Replay = new OsuAutoGenerator(beatmap).Generate()
};
}
} }
} }

View File

@ -10,7 +10,7 @@ namespace osu.Game.Rulesets.Osu.Mods
public class OsuModSpunOut : Mod public class OsuModSpunOut : Mod
{ {
public override string Name => "Spun Out"; public override string Name => "Spun Out";
public override string ShortenedName => "SO"; public override string Acronym => "SO";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_spunout; public override FontAwesome Icon => FontAwesome.fa_osu_mod_spunout;
public override ModType Type => ModType.DifficultyReduction; public override ModType Type => ModType.DifficultyReduction;
public override string Description => @"Spinners will be automatically completed."; public override string Description => @"Spinners will be automatically completed.";

View File

@ -9,7 +9,7 @@ namespace osu.Game.Rulesets.Osu.Mods
public class OsuModTarget : Mod public class OsuModTarget : Mod
{ {
public override string Name => "Target"; public override string Name => "Target";
public override string ShortenedName => "TP"; public override string Acronym => "TP";
public override ModType Type => ModType.Conversion; public override ModType Type => ModType.Conversion;
public override FontAwesome Icon => FontAwesome.fa_osu_mod_target; public override FontAwesome Icon => FontAwesome.fa_osu_mod_target;
public override string Description => @"Practice keeping up with the beat of the song."; public override string Description => @"Practice keeping up with the beat of the song.";

View File

@ -15,7 +15,7 @@ namespace osu.Game.Rulesets.Osu.Mods
internal class OsuModTransform : Mod, IApplicableToDrawableHitObjects internal class OsuModTransform : Mod, IApplicableToDrawableHitObjects
{ {
public override string Name => "Transform"; public override string Name => "Transform";
public override string ShortenedName => "TR"; public override string Acronym => "TR";
public override FontAwesome Icon => FontAwesome.fa_arrows; public override FontAwesome Icon => FontAwesome.fa_arrows;
public override ModType Type => ModType.Fun; public override ModType Type => ModType.Fun;
public override string Description => "Everything rotates. EVERYTHING."; public override string Description => "Everything rotates. EVERYTHING.";

View File

@ -16,7 +16,7 @@ namespace osu.Game.Rulesets.Osu.Mods
internal class OsuModWiggle : Mod, IApplicableToDrawableHitObjects internal class OsuModWiggle : Mod, IApplicableToDrawableHitObjects
{ {
public override string Name => "Wiggle"; public override string Name => "Wiggle";
public override string ShortenedName => "WG"; public override string Acronym => "WG";
public override FontAwesome Icon => FontAwesome.fa_certificate; public override FontAwesome Icon => FontAwesome.fa_certificate;
public override ModType Type => ModType.Fun; public override ModType Type => ModType.Fun;
public override string Description => "They just won't stay still..."; public override string Description => "They just won't stay still...";

View File

@ -11,7 +11,6 @@ using System.Collections.Generic;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Overlays.Settings; using osu.Game.Overlays.Settings;
using osu.Framework.Input.Bindings; using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Osu.Edit; using osu.Game.Rulesets.Osu.Edit;
using osu.Game.Rulesets.Edit; using osu.Game.Rulesets.Edit;
using osu.Game.Rulesets.Osu.Replays; using osu.Game.Rulesets.Osu.Replays;
@ -20,6 +19,7 @@ using osu.Game.Beatmaps.Legacy;
using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Beatmaps;
using osu.Game.Rulesets.Osu.Difficulty; using osu.Game.Rulesets.Osu.Difficulty;
using osu.Game.Scoring;
namespace osu.Game.Rulesets.Osu namespace osu.Game.Rulesets.Osu
{ {
@ -131,7 +131,7 @@ namespace osu.Game.Rulesets.Osu
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new OsuDifficultyCalculator(this, beatmap); public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new OsuDifficultyCalculator(this, beatmap);
public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, Score score) => new OsuPerformanceCalculator(this, beatmap, score); public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new OsuPerformanceCalculator(this, beatmap, score);
public override HitObjectComposer CreateHitObjectComposer() => new OsuHitObjectComposer(this); public override HitObjectComposer CreateHitObjectComposer() => new OsuHitObjectComposer(this);

View File

@ -8,8 +8,8 @@ using osu.Game.Rulesets.Osu.Objects;
using System; using System;
using System.Linq; using System.Linq;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Replays;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
namespace osu.Game.Rulesets.Osu.Replays namespace osu.Game.Rulesets.Osu.Replays

View File

@ -6,6 +6,7 @@ using osu.Game.Beatmaps;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Replays;
using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;
using osu.Game.Users; using osu.Game.Users;

View File

@ -3,8 +3,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Replays.Legacy;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Replays.Legacy;
using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Replays.Types;
using osuTK; using osuTK;

View File

@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Input.StateChanges; using osu.Framework.Input.StateChanges;
using osu.Framework.MathUtils; using osu.Framework.MathUtils;
using osu.Game.Replays;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;
using osuTK; using osuTK;

View File

@ -9,6 +9,7 @@ using osu.Game.Rulesets.Osu.Judgements;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
namespace osu.Game.Rulesets.Osu.Scoring namespace osu.Game.Rulesets.Osu.Scoring
{ {
@ -39,7 +40,7 @@ namespace osu.Game.Rulesets.Osu.Scoring
comboResultCounts.Clear(); comboResultCounts.Clear();
} }
public override void PopulateScore(Score score) public override void PopulateScore(ScoreInfo score)
{ {
base.PopulateScore(score); base.PopulateScore(score);

View File

@ -6,6 +6,7 @@ using osu.Framework.Graphics.Cursor;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Input.Handlers; using osu.Game.Input.Handlers;
using osu.Game.Replays;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.Objects.Drawables; using osu.Game.Rulesets.Osu.Objects.Drawables;
@ -14,7 +15,6 @@ using osu.Game.Rulesets.Osu.Scoring;
using osu.Game.Rulesets.Osu.UI.Cursor; using osu.Game.Rulesets.Osu.UI.Cursor;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Rulesets.Replays;
namespace osu.Game.Rulesets.Osu.UI namespace osu.Game.Rulesets.Osu.UI
{ {

View File

@ -9,6 +9,7 @@ using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Scoring;
namespace osu.Game.Rulesets.Taiko.Difficulty namespace osu.Game.Rulesets.Taiko.Difficulty
{ {
@ -22,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
private int countMeh; private int countMeh;
private int countMiss; private int countMiss;
public TaikoPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, Score score) public TaikoPerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo score)
: base(ruleset, beatmap, score) : base(ruleset, beatmap, score)
{ {
} }

View File

@ -3,22 +3,19 @@
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Replays; using osu.Game.Rulesets.Taiko.Replays;
using osu.Game.Scoring;
using osu.Game.Users; using osu.Game.Users;
namespace osu.Game.Rulesets.Taiko.Mods namespace osu.Game.Rulesets.Taiko.Mods
{ {
public class TaikoModAutoplay : ModAutoplay<TaikoHitObject> public class TaikoModAutoplay : ModAutoplay<TaikoHitObject>
{ {
protected override Score CreateReplayScore(Beatmap<TaikoHitObject> beatmap) protected override Score CreateReplayScore(Beatmap<TaikoHitObject> beatmap) => new Score
{ {
return new Score ScoreInfo = new ScoreInfo { User = new User { Username = "mekkadosu!" } },
{ Replay = new TaikoAutoGenerator(beatmap).Generate(),
User = new User { Username = "mekkadosu!" }, };
Replay = new TaikoAutoGenerator(beatmap).Generate(),
};
}
} }
} }

View File

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Replays;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;

View File

@ -5,6 +5,7 @@ using osu.Game.Rulesets.Replays;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Input.StateChanges; using osu.Framework.Input.StateChanges;
using osu.Game.Replays;
namespace osu.Game.Rulesets.Taiko.Replays namespace osu.Game.Rulesets.Taiko.Replays
{ {

View File

@ -3,8 +3,8 @@
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Replays.Legacy;
using osu.Game.Rulesets.Replays; using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Replays.Legacy;
using osu.Game.Rulesets.Replays.Types; using osu.Game.Rulesets.Replays.Types;
namespace osu.Game.Rulesets.Taiko.Replays namespace osu.Game.Rulesets.Taiko.Replays

View File

@ -14,9 +14,9 @@ using osu.Game.Rulesets.Replays.Types;
using osu.Game.Rulesets.Taiko.Replays; using osu.Game.Rulesets.Taiko.Replays;
using osu.Game.Beatmaps.Legacy; using osu.Game.Beatmaps.Legacy;
using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Difficulty;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Beatmaps; using osu.Game.Rulesets.Taiko.Beatmaps;
using osu.Game.Rulesets.Taiko.Difficulty; using osu.Game.Rulesets.Taiko.Difficulty;
using osu.Game.Scoring;
namespace osu.Game.Rulesets.Taiko namespace osu.Game.Rulesets.Taiko
{ {
@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.Taiko
public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new TaikoDifficultyCalculator(this, beatmap); public override DifficultyCalculator CreateDifficultyCalculator(WorkingBeatmap beatmap) => new TaikoDifficultyCalculator(this, beatmap);
public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, Score score) => new TaikoPerformanceCalculator(this, beatmap, score); public override PerformanceCalculator CreatePerformanceCalculator(WorkingBeatmap beatmap, ScoreInfo score) => new TaikoPerformanceCalculator(this, beatmap, score);
public override int? LegacyID => 1; public override int? LegacyID => 1;

View File

@ -5,7 +5,6 @@ using osu.Framework.Allocation;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Objects.Drawables; using osu.Game.Rulesets.Objects.Drawables;
using osu.Game.Rulesets.Objects.Types; using osu.Game.Rulesets.Objects.Types;
using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Rulesets.Taiko.Objects.Drawables; using osu.Game.Rulesets.Taiko.Objects.Drawables;
@ -16,6 +15,7 @@ using System.Linq;
using osu.Framework.Input; using osu.Framework.Input;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.Input.Handlers; using osu.Game.Input.Handlers;
using osu.Game.Replays;
using osu.Game.Rulesets.UI.Scrolling; using osu.Game.Rulesets.UI.Scrolling;
namespace osu.Game.Rulesets.Taiko.UI namespace osu.Game.Rulesets.Taiko.UI

View File

@ -102,7 +102,7 @@ namespace osu.Game.Tests.Beatmaps.IO
int fireCount = 0; int fireCount = 0;
// ReSharper disable once AccessToModifiedClosure // ReSharper disable once AccessToModifiedClosure
manager.ItemAdded += _ => fireCount++; manager.ItemAdded += (_, __) => fireCount++;
manager.ItemRemoved += _ => fireCount++; manager.ItemRemoved += _ => fireCount++;
var imported = loadOszIntoOsu(osu); var imported = loadOszIntoOsu(osu);

View File

@ -18,7 +18,7 @@ namespace osu.Game.Tests.NonVisual
var combinations = new TestDifficultyCalculator().CreateDifficultyAdjustmentModCombinations(); var combinations = new TestDifficultyCalculator().CreateDifficultyAdjustmentModCombinations();
Assert.AreEqual(1, combinations.Length); Assert.AreEqual(1, combinations.Length);
Assert.IsTrue(combinations[0] is NoModMod); Assert.IsTrue(combinations[0] is ModNoMod);
} }
[Test] [Test]
@ -27,7 +27,7 @@ namespace osu.Game.Tests.NonVisual
var combinations = new TestDifficultyCalculator(new ModA()).CreateDifficultyAdjustmentModCombinations(); var combinations = new TestDifficultyCalculator(new ModA()).CreateDifficultyAdjustmentModCombinations();
Assert.AreEqual(2, combinations.Length); Assert.AreEqual(2, combinations.Length);
Assert.IsTrue(combinations[0] is NoModMod); Assert.IsTrue(combinations[0] is ModNoMod);
Assert.IsTrue(combinations[1] is ModA); Assert.IsTrue(combinations[1] is ModA);
} }
@ -37,7 +37,7 @@ namespace osu.Game.Tests.NonVisual
var combinations = new TestDifficultyCalculator(new ModA(), new ModB()).CreateDifficultyAdjustmentModCombinations(); var combinations = new TestDifficultyCalculator(new ModA(), new ModB()).CreateDifficultyAdjustmentModCombinations();
Assert.AreEqual(4, combinations.Length); Assert.AreEqual(4, combinations.Length);
Assert.IsTrue(combinations[0] is NoModMod); Assert.IsTrue(combinations[0] is ModNoMod);
Assert.IsTrue(combinations[1] is ModA); Assert.IsTrue(combinations[1] is ModA);
Assert.IsTrue(combinations[2] is MultiMod); Assert.IsTrue(combinations[2] is MultiMod);
Assert.IsTrue(combinations[3] is ModB); Assert.IsTrue(combinations[3] is ModB);
@ -52,7 +52,7 @@ namespace osu.Game.Tests.NonVisual
var combinations = new TestDifficultyCalculator(new ModA(), new ModIncompatibleWithA()).CreateDifficultyAdjustmentModCombinations(); var combinations = new TestDifficultyCalculator(new ModA(), new ModIncompatibleWithA()).CreateDifficultyAdjustmentModCombinations();
Assert.AreEqual(3, combinations.Length); Assert.AreEqual(3, combinations.Length);
Assert.IsTrue(combinations[0] is NoModMod); Assert.IsTrue(combinations[0] is ModNoMod);
Assert.IsTrue(combinations[1] is ModA); Assert.IsTrue(combinations[1] is ModA);
Assert.IsTrue(combinations[2] is ModIncompatibleWithA); Assert.IsTrue(combinations[2] is ModIncompatibleWithA);
} }
@ -63,7 +63,7 @@ namespace osu.Game.Tests.NonVisual
var combinations = new TestDifficultyCalculator(new ModA(), new ModB(), new ModIncompatibleWithA(), new ModIncompatibleWithAAndB()).CreateDifficultyAdjustmentModCombinations(); var combinations = new TestDifficultyCalculator(new ModA(), new ModB(), new ModIncompatibleWithA(), new ModIncompatibleWithAAndB()).CreateDifficultyAdjustmentModCombinations();
Assert.AreEqual(8, combinations.Length); Assert.AreEqual(8, combinations.Length);
Assert.IsTrue(combinations[0] is NoModMod); Assert.IsTrue(combinations[0] is ModNoMod);
Assert.IsTrue(combinations[1] is ModA); Assert.IsTrue(combinations[1] is ModA);
Assert.IsTrue(combinations[2] is MultiMod); Assert.IsTrue(combinations[2] is MultiMod);
Assert.IsTrue(combinations[3] is ModB); Assert.IsTrue(combinations[3] is ModB);
@ -86,7 +86,7 @@ namespace osu.Game.Tests.NonVisual
var combinations = new TestDifficultyCalculator(new ModAofA(), new ModIncompatibleWithAofA()).CreateDifficultyAdjustmentModCombinations(); var combinations = new TestDifficultyCalculator(new ModAofA(), new ModIncompatibleWithAofA()).CreateDifficultyAdjustmentModCombinations();
Assert.AreEqual(3, combinations.Length); Assert.AreEqual(3, combinations.Length);
Assert.IsTrue(combinations[0] is NoModMod); Assert.IsTrue(combinations[0] is ModNoMod);
Assert.IsTrue(combinations[1] is ModAofA); Assert.IsTrue(combinations[1] is ModAofA);
Assert.IsTrue(combinations[2] is ModIncompatibleWithAofA); Assert.IsTrue(combinations[2] is ModIncompatibleWithAofA);
} }
@ -94,7 +94,7 @@ namespace osu.Game.Tests.NonVisual
private class ModA : Mod private class ModA : Mod
{ {
public override string Name => nameof(ModA); public override string Name => nameof(ModA);
public override string ShortenedName => nameof(ModA); public override string Acronym => nameof(ModA);
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;
public override Type[] IncompatibleMods => new[] { typeof(ModIncompatibleWithA), typeof(ModIncompatibleWithAAndB) }; public override Type[] IncompatibleMods => new[] { typeof(ModIncompatibleWithA), typeof(ModIncompatibleWithAAndB) };
@ -103,7 +103,7 @@ namespace osu.Game.Tests.NonVisual
private class ModB : Mod private class ModB : Mod
{ {
public override string Name => nameof(ModB); public override string Name => nameof(ModB);
public override string ShortenedName => nameof(ModB); public override string Acronym => nameof(ModB);
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;
public override Type[] IncompatibleMods => new[] { typeof(ModIncompatibleWithAAndB) }; public override Type[] IncompatibleMods => new[] { typeof(ModIncompatibleWithAAndB) };
@ -112,7 +112,7 @@ namespace osu.Game.Tests.NonVisual
private class ModIncompatibleWithA : Mod private class ModIncompatibleWithA : Mod
{ {
public override string Name => $"Incompatible With {nameof(ModA)}"; public override string Name => $"Incompatible With {nameof(ModA)}";
public override string ShortenedName => $"Incompatible With {nameof(ModA)}"; public override string Acronym => $"Incompatible With {nameof(ModA)}";
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;
public override Type[] IncompatibleMods => new[] { typeof(ModA) }; public override Type[] IncompatibleMods => new[] { typeof(ModA) };
@ -130,7 +130,7 @@ namespace osu.Game.Tests.NonVisual
private class ModIncompatibleWithAAndB : Mod private class ModIncompatibleWithAAndB : Mod
{ {
public override string Name => $"Incompatible With {nameof(ModA)} and {nameof(ModB)}"; public override string Name => $"Incompatible With {nameof(ModA)} and {nameof(ModB)}";
public override string ShortenedName => $"Incompatible With {nameof(ModA)} and {nameof(ModB)}"; public override string Acronym => $"Incompatible With {nameof(ModA)} and {nameof(ModB)}";
public override double ScoreMultiplier => 1; public override double ScoreMultiplier => 1;
public override Type[] IncompatibleMods => new[] { typeof(ModA), typeof(ModB) }; public override Type[] IncompatibleMods => new[] { typeof(ModA), typeof(ModB) };

View File

@ -0,0 +1,168 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using NUnit.Framework;
using osu.Framework.Allocation;
using osu.Framework.Platform;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
using osu.Game.Users;
namespace osu.Game.Tests.Scores.IO
{
public class ImportScoreTest
{
public const string TEST_OSZ_PATH = @"../../../../osu-resources/osu.Game.Resources/Beatmaps/241526 Soleily - Renatus.osz";
[Test]
public void TestBasicImport()
{
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestBasicImport"))
{
try
{
var osu = loadOsu(host);
var toImport = new ScoreInfo
{
Rank = ScoreRank.B,
TotalScore = 987654,
Accuracy = 0.8,
Health = 0.8,
MaxCombo = 500,
Combo = 250,
User = new User { Username = "Test user" },
Date = DateTimeOffset.Now,
OnlineScoreID = 12345,
};
var imported = loadIntoOsu(osu, toImport);
Assert.AreEqual(toImport.Rank, imported.Rank);
Assert.AreEqual(toImport.TotalScore, imported.TotalScore);
Assert.AreEqual(toImport.Accuracy, imported.Accuracy);
Assert.AreEqual(toImport.Health, imported.Health);
Assert.AreEqual(toImport.MaxCombo, imported.MaxCombo);
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);
}
finally
{
host.Exit();
}
}
}
[Test]
public void TestImportMods()
{
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportMods"))
{
try
{
var osu = loadOsu(host);
var toImport = new ScoreInfo
{
Mods = new Mod[] { new OsuModHardRock(), new OsuModDoubleTime() },
};
var imported = loadIntoOsu(osu, toImport);
Assert.IsTrue(imported.Mods.Any(m => m is OsuModHardRock));
Assert.IsTrue(imported.Mods.Any(m => m is OsuModDoubleTime));
}
finally
{
host.Exit();
}
}
}
[Test]
public void TestImportStatistics()
{
using (HeadlessGameHost host = new CleanRunHeadlessGameHost("TestImportStatistics"))
{
try
{
var osu = loadOsu(host);
var toImport = new ScoreInfo
{
Statistics = new Dictionary<HitResult, object>
{
{ HitResult.Perfect, 100 },
{ HitResult.Miss, 50 }
}
};
var imported = loadIntoOsu(osu, toImport);
Assert.AreEqual(toImport.Statistics[HitResult.Perfect], imported.Statistics[HitResult.Perfect]);
Assert.AreEqual(toImport.Statistics[HitResult.Miss], imported.Statistics[HitResult.Miss]);
}
finally
{
host.Exit();
}
}
}
private ScoreInfo loadIntoOsu(OsuGameBase osu, ScoreInfo score)
{
var beatmapManager = osu.Dependencies.Get<BeatmapManager>();
score.Beatmap = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First();
score.Ruleset = new OsuRuleset().RulesetInfo;
var scoreManager = osu.Dependencies.Get<ScoreManager>();
scoreManager.Import(score);
return scoreManager.GetAllUsableScores().First();
}
private string createTemporaryBeatmap()
{
var temp = Path.GetTempFileName() + ".osz";
File.Copy(TEST_OSZ_PATH, temp, true);
Assert.IsTrue(File.Exists(temp));
return temp;
}
private OsuGameBase loadOsu(GameHost host)
{
var osu = new OsuGameBase();
Task.Run(() => host.Run(osu));
waitForOrAssert(() => osu.IsLoaded, @"osu! failed to start in a reasonable amount of time");
var beatmapFile = createTemporaryBeatmap();
var beatmapManager = osu.Dependencies.Get<BeatmapManager>();
beatmapManager.Import(beatmapFile);
return osu;
}
private void waitForOrAssert(Func<bool> result, string failureMessage, int timeout = 60000)
{
Task task = Task.Run(() =>
{
while (!result()) Thread.Sleep(200);
});
Assert.IsTrue(task.Wait(timeout), failureMessage);
}
}
}

View File

@ -16,15 +16,16 @@ using osu.Framework.Graphics.Containers;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Online.API.Requests.Responses; using osu.Game.Online.API.Requests.Responses;
using osu.Game.Rulesets.Osu; using osu.Game.Rulesets.Osu;
using osu.Game.Scoring;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
{ {
[System.ComponentModel.Description("in BeatmapOverlay")] [System.ComponentModel.Description("in BeatmapOverlay")]
public class TestCaseBeatmapScoresContainer : OsuTestCase public class TestCaseBeatmapScoresContainer : OsuTestCase
{ {
private readonly IEnumerable<APIScore> scores; private readonly IEnumerable<APIScoreInfo> scores;
private readonly IEnumerable<APIScore> anotherScores; private readonly IEnumerable<APIScoreInfo> anotherScores;
private readonly APIScore topScore; private readonly APIScoreInfo topScoreInfo;
private readonly Box background; private readonly Box background;
public TestCaseBeatmapScoresContainer() public TestCaseBeatmapScoresContainer()
@ -48,7 +49,7 @@ namespace osu.Game.Tests.Visual
AddStep("scores pack 1", () => scoresContainer.Scores = scores); AddStep("scores pack 1", () => scoresContainer.Scores = scores);
AddStep("scores pack 2", () => scoresContainer.Scores = anotherScores); AddStep("scores pack 2", () => scoresContainer.Scores = anotherScores);
AddStep("only top score", () => scoresContainer.Scores = new[] { topScore }); AddStep("only top score", () => scoresContainer.Scores = new[] { topScoreInfo });
AddStep("remove scores", () => scoresContainer.Scores = null); AddStep("remove scores", () => scoresContainer.Scores = null);
AddStep("resize to big", () => container.ResizeWidthTo(1, 300)); AddStep("resize to big", () => container.ResizeWidthTo(1, 300));
AddStep("resize to normal", () => container.ResizeWidthTo(0.8f, 300)); AddStep("resize to normal", () => container.ResizeWidthTo(0.8f, 300));
@ -57,7 +58,7 @@ namespace osu.Game.Tests.Visual
scores = new[] scores = new[]
{ {
new APIScore new APIScoreInfo
{ {
User = new User User = new User
{ {
@ -80,7 +81,7 @@ namespace osu.Game.Tests.Visual
TotalScore = 1234567890, TotalScore = 1234567890,
Accuracy = 1, Accuracy = 1,
}, },
new APIScore new APIScoreInfo
{ {
User = new User User = new User
{ {
@ -102,7 +103,7 @@ namespace osu.Game.Tests.Visual
TotalScore = 1234789, TotalScore = 1234789,
Accuracy = 0.9997, Accuracy = 0.9997,
}, },
new APIScore new APIScoreInfo
{ {
User = new User User = new User
{ {
@ -123,7 +124,7 @@ namespace osu.Game.Tests.Visual
TotalScore = 12345678, TotalScore = 12345678,
Accuracy = 0.9854, Accuracy = 0.9854,
}, },
new APIScore new APIScoreInfo
{ {
User = new User User = new User
{ {
@ -143,7 +144,7 @@ namespace osu.Game.Tests.Visual
TotalScore = 1234567, TotalScore = 1234567,
Accuracy = 0.8765, Accuracy = 0.8765,
}, },
new APIScore new APIScoreInfo
{ {
User = new User User = new User
{ {
@ -169,7 +170,7 @@ namespace osu.Game.Tests.Visual
anotherScores = new[] anotherScores = new[]
{ {
new APIScore new APIScoreInfo
{ {
User = new User User = new User
{ {
@ -191,7 +192,7 @@ namespace osu.Game.Tests.Visual
TotalScore = 1234789, TotalScore = 1234789,
Accuracy = 0.9997, Accuracy = 0.9997,
}, },
new APIScore new APIScoreInfo
{ {
User = new User User = new User
{ {
@ -214,7 +215,7 @@ namespace osu.Game.Tests.Visual
TotalScore = 1234567890, TotalScore = 1234567890,
Accuracy = 1, Accuracy = 1,
}, },
new APIScore new APIScoreInfo
{ {
User = new User User = new User
{ {
@ -230,7 +231,7 @@ namespace osu.Game.Tests.Visual
TotalScore = 123456, TotalScore = 123456,
Accuracy = 0.6543, Accuracy = 0.6543,
}, },
new APIScore new APIScoreInfo
{ {
User = new User User = new User
{ {
@ -251,7 +252,7 @@ namespace osu.Game.Tests.Visual
TotalScore = 12345678, TotalScore = 12345678,
Accuracy = 0.9854, Accuracy = 0.9854,
}, },
new APIScore new APIScoreInfo
{ {
User = new User User = new User
{ {
@ -279,7 +280,7 @@ namespace osu.Game.Tests.Visual
s.Statistics.Add(HitResult.Meh, RNG.Next(2000)); s.Statistics.Add(HitResult.Meh, RNG.Next(2000));
} }
topScore = new APIScore topScoreInfo = new APIScoreInfo
{ {
User = new User User = new User
{ {
@ -301,9 +302,9 @@ namespace osu.Game.Tests.Visual
TotalScore = 987654321, TotalScore = 987654321,
Accuracy = 0.8487, Accuracy = 0.8487,
}; };
topScore.Statistics.Add(HitResult.Great, RNG.Next(2000)); topScoreInfo.Statistics.Add(HitResult.Great, RNG.Next(2000));
topScore.Statistics.Add(HitResult.Good, RNG.Next(2000)); topScoreInfo.Statistics.Add(HitResult.Good, RNG.Next(2000));
topScore.Statistics.Add(HitResult.Meh, RNG.Next(2000)); topScoreInfo.Statistics.Add(HitResult.Meh, RNG.Next(2000));
} }
[BackgroundDependencyLoader] [BackgroundDependencyLoader]

View File

@ -5,7 +5,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.ComponentModel; using System.ComponentModel;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Select.Leaderboards; using osu.Game.Screens.Select.Leaderboards;
using osu.Game.Users; using osu.Game.Users;
using osu.Framework.Allocation; using osu.Framework.Allocation;
@ -13,6 +12,7 @@ using osuTK;
using System.Linq; using System.Linq;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Scoring;
namespace osu.Game.Tests.Visual namespace osu.Game.Tests.Visual
{ {
@ -58,7 +58,7 @@ namespace osu.Game.Tests.Visual
{ {
var scores = new[] var scores = new[]
{ {
new Score new ScoreInfo
{ {
Rank = ScoreRank.XH, Rank = ScoreRank.XH,
Accuracy = 1, Accuracy = 1,
@ -76,7 +76,7 @@ namespace osu.Game.Tests.Visual
}, },
}, },
}, },
new Score new ScoreInfo
{ {
Rank = ScoreRank.X, Rank = ScoreRank.X,
Accuracy = 1, Accuracy = 1,
@ -94,7 +94,7 @@ namespace osu.Game.Tests.Visual
}, },
}, },
}, },
new Score new ScoreInfo
{ {
Rank = ScoreRank.SH, Rank = ScoreRank.SH,
Accuracy = 1, Accuracy = 1,
@ -112,7 +112,7 @@ namespace osu.Game.Tests.Visual
}, },
}, },
}, },
new Score new ScoreInfo
{ {
Rank = ScoreRank.S, Rank = ScoreRank.S,
Accuracy = 1, Accuracy = 1,
@ -130,7 +130,7 @@ namespace osu.Game.Tests.Visual
}, },
}, },
}, },
new Score new ScoreInfo
{ {
Rank = ScoreRank.A, Rank = ScoreRank.A,
Accuracy = 1, Accuracy = 1,
@ -148,7 +148,7 @@ namespace osu.Game.Tests.Visual
}, },
}, },
}, },
new Score new ScoreInfo
{ {
Rank = ScoreRank.B, Rank = ScoreRank.B,
Accuracy = 0.9826, Accuracy = 0.9826,
@ -166,7 +166,7 @@ namespace osu.Game.Tests.Visual
}, },
}, },
}, },
new Score new ScoreInfo
{ {
Rank = ScoreRank.C, Rank = ScoreRank.C,
Accuracy = 0.9654, Accuracy = 0.9654,
@ -184,7 +184,7 @@ namespace osu.Game.Tests.Visual
}, },
}, },
}, },
new Score new ScoreInfo
{ {
Rank = ScoreRank.F, Rank = ScoreRank.F,
Accuracy = 0.6025, Accuracy = 0.6025,
@ -202,7 +202,7 @@ namespace osu.Game.Tests.Visual
}, },
}, },
}, },
new Score new ScoreInfo
{ {
Rank = ScoreRank.F, Rank = ScoreRank.F,
Accuracy = 0.5140, Accuracy = 0.5140,
@ -220,7 +220,7 @@ namespace osu.Game.Tests.Visual
}, },
}, },
}, },
new Score new ScoreInfo
{ {
Rank = ScoreRank.F, Rank = ScoreRank.F,
Accuracy = 0.4222, Accuracy = 0.4222,

View File

@ -187,7 +187,7 @@ namespace osu.Game.Tests.Visual
private static int importId; private static int importId;
private int getImportId() => ++importId; private int getImportId() => ++importId;
private void changeMods(params Mod[] mods) => AddStep($"change mods to {string.Join(", ", mods.Select(m => m.ShortenedName))}", () => selectedMods.Value = mods); private void changeMods(params Mod[] mods) => AddStep($"change mods to {string.Join(", ", mods.Select(m => m.Acronym))}", () => selectedMods.Value = mods);
private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id)); private void changeRuleset(int id) => AddStep($"change ruleset to {id}", () => Ruleset.Value = rulesets.AvailableRulesets.First(r => r.ID == id));

View File

@ -7,6 +7,7 @@ using NUnit.Framework;
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
using osu.Game.Screens.Ranking; using osu.Game.Screens.Ranking;
using osu.Game.Users; using osu.Game.Users;
@ -19,7 +20,7 @@ namespace osu.Game.Tests.Visual
public override IReadOnlyList<Type> RequiredTypes => new[] public override IReadOnlyList<Type> RequiredTypes => new[]
{ {
typeof(Score), typeof(ScoreInfo),
typeof(Results), typeof(Results),
typeof(ResultsPage), typeof(ResultsPage),
typeof(ResultsPageScore), typeof(ResultsPageScore),
@ -40,7 +41,7 @@ namespace osu.Game.Tests.Visual
if (beatmapInfo != null) if (beatmapInfo != null)
Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo); Beatmap.Value = beatmaps.GetWorkingBeatmap(beatmapInfo);
Add(new Results(new Score Add(new Results(new ScoreInfo
{ {
TotalScore = 2845370, TotalScore = 2845370,
Accuracy = 0.98, Accuracy = 0.98,

View File

@ -1,20 +1,17 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.ComponentModel.DataAnnotations.Schema; using osu.Game.Database;
using Newtonsoft.Json;
namespace osu.Game.Beatmaps namespace osu.Game.Beatmaps
{ {
public class BeatmapDifficulty public class BeatmapDifficulty : IHasPrimaryKey
{ {
/// <summary> /// <summary>
/// The default value used for all difficulty settings except <see cref="SliderMultiplier"/> and <see cref="SliderTickRate"/>. /// The default value used for all difficulty settings except <see cref="SliderMultiplier"/> and <see cref="SliderTickRate"/>.
/// </summary> /// </summary>
public const float DEFAULT_DIFFICULTY = 5; public const float DEFAULT_DIFFICULTY = 5;
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[JsonIgnore]
public int ID { get; set; } public int ID { get; set; }
public float DrainRate { get; set; } = DEFAULT_DIFFICULTY; public float DrainRate { get; set; } = DEFAULT_DIFFICULTY;

View File

@ -15,8 +15,6 @@ namespace osu.Game.Beatmaps
[Serializable] [Serializable]
public class BeatmapInfo : IEquatable<BeatmapInfo>, IJsonSerializable, IHasPrimaryKey public class BeatmapInfo : IEquatable<BeatmapInfo>, IJsonSerializable, IHasPrimaryKey
{ {
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[JsonIgnore]
public int ID { get; set; } public int ID { get; set; }
public int BeatmapVersion; public int BeatmapVersion;

View File

@ -6,14 +6,14 @@ using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.Linq; using System.Linq;
using Newtonsoft.Json; using Newtonsoft.Json;
using osu.Game.Database;
using osu.Game.Users; using osu.Game.Users;
namespace osu.Game.Beatmaps namespace osu.Game.Beatmaps
{ {
[Serializable] [Serializable]
public class BeatmapMetadata : IEquatable<BeatmapMetadata> public class BeatmapMetadata : IEquatable<BeatmapMetadata>, IHasPrimaryKey
{ {
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; } public int ID { get; set; }
public string Title { get; set; } public string Title { get; set; }

View File

@ -2,15 +2,13 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using osu.Game.Database; using osu.Game.Database;
using osu.Game.IO; using osu.Game.IO;
namespace osu.Game.Beatmaps namespace osu.Game.Beatmaps
{ {
public class BeatmapSetFileInfo : INamedFileInfo public class BeatmapSetFileInfo : INamedFileInfo, IHasPrimaryKey
{ {
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; } public int ID { get; set; }
public int BeatmapSetInfoID { get; set; } public int BeatmapSetInfoID { get; set; }

View File

@ -10,7 +10,6 @@ namespace osu.Game.Beatmaps
{ {
public class BeatmapSetInfo : IHasPrimaryKey, IHasFiles<BeatmapSetFileInfo>, ISoftDelete public class BeatmapSetInfo : IHasPrimaryKey, IHasFiles<BeatmapSetFileInfo>, ISoftDelete
{ {
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; } public int ID { get; set; }
private int? onlineBeatmapSetID; private int? onlineBeatmapSetID;

View File

@ -78,7 +78,7 @@ namespace osu.Game.Beatmaps.Drawables
} }
} }
private void setAdded(BeatmapSetInfo s) => Schedule(() => private void setAdded(BeatmapSetInfo s, bool existing) => Schedule(() =>
{ {
if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID) if (s.OnlineBeatmapSetID == set.OnlineBeatmapSetID)
DownloadState.Value = DownloadStatus.Downloaded; DownloadState.Value = DownloadStatus.Downloaded;

View File

@ -9,7 +9,6 @@ namespace osu.Game.Configuration
[Table("Settings")] [Table("Settings")]
public class DatabasedSetting : IHasPrimaryKey public class DatabasedSetting : IHasPrimaryKey
{ {
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; } public int ID { get; set; }
public int? RulesetID { get; set; } public int? RulesetID { get; set; }

View File

@ -32,6 +32,8 @@ namespace osu.Game.Database
where TModel : class, IHasFiles<TFileModel>, IHasPrimaryKey, ISoftDelete where TModel : class, IHasFiles<TFileModel>, IHasPrimaryKey, ISoftDelete
where TFileModel : INamedFileInfo, new() where TFileModel : INamedFileInfo, new()
{ {
public delegate void ItemAddedDelegate(TModel model, bool existing);
/// <summary> /// <summary>
/// Set an endpoint for notifications to be posted to. /// Set an endpoint for notifications to be posted to.
/// </summary> /// </summary>
@ -41,7 +43,7 @@ namespace osu.Game.Database
/// Fired when a new <see cref="TModel"/> becomes available in the database. /// Fired when a new <see cref="TModel"/> becomes available in the database.
/// This is not guaranteed to run on the update thread. /// This is not guaranteed to run on the update thread.
/// </summary> /// </summary>
public event Action<TModel> ItemAdded; public event ItemAddedDelegate ItemAdded;
/// <summary> /// <summary>
/// Fired when a <see cref="TModel"/> is removed from the database. /// Fired when a <see cref="TModel"/> is removed from the database.
@ -108,7 +110,7 @@ namespace osu.Game.Database
ContextFactory = contextFactory; ContextFactory = contextFactory;
ModelStore = modelStore; ModelStore = modelStore;
ModelStore.ItemAdded += s => handleEvent(() => ItemAdded?.Invoke(s)); ModelStore.ItemAdded += s => handleEvent(() => ItemAdded?.Invoke(s, false));
ModelStore.ItemRemoved += s => handleEvent(() => ItemRemoved?.Invoke(s)); ModelStore.ItemRemoved += s => handleEvent(() => ItemRemoved?.Invoke(s));
Files = new FileStore(contextFactory, storage); Files = new FileStore(contextFactory, storage);
@ -264,6 +266,7 @@ namespace osu.Game.Database
{ {
Undelete(existing); Undelete(existing);
Logger.Log($"Found existing {typeof(TModel)} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database); Logger.Log($"Found existing {typeof(TModel)} for {item} (ID {existing.ID}). Skipping import.", LoggingTarget.Database);
handleEvent(() => ItemAdded?.Invoke(existing, true));
return existing; return existing;
} }
@ -518,7 +521,9 @@ namespace osu.Game.Database
if (ZipUtils.IsZipArchive(path)) if (ZipUtils.IsZipArchive(path))
return new ZipArchiveReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read), Path.GetFileName(path)); return new ZipArchiveReader(File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read), Path.GetFileName(path));
if (Directory.Exists(path)) if (Directory.Exists(path))
return new LegacyFilesystemReader(path); return new LegacyDirectoryArchiveReader(path);
if (File.Exists(path))
return new LegacyFileArchiveReader(path);
throw new InvalidFormatException($"{path} is not a valid archive"); throw new InvalidFormatException($"{path} is not a valid archive");
} }
} }

View File

@ -11,7 +11,6 @@ namespace osu.Game.Database
/// <typeparam name="TFile">The model representing a file.</typeparam> /// <typeparam name="TFile">The model representing a file.</typeparam>
public interface IHasFiles<TFile> public interface IHasFiles<TFile>
where TFile : INamedFileInfo where TFile : INamedFileInfo
{ {
List<TFile> Files { get; set; } List<TFile> Files { get; set; }

View File

@ -1,10 +1,15 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.ComponentModel.DataAnnotations.Schema;
using Newtonsoft.Json;
namespace osu.Game.Database namespace osu.Game.Database
{ {
public interface IHasPrimaryKey public interface IHasPrimaryKey
{ {
[JsonIgnore]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
int ID { get; set; } int ID { get; set; }
} }
} }

View File

@ -10,7 +10,11 @@ namespace osu.Game.Database
/// </summary> /// </summary>
public interface INamedFileInfo public interface INamedFileInfo
{ {
// An explicit foreign key property isn't required but is recommended and may be helpful to have
int FileInfoID { get; set; }
FileInfo FileInfo { get; set; } FileInfo FileInfo { get; set; }
string Filename { get; set; } string Filename { get; set; }
} }
} }

View File

@ -10,6 +10,7 @@ using osu.Game.Beatmaps;
using osu.Game.Configuration; using osu.Game.Configuration;
using osu.Game.IO; using osu.Game.IO;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Scoring;
using DatabasedKeyBinding = osu.Game.Input.Bindings.DatabasedKeyBinding; using DatabasedKeyBinding = osu.Game.Input.Bindings.DatabasedKeyBinding;
using LogLevel = Microsoft.Extensions.Logging.LogLevel; using LogLevel = Microsoft.Extensions.Logging.LogLevel;
using osu.Game.Skinning; using osu.Game.Skinning;
@ -27,6 +28,7 @@ namespace osu.Game.Database
public DbSet<FileInfo> FileInfo { get; set; } public DbSet<FileInfo> FileInfo { get; set; }
public DbSet<RulesetInfo> RulesetInfo { get; set; } public DbSet<RulesetInfo> RulesetInfo { get; set; }
public DbSet<SkinInfo> SkinInfo { get; set; } public DbSet<SkinInfo> SkinInfo { get; set; }
public DbSet<ScoreInfo> ScoreInfo { get; set; }
private readonly string connectionString; private readonly string connectionString;
@ -120,6 +122,8 @@ namespace osu.Game.Database
modelBuilder.Entity<RulesetInfo>().HasIndex(b => b.ShortName).IsUnique(); modelBuilder.Entity<RulesetInfo>().HasIndex(b => b.ShortName).IsUnique();
modelBuilder.Entity<BeatmapInfo>().HasOne(b => b.BaseDifficulty); modelBuilder.Entity<BeatmapInfo>().HasOne(b => b.BaseDifficulty);
modelBuilder.Entity<ScoreInfo>().HasIndex(b => b.OnlineScoreID).IsUnique();
} }
private class OsuDbLoggerFactory : ILoggerFactory private class OsuDbLoggerFactory : ILoggerFactory

View File

@ -8,13 +8,13 @@ using System.Linq;
namespace osu.Game.IO.Archives namespace osu.Game.IO.Archives
{ {
/// <summary> /// <summary>
/// Reads an extracted legacy beatmap from disk. /// Reads an archive from a directory on disk.
/// </summary> /// </summary>
public class LegacyFilesystemReader : ArchiveReader public class LegacyDirectoryArchiveReader : ArchiveReader
{ {
private readonly string path; private readonly string path;
public LegacyFilesystemReader(string path) public LegacyDirectoryArchiveReader(string path)
: base(Path.GetFileName(path)) : base(Path.GetFileName(path))
{ {
// re-get full path to standardise with Directory.GetFiles return values below. // re-get full path to standardise with Directory.GetFiles return values below.

View File

@ -0,0 +1,34 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic;
using System.IO;
namespace osu.Game.IO.Archives
{
/// <summary>
/// Reads a file on disk as an archive.
/// Note: In this case, the file is not an extractable archive, use <see cref="ZipArchiveReader"/> instead.
/// </summary>
public class LegacyFileArchiveReader : ArchiveReader
{
private readonly string path;
public LegacyFileArchiveReader(string path)
: base(Path.GetFileName(path))
{
// re-get full path to standardise
this.path = Path.GetFullPath(path);
}
public override Stream GetStream(string name) => File.OpenRead(path);
public override void Dispose()
{
}
public override IEnumerable<string> Filenames => new[] { Name };
public override Stream GetUnderlyingStream() => null;
}
}

View File

@ -1,14 +1,13 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.ComponentModel.DataAnnotations.Schema;
using System.IO; using System.IO;
using osu.Game.Database;
namespace osu.Game.IO namespace osu.Game.IO
{ {
public class FileInfo public class FileInfo : IHasPrimaryKey
{ {
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; } public int ID { get; set; }
public string Hash { get; set; } public string Hash { get; set; }

View File

@ -1,46 +0,0 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Diagnostics;
using System.Threading.Tasks;
using osu.Framework.Platform;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.IPC
{
public class ScoreIPCChannel : IpcChannel<ScoreImportMessage>
{
private readonly ScoreStore scores;
public ScoreIPCChannel(IIpcHost host, ScoreStore scores = null)
: base(host)
{
this.scores = scores;
MessageReceived += msg =>
{
Debug.Assert(scores != null);
ImportAsync(msg.Path).ContinueWith(t =>
{
if (t.Exception != null) throw t.Exception;
}, TaskContinuationOptions.OnlyOnFaulted);
};
}
public async Task ImportAsync(string path)
{
if (scores == null)
{
//we want to contact a remote osu! to handle the import.
await SendMessageAsync(new ScoreImportMessage { Path = path });
return;
}
scores.ReadReplayFile(path);
}
}
public class ScoreImportMessage
{
public string Path;
}
}

View File

@ -10,7 +10,6 @@ namespace osu.Game.Input.Bindings
[Table("KeyBinding")] [Table("KeyBinding")]
public class DatabasedKeyBinding : KeyBinding, IHasPrimaryKey public class DatabasedKeyBinding : KeyBinding, IHasPrimaryKey
{ {
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ID { get; set; } public int ID { get; set; }
public int? RulesetID { get; set; } public int? RulesetID { get; set; }

View File

@ -0,0 +1,485 @@
// <auto-generated />
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using osu.Game.Database;
namespace osu.Game.Migrations
{
[DbContext(typeof(OsuDbContext))]
[Migration("20181130084152_AddScoreInfoTables")]
partial class AddScoreInfoTables
{
protected override void BuildTargetModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
.HasAnnotation("ProductVersion", "2.1.4-rtm-31024");
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapDifficulty", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<float>("ApproachRate");
b.Property<float>("CircleSize");
b.Property<float>("DrainRate");
b.Property<float>("OverallDifficulty");
b.Property<double>("SliderMultiplier");
b.Property<double>("SliderTickRate");
b.HasKey("ID");
b.ToTable("BeatmapDifficulty");
});
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<int>("AudioLeadIn");
b.Property<int>("BaseDifficultyID");
b.Property<int>("BeatDivisor");
b.Property<int>("BeatmapSetInfoID");
b.Property<bool>("Countdown");
b.Property<double>("DistanceSpacing");
b.Property<int>("GridSize");
b.Property<string>("Hash");
b.Property<bool>("Hidden");
b.Property<bool>("LetterboxInBreaks");
b.Property<string>("MD5Hash");
b.Property<int?>("MetadataID");
b.Property<int?>("OnlineBeatmapID");
b.Property<string>("Path");
b.Property<int>("RulesetID");
b.Property<bool>("SpecialStyle");
b.Property<float>("StackLeniency");
b.Property<double>("StarDifficulty");
b.Property<int>("Status");
b.Property<string>("StoredBookmarks");
b.Property<double>("TimelineZoom");
b.Property<string>("Version");
b.Property<bool>("WidescreenStoryboard");
b.HasKey("ID");
b.HasIndex("BaseDifficultyID");
b.HasIndex("BeatmapSetInfoID");
b.HasIndex("Hash");
b.HasIndex("MD5Hash");
b.HasIndex("MetadataID");
b.HasIndex("OnlineBeatmapID")
.IsUnique();
b.HasIndex("RulesetID");
b.ToTable("BeatmapInfo");
});
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapMetadata", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<string>("Artist");
b.Property<string>("ArtistUnicode");
b.Property<string>("AudioFile");
b.Property<string>("AuthorString")
.HasColumnName("Author");
b.Property<string>("BackgroundFile");
b.Property<int>("PreviewTime");
b.Property<string>("Source");
b.Property<string>("Tags");
b.Property<string>("Title");
b.Property<string>("TitleUnicode");
b.HasKey("ID");
b.ToTable("BeatmapMetadata");
});
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<int>("BeatmapSetInfoID");
b.Property<int>("FileInfoID");
b.Property<string>("Filename")
.IsRequired();
b.HasKey("ID");
b.HasIndex("BeatmapSetInfoID");
b.HasIndex("FileInfoID");
b.ToTable("BeatmapSetFileInfo");
});
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<bool>("DeletePending");
b.Property<string>("Hash");
b.Property<int?>("MetadataID");
b.Property<int?>("OnlineBeatmapSetID");
b.Property<bool>("Protected");
b.Property<int>("Status");
b.HasKey("ID");
b.HasIndex("DeletePending");
b.HasIndex("Hash")
.IsUnique();
b.HasIndex("MetadataID");
b.HasIndex("OnlineBeatmapSetID")
.IsUnique();
b.ToTable("BeatmapSetInfo");
});
modelBuilder.Entity("osu.Game.Configuration.DatabasedSetting", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<int>("IntKey")
.HasColumnName("Key");
b.Property<int?>("RulesetID");
b.Property<string>("StringValue")
.HasColumnName("Value");
b.Property<int?>("Variant");
b.HasKey("ID");
b.HasIndex("RulesetID", "Variant");
b.ToTable("Settings");
});
modelBuilder.Entity("osu.Game.Input.Bindings.DatabasedKeyBinding", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<int>("IntAction")
.HasColumnName("Action");
b.Property<string>("KeysString")
.HasColumnName("Keys");
b.Property<int?>("RulesetID");
b.Property<int?>("Variant");
b.HasKey("ID");
b.HasIndex("IntAction");
b.HasIndex("RulesetID", "Variant");
b.ToTable("KeyBinding");
});
modelBuilder.Entity("osu.Game.IO.FileInfo", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<string>("Hash");
b.Property<int>("ReferenceCount");
b.HasKey("ID");
b.HasIndex("Hash")
.IsUnique();
b.HasIndex("ReferenceCount");
b.ToTable("FileInfo");
});
modelBuilder.Entity("osu.Game.Rulesets.RulesetInfo", b =>
{
b.Property<int?>("ID")
.ValueGeneratedOnAdd();
b.Property<bool>("Available");
b.Property<string>("InstantiationInfo");
b.Property<string>("Name");
b.Property<string>("ShortName");
b.HasKey("ID");
b.HasIndex("Available");
b.HasIndex("ShortName")
.IsUnique();
b.ToTable("RulesetInfo");
});
modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<int>("FileInfoID");
b.Property<string>("Filename")
.IsRequired();
b.Property<int?>("ScoreInfoID");
b.HasKey("ID");
b.HasIndex("FileInfoID");
b.HasIndex("ScoreInfoID");
b.ToTable("ScoreFileInfo");
});
modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<double>("Accuracy");
b.Property<int>("BeatmapInfoID");
b.Property<int>("Combo");
b.Property<DateTimeOffset>("Date");
b.Property<bool>("DeletePending");
b.Property<string>("Hash");
b.Property<double>("Health");
b.Property<int>("MaxCombo");
b.Property<string>("ModsJson")
.HasColumnName("Mods");
b.Property<long?>("OnlineScoreID");
b.Property<double?>("PP");
b.Property<int>("Rank");
b.Property<int>("RulesetID");
b.Property<string>("StatisticsJson")
.HasColumnName("Statistics");
b.Property<double>("TotalScore");
b.Property<string>("UserString")
.HasColumnName("User");
b.HasKey("ID");
b.HasIndex("BeatmapInfoID");
b.HasIndex("OnlineScoreID")
.IsUnique();
b.HasIndex("RulesetID");
b.ToTable("ScoreInfo");
});
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<int>("FileInfoID");
b.Property<string>("Filename")
.IsRequired();
b.Property<int>("SkinInfoID");
b.HasKey("ID");
b.HasIndex("FileInfoID");
b.HasIndex("SkinInfoID");
b.ToTable("SkinFileInfo");
});
modelBuilder.Entity("osu.Game.Skinning.SkinInfo", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<string>("Creator");
b.Property<bool>("DeletePending");
b.Property<string>("Hash");
b.Property<string>("Name");
b.HasKey("ID");
b.HasIndex("DeletePending");
b.HasIndex("Hash")
.IsUnique();
b.ToTable("SkinInfo");
});
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapInfo", b =>
{
b.HasOne("osu.Game.Beatmaps.BeatmapDifficulty", "BaseDifficulty")
.WithMany()
.HasForeignKey("BaseDifficultyID")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo", "BeatmapSet")
.WithMany("Beatmaps")
.HasForeignKey("BeatmapSetInfoID")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
.WithMany("Beatmaps")
.HasForeignKey("MetadataID");
b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset")
.WithMany()
.HasForeignKey("RulesetID")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetFileInfo", b =>
{
b.HasOne("osu.Game.Beatmaps.BeatmapSetInfo")
.WithMany("Files")
.HasForeignKey("BeatmapSetInfoID")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
.WithMany()
.HasForeignKey("FileInfoID")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("osu.Game.Beatmaps.BeatmapSetInfo", b =>
{
b.HasOne("osu.Game.Beatmaps.BeatmapMetadata", "Metadata")
.WithMany("BeatmapSets")
.HasForeignKey("MetadataID");
});
modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b =>
{
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
.WithMany()
.HasForeignKey("FileInfoID")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("osu.Game.Scoring.ScoreInfo")
.WithMany("Files")
.HasForeignKey("ScoreInfoID");
});
modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b =>
{
b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap")
.WithMany()
.HasForeignKey("BeatmapInfoID")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset")
.WithMany()
.HasForeignKey("RulesetID")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
{
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
.WithMany()
.HasForeignKey("FileInfoID")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("osu.Game.Skinning.SkinInfo")
.WithMany("Files")
.HasForeignKey("SkinInfoID")
.OnDelete(DeleteBehavior.Cascade);
});
#pragma warning restore 612, 618
}
}
}

View File

@ -0,0 +1,113 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
namespace osu.Game.Migrations
{
public partial class AddScoreInfoTables : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "ScoreInfo",
columns: table => new
{
ID = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
Rank = table.Column<int>(nullable: false),
TotalScore = table.Column<double>(nullable: false),
Accuracy = table.Column<double>(nullable: false),
Health = table.Column<double>(nullable: false),
PP = table.Column<double>(nullable: true),
MaxCombo = table.Column<int>(nullable: false),
Combo = table.Column<int>(nullable: false),
RulesetID = table.Column<int>(nullable: false),
Mods = table.Column<string>(nullable: true),
User = table.Column<string>(nullable: true),
BeatmapInfoID = table.Column<int>(nullable: false),
OnlineScoreID = table.Column<long>(nullable: true),
Date = table.Column<DateTimeOffset>(nullable: false),
Statistics = table.Column<string>(nullable: true),
Hash = table.Column<string>(nullable: true),
DeletePending = table.Column<bool>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_ScoreInfo", x => x.ID);
table.ForeignKey(
name: "FK_ScoreInfo_BeatmapInfo_BeatmapInfoID",
column: x => x.BeatmapInfoID,
principalTable: "BeatmapInfo",
principalColumn: "ID",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ScoreInfo_RulesetInfo_RulesetID",
column: x => x.RulesetID,
principalTable: "RulesetInfo",
principalColumn: "ID",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateTable(
name: "ScoreFileInfo",
columns: table => new
{
ID = table.Column<int>(nullable: false)
.Annotation("Sqlite:Autoincrement", true),
FileInfoID = table.Column<int>(nullable: false),
Filename = table.Column<string>(nullable: false),
ScoreInfoID = table.Column<int>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_ScoreFileInfo", x => x.ID);
table.ForeignKey(
name: "FK_ScoreFileInfo_FileInfo_FileInfoID",
column: x => x.FileInfoID,
principalTable: "FileInfo",
principalColumn: "ID",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_ScoreFileInfo_ScoreInfo_ScoreInfoID",
column: x => x.ScoreInfoID,
principalTable: "ScoreInfo",
principalColumn: "ID",
onDelete: ReferentialAction.Restrict);
});
migrationBuilder.CreateIndex(
name: "IX_ScoreFileInfo_FileInfoID",
table: "ScoreFileInfo",
column: "FileInfoID");
migrationBuilder.CreateIndex(
name: "IX_ScoreFileInfo_ScoreInfoID",
table: "ScoreFileInfo",
column: "ScoreInfoID");
migrationBuilder.CreateIndex(
name: "IX_ScoreInfo_BeatmapInfoID",
table: "ScoreInfo",
column: "BeatmapInfoID");
migrationBuilder.CreateIndex(
name: "IX_ScoreInfo_OnlineScoreID",
table: "ScoreInfo",
column: "OnlineScoreID",
unique: true);
migrationBuilder.CreateIndex(
name: "IX_ScoreInfo_RulesetID",
table: "ScoreInfo",
column: "RulesetID");
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "ScoreFileInfo");
migrationBuilder.DropTable(
name: "ScoreInfo");
}
}
}

View File

@ -281,6 +281,79 @@ namespace osu.Game.Migrations
b.ToTable("RulesetInfo"); b.ToTable("RulesetInfo");
}); });
modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<int>("FileInfoID");
b.Property<string>("Filename")
.IsRequired();
b.Property<int?>("ScoreInfoID");
b.HasKey("ID");
b.HasIndex("FileInfoID");
b.HasIndex("ScoreInfoID");
b.ToTable("ScoreFileInfo");
});
modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b =>
{
b.Property<int>("ID")
.ValueGeneratedOnAdd();
b.Property<double>("Accuracy");
b.Property<int>("BeatmapInfoID");
b.Property<int>("Combo");
b.Property<DateTimeOffset>("Date");
b.Property<bool>("DeletePending");
b.Property<string>("Hash");
b.Property<double>("Health");
b.Property<int>("MaxCombo");
b.Property<string>("ModsJson")
.HasColumnName("Mods");
b.Property<long?>("OnlineScoreID");
b.Property<double?>("PP");
b.Property<int>("Rank");
b.Property<int>("RulesetID");
b.Property<string>("StatisticsJson")
.HasColumnName("Statistics");
b.Property<double>("TotalScore");
b.Property<string>("UserString")
.HasColumnName("User");
b.HasKey("ID");
b.HasIndex("BeatmapInfoID");
b.HasIndex("OnlineScoreID")
.IsUnique();
b.HasIndex("RulesetID");
b.ToTable("ScoreInfo");
});
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
{ {
b.Property<int>("ID") b.Property<int>("ID")
@ -367,6 +440,31 @@ namespace osu.Game.Migrations
.HasForeignKey("MetadataID"); .HasForeignKey("MetadataID");
}); });
modelBuilder.Entity("osu.Game.Scoring.ScoreFileInfo", b =>
{
b.HasOne("osu.Game.IO.FileInfo", "FileInfo")
.WithMany()
.HasForeignKey("FileInfoID")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("osu.Game.Scoring.ScoreInfo")
.WithMany("Files")
.HasForeignKey("ScoreInfoID");
});
modelBuilder.Entity("osu.Game.Scoring.ScoreInfo", b =>
{
b.HasOne("osu.Game.Beatmaps.BeatmapInfo", "Beatmap")
.WithMany()
.HasForeignKey("BeatmapInfoID")
.OnDelete(DeleteBehavior.Cascade);
b.HasOne("osu.Game.Rulesets.RulesetInfo", "Ruleset")
.WithMany()
.HasForeignKey("RulesetID")
.OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b => modelBuilder.Entity("osu.Game.Skinning.SkinFileInfo", b =>
{ {
b.HasOne("osu.Game.IO.FileInfo", "FileInfo") b.HasOne("osu.Game.IO.FileInfo", "FileInfo")

View File

@ -33,8 +33,8 @@ namespace osu.Game.Online.API.Requests
private void onSuccess(APIScores r) private void onSuccess(APIScores r)
{ {
foreach (APIScore score in r.Scores) foreach (APIScoreInfo score in r.Scores)
score.ApplyBeatmap(beatmap); score.Beatmap = beatmap;
} }
protected override WebRequest CreateWebRequest() protected override WebRequest CreateWebRequest()

View File

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

View File

@ -4,7 +4,7 @@
using System; using System;
using Humanizer; using Humanizer;
using Newtonsoft.Json; using Newtonsoft.Json;
using osu.Game.Rulesets.Scoring; using osu.Game.Scoring;
namespace osu.Game.Online.API.Requests.Responses namespace osu.Game.Online.API.Requests.Responses
{ {

View File

@ -7,13 +7,13 @@ using System.Linq;
using Newtonsoft.Json; using Newtonsoft.Json;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
using osu.Game.Users; using osu.Game.Users;
namespace osu.Game.Online.API.Requests.Responses namespace osu.Game.Online.API.Requests.Responses
{ {
public class APIScore : Score public class APIScoreInfo : ScoreInfo
{ {
[JsonProperty(@"score")] [JsonProperty(@"score")]
private double totalScore private double totalScore
@ -33,15 +33,6 @@ namespace osu.Game.Online.API.Requests.Responses
set => User = value; set => User = value;
} }
[JsonProperty(@"replay_data")]
private Replay replay
{
set => Replay = value;
}
[JsonProperty(@"mode_int")]
public int OnlineRulesetID { get; set; }
[JsonProperty(@"score_id")] [JsonProperty(@"score_id")]
private long onlineScoreID private long onlineScoreID
{ {
@ -104,21 +95,36 @@ namespace osu.Game.Online.API.Requests.Responses
} }
} }
[JsonProperty(@"mode_int")]
public int OnlineRulesetID { get; set; }
[JsonProperty(@"mods")] [JsonProperty(@"mods")]
private string[] modStrings { get; set; } private string[] modStrings { get; set; }
public void ApplyBeatmap(BeatmapInfo beatmap) public override BeatmapInfo Beatmap
{ {
Beatmap = beatmap; get => base.Beatmap;
ApplyRuleset(beatmap.Ruleset); set
{
base.Beatmap = value;
if (Beatmap.Ruleset != null)
Ruleset = value.Ruleset;
}
} }
public void ApplyRuleset(RulesetInfo ruleset) public override RulesetInfo Ruleset
{ {
Ruleset = ruleset; get => base.Ruleset;
set
{
base.Ruleset = value;
// Evaluate the mod string if (modStrings != null)
Mods = Ruleset.CreateInstance().GetAllMods().Where(mod => modStrings.Contains(mod.ShortenedName)).ToArray(); {
// Evaluate the mod string
Mods = Ruleset.CreateInstance().GetAllMods().Where(mod => modStrings.Contains(mod.Acronym)).ToArray();
}
}
} }
} }
} }

View File

@ -9,6 +9,6 @@ namespace osu.Game.Online.API.Requests.Responses
public class APIScores public class APIScores
{ {
[JsonProperty(@"scores")] [JsonProperty(@"scores")]
public IEnumerable<APIScore> Scores; public IEnumerable<APIScoreInfo> Scores;
} }
} }

View File

@ -27,7 +27,6 @@ using osu.Framework.Threading;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Input; using osu.Game.Input;
using osu.Game.Rulesets.Scoring;
using osu.Game.Overlays.Notifications; using osu.Game.Overlays.Notifications;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Screens.Play; using osu.Game.Screens.Play;
@ -37,6 +36,7 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Skinning; using osu.Game.Skinning;
using osuTK.Graphics; using osuTK.Graphics;
using osu.Game.Overlays.Volume; using osu.Game.Overlays.Volume;
using osu.Game.Scoring;
using osu.Game.Screens.Select; using osu.Game.Screens.Select;
using osu.Game.Utils; using osu.Game.Utils;
using LogLevel = osu.Framework.Logging.LogLevel; using LogLevel = osu.Framework.Logging.LogLevel;
@ -148,7 +148,7 @@ namespace osu.Game
{ {
this.frameworkConfig = frameworkConfig; this.frameworkConfig = frameworkConfig;
ScoreStore.ScoreImported += score => Schedule(() => LoadScore(score)); ScoreManager.ItemAdded += (score, _) => Schedule(() => LoadScore(score));
if (!Host.IsPrimaryInstance) if (!Host.IsPrimaryInstance)
{ {
@ -248,7 +248,7 @@ namespace osu.Game
/// <param name="beatmapId">The beatmap to show.</param> /// <param name="beatmapId">The beatmap to show.</param>
public void ShowBeatmap(int beatmapId) => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId); public void ShowBeatmap(int beatmapId) => beatmapSetOverlay.FetchAndShowBeatmap(beatmapId);
protected void LoadScore(Score score) protected void LoadScore(ScoreInfo score)
{ {
scoreLoad?.Cancel(); scoreLoad?.Cancel();
@ -267,7 +267,9 @@ namespace osu.Game
return; return;
} }
if (score.Beatmap == null) var databasedBeatmap = BeatmapManager.QueryBeatmap(b => b.ID == score.Beatmap.ID);
if (databasedBeatmap == null)
{ {
notifications.Post(new SimpleNotification notifications.Post(new SimpleNotification
{ {
@ -279,10 +281,10 @@ namespace osu.Game
ruleset.Value = score.Ruleset; ruleset.Value = score.Ruleset;
Beatmap.Value = BeatmapManager.GetWorkingBeatmap(score.Beatmap); Beatmap.Value = BeatmapManager.GetWorkingBeatmap(databasedBeatmap);
Beatmap.Value.Mods.Value = score.Mods; Beatmap.Value.Mods.Value = score.Mods;
menu.Push(new PlayerLoader(new ReplayPlayer(score.Replay))); menu.Push(new PlayerLoader(new ReplayPlayer(ScoreManager.GetScore(score).Replay)));
} }
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)

View File

@ -28,7 +28,7 @@ using osu.Game.Input;
using osu.Game.Input.Bindings; using osu.Game.Input.Bindings;
using osu.Game.IO; using osu.Game.IO;
using osu.Game.Rulesets; using osu.Game.Rulesets;
using osu.Game.Rulesets.Scoring; using osu.Game.Scoring;
using osu.Game.Skinning; using osu.Game.Skinning;
using osuTK.Input; using osuTK.Input;
using DebugUtils = osu.Game.Utils.DebugUtils; using DebugUtils = osu.Game.Utils.DebugUtils;
@ -46,14 +46,14 @@ namespace osu.Game
protected BeatmapManager BeatmapManager; protected BeatmapManager BeatmapManager;
protected ScoreManager ScoreManager;
protected SkinManager SkinManager; protected SkinManager SkinManager;
protected RulesetStore RulesetStore; protected RulesetStore RulesetStore;
protected FileStore FileStore; protected FileStore FileStore;
protected ScoreStore ScoreStore;
protected KeyBindingStore KeyBindingStore; protected KeyBindingStore KeyBindingStore;
protected SettingsStore SettingsStore; protected SettingsStore SettingsStore;
@ -154,14 +154,14 @@ namespace osu.Game
dependencies.Cache(RulesetStore = new RulesetStore(contextFactory)); dependencies.Cache(RulesetStore = new RulesetStore(contextFactory));
dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage)); dependencies.Cache(FileStore = new FileStore(contextFactory, Host.Storage));
dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, api, Audio, Host)); dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, contextFactory, RulesetStore, api, Audio, Host));
dependencies.Cache(ScoreStore = new ScoreStore(contextFactory, Host, BeatmapManager, RulesetStore)); dependencies.Cache(ScoreManager = new ScoreManager(RulesetStore, BeatmapManager, Host.Storage, contextFactory, Host));
dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore)); dependencies.Cache(KeyBindingStore = new KeyBindingStore(contextFactory, RulesetStore));
dependencies.Cache(SettingsStore = new SettingsStore(contextFactory)); dependencies.Cache(SettingsStore = new SettingsStore(contextFactory));
dependencies.Cache(RulesetConfigCache = new RulesetConfigCache(SettingsStore)); dependencies.Cache(RulesetConfigCache = new RulesetConfigCache(SettingsStore));
dependencies.Cache(new OsuColour()); dependencies.Cache(new OsuColour());
fileImporters.Add(BeatmapManager); fileImporters.Add(BeatmapManager);
fileImporters.Add(ScoreStore); fileImporters.Add(ScoreManager);
fileImporters.Add(SkinManager); fileImporters.Add(SkinManager);
var defaultBeatmap = new DummyWorkingBeatmap(this); var defaultBeatmap = new DummyWorkingBeatmap(this);

View File

@ -26,7 +26,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
private readonly Box background; private readonly Box background;
public DrawableScore(int index, APIScore score) public DrawableScore(int index, APIScoreInfo score)
{ {
ScoreModsContainer modsContainer; ScoreModsContainer modsContainer;

View File

@ -16,6 +16,7 @@ using osu.Game.Overlays.Profile.Sections.Ranks;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
using osu.Game.Screens.Select.Leaderboards; using osu.Game.Screens.Select.Leaderboards;
using osu.Game.Users; using osu.Game.Users;
@ -42,8 +43,8 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
private readonly InfoColumn statistics; private readonly InfoColumn statistics;
private readonly ScoreModsContainer modsContainer; private readonly ScoreModsContainer modsContainer;
private APIScore score; private APIScoreInfo score;
public APIScore Score public APIScoreInfo Score
{ {
get { return score; } get { return score; }
set set

View File

@ -29,10 +29,10 @@ namespace osu.Game.Overlays.BeatmapSet.Scores
set => loadingAnimation.FadeTo(value ? 1 : 0, fade_duration); set => loadingAnimation.FadeTo(value ? 1 : 0, fade_duration);
} }
private IEnumerable<APIScore> scores; private IEnumerable<APIScoreInfo> scores;
private BeatmapInfo beatmap; private BeatmapInfo beatmap;
public IEnumerable<APIScore> Scores public IEnumerable<APIScoreInfo> Scores
{ {
get { return scores; } get { return scores; }
set set

View File

@ -174,7 +174,7 @@ namespace osu.Game.Overlays.Direct
}; };
} }
private void setAdded(BeatmapSetInfo s) => Schedule(() => private void setAdded(BeatmapSetInfo s, bool existing) => Schedule(() =>
{ {
if (s.OnlineBeatmapSetID == SetInfo.OnlineBeatmapSetID) if (s.OnlineBeatmapSetID == SetInfo.OnlineBeatmapSetID)
progressBar.FadeOut(500); progressBar.FadeOut(500);

View File

@ -75,7 +75,7 @@ namespace osu.Game.Overlays.Music
[BackgroundDependencyLoader] [BackgroundDependencyLoader]
private void load(BeatmapManager beatmaps, IBindableBeatmap beatmap) private void load(BeatmapManager beatmaps, IBindableBeatmap beatmap)
{ {
beatmaps.GetAllUsableBeatmapSets().ForEach(addBeatmapSet); beatmaps.GetAllUsableBeatmapSets().ForEach(b => addBeatmapSet(b, false));
beatmaps.ItemAdded += addBeatmapSet; beatmaps.ItemAdded += addBeatmapSet;
beatmaps.ItemRemoved += removeBeatmapSet; beatmaps.ItemRemoved += removeBeatmapSet;
@ -83,8 +83,11 @@ namespace osu.Game.Overlays.Music
beatmapBacking.ValueChanged += _ => updateSelectedSet(); beatmapBacking.ValueChanged += _ => updateSelectedSet();
} }
private void addBeatmapSet(BeatmapSetInfo obj) => Schedule(() => private void addBeatmapSet(BeatmapSetInfo obj, bool existing) => Schedule(() =>
{ {
if (existing)
return;
var newItem = new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) }; var newItem = new PlaylistItem(obj) { OnSelect = set => Selected?.Invoke(set) };
items.Add(newItem); items.Add(newItem);

View File

@ -214,7 +214,14 @@ namespace osu.Game.Overlays
beatmapSets.Insert(index, beatmapSetInfo); beatmapSets.Insert(index, beatmapSetInfo);
} }
private void handleBeatmapAdded(BeatmapSetInfo obj) => Schedule(() => beatmapSets.Add(obj)); private void handleBeatmapAdded(BeatmapSetInfo obj, bool existing)
{
if (existing)
return;
Schedule(() => beatmapSets.Add(obj));
}
private void handleBeatmapRemoved(BeatmapSetInfo obj) => Schedule(() => beatmapSets.RemoveAll(s => s.ID == obj.ID)); private void handleBeatmapRemoved(BeatmapSetInfo obj) => Schedule(() => beatmapSets.RemoveAll(s => s.ID == obj.ID));
protected override void LoadComplete() protected override void LoadComplete()

View File

@ -5,7 +5,7 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Scoring; using osu.Game.Scoring;
namespace osu.Game.Overlays.Profile.Sections.Ranks namespace osu.Game.Overlays.Profile.Sections.Ranks
{ {
@ -13,7 +13,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
{ {
private readonly double? weight; private readonly double? weight;
public DrawablePerformanceScore(Score score, double? weight = null) public DrawablePerformanceScore(ScoreInfo score, double? weight = null)
: base(score) : base(score)
{ {
this.weight = weight; this.weight = weight;

View File

@ -8,17 +8,17 @@ using osu.Game.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Screens.Select.Leaderboards; using osu.Game.Screens.Select.Leaderboards;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
namespace osu.Game.Overlays.Profile.Sections.Ranks namespace osu.Game.Overlays.Profile.Sections.Ranks
{ {
public abstract class DrawableProfileScore : DrawableProfileRow public abstract class DrawableProfileScore : DrawableProfileRow
{ {
private readonly ScoreModsContainer modsContainer; private readonly ScoreModsContainer modsContainer;
protected readonly Score Score; protected readonly ScoreInfo Score;
protected DrawableProfileScore(Score score) protected DrawableProfileScore(ScoreInfo score)
{ {
Score = score; Score = score;

View File

@ -4,13 +4,13 @@
using osu.Framework.Allocation; using osu.Framework.Allocation;
using osu.Framework.Graphics; using osu.Framework.Graphics;
using osu.Game.Graphics.Sprites; using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Scoring; using osu.Game.Scoring;
namespace osu.Game.Overlays.Profile.Sections.Ranks namespace osu.Game.Overlays.Profile.Sections.Ranks
{ {
public class DrawableTotalScore : DrawableProfileScore public class DrawableTotalScore : DrawableProfileScore
{ {
public DrawableTotalScore(Score score) public DrawableTotalScore(ScoreInfo score)
: base(score) : base(score)
{ {
} }

View File

@ -37,7 +37,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
request.Success += scores => Schedule(() => request.Success += scores => Schedule(() =>
{ {
foreach (var s in scores) foreach (var s in scores)
s.ApplyRuleset(Rulesets.GetRuleset(s.OnlineRulesetID)); s.Ruleset = Rulesets.GetRuleset(s.RulesetID);
ShowMoreButton.FadeTo(scores.Count == ItemsPerPage ? 1 : 0); ShowMoreButton.FadeTo(scores.Count == ItemsPerPage ? 1 : 0);
ShowMoreLoading.Hide(); ShowMoreLoading.Hide();
@ -50,7 +50,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
MissingText.Hide(); MissingText.Hide();
foreach (APIScore score in scores) foreach (APIScoreInfo score in scores)
{ {
DrawableProfileScore drawableScore; DrawableProfileScore drawableScore;

View File

@ -71,7 +71,14 @@ namespace osu.Game.Overlays.Settings.Sections
} }
private void itemRemoved(SkinInfo s) => Schedule(() => skinDropdown.Items = skinDropdown.Items.Where(i => i.ID != s.ID).ToArray()); private void itemRemoved(SkinInfo s) => Schedule(() => skinDropdown.Items = skinDropdown.Items.Where(i => i.ID != s.ID).ToArray());
private void itemAdded(SkinInfo s) => Schedule(() => skinDropdown.Items = skinDropdown.Items.Append(s).ToArray());
private void itemAdded(SkinInfo s, bool existing)
{
if (existing)
return;
Schedule(() => skinDropdown.Items = skinDropdown.Items.Append(s).ToArray());
}
protected override void Dispose(bool isDisposing) protected override void Dispose(bool isDisposing)
{ {

View File

@ -1,9 +1,10 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>. // Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Replays;
using osuTK; using osuTK;
namespace osu.Game.Rulesets.Replays.Legacy namespace osu.Game.Replays.Legacy
{ {
public class LegacyReplayFrame : ReplayFrame public class LegacyReplayFrame : ReplayFrame
{ {

View File

@ -3,7 +3,7 @@
using System; using System;
namespace osu.Game.Rulesets.Replays.Legacy namespace osu.Game.Replays.Legacy
{ {
[Flags] [Flags]
public enum ReplayButtonState public enum ReplayButtonState

View File

@ -2,9 +2,10 @@
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE // Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Rulesets.Replays;
using osu.Game.Users; using osu.Game.Users;
namespace osu.Game.Rulesets.Replays namespace osu.Game.Replays
{ {
public class Replay public class Replay
{ {

View File

@ -66,7 +66,7 @@ namespace osu.Game.Rulesets.Difficulty
{ {
case 0: case 0:
// Initial-case: Empty current set // Initial-case: Empty current set
yield return new NoModMod(); yield return new ModNoMod();
break; break;
case 1: case 1:
yield return currentSet.Single(); yield return currentSet.Single();

View File

@ -7,7 +7,7 @@ using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Framework.Timing; using osu.Framework.Timing;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring; using osu.Game.Scoring;
namespace osu.Game.Rulesets.Difficulty namespace osu.Game.Rulesets.Difficulty
{ {
@ -17,11 +17,11 @@ namespace osu.Game.Rulesets.Difficulty
protected readonly Ruleset Ruleset; protected readonly Ruleset Ruleset;
protected readonly IBeatmap Beatmap; protected readonly IBeatmap Beatmap;
protected readonly Score Score; protected readonly ScoreInfo Score;
protected double TimeRate { get; private set; } = 1; protected double TimeRate { get; private set; } = 1;
protected PerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, Score score) protected PerformanceCalculator(Ruleset ruleset, WorkingBeatmap beatmap, ScoreInfo score)
{ {
Ruleset = ruleset; Ruleset = ruleset;
Score = score; Score = score;

View File

@ -0,0 +1,13 @@
// Copyright (c) 2007-2018 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
namespace osu.Game.Rulesets.Mods
{
public interface IMod
{
/// <summary>
/// The shortened name of this mod.
/// </summary>
string Acronym { get; }
}
}

View File

@ -3,57 +3,67 @@
using osu.Game.Graphics; using osu.Game.Graphics;
using System; using System;
using Newtonsoft.Json;
using osu.Game.IO.Serialization;
namespace osu.Game.Rulesets.Mods namespace osu.Game.Rulesets.Mods
{ {
/// <summary> /// <summary>
/// The base class for gameplay modifiers. /// The base class for gameplay modifiers.
/// </summary> /// </summary>
public abstract class Mod public abstract class Mod : IMod, IJsonSerializable
{ {
/// <summary> /// <summary>
/// The name of this mod. /// The name of this mod.
/// </summary> /// </summary>
[JsonIgnore]
public abstract string Name { get; } public abstract string Name { get; }
/// <summary> /// <summary>
/// The shortened name of this mod. /// The shortened name of this mod.
/// </summary> /// </summary>
public abstract string ShortenedName { get; } public abstract string Acronym { get; }
/// <summary> /// <summary>
/// The icon of this mod. /// The icon of this mod.
/// </summary> /// </summary>
[JsonIgnore]
public virtual FontAwesome Icon => FontAwesome.fa_question; public virtual FontAwesome Icon => FontAwesome.fa_question;
/// <summary> /// <summary>
/// The type of this mod. /// The type of this mod.
/// </summary> /// </summary>
[JsonIgnore]
public virtual ModType Type => ModType.Fun; public virtual ModType Type => ModType.Fun;
/// <summary> /// <summary>
/// The user readable description of this mod. /// The user readable description of this mod.
/// </summary> /// </summary>
[JsonIgnore]
public virtual string Description => string.Empty; public virtual string Description => string.Empty;
/// <summary> /// <summary>
/// The score multiplier of this mod. /// The score multiplier of this mod.
/// </summary> /// </summary>
[JsonIgnore]
public abstract double ScoreMultiplier { get; } public abstract double ScoreMultiplier { get; }
/// <summary> /// <summary>
/// Returns true if this mod is implemented (and playable). /// Returns true if this mod is implemented (and playable).
/// </summary> /// </summary>
[JsonIgnore]
public virtual bool HasImplementation => this is IApplicableMod; public virtual bool HasImplementation => this is IApplicableMod;
/// <summary> /// <summary>
/// Returns if this mod is ranked. /// Returns if this mod is ranked.
/// </summary> /// </summary>
[JsonIgnore]
public virtual bool Ranked => false; public virtual bool Ranked => false;
/// <summary> /// <summary>
/// The mods this mod cannot be enabled with. /// The mods this mod cannot be enabled with.
/// </summary> /// </summary>
[JsonIgnore]
public virtual Type[] IncompatibleMods => new Type[] { }; public virtual Type[] IncompatibleMods => new Type[] { };
} }
} }

View File

@ -4,10 +4,10 @@
using System; using System;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Graphics; using osu.Game.Graphics;
using osu.Game.Replays;
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
namespace osu.Game.Rulesets.Mods namespace osu.Game.Rulesets.Mods
{ {
@ -24,7 +24,7 @@ namespace osu.Game.Rulesets.Mods
public abstract class ModAutoplay : Mod, IApplicableFailOverride public abstract class ModAutoplay : Mod, IApplicableFailOverride
{ {
public override string Name => "Autoplay"; public override string Name => "Autoplay";
public override string ShortenedName => "AT"; public override string Acronym => "AT";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_auto; public override FontAwesome Icon => FontAwesome.fa_osu_mod_auto;
public override ModType Type => ModType.Automation; public override ModType Type => ModType.Automation;
public override string Description => "Watch a perfect automated play through the song."; public override string Description => "Watch a perfect automated play through the song.";

Some files were not shown because too many files have changed in this diff Show More