mirror of
https://github.com/ppy/osu.git
synced 2025-01-28 08:02:55 +08:00
show recent scores
This commit is contained in:
parent
9a9a1a680e
commit
aadc699e73
@ -1,6 +1,10 @@
|
|||||||
// Copyright (c) 2007-2017 ppy Pty Ltd <contact@ppy.sh>.
|
// Copyright (c) 2007-2017 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.Online.API.Requests;
|
||||||
|
using osu.Game.Overlays.Profile.Sections.Ranks;
|
||||||
|
using osu.Game.Users;
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Profile.Sections
|
namespace osu.Game.Overlays.Profile.Sections
|
||||||
{
|
{
|
||||||
public class HistoricalSection : ProfileSection
|
public class HistoricalSection : ProfileSection
|
||||||
@ -8,5 +12,18 @@ namespace osu.Game.Overlays.Profile.Sections
|
|||||||
public override string Title => "Historical";
|
public override string Title => "Historical";
|
||||||
|
|
||||||
public override string Identifier => "historical";
|
public override string Identifier => "historical";
|
||||||
|
|
||||||
|
private readonly ScoreContainer recent;
|
||||||
|
|
||||||
|
public HistoricalSection()
|
||||||
|
{
|
||||||
|
Child = recent = new ScoreContainer.TotalScoreContainer(ScoreType.Recent, "Recent Plays (24h)", "No performance records. :(");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override User User
|
||||||
|
{
|
||||||
|
get => base.User;
|
||||||
|
set => base.User = recent.User = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,12 +24,10 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
|||||||
private readonly FillFlowContainer metadata;
|
private readonly FillFlowContainer metadata;
|
||||||
private readonly ModContainer modContainer;
|
private readonly ModContainer modContainer;
|
||||||
private readonly Score score;
|
private readonly Score score;
|
||||||
private readonly double? weight;
|
|
||||||
|
|
||||||
public DrawableScore(Score score, double? weight = null)
|
private DrawableScore(Score score)
|
||||||
{
|
{
|
||||||
this.score = score;
|
this.score = score;
|
||||||
this.weight = weight;
|
|
||||||
|
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
@ -77,29 +75,6 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load(OsuColour colour, LocalisationEngine locale, BeatmapSetOverlay beatmapSetOverlay)
|
private void load(OsuColour colour, LocalisationEngine locale, BeatmapSetOverlay beatmapSetOverlay)
|
||||||
{
|
{
|
||||||
double pp = score.PP ?? 0;
|
|
||||||
stats.Add(new OsuSpriteText
|
|
||||||
{
|
|
||||||
Text = $"{pp:0}pp",
|
|
||||||
Anchor = Anchor.TopRight,
|
|
||||||
Origin = Anchor.TopRight,
|
|
||||||
TextSize = 18,
|
|
||||||
Font = "Exo2.0-BoldItalic",
|
|
||||||
});
|
|
||||||
|
|
||||||
if (weight.HasValue)
|
|
||||||
{
|
|
||||||
stats.Add(new OsuSpriteText
|
|
||||||
{
|
|
||||||
Text = $"weighted: {pp * weight:0}pp ({weight:P0})",
|
|
||||||
Anchor = Anchor.TopRight,
|
|
||||||
Origin = Anchor.TopRight,
|
|
||||||
Colour = colour.GrayA,
|
|
||||||
TextSize = 11,
|
|
||||||
Font = "Exo2.0-RegularItalic",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
stats.Add(new OsuSpriteText
|
stats.Add(new OsuSpriteText
|
||||||
{
|
{
|
||||||
Text = $"accuracy: {score.Accuracy:P2}",
|
Text = $"accuracy: {score.Accuracy:P2}",
|
||||||
@ -108,6 +83,7 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
|||||||
Colour = colour.GrayA,
|
Colour = colour.GrayA,
|
||||||
TextSize = 11,
|
TextSize = 11,
|
||||||
Font = "Exo2.0-RegularItalic",
|
Font = "Exo2.0-RegularItalic",
|
||||||
|
Depth = -1,
|
||||||
});
|
});
|
||||||
|
|
||||||
metadata.Add(new OsuHoverContainer
|
metadata.Add(new OsuHoverContainer
|
||||||
@ -159,5 +135,61 @@ namespace osu.Game.Overlays.Profile.Sections.Ranks
|
|||||||
yield return new Vector2(DrawWidth * i * (count == 1 ? 0 : 1f / (count - 1)), 0);
|
yield return new Vector2(DrawWidth * i * (count == 1 ? 0 : 1f / (count - 1)), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class PPScore : DrawableScore
|
||||||
|
{
|
||||||
|
private readonly double? weight;
|
||||||
|
|
||||||
|
public PPScore(Score score, double? weight = null) : base(score)
|
||||||
|
{
|
||||||
|
this.weight = weight;
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private new void load(OsuColour colour, LocalisationEngine locale, BeatmapSetOverlay beatmapSetOverlay)
|
||||||
|
{
|
||||||
|
double pp = score.PP ?? 0;
|
||||||
|
stats.Add(new OsuSpriteText
|
||||||
|
{
|
||||||
|
Text = $"{pp:0}pp",
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Origin = Anchor.TopRight,
|
||||||
|
TextSize = 18,
|
||||||
|
Font = "Exo2.0-BoldItalic",
|
||||||
|
});
|
||||||
|
|
||||||
|
if (weight.HasValue)
|
||||||
|
{
|
||||||
|
stats.Add(new OsuSpriteText
|
||||||
|
{
|
||||||
|
Text = $"weighted: {pp * weight:0}pp ({weight:P0})",
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Origin = Anchor.TopRight,
|
||||||
|
Colour = colour.GrayA,
|
||||||
|
TextSize = 11,
|
||||||
|
Font = "Exo2.0-RegularItalic",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TotalScore : DrawableScore
|
||||||
|
{
|
||||||
|
public TotalScore(Score score) : base(score)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private new void load(OsuColour colour, LocalisationEngine locale, BeatmapSetOverlay beatmapSetOverlay)
|
||||||
|
{
|
||||||
|
stats.Add(new OsuSpriteText
|
||||||
|
{
|
||||||
|
Text = score.TotalScore.ToString("#,###"),
|
||||||
|
Anchor = Anchor.TopRight,
|
||||||
|
Origin = Anchor.TopRight,
|
||||||
|
TextSize = 18,
|
||||||
|
Font = "Exo2.0-BoldItalic",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
157
osu.Game/Overlays/Profile/Sections/Ranks/ScoreContainer.cs
Normal file
157
osu.Game/Overlays/Profile/Sections/Ranks/ScoreContainer.cs
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
// 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.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Graphics.Sprites;
|
||||||
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Online.API;
|
||||||
|
using osu.Game.Online.API.Requests;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Users;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace osu.Game.Overlays.Profile.Sections.Ranks
|
||||||
|
{
|
||||||
|
public abstract class ScoreContainer : FillFlowContainer
|
||||||
|
{
|
||||||
|
private readonly FillFlowContainer<DrawableScore> scoreContainer;
|
||||||
|
private readonly OsuSpriteText missing;
|
||||||
|
private readonly OsuHoverContainer showMoreButton;
|
||||||
|
private readonly LoadingAnimation showMoreLoading;
|
||||||
|
|
||||||
|
private readonly ScoreType type;
|
||||||
|
private int visiblePages;
|
||||||
|
private User user;
|
||||||
|
|
||||||
|
private RulesetStore rulesets;
|
||||||
|
private APIAccess api;
|
||||||
|
|
||||||
|
public User User
|
||||||
|
{
|
||||||
|
set
|
||||||
|
{
|
||||||
|
user = value;
|
||||||
|
visiblePages = 0;
|
||||||
|
scoreContainer.Clear();
|
||||||
|
showMoreButton.Hide();
|
||||||
|
missing.Show();
|
||||||
|
showMore();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ScoreContainer(ScoreType type, string header, string missingText)
|
||||||
|
{
|
||||||
|
this.type = type;
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.X;
|
||||||
|
AutoSizeAxes = Axes.Y;
|
||||||
|
Direction = FillDirection.Vertical;
|
||||||
|
|
||||||
|
Children = new Drawable[]
|
||||||
|
{
|
||||||
|
new OsuSpriteText
|
||||||
|
{
|
||||||
|
TextSize = 15,
|
||||||
|
Text = header,
|
||||||
|
Font = "Exo2.0-RegularItalic",
|
||||||
|
Margin = new MarginPadding { Top = 10, Bottom = 10 },
|
||||||
|
},
|
||||||
|
scoreContainer = new FillFlowContainer<DrawableScore>
|
||||||
|
{
|
||||||
|
AutoSizeAxes = Axes.Y,
|
||||||
|
RelativeSizeAxes = Axes.X,
|
||||||
|
Direction = FillDirection.Vertical,
|
||||||
|
},
|
||||||
|
showMoreButton = new OsuHoverContainer
|
||||||
|
{
|
||||||
|
Alpha = 0,
|
||||||
|
Action = showMore,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Child = new OsuSpriteText
|
||||||
|
{
|
||||||
|
TextSize = 14,
|
||||||
|
Text = "show more",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
showMoreLoading = new LoadingAnimation
|
||||||
|
{
|
||||||
|
Anchor = Anchor.TopCentre,
|
||||||
|
Origin = Anchor.TopCentre,
|
||||||
|
Size = new Vector2(14),
|
||||||
|
},
|
||||||
|
missing = new OsuSpriteText
|
||||||
|
{
|
||||||
|
TextSize = 14,
|
||||||
|
Text = missingText,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(APIAccess api, RulesetStore rulesets)
|
||||||
|
{
|
||||||
|
this.api = api;
|
||||||
|
this.rulesets = rulesets;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showMore()
|
||||||
|
{
|
||||||
|
var req = new GetUserScoresRequest(user.Id, type, visiblePages++ * 5);
|
||||||
|
|
||||||
|
showMoreLoading.Show();
|
||||||
|
showMoreButton.Hide();
|
||||||
|
|
||||||
|
req.Success += scores =>
|
||||||
|
{
|
||||||
|
foreach (var s in scores)
|
||||||
|
s.ApplyRuleset(rulesets.GetRuleset(s.OnlineRulesetID));
|
||||||
|
|
||||||
|
showMoreButton.FadeTo(scores.Count == 5 ? 1 : 0);
|
||||||
|
showMoreLoading.Hide();
|
||||||
|
|
||||||
|
if (scores.Any())
|
||||||
|
{
|
||||||
|
missing.Hide();
|
||||||
|
foreach (OnlineScore score in scores)
|
||||||
|
{
|
||||||
|
var drawableScore = CreateScore(score, scoreContainer.Count);
|
||||||
|
drawableScore.RelativeSizeAxes = Axes.X;
|
||||||
|
drawableScore.Height = 60;
|
||||||
|
scoreContainer.Add(drawableScore);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Schedule(() => { api.Queue(req); });
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract DrawableScore CreateScore(OnlineScore score, int index);
|
||||||
|
|
||||||
|
public class PPScoreContainer : ScoreContainer
|
||||||
|
{
|
||||||
|
private readonly bool includeWeight;
|
||||||
|
|
||||||
|
public PPScoreContainer(ScoreType type, string header, string missing, bool includeWeight = false) : base(type, header, missing)
|
||||||
|
{
|
||||||
|
this.includeWeight = includeWeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override DrawableScore CreateScore(OnlineScore score, int index) => new DrawableScore.PPScore(score, includeWeight ? Math.Pow(0.95, scoreContainer.Count) : (double?)null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TotalScoreContainer : ScoreContainer
|
||||||
|
{
|
||||||
|
public TotalScoreContainer(ScoreType type, string header, string missing) : base(type, header, missing)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
protected override DrawableScore CreateScore(OnlineScore score, int index) => new DrawableScore.TotalScore(score);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,19 +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.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
|
||||||
using osu.Game.Graphics.Containers;
|
|
||||||
using osu.Game.Graphics.Sprites;
|
|
||||||
using osu.Game.Overlays.Profile.Sections.Ranks;
|
using osu.Game.Overlays.Profile.Sections.Ranks;
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using osu.Game.Online.API;
|
|
||||||
using osu.Game.Online.API.Requests;
|
using osu.Game.Online.API.Requests;
|
||||||
using osu.Game.Rulesets;
|
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using OpenTK;
|
|
||||||
using osu.Framework.Allocation;
|
|
||||||
|
|
||||||
namespace osu.Game.Overlays.Profile.Sections
|
namespace osu.Game.Overlays.Profile.Sections
|
||||||
{
|
{
|
||||||
@ -30,8 +20,8 @@ namespace osu.Game.Overlays.Profile.Sections
|
|||||||
{
|
{
|
||||||
Children = new Drawable[]
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
best = new ScoreContainer(ScoreType.Best, "Best Performance", true),
|
best = new ScoreContainer.PPScoreContainer(ScoreType.Best, "Best Performance", "No awesome performance records yet. :(", true),
|
||||||
first = new ScoreContainer(ScoreType.Firsts, "First Place Ranks"),
|
first = new ScoreContainer.PPScoreContainer(ScoreType.Firsts, "First Place Ranks", "No awesome performance records yet. :("),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,122 +39,5 @@ namespace osu.Game.Overlays.Profile.Sections
|
|||||||
first.User = value;
|
first.User = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ScoreContainer : FillFlowContainer
|
|
||||||
{
|
|
||||||
private readonly FillFlowContainer<DrawableScore> scoreContainer;
|
|
||||||
private readonly OsuSpriteText missing;
|
|
||||||
private readonly OsuHoverContainer showMoreButton;
|
|
||||||
private readonly LoadingAnimation showMoreLoading;
|
|
||||||
|
|
||||||
private readonly ScoreType type;
|
|
||||||
private int visiblePages;
|
|
||||||
private User user;
|
|
||||||
private readonly bool includeWeigth;
|
|
||||||
|
|
||||||
private RulesetStore rulesets;
|
|
||||||
private APIAccess api;
|
|
||||||
|
|
||||||
public User User
|
|
||||||
{
|
|
||||||
set
|
|
||||||
{
|
|
||||||
user = value;
|
|
||||||
visiblePages = 0;
|
|
||||||
scoreContainer.Clear();
|
|
||||||
showMoreButton.Hide();
|
|
||||||
missing.Show();
|
|
||||||
showMore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ScoreContainer(ScoreType type, string header, bool includeWeigth = false)
|
|
||||||
{
|
|
||||||
this.type = type;
|
|
||||||
this.includeWeigth = includeWeigth;
|
|
||||||
|
|
||||||
RelativeSizeAxes = Axes.X;
|
|
||||||
AutoSizeAxes = Axes.Y;
|
|
||||||
Direction = FillDirection.Vertical;
|
|
||||||
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
|
||||||
new OsuSpriteText
|
|
||||||
{
|
|
||||||
TextSize = 15,
|
|
||||||
Text = header,
|
|
||||||
Font = "Exo2.0-RegularItalic",
|
|
||||||
Margin = new MarginPadding { Top = 10, Bottom = 10 },
|
|
||||||
},
|
|
||||||
scoreContainer = new FillFlowContainer<DrawableScore>
|
|
||||||
{
|
|
||||||
AutoSizeAxes = Axes.Y,
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Direction = FillDirection.Vertical,
|
|
||||||
},
|
|
||||||
showMoreButton = new OsuHoverContainer
|
|
||||||
{
|
|
||||||
Alpha = 0,
|
|
||||||
Action = showMore,
|
|
||||||
AutoSizeAxes = Axes.Both,
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Child = new OsuSpriteText
|
|
||||||
{
|
|
||||||
TextSize = 14,
|
|
||||||
Text = "show more",
|
|
||||||
}
|
|
||||||
},
|
|
||||||
showMoreLoading = new LoadingAnimation
|
|
||||||
{
|
|
||||||
Anchor = Anchor.TopCentre,
|
|
||||||
Origin = Anchor.TopCentre,
|
|
||||||
Size = new Vector2(14),
|
|
||||||
},
|
|
||||||
missing = new OsuSpriteText
|
|
||||||
{
|
|
||||||
TextSize = 14,
|
|
||||||
Text = "No awesome performance records yet. :(",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
|
||||||
private void load(APIAccess api, RulesetStore rulesets)
|
|
||||||
{
|
|
||||||
this.api = api;
|
|
||||||
this.rulesets = rulesets;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void showMore()
|
|
||||||
{
|
|
||||||
var req = new GetUserScoresRequest(user.Id, type, visiblePages++ * 5);
|
|
||||||
|
|
||||||
showMoreLoading.Show();
|
|
||||||
showMoreButton.Hide();
|
|
||||||
|
|
||||||
req.Success += scores =>
|
|
||||||
{
|
|
||||||
foreach (var s in scores)
|
|
||||||
s.ApplyRuleset(rulesets.GetRuleset(s.OnlineRulesetID));
|
|
||||||
|
|
||||||
showMoreButton.FadeTo(scores.Count == 5 ? 1 : 0);
|
|
||||||
showMoreLoading.Hide();
|
|
||||||
|
|
||||||
if (scores.Any())
|
|
||||||
{
|
|
||||||
missing.Hide();
|
|
||||||
foreach (OnlineScore score in scores)
|
|
||||||
scoreContainer.Add(new DrawableScore(score, includeWeigth ? Math.Pow(0.95, scoreContainer.Count) : (double?)null)
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.X,
|
|
||||||
Height = 60,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Schedule(() => { api.Queue(req); });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ namespace osu.Game.Overlays
|
|||||||
//new RecentSection(),
|
//new RecentSection(),
|
||||||
new RanksSection(),
|
new RanksSection(),
|
||||||
//new MedalsSection(),
|
//new MedalsSection(),
|
||||||
//new HistoricalSection(),
|
new HistoricalSection(),
|
||||||
//new BeatmapsSection(),
|
//new BeatmapsSection(),
|
||||||
//new KudosuSection()
|
//new KudosuSection()
|
||||||
};
|
};
|
||||||
|
@ -289,6 +289,7 @@
|
|||||||
<Compile Include="Migrations\OsuDbContextModelSnapshot.cs" />
|
<Compile Include="Migrations\OsuDbContextModelSnapshot.cs" />
|
||||||
<Compile Include="Online\API\Requests\GetBeatmapSetRequest.cs" />
|
<Compile Include="Online\API\Requests\GetBeatmapSetRequest.cs" />
|
||||||
<Compile Include="Online\API\Requests\GetBeatmapSetsResponse.cs" />
|
<Compile Include="Online\API\Requests\GetBeatmapSetsResponse.cs" />
|
||||||
|
<Compile Include="Overlays\Profile\Sections\Ranks\ScoreContainer.cs" />
|
||||||
<Compile Include="Screens\Edit\Screens\Compose\Timeline\BeatmapWaveformGraph.cs" />
|
<Compile Include="Screens\Edit\Screens\Compose\Timeline\BeatmapWaveformGraph.cs" />
|
||||||
<Compile Include="Beatmaps\Drawables\DifficultyColouredContainer.cs" />
|
<Compile Include="Beatmaps\Drawables\DifficultyColouredContainer.cs" />
|
||||||
<Compile Include="Beatmaps\Drawables\DifficultyIcon.cs" />
|
<Compile Include="Beatmaps\Drawables\DifficultyIcon.cs" />
|
||||||
|
Loading…
Reference in New Issue
Block a user