Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add initial beatmap submission support #31805

Merged
merged 23 commits into from
Feb 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
b6731ff
Add completion flag to `WizardOverlay`
bdach Feb 5, 2025
fff99a8
Implement special exporter intended specifically for submission flows
bdach Feb 5, 2025
78e85dc
Add beatmap submission support
bdach Feb 5, 2025
070d402
Merge branch 'bss/api-setup' into bss/the-actual-submission
bdach Feb 6, 2025
e1a146d
Remove unnecessary suppressions
bdach Feb 6, 2025
6335228
Merge branch 'master' into bss/the-actual-submission
peppy Feb 7, 2025
bf57fef
Fix missing cached settings in `BetamapSubmissionOverlay` test
peppy Feb 7, 2025
46290ae
Disallow changing beatmap / ruleset while submitting beatmap
peppy Feb 7, 2025
12881f3
Don't show informational screens for subsequent submissions
peppy Feb 7, 2025
95967a2
Adjust beatmap stream creation to make a bit more sense
peppy Feb 7, 2025
783ef00
Change `BeatmapSubmissionScreen` to use global back button instead of…
peppy Feb 7, 2025
ce88ecf
Adjust timeouts to be much higher for upload requests
peppy Feb 7, 2025
753eae4
Update strings
peppy Feb 7, 2025
1afd1f5
Merge branch 'master' into bss/the-actual-submission
bdach Feb 7, 2025
de0aabb
Add staging submission service URL to development endpoint config
bdach Feb 7, 2025
64f0d23
Fix exiting being eternally blocked after successful beatmap submission
bdach Feb 7, 2025
7853456
Add delay before browser displays beatmap
peppy Feb 10, 2025
930aaec
Fix back button displaying before it should
peppy Feb 10, 2025
eae1ea7
Adjust animations and induce some short delays to make things more gr…
peppy Feb 10, 2025
8954938
Allow performing beatmap reload after submission from song select
bdach Feb 10, 2025
45259b3
Remove unused using
bdach Feb 10, 2025
b8e33a2
Minor code refactors
peppy Feb 10, 2025
de9362d
Merge branch 'master' into bss/the-actual-submission
bdach Feb 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ public void SetUpSteps()
Child = new DependencyProvidingContainer
{
RelativeSizeAxes = Axes.Both,
CachedDependencies = new[] { (typeof(ScreenFooter), (object)footer) },
CachedDependencies = new[]
{
(typeof(ScreenFooter), (object)footer),
(typeof(BeatmapSubmissionSettings), new BeatmapSubmissionSettings()),
},
Children = new Drawable[]
{
receptor,
Expand Down
23 changes: 14 additions & 9 deletions osu.Game/Database/LegacyBeatmapExporter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,20 @@ public LegacyBeatmapExporter(Storage storage)
Configuration = new LegacySkinDecoder().Decode(skinStreamReader)
};

MutateBeatmap(model, playableBeatmap);

// Encode to legacy format
var stream = new MemoryStream();
using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true))
new LegacyBeatmapEncoder(playableBeatmap, beatmapSkin).Encode(sw);

stream.Seek(0, SeekOrigin.Begin);

return stream;
}

protected virtual void MutateBeatmap(BeatmapSetInfo beatmapSet, IBeatmap playableBeatmap)
{
// Convert beatmap elements to be compatible with legacy format
// So we truncate time and position values to integers, and convert paths with multiple segments to Bézier curves

Expand Down Expand Up @@ -145,15 +159,6 @@ public LegacyBeatmapExporter(Storage storage)
hasPath.Path.ControlPoints.Add(new PathControlPoint(position));
}
}

// Encode to legacy format
var stream = new MemoryStream();
using (var sw = new StreamWriter(stream, Encoding.UTF8, 1024, true))
new LegacyBeatmapEncoder(playableBeatmap, beatmapSkin).Encode(sw);

stream.Seek(0, SeekOrigin.Begin);

return stream;
}

protected override string FileExtension => @".osz";
Expand Down
44 changes: 42 additions & 2 deletions osu.Game/Localisation/BeatmapSubmissionStrings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,31 @@ public static class BeatmapSubmissionStrings
/// </summary>
public static LocalisableString SubmissionSettings => new TranslatableString(getKey(@"submission_settings"), @"Submission settings");

/// <summary>
/// "Submit beatmap!"
/// </summary>
public static LocalisableString ConfirmSubmission => new TranslatableString(getKey(@"confirm_submission"), @"Submit beatmap!");

/// <summary>
/// "Exporting beatmap for compatibility..."
/// </summary>
public static LocalisableString Exporting => new TranslatableString(getKey(@"exporting"), @"Exporting beatmap for compatibility...");

/// <summary>
/// "Preparing for upload..."
/// </summary>
public static LocalisableString Preparing => new TranslatableString(getKey(@"preparing"), @"Preparing for upload...");

/// <summary>
/// "Uploading beatmap contents..."
/// </summary>
public static LocalisableString Uploading => new TranslatableString(getKey(@"uploading"), @"Uploading beatmap contents...");

