1
0
mirror of https://github.com/ppy/osu.git synced 2024-09-22 10:07:36 +08:00

Merge branch 'master' into beatmap-details-rewrite

This commit is contained in:
Dean Herbert 2017-09-10 11:26:00 +09:00 committed by GitHub
commit 6d33e39c5e
45 changed files with 374 additions and 238 deletions

@ -1 +1 @@
Subproject commit 5f2d5a57e5d506d7e5d87eeeb442adf10be061f6
Subproject commit 4e7ea6af4f59f21f6afc522fb063c05417e1a5fe

View File

@ -41,12 +41,14 @@ namespace osu.Desktop.Tests.Visual
{
new BeatmapSetInfo
{
OnlineBeatmapSetID = 578332,
Metadata = new BeatmapMetadata
{
Title = @"OrVid",
Artist = @"An",
Author = @"RLC",
Source = @"",
Tags = @"acuticnotes an-fillnote revid tear tearvid encrpted encryption axi axivid quad her hervid recoll",
},
OnlineInfo = new BeatmapSetOnlineInfo
{
@ -71,12 +73,14 @@ namespace osu.Desktop.Tests.Visual
},
new BeatmapSetInfo
{
OnlineBeatmapSetID = 599627,
Metadata = new BeatmapMetadata
{
Title = @"tiny lamp",
Artist = @"fhana",
Author = @"Sotarks",
Source = @"ぎんぎつね",
Tags = @"lantis junichi sato yuxuki waga kevin mitsunaga towana gingitsune opening op full ver version kalibe collab collaboration",
},
OnlineInfo = new BeatmapSetOnlineInfo
{
@ -101,12 +105,14 @@ namespace osu.Desktop.Tests.Visual
},
new BeatmapSetInfo
{
OnlineBeatmapSetID = 513268,
Metadata = new BeatmapMetadata
{
Title = @"At Gwanghwamun",
Artist = @"KYUHYUN",
Author = @"Cerulean Veyron",
Source = @"",
Tags = @"soul ballad kh super junior sj suju 슈퍼주니어 kt뮤직 sm엔터테인먼트 s.m.entertainment kt music 1st mini album ep",
},
OnlineInfo = new BeatmapSetOnlineInfo
{
@ -146,12 +152,14 @@ namespace osu.Desktop.Tests.Visual
},
new BeatmapSetInfo
{
OnlineBeatmapSetID = 586841,
Metadata = new BeatmapMetadata
{
Title = @"RHAPSODY OF BLUE SKY",
Artist = @"fhana",
Author = @"[Kamiya]",
Source = @"小林さんちのメイドラゴン",
Tags = @"kobayashi san chi no maidragon aozora no opening anime maid dragon oblivion karen dynamix imoutosan pata-mon gxytcgxytc",
},
OnlineInfo = new BeatmapSetOnlineInfo
{

View File

@ -1,13 +1,13 @@
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
// Licensed under the MIT Licence - https://raw.githubusercontent.com/ppy/osu/master/LICENCE
using OpenTK;
using osu.Framework.Graphics;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Screens.Select.Leaderboards;
using osu.Game.Users;
using OpenTK;
namespace osu.Desktop.Tests.Visual
{
@ -24,7 +24,7 @@ namespace osu.Desktop.Tests.Visual
new Score
{
Rank = ScoreRank.XH,
Accuracy = 100,
Accuracy = 1,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
@ -42,7 +42,7 @@ namespace osu.Desktop.Tests.Visual
new Score
{
Rank = ScoreRank.X,
Accuracy = 100,
Accuracy = 1,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
@ -60,7 +60,7 @@ namespace osu.Desktop.Tests.Visual
new Score
{
Rank = ScoreRank.SH,
Accuracy = 100,
Accuracy = 1,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
@ -78,7 +78,7 @@ namespace osu.Desktop.Tests.Visual
new Score
{
Rank = ScoreRank.S,
Accuracy = 100,
Accuracy = 1,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
@ -96,7 +96,7 @@ namespace osu.Desktop.Tests.Visual
new Score
{
Rank = ScoreRank.A,
Accuracy = 100,
Accuracy = 1,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
@ -114,7 +114,7 @@ namespace osu.Desktop.Tests.Visual
new Score
{
Rank = ScoreRank.B,
Accuracy = 98.26,
Accuracy = 0.9826,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
@ -132,7 +132,7 @@ namespace osu.Desktop.Tests.Visual
new Score
{
Rank = ScoreRank.C,
Accuracy = 96.54,
Accuracy = 0.9654,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
@ -150,7 +150,7 @@ namespace osu.Desktop.Tests.Visual
new Score
{
Rank = ScoreRank.F,
Accuracy = 60.25,
Accuracy = 0.6025,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
@ -168,7 +168,7 @@ namespace osu.Desktop.Tests.Visual
new Score
{
Rank = ScoreRank.F,
Accuracy = 51.40,
Accuracy = 0.5140,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
@ -186,7 +186,7 @@ namespace osu.Desktop.Tests.Visual
new Score
{
Rank = ScoreRank.F,
Accuracy = 42.22,
Accuracy = 0.4222,
MaxCombo = 244,
TotalScore = 1707827,
Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },

View File

@ -32,7 +32,7 @@ namespace osu.Desktop.Tests.Visual
backingDatabase.CreateTable<StoreVersion>();
rulesets = new RulesetStore(backingDatabase);
manager = new BeatmapManager(storage, null, backingDatabase, rulesets);
manager = new BeatmapManager(storage, null, backingDatabase, rulesets, null);
for (int i = 0; i < 100; i += 10)
manager.Import(createTestBeatmapSet(i));

View File

@ -93,8 +93,6 @@ namespace osu.Game.Rulesets.Catch
}
}
public override Mod GetAutoplayMod() => new ModAutoplay();
public override string Description => "osu!catch";
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_fruits_o };

View File

@ -105,8 +105,6 @@ namespace osu.Game.Rulesets.Mania
}
}
public override Mod GetAutoplayMod() => new ModAutoplay();
public override string Description => "osu!mania";
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_mania_o };

View File

@ -68,6 +68,7 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModFadeIn : Mod
{
public override string Name => "FadeIn";
public override string ShortenedName => "FI";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden;
public override ModType Type => ModType.DifficultyIncrease;
public override double ScoreMultiplier => 1;
@ -78,12 +79,14 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModRandom : Mod
{
public override string Name => "Random";
public override string ShortenedName => "RD";
public override string Description => @"Shuffle around the notes!";
public override double ScoreMultiplier => 1;
}
public abstract class ManiaKeyMod : Mod
{
public override string ShortenedName => Name;
public abstract int KeyCount { get; }
public override double ScoreMultiplier => 1; // TODO: Implement the mania key mod score multiplier
public override bool Ranked => true;
@ -146,6 +149,7 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModKeyCoop : Mod
{
public override string Name => "KeyCoop";
public override string ShortenedName => "2P";
public override string Description => @"Double the key amount, double the fun!";
public override double ScoreMultiplier => 1;
public override bool Ranked => true;

View File

@ -15,6 +15,7 @@ namespace osu.Game.Rulesets.Mania.Mods
public class ManiaModGravity : Mod, IGenerateSpeedAdjustments
{
public override string Name => "Gravity";
public override string ShortenedName => "GR";
public override double ScoreMultiplier => 0;

View File

@ -96,6 +96,7 @@ namespace osu.Game.Rulesets.Osu.Mods
public class OsuModSpunOut : Mod
{
public override string Name => "Spun Out";
public override string ShortenedName => "SO";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_spunout;
public override string Description => @"Spinners will be automatically completed";
public override double ScoreMultiplier => 0.9;
@ -106,6 +107,7 @@ namespace osu.Game.Rulesets.Osu.Mods
public class OsuModAutopilot : Mod
{
public override string Name => "Autopilot";
public override string ShortenedName => "AP";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_autopilot;
public override string Description => @"Automatic cursor movement - just follow the rhythm.";
public override double ScoreMultiplier => 0;
@ -126,6 +128,7 @@ namespace osu.Game.Rulesets.Osu.Mods
public class OsuModTarget : Mod
{
public override string Name => "Target";
public override string ShortenedName => "TP";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_target;
public override string Description => @"";
public override double ScoreMultiplier => 1;

View File

@ -112,8 +112,6 @@ namespace osu.Game.Rulesets.Osu
}
}
public override Mod GetAutoplayMod() => new OsuModAutoplay();
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_osu_o };
public override DifficultyCalculator CreateDifficultyCalculator(Beatmap beatmap) => new OsuDifficultyCalculator(beatmap);

View File

@ -95,8 +95,6 @@ namespace osu.Game.Rulesets.Taiko
}
}
public override Mod GetAutoplayMod() => new TaikoModAutoplay();
public override string Description => "osu!taiko";
public override Drawable CreateIcon() => new SpriteIcon { Icon = FontAwesome.fa_osu_taiko_o };

View File

@ -17,7 +17,7 @@ namespace osu.Game.Beatmaps
public class Beatmap<T>
where T : HitObject
{
public BeatmapInfo BeatmapInfo;
public BeatmapInfo BeatmapInfo = new BeatmapInfo();
public ControlPointInfo ControlPointInfo = new ControlPointInfo();
public List<BreakPeriod> Breaks = new List<BreakPeriod>();
public readonly List<Color4> ComboColors = new List<Color4>
@ -33,7 +33,7 @@ namespace osu.Game.Beatmaps
/// <summary>
/// The HitObjects this Beatmap contains.
/// </summary>
public List<T> HitObjects;
public List<T> HitObjects = new List<T>();
/// <summary>
/// Total amount of break time in the beatmap.
@ -44,12 +44,13 @@ namespace osu.Game.Beatmaps
/// Constructs a new beatmap.
/// </summary>
/// <param name="original">The original beatmap to use the parameters of.</param>
public Beatmap(Beatmap original = null)
public Beatmap(Beatmap<T> original = null)
{
BeatmapInfo = original?.BeatmapInfo.DeepClone() ?? BeatmapInfo;
ControlPointInfo = original?.ControlPointInfo ?? ControlPointInfo;
Breaks = original?.Breaks ?? Breaks;
ComboColors = original?.ComboColors ?? ComboColors;
HitObjects = original?.HitObjects ?? HitObjects;
}
}
@ -65,7 +66,6 @@ namespace osu.Game.Beatmaps
public Beatmap(Beatmap original = null)
: base(original)
{
HitObjects = original?.HitObjects;
}
}
}

View File

@ -20,6 +20,9 @@ using osu.Game.IPC;
using osu.Game.Overlays.Notifications;
using osu.Game.Rulesets;
using SQLite.Net;
using osu.Game.Online.API.Requests;
using System.Threading.Tasks;
using osu.Game.Online.API;
namespace osu.Game.Beatmaps
{
@ -63,6 +66,10 @@ namespace osu.Game.Beatmaps
private readonly BeatmapStore beatmaps;
private readonly APIAccess api;
private readonly List<DownloadBeatmapSetRequest> currentDownloads = new List<DownloadBeatmapSetRequest>();
// ReSharper disable once NotAccessedField.Local (we should keep a reference to this so it is not finalised)
private BeatmapIPCChannel ipc;
@ -76,7 +83,7 @@ namespace osu.Game.Beatmaps
/// </summary>
public Func<Storage> GetStableStorage { private get; set; }
public BeatmapManager(Storage storage, FileStore files, SQLiteConnection connection, RulesetStore rulesets, IIpcHost importHost = null)
public BeatmapManager(Storage storage, FileStore files, SQLiteConnection connection, RulesetStore rulesets, APIAccess api, IIpcHost importHost = null)
{
beatmaps = new BeatmapStore(connection);
beatmaps.BeatmapSetAdded += s => BeatmapSetAdded?.Invoke(s);
@ -88,6 +95,7 @@ namespace osu.Game.Beatmaps
this.files = files;
this.connection = connection;
this.rulesets = rulesets;
this.api = api;
if (importHost != null)
ipc = new BeatmapIPCChannel(importHost, this);
@ -177,6 +185,74 @@ namespace osu.Game.Beatmaps
beatmaps.Add(beatmapSetInfo);
}
/// <summary>
/// Downloads a beatmap.
/// </summary>
/// <param name="beatmapSetInfo">The <see cref="BeatmapSetInfo"/> to be downloaded.</param>
/// <returns>A new <see cref="DownloadBeatmapSetRequest"/>, or an existing one if a download is already in progress.</returns>
public DownloadBeatmapSetRequest Download(BeatmapSetInfo beatmapSetInfo)
{
var existing = GetExistingDownload(beatmapSetInfo);
if (existing != null) return existing;
if (api == null) return null;
ProgressNotification downloadNotification = new ProgressNotification
{
Text = $"Downloading {beatmapSetInfo.Metadata.Artist} - {beatmapSetInfo.Metadata.Title}",
};
var request = new DownloadBeatmapSetRequest(beatmapSetInfo);
request.DownloadProgressed += progress =>
{
downloadNotification.State = ProgressNotificationState.Active;
downloadNotification.Progress = progress;
};
request.Success += data =>
{
downloadNotification.State = ProgressNotificationState.Completed;
using (var stream = new MemoryStream(data))
using (var archive = new OszArchiveReader(stream))
Import(archive);
currentDownloads.Remove(request);
};
request.Failure += data =>
{
downloadNotification.State = ProgressNotificationState.Completed;
Logger.Error(data, "Failed to get beatmap download information");
currentDownloads.Remove(request);
};
downloadNotification.CancelRequested += () =>
{
request.Cancel();
currentDownloads.Remove(request);
downloadNotification.State = ProgressNotificationState.Cancelled;
return true;
};
currentDownloads.Add(request);
PostNotification?.Invoke(downloadNotification);
// don't run in the main api queue as this is a long-running task.
Task.Run(() => request.Perform(api));
return request;
}
/// <summary>
/// Get an existing download request if it exists.
/// </summary>
/// <param name="beatmap">The <see cref="BeatmapSetInfo"/> whose download request is wanted.</param>
/// <returns>The <see cref="DownloadBeatmapSetRequest"/> object if it exists, or null.</returns>
public DownloadBeatmapSetRequest GetExistingDownload(BeatmapSetInfo beatmap) => currentDownloads.Find(d => d.BeatmapSet.OnlineBeatmapSetID == beatmap.OnlineBeatmapSetID);
/// <summary>
/// Delete a beatmap from the manager.
/// Is a no-op for already deleted beatmaps.

View File

@ -7,7 +7,6 @@ using osu.Framework.Audio.Track;
using osu.Framework.Graphics.Textures;
using osu.Game.Rulesets;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
@ -42,10 +41,7 @@ namespace osu.Game.Beatmaps
this.game = game;
}
protected override Beatmap GetBeatmap() => new Beatmap
{
HitObjects = new List<HitObject>(),
};
protected override Beatmap GetBeatmap() => new Beatmap();
protected override Texture GetBackground() => game.Textures.Get(@"Backgrounds/bg4");
@ -59,8 +55,6 @@ namespace osu.Game.Beatmaps
{
public override IEnumerable<Mod> GetModsFor(ModType type) => new Mod[] { };
public override Mod GetAutoplayMod() => new ModAutoplay();
public override RulesetContainer CreateRulesetContainerWith(WorkingBeatmap beatmap, bool isForCurrentRuleset)
{
throw new NotImplementedException();

View File

@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using osu.Game.Rulesets.Objects;
namespace osu.Game.Beatmaps.Formats
{
@ -21,7 +20,7 @@ namespace osu.Game.Beatmaps.Formats
{
string line;
do { line = stream.ReadLine()?.Trim(); }
while (line != null && line.Length == 0);
while (line != null && line.Length == 0);
if (line == null || !decoders.ContainsKey(line))
throw new IOException(@"Unknown file format");
@ -47,7 +46,6 @@ namespace osu.Game.Beatmaps.Formats
{
var beatmap = new Beatmap
{
HitObjects = new List<HitObject>(),
BeatmapInfo = new BeatmapInfo
{
Metadata = new BeatmapMetadata(),

View File

@ -54,7 +54,7 @@ namespace osu.Game.Beatmaps
{
if (beatmap != null) return beatmap;
beatmap = GetBeatmap();
beatmap = GetBeatmap() ?? new Beatmap();
// use the database-backed info.
beatmap.BeatmapInfo = BeatmapInfo;

View File

@ -0,0 +1,24 @@
// 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.Beatmaps;
using System;
namespace osu.Game.Online.API.Requests
{
public class DownloadBeatmapSetRequest : APIDownloadRequest
{
public readonly BeatmapSetInfo BeatmapSet;
public Action<float> DownloadProgressed;
public DownloadBeatmapSetRequest(BeatmapSetInfo set)
{
BeatmapSet = set;
Progress += (current, total) => DownloadProgressed?.Invoke((float) current / total);
}
protected override string Target => $@"beatmapsets/{BeatmapSet.OnlineBeatmapSetID}/download";
}
}

View File

@ -1,10 +1,14 @@
// Copyright (c) 2007-2017 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.Linq;
using Newtonsoft.Json;
using osu.Framework.IO.Network;
using osu.Game.Beatmaps;
using osu.Game.Users;
using osu.Game.Rulesets.Replays;
using osu.Game.Rulesets.Scoring;
namespace osu.Game.Online.API.Requests
@ -16,6 +20,14 @@ namespace osu.Game.Online.API.Requests
public GetScoresRequest(BeatmapInfo beatmap)
{
this.beatmap = beatmap;
Success += onSuccess;
}
private void onSuccess(GetScoresResponse r)
{
foreach (OnlineScore score in r.Scores)
score.ApplyBeatmap(beatmap);
}
protected override WebRequest CreateWebRequest()
@ -32,6 +44,88 @@ namespace osu.Game.Online.API.Requests
public class GetScoresResponse
{
[JsonProperty(@"scores")]
public IEnumerable<Score> Scores;
public IEnumerable<OnlineScore> Scores;
}
public class OnlineScore : Score
{
[JsonProperty(@"score")]
private double totalScore
{
set { TotalScore = value; }
}
[JsonProperty(@"max_combo")]
private int maxCombo
{
set { MaxCombo = value; }
}
[JsonProperty(@"user")]
private User user
{
set { User = value; }
}
[JsonProperty(@"replay_data")]
private Replay replay
{
set { Replay = value; }
}
[JsonProperty(@"score_id")]
private long onlineScoreID
{
set { OnlineScoreID = value; }
}
[JsonProperty(@"created_at")]
private DateTimeOffset date
{
set { Date = value; }
}
[JsonProperty(@"statistics")]
private Dictionary<string, dynamic> jsonStats
{
set
{
foreach (var kvp in value)
{
string key = kvp.Key;
switch (key)
{
case @"count_300":
key = @"300";
break;
case @"count_100":
key = @"100";
break;
case @"count_50":
key = @"50";
break;
case @"count_miss":
key = @"x";
break;
default:
continue;
}
Statistics.Add(key, kvp.Value);
}
}
}
[JsonProperty(@"mods")]
private string[] modStrings { get; set; }
public void ApplyBeatmap(BeatmapInfo beatmap)
{
Beatmap = beatmap;
Ruleset = beatmap.Ruleset;
// Evaluate the mod string
Mods = Ruleset.CreateInstance().GetAllMods().Where(mod => modStrings.Contains(mod.ShortenedName)).ToArray();
}
}
}

View File

@ -245,7 +245,11 @@ namespace osu.Game
LoadComponentAsync(Toolbar = new Toolbar
{
Depth = -4,
OnHome = delegate { intro?.ChildScreen?.MakeCurrent(); },
OnHome = delegate
{
hideAllOverlays();
intro?.ChildScreen?.MakeCurrent();
},
}, overlayContent.Add);
settings.StateChanged += delegate
@ -310,6 +314,16 @@ namespace osu.Game
private OsuScreen currentScreen;
private FrameworkConfigManager frameworkConfig;
private void hideAllOverlays()
{
settings.State = Visibility.Hidden;
chat.State = Visibility.Hidden;
direct.State = Visibility.Hidden;
social.State = Visibility.Hidden;
userProfile.State = Visibility.Hidden;
notificationOverlay.State = Visibility.Hidden;
}
private void screenChanged(Screen newScreen)
{
currentScreen = newScreen as OsuScreen;
@ -323,19 +337,12 @@ namespace osu.Game
//central game screen change logic.
if (!currentScreen.ShowOverlays)
{
settings.State = Visibility.Hidden;
Toolbar.State = Visibility.Hidden;
hideAllOverlays();
musicController.State = Visibility.Hidden;
chat.State = Visibility.Hidden;
direct.State = Visibility.Hidden;
social.State = Visibility.Hidden;
userProfile.State = Visibility.Hidden;
notificationOverlay.State = Visibility.Hidden;
Toolbar.State = Visibility.Hidden;
}
else
{
Toolbar.State = Visibility.Visible;
}
ScreenChanged?.Invoke(newScreen);
}

View File

@ -106,9 +106,15 @@ namespace osu.Game
connection.CreateTable<StoreVersion>();
dependencies.Cache(API = new APIAccess
{
Username = LocalConfig.Get<string>(OsuSetting.Username),
Token = LocalConfig.Get<string>(OsuSetting.Token)
});
dependencies.Cache(RulesetStore = new RulesetStore(connection));
dependencies.Cache(FileStore = new FileStore(connection, Host.Storage));
dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, FileStore, connection, RulesetStore, Host));
dependencies.Cache(BeatmapManager = new BeatmapManager(Host.Storage, FileStore, connection, RulesetStore, API, Host));
dependencies.Cache(ScoreStore = new ScoreStore(Host.Storage, connection, Host, BeatmapManager, RulesetStore));
dependencies.Cache(KeyBindingStore = new KeyBindingStore(connection, RulesetStore));
dependencies.Cache(new OsuColour());
@ -144,12 +150,6 @@ namespace osu.Game
Beatmap = new NonNullableBindable<WorkingBeatmap>(defaultBeatmap);
BeatmapManager.DefaultBeatmap = defaultBeatmap;
dependencies.Cache(API = new APIAccess
{
Username = LocalConfig.Get<string>(OsuSetting.Username),
Token = LocalConfig.Get<string>(OsuSetting.Token)
});
Beatmap.ValueChanged += b =>
{
// compare to last beatmap as sometimes the two may share a track representation (optimisation, see WorkingBeatmap.TransferTo)

View File

@ -76,7 +76,6 @@ namespace osu.Game.Overlays.Chat
Size = new Vector2(text_size),
Shadow = false,
Margin = new MarginPadding { Right = 10f },
Alpha = 0f,
},
},
},
@ -109,7 +108,6 @@ namespace osu.Game.Overlays.Chat
TextSize = text_size,
Font = @"Exo2.0-SemiBold",
Shadow = false,
Alpha = 0.8f,
},
},
},
@ -151,6 +149,9 @@ namespace osu.Game.Overlays.Chat
joinedBind.ValueChanged += updateColour;
joinedBind.BindTo(channel.Joined);
joinedBind.TriggerChange();
FinishTransforms(true);
}
protected override bool OnHover(InputState state)

View File

@ -4,8 +4,6 @@
using System.Collections.Generic;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using System.IO;
using System.Threading.Tasks;
using OpenTK;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
@ -20,8 +18,8 @@ using osu.Framework.Input;
using osu.Game.Graphics.UserInterface;
using osu.Game.Online.API;
using osu.Framework.Logging;
using osu.Game.Beatmaps.IO;
using osu.Game.Overlays.Notifications;
using osu.Game.Online.API.Requests;
namespace osu.Game.Overlays.Direct
{
@ -97,6 +95,11 @@ namespace osu.Game.Overlays.Direct
},
}
});
var downloadRequest = beatmaps.GetExistingDownload(SetInfo);
if (downloadRequest != null)
attachDownload(downloadRequest);
}
protected override bool OnHover(InputState state)
@ -115,23 +118,8 @@ namespace osu.Game.Overlays.Direct
base.OnHoverLost(state);
}
// this should eventually be moved to a more central place, like BeatmapManager.
private DownloadBeatmapSetRequest downloadRequest;
protected void StartDownload()
{
if (api == null) return;
// we already have an active download running.
if (downloadRequest != null)
{
content.MoveToX(-5, 50, Easing.OutSine).Then()
.MoveToX(5, 100, Easing.InOutSine).Then()
.MoveToX(-5, 100, Easing.InOutSine).Then()
.MoveToX(0, 50, Easing.InSine).Then();
return;
}
if (!api.LocalUser.Value.IsSupporter)
{
notifications.Post(new SimpleNotification
@ -142,72 +130,43 @@ namespace osu.Game.Overlays.Direct
return;
}
if (beatmaps.GetExistingDownload(SetInfo) != null)
{
// we already have an active download running.
content.MoveToX(-5, 50, Easing.OutSine).Then()
.MoveToX(5, 100, Easing.InOutSine).Then()
.MoveToX(-5, 100, Easing.InOutSine).Then()
.MoveToX(0, 50, Easing.InSine).Then();
return;
}
var request = beatmaps.Download(SetInfo);
attachDownload(request);
}
private void attachDownload(DownloadBeatmapSetRequest request)
{
progressBar.FadeIn(400, Easing.OutQuint);
progressBar.ResizeHeightTo(4, 400, Easing.OutQuint);
progressBar.Current.Value = 0;
ProgressNotification downloadNotification = new ProgressNotification
{
Text = $"Downloading {SetInfo.Metadata.Artist} - {SetInfo.Metadata.Title}",
};
downloadRequest = new DownloadBeatmapSetRequest(SetInfo);
downloadRequest.Failure += e =>
request.Failure += e =>
{
progressBar.Current.Value = 0;
progressBar.FadeOut(500);
downloadNotification.State = ProgressNotificationState.Completed;
Logger.Error(e, "Failed to get beatmap download information");
downloadRequest = null;
};
downloadRequest.Progress += (current, total) =>
{
float progress = (float)current / total;
request.DownloadProgressed += progress => progressBar.Current.Value = progress;
progressBar.Current.Value = progress;
downloadNotification.State = ProgressNotificationState.Active;
downloadNotification.Progress = progress;
};
downloadRequest.Success += data =>
request.Success += data =>
{
progressBar.Current.Value = 1;
progressBar.FadeOut(500);
downloadNotification.State = ProgressNotificationState.Completed;
using (var stream = new MemoryStream(data))
using (var archive = new OszArchiveReader(stream))
beatmaps.Import(archive);
};
downloadNotification.CancelRequested += () =>
{
downloadRequest.Cancel();
downloadRequest = null;
return true;
};
notifications.Post(downloadNotification);
// don't run in the main api queue as this is a long-running task.
Task.Run(() => downloadRequest.Perform(api));
}
public class DownloadBeatmapSetRequest : APIDownloadRequest
{
private readonly BeatmapSetInfo beatmapSet;
public DownloadBeatmapSetRequest(BeatmapSetInfo beatmapSet)
{
this.beatmapSet = beatmapSet;
}
protected override string Target => $@"beatmapsets/{beatmapSet.OnlineBeatmapSetID}/download";
}
protected override void LoadComplete()

View File

@ -27,6 +27,7 @@ namespace osu.Game.Overlays
private APIAccess api;
private RulesetStore rulesets;
private BeatmapManager beatmaps;
private readonly FillFlowContainer resultCountsContainer;
private readonly OsuSpriteText resultCountsText;
@ -46,9 +47,26 @@ namespace osu.Game.Overlays
set
{
if (beatmapSets?.Equals(value) ?? false) return;
beatmapSets = value;
recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value);
if (beatmapSets == null) return;
var artists = new List<string>();
var songs = new List<string>();
var tags = new List<string>();
foreach (var s in beatmapSets)
{
artists.Add(s.Metadata.Artist);
songs.Add(s.Metadata.Title);
tags.AddRange(s.Metadata.Tags.Split(' '));
}
ResultAmounts = new ResultCounts(distinctCount(artists), distinctCount(songs), distinctCount(tags));
if (beatmapSets.Any() && panels == null)
// real use case? currently only seems to be for test case
recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value);
}
}
@ -147,6 +165,8 @@ namespace osu.Game.Overlays
{
this.api = api;
this.rulesets = rulesets;
this.beatmaps = beatmaps;
resultCountsContainer.Colour = colours.Yellow;
beatmaps.BeatmapSetAdded += setAdded;
@ -156,6 +176,7 @@ namespace osu.Game.Overlays
{
// if a new map was imported, we should remove it from search results (download completed etc.)
panels?.FirstOrDefault(p => p.SetInfo.OnlineBeatmapSetID == set.OnlineBeatmapSetID)?.FadeOut(400).Expire();
BeatmapSets = BeatmapSets?.Where(b => b.OnlineBeatmapSetID != set.OnlineBeatmapSetID);
}
private void updateResultCounts()
@ -237,20 +258,11 @@ namespace osu.Game.Overlays
getSetsRequest.Success += r =>
{
BeatmapSets = r?.Select(response => response.ToBeatmapSet(rulesets));
if (BeatmapSets == null) return;
BeatmapSets = r?.
Select(response => response.ToBeatmapSet(rulesets)).
Where(b => beatmaps.QueryBeatmapSet(q => q.OnlineBeatmapSetID == b.OnlineBeatmapSetID) == null);
var artists = new List<string>();
var songs = new List<string>();
var tags = new List<string>();
foreach (var s in BeatmapSets)
{
artists.Add(s.Metadata.Artist);
songs.Add(s.Metadata.Title);
tags.AddRange(s.Metadata.Tags.Split(' '));
}
ResultAmounts = new ResultCounts(distinctCount(artists), distinctCount(songs), distinctCount(tags));
recreatePanels(Filter.DisplayStyleControl.DisplayStyle.Value);
};
api.Queue(getSetsRequest);

View File

@ -16,6 +16,11 @@ namespace osu.Game.Rulesets.Mods
/// </summary>
public abstract string Name { get; }
/// <summary>
/// The shortened name of this mod.
/// </summary>
public abstract string ShortenedName { get; }
/// <summary>
/// The icon of this mod.
/// </summary>

View File

@ -24,6 +24,7 @@ namespace osu.Game.Rulesets.Mods
public class ModAutoplay : Mod
{
public override string Name => "Autoplay";
public override string ShortenedName => "AT";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_auto;
public override string Description => "Watch a perfect automated play through the song";
public override double ScoreMultiplier => 0;

View File

@ -8,6 +8,7 @@ namespace osu.Game.Rulesets.Mods
public class ModCinema : ModAutoplay
{
public override string Name => "Cinema";
public override string ShortenedName => "CN";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_cinema;
}
}

View File

@ -10,6 +10,7 @@ namespace osu.Game.Rulesets.Mods
public abstract class ModDaycore : ModHalfTime
{
public override string Name => "Daycore";
public override string ShortenedName => "DC";
public override FontAwesome Icon => FontAwesome.fa_question;
public override string Description => "whoaaaaa";

View File

@ -10,6 +10,7 @@ namespace osu.Game.Rulesets.Mods
public class ModDoubleTime : Mod, IApplicableToClock
{
public override string Name => "Double Time";
public override string ShortenedName => "DT";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_doubletime;
public override ModType Type => ModType.DifficultyIncrease;
public override string Description => "Zoooooooooom";

View File

@ -10,6 +10,7 @@ namespace osu.Game.Rulesets.Mods
public abstract class ModEasy : Mod, IApplicableToDifficulty
{
public override string Name => "Easy";
public override string ShortenedName => "EZ";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_easy;
public override ModType Type => ModType.DifficultyReduction;
public override string Description => "Reduces overall difficulty - larger circles, more forgiving HP drain, less accuracy required.";

View File

@ -8,6 +8,7 @@ namespace osu.Game.Rulesets.Mods
public abstract class ModFlashlight : Mod
{
public override string Name => "Flashlight";
public override string ShortenedName => "FL";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_flashlight;
public override ModType Type => ModType.DifficultyIncrease;
public override string Description => "Restricted view area.";

View File

@ -10,6 +10,7 @@ namespace osu.Game.Rulesets.Mods
public abstract class ModHalfTime : Mod, IApplicableToClock
{
public override string Name => "Half Time";
public override string ShortenedName => "HT";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_halftime;
public override ModType Type => ModType.DifficultyReduction;
public override string Description => "Less zoom";

View File

@ -10,6 +10,7 @@ namespace osu.Game.Rulesets.Mods
public abstract class ModHardRock : Mod, IApplicableToDifficulty
{
public override string Name => "Hard Rock";
public override string ShortenedName => "HR";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_hardrock;
public override ModType Type => ModType.DifficultyIncrease;
public override string Description => "Everything just got a bit harder...";

View File

@ -8,6 +8,7 @@ namespace osu.Game.Rulesets.Mods
public abstract class ModHidden : Mod
{
public override string Name => "Hidden";
public override string ShortenedName => "HD";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_hidden;
public override ModType Type => ModType.DifficultyIncrease;
public override bool Ranked => true;

View File

@ -10,6 +10,7 @@ namespace osu.Game.Rulesets.Mods
public abstract class ModNightcore : ModDoubleTime
{
public override string Name => "Nightcore";
public override string ShortenedName => "NC";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_nightcore;
public override string Description => "uguuuuuuuu";

View File

@ -9,6 +9,7 @@ namespace osu.Game.Rulesets.Mods
public abstract class ModNoFail : Mod
{
public override string Name => "NoFail";
public override string ShortenedName => "NF";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_nofail;
public override ModType Type => ModType.DifficultyReduction;
public override string Description => "You can't fail, no matter what.";

View File

@ -6,6 +6,7 @@ namespace osu.Game.Rulesets.Mods
public abstract class ModPerfect : ModSuddenDeath
{
public override string Name => "Perfect";
public override string ShortenedName => "PF";
public override string Description => "SS or quit.";
}
}

View File

@ -9,6 +9,7 @@ namespace osu.Game.Rulesets.Mods
public abstract class ModRelax : Mod
{
public override string Name => "Relax";
public override string ShortenedName => "RX";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_relax;
public override double ScoreMultiplier => 0;
public override Type[] IncompatibleMods => new[] { typeof(ModAutoplay), typeof(ModNoFail), typeof(ModSuddenDeath) };

View File

@ -9,6 +9,7 @@ namespace osu.Game.Rulesets.Mods
public abstract class ModSuddenDeath : Mod
{
public override string Name => "Sudden Death";
public override string ShortenedName => "SD";
public override FontAwesome Icon => FontAwesome.fa_osu_mod_suddendeath;
public override ModType Type => ModType.DifficultyIncrease;
public override string Description => "Miss a note and fail.";

View File

@ -6,6 +6,7 @@ namespace osu.Game.Rulesets.Mods
public class MultiMod : Mod
{
public override string Name => string.Empty;
public override string ShortenedName => string.Empty;
public override string Description => string.Empty;
public override double ScoreMultiplier => 0.0;

View File

@ -1,15 +1,17 @@
// 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.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.UI;
using System;
using System.Collections.Generic;
using System.Linq;
using osu.Framework.Graphics;
using osu.Framework.Input.Bindings;
using osu.Game.Rulesets.Scoring;
using osu.Game.Beatmaps;
using osu.Game.Graphics;
using osu.Game.Overlays.Settings;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
namespace osu.Game.Rulesets
{
@ -19,9 +21,18 @@ namespace osu.Game.Rulesets
public virtual IEnumerable<BeatmapStatistic> GetBeatmapStatistics(WorkingBeatmap beatmap) => new BeatmapStatistic[] { };
public IEnumerable<Mod> GetAllMods() => Enum.GetValues(typeof(ModType)).Cast<ModType>()
// Get all mod types as an IEnumerable<ModType>
.SelectMany(GetModsFor)
// Confine all mods of each mod type into a single IEnumerable<Mod>
.Where(mod => mod != null)
// Filter out all null mods
.SelectMany(mod => (mod as MultiMod)?.Mods ?? new[] { mod });
// Resolve MultiMods as their .Mods property
public abstract IEnumerable<Mod> GetModsFor(ModType type);
public abstract Mod GetAutoplayMod();
public Mod GetAutoplayMod() => GetAllMods().First(mod => mod is ModAutoplay);
protected Ruleset(RulesetInfo rulesetInfo)
{

View File

@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using osu.Game.Beatmaps;
using osu.Game.Rulesets.Mods;
using osu.Game.Users;
@ -15,70 +14,30 @@ namespace osu.Game.Rulesets.Scoring
{
public ScoreRank Rank { get; set; }
[JsonProperty(@"score")]
public double TotalScore { get; set; }
public double Accuracy { get; set; }
public double Health { get; set; } = 1;
[JsonProperty(@"max_combo")]
public int MaxCombo { get; set; }
public int Combo { get; set; }
[JsonProperty(@"mods")]
protected string[] ModStrings { get; set; } //todo: parse to Mod objects
public RulesetInfo Ruleset { get; set; }
public Mod[] Mods { get; set; }
[JsonProperty(@"user")]
public User User;
[JsonProperty(@"replay_data")]
public Replay Replay;
public BeatmapInfo Beatmap;
[JsonProperty(@"score_id")]
public long OnlineScoreID;
[JsonProperty(@"created_at")]
public DateTimeOffset Date;
[JsonProperty(@"statistics")]
private Dictionary<string, dynamic> jsonStats
{
set
{
foreach (var kvp in value)
{
string key = kvp.Key;
switch (key)
{
case @"count_300":
key = @"300";
break;
case @"count_100":
key = @"100";
break;
case @"count_50":
key = @"50";
break;
case @"count_miss":
key = @"x";
break;
default:
continue;
}
Statistics.Add(key, kvp.Value);
}
}
}
public Dictionary<string, dynamic> Statistics = new Dictionary<string, dynamic>();
}
}

View File

@ -17,7 +17,7 @@ namespace osu.Game.Rulesets.UI
private readonly SpriteIcon modIcon;
private readonly SpriteIcon background;
private const float icon_size = 80;
private const float background_size = 80;
public FontAwesome Icon
{
@ -39,7 +39,7 @@ namespace osu.Game.Rulesets.UI
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Size = new Vector2(icon_size),
Size = new Vector2(background_size),
Icon = FontAwesome.fa_osu_mod_bg,
Shadow = true,
},
@ -48,7 +48,7 @@ namespace osu.Game.Rulesets.UI
Origin = Anchor.TopCentre,
Anchor = Anchor.TopCentre,
Colour = OsuColour.Gray(84),
Size = new Vector2(icon_size - 35),
Size = new Vector2(background_size - 35),
Y = 25,
Icon = mod.Icon
},

View File

@ -1,15 +1,15 @@
// Copyright (c) 2007-2017 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 OpenTK;
using OpenTK.Graphics;
using osu.Framework.Allocation;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Colour;
using osu.Framework.Graphics.Containers;
using System;
using osu.Framework.Allocation;
using osu.Framework.Threading;
using osu.Game.Beatmaps;
using osu.Game.Graphics.Containers;

View File

@ -4,17 +4,19 @@
using System;
using OpenTK;
using OpenTK.Graphics;
using osu.Framework;
using osu.Framework.Extensions.Color4Extensions;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input;
using osu.Game.Graphics;
using osu.Game.Graphics.Sprites;
using osu.Framework.Extensions.Color4Extensions;
using osu.Game.Rulesets.Mods;
using osu.Game.Users;
using osu.Framework;
using osu.Game.Rulesets.Scoring;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.UI;
using osu.Game.Users;
namespace osu.Game.Screens.Select.Leaderboards
{
@ -41,7 +43,7 @@ namespace osu.Game.Screens.Select.Leaderboards
private readonly ScoreComponentLabel maxCombo;
private readonly ScoreComponentLabel accuracy;
private readonly Container flagBadgeContainer;
private readonly FillFlowContainer<ScoreModIcon> modsContainer;
private readonly FillFlowContainer<ModIcon> modsContainer;
private Visibility state;
@ -247,7 +249,7 @@ namespace osu.Game.Screens.Select.Leaderboards
},
},
},
modsContainer = new FillFlowContainer<ScoreModIcon>
modsContainer = new FillFlowContainer<ModIcon>
{
Anchor = Anchor.BottomRight,
Origin = Anchor.BottomRight,
@ -260,13 +262,13 @@ namespace osu.Game.Screens.Select.Leaderboards
},
};
if (Score.Mods != null)
foreach (Mod mod in Score.Mods)
{
foreach (Mod mod in Score.Mods)
modsContainer.Add(new ModIcon(mod)
{
// TODO: Get actual mod colours
modsContainer.Add(new ScoreModIcon(mod.Icon, OsuColour.FromHex(@"ffcc22")));
}
AutoSizeAxes = Axes.Both,
Scale = new Vector2(0.375f)
});
}
}
@ -275,13 +277,13 @@ namespace osu.Game.Screens.Select.Leaderboards
public override void Hide() => State = Visibility.Hidden;
public override void Show() => State = Visibility.Visible;
protected override bool OnHover(Framework.Input.InputState state)
protected override bool OnHover(InputState state)
{
background.FadeTo(0.5f, 300, Easing.OutQuint);
return base.OnHover(state);
}
protected override void OnHoverLost(Framework.Input.InputState state)
protected override void OnHoverLost(InputState state)
{
background.FadeTo(background_alpha, 200, Easing.OutQuint);
base.OnHoverLost(state);
@ -311,8 +313,8 @@ namespace osu.Game.Screens.Select.Leaderboards
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
Font = font,
TextSize = textSize,
FixedWidth = true,
TextSize = textSize,
Text = text,
Colour = glowColour,
Shadow = false,
@ -334,36 +336,6 @@ namespace osu.Game.Screens.Select.Leaderboards
}
}
private class ScoreModIcon : Container
{
public ScoreModIcon(FontAwesome icon, Color4 colour)
{
AutoSizeAxes = Axes.Both;
Children = new[]
{
new SpriteIcon
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Icon = FontAwesome.fa_osu_mod_bg,
Colour = colour,
Shadow = true,
Size = new Vector2(30),
},
new SpriteIcon
{
Origin = Anchor.Centre,
Anchor = Anchor.Centre,
Icon = icon,
Colour = OsuColour.Gray(84),
Size = new Vector2(18),
Position = new Vector2(0f, 2f),
},
};
}
}
private class ScoreComponentLabel : Container
{
public ScoreComponentLabel(FontAwesome icon, string value)

View File

@ -98,6 +98,7 @@
<Compile Include="Input\Bindings\GlobalKeyBindingInputManager.cs" />
<Compile Include="IO\FileStore.cs" />
<Compile Include="IO\FileInfo.cs" />
<Compile Include="Online\API\Requests\DownloadBeatmapSetRequest.cs" />
<Compile Include="Online\API\Requests\GetUsersRequest.cs" />
<Compile Include="Online\API\Requests\PostMessageRequest.cs" />
<Compile Include="Online\Chat\ErrorMessage.cs" />