1
0
mirror of https://github.com/ppy/osu.git synced 2025-02-16 17:03:18 +08:00

Merge remote-tracking branch 'upstream/master' into optimise-leaderboards

This commit is contained in:
Dean Herbert 2017-11-17 17:28:01 +09:00
commit ea487861f8
19 changed files with 125 additions and 89 deletions

View File

@ -14,11 +14,8 @@ namespace osu.Game.Rulesets.Catch
{ {
} }
protected override double CalculateInternal(Dictionary<string, string> categoryDifficulty) public override double Calculate(Dictionary<string, string> categoryDifficulty = null) => 0;
{
return 0;
}
protected override BeatmapConverter<CatchBaseHit> CreateBeatmapConverter() => new CatchBeatmapConverter(); protected override BeatmapConverter<CatchBaseHit> CreateBeatmapConverter(Beatmap beatmap) => new CatchBeatmapConverter();
} }
} }

View File

@ -95,7 +95,7 @@ namespace osu.Game.Rulesets.Catch
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_fruits_o }; public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_fruits_o };
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new CatchDifficultyCalculator(beatmap); public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new CatchDifficultyCalculator(beatmap);
public override int LegacyID => 2; public override int LegacyID => 2;

View File

@ -16,11 +16,8 @@ namespace osu.Game.Rulesets.Mania
{ {
} }
protected override double CalculateInternal(Dictionary<string, string> categoryDifficulty) public override double Calculate(Dictionary<string, string> categoryDifficulty = null) => 0;
{
return 0;
}
protected override BeatmapConverter<ManiaHitObject> CreateBeatmapConverter() => new ManiaBeatmapConverter(true, (int)Math.Max(1, Math.Round(Beatmap.BeatmapInfo.BaseDifficulty.CircleSize))); protected override BeatmapConverter<ManiaHitObject> CreateBeatmapConverter(Beatmap beatmap) => new ManiaBeatmapConverter(true, (int)Math.Max(1, Math.Round(beatmap.BeatmapInfo.BaseDifficulty.CircleSize)));
} }
} }

View File

@ -107,7 +107,7 @@ namespace osu.Game.Rulesets.Mania
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_mania_o }; public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_mania_o };
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new ManiaDifficultyCalculator(beatmap); public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new ManiaDifficultyCalculator(beatmap);
public override int LegacyID => 3; public override int LegacyID => 3;

View File

@ -86,7 +86,7 @@ namespace osu.Game.Rulesets.Mania.Mods
public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) }; public override Type[] IncompatibleMods => new[] { typeof(ModFlashlight) };
} }
public class ManiaModRandom : Mod, IApplicableMod<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 ShortenedName => "RD";
@ -97,7 +97,6 @@ namespace osu.Game.Rulesets.Mania.Mods
public void ApplyToRulesetContainer(RulesetContainer<ManiaHitObject> rulesetContainer) public void ApplyToRulesetContainer(RulesetContainer<ManiaHitObject> rulesetContainer)
{ {
int availableColumns = ((ManiaRulesetContainer)rulesetContainer).AvailableColumns; int availableColumns = ((ManiaRulesetContainer)rulesetContainer).AvailableColumns;
var shuffledColumns = Enumerable.Range(0, availableColumns).OrderBy(item => RNG.Next()).ToList(); var shuffledColumns = Enumerable.Range(0, availableColumns).OrderBy(item => RNG.Next()).ToList();
rulesetContainer.Objects.OfType<ManiaHitObject>().ForEach(h => h.Column = shuffledColumns[h.Column]); rulesetContainer.Objects.OfType<ManiaHitObject>().ForEach(h => h.Column = shuffledColumns[h.Column]);
@ -188,6 +187,7 @@ namespace osu.Game.Rulesets.Mania.Mods
base.ApplyToRulesetContainer(rulesetContainer); base.ApplyToRulesetContainer(rulesetContainer);
} }
protected override Score CreateReplayScore(Beatmap<ManiaHitObject> beatmap) => new Score protected override Score CreateReplayScore(Beatmap<ManiaHitObject> beatmap) => new Score
{ {
User = new User { Username = "osu!topus!" }, User = new User { Username = "osu!topus!" },

View File

@ -9,7 +9,6 @@ using osu.Game.Rulesets.Osu.Objects;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using osu.Framework.Extensions.IEnumerableExtensions;
using osu.Game.Rulesets.Osu.UI; using osu.Game.Rulesets.Osu.UI;
using osu.Game.Rulesets.Scoring; using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI; using osu.Game.Rulesets.UI;
@ -33,22 +32,29 @@ namespace osu.Game.Rulesets.Osu.Mods
public override double ScoreMultiplier => 1.06; public override double ScoreMultiplier => 1.06;
} }
public class OsuModHardRock : ModHardRock, IApplicableMod<OsuHitObject> public class OsuModHardRock : ModHardRock, IApplicableToHitObject<OsuHitObject>
{ {
public override double ScoreMultiplier => 1.06; public override double ScoreMultiplier => 1.06;
public override bool Ranked => true; public override bool Ranked => true;
public void ApplyToRulesetContainer(RulesetContainer<OsuHitObject> rulesetContainer) public void ApplyToHitObject(OsuHitObject hitObject)
{
hitObject.Position = new Vector2(hitObject.Position.X, OsuPlayfield.BASE_SIZE.Y - hitObject.Y);
var slider = hitObject as Slider;
if (slider == null)
return;
var newControlPoints = new List<Vector2>();
slider.ControlPoints.ForEach(c => newControlPoints.Add(new Vector2(c.X, OsuPlayfield.BASE_SIZE.Y - c.Y)));
slider.ControlPoints = newControlPoints;
slider.Curve?.Calculate(); // Recalculate the slider curve
}
public void ApplyToHitObjects(RulesetContainer<OsuHitObject> rulesetContainer)
{ {
rulesetContainer.Objects.OfType<OsuHitObject>().ForEach(h => h.Position = new Vector2(h.Position.X, OsuPlayfield.BASE_SIZE.Y - h.Y));
rulesetContainer.Objects.OfType<Slider>().ForEach(s =>
{
var newControlPoints = new List<Vector2>();
s.ControlPoints.ForEach(c => newControlPoints.Add(new Vector2(c.X, OsuPlayfield.BASE_SIZE.Y - c.Y)));
s.ControlPoints = newControlPoints;
s.Curve?.Calculate(); // Recalculate the slider curve
});
} }
} }