/// <summary>
/// "Finishing up..."
/// </summary>
public static LocalisableString Finishing => new TranslatableString(getKey(@"finishing"), @"Finishing up...");

/// <summary>
/// "Before you continue, we ask you to check whether the content you are uploading has been cleared for upload. Please understand that you are responsible for the content you upload to the platform and if in doubt, should ask permission from the creators before uploading!"
/// </summary>
Expand Down Expand Up @@ -115,9 +140,24 @@ public static class BeatmapSubmissionStrings
public static LocalisableString LoadInBrowserAfterSubmission => new TranslatableString(getKey(@"load_in_browser_after_submission"), @"Load in browser after submission");

/// <summary>
/// "Note: In order to make it possible for users of all osu! versions to enjoy your beatmap, it will be exported in a backwards-compatible format. While we have made efforts to ensure that that process keeps the beatmap playable in its intended form, some data related to features that previous versions of osu! do not support may be lost."
/// "Note: In order to make it possible for users of all osu! versions to enjoy your beatmap, it will be exported in a backwards-compatible format. While we have made efforts to ensure that process keeps the beatmap playable in its intended form, some data related to features that previous versions of osu! do not support may be lost."
/// </summary>
public static LocalisableString LegacyExportDisclaimer => new TranslatableString(getKey(@"legacy_export_disclaimer"), @"Note: In order to make it possible for users of all osu! versions to enjoy your beatmap, it will be exported in a backwards-compatible format. While we have made efforts to ensure that process keeps the beatmap playable in its intended form, some data related to features that previous versions of osu! do not support may be lost.");

/// <summary>
/// "Empty beatmaps cannot be submitted."
/// </summary>
public static LocalisableString EmptyBeatmapsCannotBeSubmitted => new TranslatableString(getKey(@"empty_beatmaps_cannot_be_submitted"), @"Empty beatmaps cannot be submitted.");

/// <summary>
/// "Update beatmap!"
/// </summary>
public static LocalisableString UpdateBeatmap => new TranslatableString(getKey(@"update_beatmap"), @"Update beatmap!");

/// <summary>
/// "Upload NEW beatmap!"
/// </summary>
public static LocalisableString LegacyExportDisclaimer => new TranslatableString(getKey(@"legacy_export_disclaimer"), @"Note: In order to make it possible for users of all osu! versions to enjoy your beatmap, it will be exported in a backwards-compatible format. While we have made efforts to ensure that that process keeps the beatmap playable in its intended form, some data related to features that previous versions of osu! do not support may be lost.");
public static LocalisableString UploadNewBeatmap => new TranslatableString(getKey(@"upload_new_beatmap"), @"Upload NEW beatmap!");

private static string getKey(string key) => $@"{prefix}:{key}";
}
Expand Down
10 changes: 10 additions & 0 deletions osu.Game/Localisation/EditorStrings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,16 @@ public static class EditorStrings
/// </summary>
public static LocalisableString DeleteDifficulty => new TranslatableString(getKey(@"delete_difficulty"), @"Delete difficulty");

/// <summary>
/// "Edit externally"
/// </summary>
public static LocalisableString EditExternally => new TranslatableString(getKey(@"edit_externally"), @"Edit externally");

/// <summary>
/// "Submit beatmap"
/// </summary>
public static LocalisableString SubmitBeatmap => new TranslatableString(getKey(@"submit_beatmap"), @"Submit beatmap");

/// <summary>
/// "setup"
/// </summary>
Expand Down
4 changes: 1 addition & 3 deletions osu.Game/Online/API/Requests/PatchBeatmapPackageRequest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,8 @@ protected override string Uri

public uint BeatmapSetID { get; }

// ReSharper disable once CollectionNeverUpdated.Global
public Dictionary<string, byte[]> FilesChanged { get; } = new Dictionary<string, byte[]>();

// ReSharper disable once CollectionNeverUpdated.Global
public HashSet<string> FilesDeleted { get; } = new HashSet<string>();

public PatchBeatmapPackageRequest(uint beatmapSetId)
Expand All @@ -48,7 +46,7 @@ protected override WebRequest CreateWebRequest()
foreach (string filename in FilesDeleted)
request.AddParameter(@"filesDeleted", filename, RequestParameterType.Form);

request.Timeout = 60_000;
request.Timeout = 600_000;
return request;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ protected override WebRequest CreateWebRequest()
var request = base.CreateWebRequest();
request.AddFile(@"beatmapArchive", oszPackage);
request.Method = HttpMethod.Put;
request.Timeout = 60_000;
request.Timeout = 600_000;
return request;
}
}
Expand Down
1 change: 1 addition & 0 deletions osu.Game/Online/DevelopmentEndpointConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public DevelopmentEndpointConfiguration()
SpectatorUrl = $@"{APIUrl}/signalr/spectator";
MultiplayerUrl = $@"{APIUrl}/signalr/multiplayer";
MetadataUrl = $@"{APIUrl}/signalr/metadata";
BeatmapSubmissionServiceUrl = $@"{APIUrl}/beatmap-submission";
}
}
}
3 changes: 3 additions & 0 deletions osu.Game/Overlays/WizardOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ public partial class WizardOverlay : ShearedOverlayContainer
private LoadingSpinner loading = null!;
private ScheduledDelegate? loadingShowDelegate;

public bool Completed { get; private set; }

protected WizardOverlay(OverlayColourScheme scheme)
: base(scheme)
{
Expand Down Expand Up @@ -221,6 +223,7 @@ protected virtual void ShowNextStep()
else
{
CurrentStepIndex = null;
Completed = true;
Hide();
}

Expand Down
55 changes: 54 additions & 1 deletion osu.Game/Screens/Edit/Editor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
using osu.Game.Beatmaps.ControlPoints;
using osu.Game.Configuration;
using osu.Game.Database;
using osu.Game.Extensions;
using osu.Game.Graphics.Cursor;
using osu.Game.Graphics.UserInterface;
using osu.Game.Input.Bindings;
Expand All @@ -52,6 +53,7 @@
using osu.Game.Screens.Edit.Design;
using osu.Game.Screens.Edit.GameplayTest;
using osu.Game.Screens.Edit.Setup;
using osu.Game.Screens.Edit.Submission;
using osu.Game.Screens.Edit.Timing;
using osu.Game.Screens.Edit.Verify;
using osu.Game.Screens.OnlinePlay;
Expand Down Expand Up @@ -111,6 +113,10 @@ protected bool HasUnsavedChanges
[Resolved(canBeNull: true)]
private INotificationOverlay notifications { get; set; }

[Resolved(canBeNull: true)]
[CanBeNull]
private LoginOverlay loginOverlay { get; set; }

[Resolved]
private RealmAccess realm { get; set; }

Expand Down Expand Up @@ -1251,11 +1257,22 @@ private IEnumerable<MenuItem> createFileMenuItems()

if (RuntimeInfo.IsDesktop)
{
var externalEdit = new EditorMenuItem("Edit externally", MenuItemType.Standard, editExternally);
var externalEdit = new EditorMenuItem(EditorStrings.EditExternally, MenuItemType.Standard, editExternally);
saveRelatedMenuItems.Add(externalEdit);
yield return externalEdit;
}

bool isSetMadeOfLegacyRulesetBeatmaps = (isNewBeatmap && Ruleset.Value.IsLegacyRuleset())
|| (!isNewBeatmap && Beatmap.Value.BeatmapSetInfo.Beatmaps.All(b => b.Ruleset.IsLegacyRuleset()));
bool submissionAvailable = api.Endpoints.BeatmapSubmissionServiceUrl != null;

if (isSetMadeOfLegacyRulesetBeatmaps && submissionAvailable)
{
var upload = new EditorMenuItem(EditorStrings.SubmitBeatmap, MenuItemType.Standard, submitBeatmap);
saveRelatedMenuItems.Add(upload);
yield return upload;
}

if (editorBeatmap.BeatmapInfo.OnlineID > 0)
{
yield return new OsuMenuItemSpacer();
Expand Down Expand Up @@ -1304,6 +1321,42 @@ void startEdit()
}
}

private void submitBeatmap()
{
if (api.State.Value != APIState.Online)
{
loginOverlay?.Show();
return;
}

if (!editorBeatmap.HitObjects.Any())
{
notifications?.Post(new SimpleNotification
{
Text = BeatmapSubmissionStrings.EmptyBeatmapsCannotBeSubmitted,
});
return;
}

if (HasUnsavedChanges)
{
dialogOverlay.Push(new SaveRequiredPopupDialog(() => attemptMutationOperation(() =>
{
if (!Save())
return false;

startSubmission();
return true;
})));
}
else
{
startSubmission();
}

void startSubmission() => this.Push(new BeatmapSubmissionScreen());
}

private void exportBeatmap(bool legacy)
{
if (HasUnsavedChanges)
Expand Down
12 changes: 9 additions & 3 deletions osu.Game/Screens/Edit/Submission/BeatmapSubmissionOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
// See the LICENCE file in the repository root for full licence text.

using osu.Framework.Allocation;
using osu.Framework.Bindables;
using osu.Game.Beatmaps;
using osu.Game.Overlays;
using osu.Game.Localisation;

Expand All @@ -15,10 +17,14 @@ public BeatmapSubmissionOverlay()
}

[BackgroundDependencyLoader]
private void load()
private void load(IBindable<WorkingBeatmap> beatmap)
{
AddStep<ScreenContentPermissions>();
AddStep<ScreenFrequentlyAskedQuestions>();
if (beatmap.Value.BeatmapSetInfo.OnlineID <= 0)
{
AddStep<ScreenContentPermissions>();
AddStep<ScreenFrequentlyAskedQuestions>();
}

AddStep<ScreenSubmissionSettings>();

Header.Title = BeatmapSubmissionStrings.BeatmapSubmissionTitle;
Expand Down
Loading
Loading