View File

@ -4,6 +4,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Beatmaps; using osu.Game.Rulesets.Osu.Beatmaps;
using osu.Game.Rulesets.Osu.Objects; using osu.Game.Rulesets.Osu.Objects;
using osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing; using osu.Game.Rulesets.Osu.OsuDifficulty.Preprocessing;
@ -16,19 +17,25 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty
private const int section_length = 400; private const int section_length = 400;
private const double difficulty_multiplier = 0.0675; private const double difficulty_multiplier = 0.0675;
public OsuDifficultyCalculator(Beatmap beatmap) : base(beatmap) public OsuDifficultyCalculator(Beatmap beatmap)
: base(beatmap)
{
}
public OsuDifficultyCalculator(Beatmap beatmap, Mod[] mods)
: base(beatmap, mods)
{ {
} }
protected override void PreprocessHitObjects() protected override void PreprocessHitObjects()
{ {
foreach (OsuHitObject h in Objects) foreach (OsuHitObject h in Beatmap.HitObjects)
(h as Slider)?.Curve?.Calculate(); (h as Slider)?.Curve?.Calculate();
} }
protected override double CalculateInternal(Dictionary<string, string> categoryDifficulty) public override double Calculate(Dictionary<string, string> categoryDifficulty = null)
{ {
OsuDifficultyBeatmap beatmap = new OsuDifficultyBeatmap(Objects); OsuDifficultyBeatmap beatmap = new OsuDifficultyBeatmap(Beatmap.HitObjects);
Skill[] skills = Skill[] skills =
{ {
new Aim(), new Aim(),
@ -67,6 +74,6 @@ namespace osu.Game.Rulesets.Osu.OsuDifficulty
return starRating; return starRating;
} }
protected override BeatmapConverter<OsuHitObject> CreateBeatmapConverter() => new OsuBeatmapConverter(); protected override BeatmapConverter<OsuHitObject> CreateBeatmapConverter(Beatmap beatmap) => new OsuBeatmapConverter();
} }
} }

View File

@ -112,7 +112,7 @@ namespace osu.Game.Rulesets.Osu
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_osu_o }; public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_osu_o };
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new OsuDifficultyCalculator(beatmap); public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new OsuDifficultyCalculator(beatmap, mods);
public override string Description => "osu!"; public override string Description => "osu!";

View File

@ -36,12 +36,12 @@ namespace osu.Game.Rulesets.Taiko
{ {
} }
protected override double CalculateInternal(Dictionary<string, string> categoryDifficulty) public override double Calculate(Dictionary<string, string> categoryDifficulty = null)
{ {
// Fill our custom DifficultyHitObject class, that carries additional information // Fill our custom DifficultyHitObject class, that carries additional information
difficultyHitObjects.Clear(); difficultyHitObjects.Clear();
foreach (var hitObject in Objects) foreach (var hitObject in Beatmap.HitObjects)
difficultyHitObjects.Add(new TaikoHitObjectDifficulty(hitObject)); difficultyHitObjects.Add(new TaikoHitObjectDifficulty(hitObject));
// Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure. // Sort DifficultyHitObjects by StartTime of the HitObjects - just to make sure.
@ -134,6 +134,6 @@ namespace osu.Game.Rulesets.Taiko
return difficulty; return difficulty;
} }
protected override BeatmapConverter<TaikoHitObject> CreateBeatmapConverter() => new TaikoBeatmapConverter(true); protected override BeatmapConverter<TaikoHitObject> CreateBeatmapConverter(Beatmap beatmap) => new TaikoBeatmapConverter(true);
} }
} }

View File

@ -97,7 +97,7 @@ namespace osu.Game.Rulesets.Taiko
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_taiko_o }; public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_taiko_o };
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new TaikoDifficultyCalculator(beatmap); public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => new TaikoDifficultyCalculator(beatmap);
public override int LegacyID => 1; public override int LegacyID => 1;

View File

@ -3,6 +3,10 @@
using osu.Game.Rulesets.Objects; using osu.Game.Rulesets.Objects;
using System.Collections.Generic; using System.Collections.Generic;
using osu.Game.Rulesets.Mods;
using osu.Framework.Timing;
using System.Linq;
using osu.Framework.Extensions.IEnumerableExtensions;
namespace osu.Game.Beatmaps namespace osu.Game.Beatmaps
{ {
@ -10,45 +14,46 @@ namespace osu.Game.Beatmaps
{ {
protected double TimeRate = 1; protected double TimeRate = 1;
protected abstract double CalculateInternal(Dictionary<string, string> categoryDifficulty); public abstract double Calculate(Dictionary<string, string> categoryDifficulty = null);
private void loadTiming()
{
// TODO: Handle mods
const int audio_rate = 100;
TimeRate = audio_rate / 100.0;
}
public double Calculate(Dictionary<string, string> categoryDifficulty = null)
{
loadTiming();
double difficulty = CalculateInternal(categoryDifficulty);
return difficulty;
}
} }
public abstract class DifficultyCalculator<T> : DifficultyCalculator where T : HitObject public abstract class DifficultyCalculator<T> : DifficultyCalculator where T : HitObject
{ {
protected readonly Beatmap Beatmap; protected readonly Beatmap<T> Beatmap;
protected readonly Mod[] Mods;
protected List<T> Objects; protected DifficultyCalculator(Beatmap beatmap, Mod[] mods = null)
protected DifficultyCalculator(Beatmap beatmap)
{ {
Beatmap = beatmap; Beatmap = CreateBeatmapConverter(beatmap).Convert(beatmap);
Mods = mods ?? new Mod[0];
Objects = CreateBeatmapConverter().Convert(beatmap).HitObjects;
foreach (var h in Objects) ApplyMods(Mods);
h.ApplyDefaults(beatmap.ControlPointInfo, beatmap.BeatmapInfo.BaseDifficulty);
PreprocessHitObjects(); PreprocessHitObjects();
} }
protected virtual void ApplyMods(Mod[] mods)
{
var clock = new StopwatchClock();
mods.OfType<IApplicableToClock>().ForEach(m => m.ApplyToClock(clock));
TimeRate = clock.Rate;
foreach (var mod in Mods.OfType<IApplicableToDifficulty>())
mod.ApplyToDifficulty(Beatmap.BeatmapInfo.BaseDifficulty);
foreach (var mod in mods.OfType<IApplicableToHitObject<T>>())
foreach (var obj in Beatmap.HitObjects)
mod.ApplyToHitObject(obj);
foreach (var h in Beatmap.HitObjects)
h.ApplyDefaults(Beatmap.ControlPointInfo, Beatmap.BeatmapInfo.BaseDifficulty);
}
protected virtual void PreprocessHitObjects() protected virtual void PreprocessHitObjects()
{ {
} }
protected abstract BeatmapConverter<T> CreateBeatmapConverter(); protected abstract BeatmapConverter<T> CreateBeatmapConverter(Beatmap beatmap);
} }
} }

View File

@ -59,7 +59,7 @@ namespace osu.Game.Beatmaps
throw new NotImplementedException(); throw new NotImplementedException();
} }
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => null; public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null) => null;
public override string Description => "dummy"; public override string Description => "dummy";

View File

@ -1,22 +0,0 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Mods
{
/// <summary>
/// An interface for mods that are applied to a RulesetContainer.
/// </summary>
/// <typeparam name="TObject">The type of HitObject the RulesetContainer contains.</typeparam>
public interface IApplicableMod<TObject>
where TObject : HitObject
{
/// <summary>
/// Applies the mod to a RulesetContainer.
/// </summary>
/// <param name="rulesetContainer">The RulesetContainer to apply the mod to.</param>
void ApplyToRulesetContainer(RulesetContainer<TObject> rulesetContainer);
}
}

View File

@ -0,0 +1,20 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Objects;
namespace osu.Game.Rulesets.Mods
{
/// <summary>
/// An interface for <see cref="Mod"/>s that can be applied to <see cref="HitObject"/>s.
/// </summary>
public interface IApplicableToHitObject<in TObject>
where TObject : HitObject
{
/// <summary>
/// Applies this <see cref="IApplicableToHitObject{TObject}"/> to a <see cref="HitObject"/>.
/// </summary>
/// <param name="hitObject">The <see cref="HitObject"/> to apply to.</param>
void ApplyToHitObject(TObject hitObject);
}
}

View File

@ -0,0 +1,21 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Mods
{
/// <summary>
/// An interface for <see cref="Mod"/>s that can be applied to <see cref="RulesetContainer"/>s.
/// </summary>
public interface IApplicableToRulesetContainer<TObject>
where TObject : HitObject
{
/// <summary>
/// Applies this <see cref="IApplicableToRulesetContainer{TObject}"/> to a <see cref="RulesetContainer{TObject}"/>.
/// </summary>
/// <param name="rulesetContainer">The <see cref="RulesetContainer{TObject}"/> to apply to.</param>
void ApplyToRulesetContainer(RulesetContainer<TObject> rulesetContainer);
}
}

View File

@ -10,7 +10,7 @@ using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets.Mods namespace osu.Game.Rulesets.Mods
{ {
public abstract class ModAutoplay<T> : ModAutoplay, IApplicableMod<T> public abstract class ModAutoplay<T> : ModAutoplay, IApplicableToRulesetContainer<T>
where T : HitObject where T : HitObject
{ {
protected abstract Score CreateReplayScore(Beatmap<T> beatmap); protected abstract Score CreateReplayScore(Beatmap<T> beatmap);

View File

@ -47,7 +47,7 @@ namespace osu.Game.Rulesets
/// <returns></returns> /// <returns></returns>
public abstract RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset); public abstract RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset);
public abstract DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap); public abstract DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap, Mod[] mods = null);
public virtual Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_question_circle }; public virtual Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_question_circle };

View File

@ -212,7 +212,11 @@ namespace osu.Game.Rulesets.UI
if (mods == null) if (mods == null)
return; return;
foreach (var mod in mods.OfType<IApplicableMod<TObject>>()) foreach (var mod in mods.OfType<IApplicableToHitObject<TObject>>())
foreach (var obj in Beatmap.HitObjects)
mod.ApplyToHitObject(obj);
foreach (var mod in mods.OfType<IApplicableToRulesetContainer<TObject>>())
mod.ApplyToRulesetContainer(this); mod.ApplyToRulesetContainer(this);
} }

View File

@ -549,9 +549,10 @@
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Rulesets\Judgements\DrawableJudgement.cs" /> <Compile Include="Rulesets\Judgements\DrawableJudgement.cs" />
<Compile Include="Rulesets\Judgements\Judgement.cs" /> <Compile Include="Rulesets\Judgements\Judgement.cs" />
<Compile Include="Rulesets\Mods\IApplicableMod.cs" />
<Compile Include="Rulesets\Mods\IApplicableToClock.cs" /> <Compile Include="Rulesets\Mods\IApplicableToClock.cs" />
<Compile Include="Rulesets\Mods\IApplicableToDifficulty.cs" /> <Compile Include="Rulesets\Mods\IApplicableToDifficulty.cs" />
<Compile Include="Rulesets\Mods\IApplicableToHitObject.cs" />
<Compile Include="Rulesets\Mods\IApplicableToRulesetContainer.cs" />
<Compile Include="Rulesets\Mods\Mod.cs" /> <Compile Include="Rulesets\Mods\Mod.cs" />
<Compile Include="Rulesets\Mods\ModAutoplay.cs" /> <Compile Include="Rulesets\Mods\ModAutoplay.cs" />
<Compile Include="Rulesets\Mods\ModCinema.cs" /> <Compile Include="Rulesets\Mods\ModCinema.cs" />