mirror of
https://github.com/ppy/osu.git
synced 2026-06-03 17:23:57 +08:00
Isolate operation of multiplayer mod overlay
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
@@ -27,6 +26,7 @@ using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.Menu;
|
||||
using osu.Game.Screens.OnlinePlay.Match.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||
using osu.Game.Screens.OnlinePlay.Multiplayer.Match;
|
||||
using osu.Game.Utils;
|
||||
using Container = osu.Framework.Graphics.Containers.Container;
|
||||
|
||||
@@ -62,11 +62,6 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
|
||||
private Sample? sampleStart;
|
||||
|
||||
/// <summary>
|
||||
/// Any mods applied by/to the local user.
|
||||
/// </summary>
|
||||
protected readonly Bindable<IReadOnlyList<Mod>> UserMods = new Bindable<IReadOnlyList<Mod>>(Array.Empty<Mod>());
|
||||
|
||||
[Resolved(CanBeNull = true)]
|
||||
private IOverlayManager? overlayManager { get; set; }
|
||||
|
||||
@@ -245,12 +240,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
}
|
||||
};
|
||||
|
||||
LoadComponent(UserModsSelectOverlay = new RoomModSelectOverlay
|
||||
{
|
||||
SelectedItem = { BindTarget = SelectedItem },
|
||||
SelectedMods = { BindTarget = UserMods },
|
||||
IsValidMod = _ => false
|
||||
});
|
||||
LoadComponent(UserModsSelectOverlay = new MultiplayerUserModSelectOverlay());
|
||||
}
|
||||
|
||||
protected override void LoadComplete()
|
||||
@@ -258,7 +248,6 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
base.LoadComplete();
|
||||
|
||||
SelectedItem.BindValueChanged(_ => updateSpecifics());
|
||||
UserMods.BindValueChanged(_ => updateSpecifics());
|
||||
|
||||
beatmapAvailabilityTracker.Availability.BindValueChanged(_ => updateSpecifics());
|
||||
|
||||
@@ -441,11 +430,6 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
? rulesetInstance.AllMods.OfType<Mod>().Where(m => ModUtils.IsValidFreeModForMatchType(m, Room.Type)).ToArray()
|
||||
: item.AllowedMods.Select(m => m.ToMod(rulesetInstance)).ToArray();
|
||||
|
||||
// Remove any user mods that are no longer allowed.
|
||||
Mod[] newUserMods = UserMods.Value.Where(m => allowedMods.Any(a => m.GetType() == a.GetType())).ToArray();
|
||||
if (!newUserMods.SequenceEqual(UserMods.Value))
|
||||
UserMods.Value = newUserMods;
|
||||
|
||||
// Retrieve the corresponding local beatmap, since we can't directly use the playlist's beatmap info
|
||||
int beatmapId = GetGameplayBeatmap().OnlineID;
|
||||
var localBeatmap = beatmapManager.QueryBeatmap($@"{nameof(BeatmapInfo.OnlineID)} == $0 AND {nameof(BeatmapInfo.MD5Hash)} == {nameof(BeatmapInfo.OnlineMD5Hash)}", beatmapId);
|
||||
@@ -456,15 +440,11 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
Ruleset.Value = GetGameplayRuleset();
|
||||
|
||||
if (allowedMods.Length > 0)
|
||||
{
|
||||
UserModsSection.Show();
|
||||
UserModsSelectOverlay.IsValidMod = m => allowedMods.Any(a => a.GetType() == m.GetType());
|
||||
}
|
||||
else
|
||||
{
|
||||
UserModsSection.Hide();
|
||||
UserModsSelectOverlay.Hide();
|
||||
UserModsSelectOverlay.IsValidMod = _ => false;
|
||||
}
|
||||
|
||||
if (item.Freestyle)
|
||||
@@ -488,7 +468,7 @@ namespace osu.Game.Screens.OnlinePlay.Match
|
||||
UserStyleSection.Hide();
|
||||
}
|
||||
|
||||
protected virtual APIMod[] GetGameplayMods() => UserMods.Value.Select(m => new APIMod(m)).Concat(SelectedItem.Value!.RequiredMods).ToArray();
|
||||
protected virtual APIMod[] GetGameplayMods() => SelectedItem.Value!.RequiredMods;
|
||||
|
||||
protected virtual RulesetInfo GetGameplayRuleset() => Rulesets.GetRuleset(SelectedItem.Value!.RulesetID)!;
|
||||
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
using osu.Framework.Bindables;
|
||||
using osu.Framework.Extensions.ObjectExtensions;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Online.Multiplayer;
|
||||
using osu.Game.Online.Rooms;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.OnlinePlay.Match;
|
||||
using osu.Game.Utils;
|
||||
|
||||
namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
||||
{
|
||||
public class MultiplayerUserModSelectOverlay : RoomModSelectOverlay
|
||||
{
|
||||
[Resolved]
|
||||
private MultiplayerClient client { get; set; } = null!;
|
||||
|
||||
[Resolved]
|
||||
private RulesetStore rulesets { get; set; } = null!;
|
||||
|
||||
private ModSettingChangeTracker? modSettingChangeTracker;
|
||||
private ScheduledDelegate? debouncedModSettingsUpdate;
|
||||
|
||||
protected override void LoadComplete()
|
||||
{
|
||||
base.LoadComplete();
|
||||
|
||||
IsValidMod = _ => false;
|
||||
|
||||
client.RoomUpdated += onRoomUpdated;
|
||||
|
||||
SelectedItem.BindValueChanged(_ => updateSpecifics());
|
||||
SelectedMods.BindValueChanged(_ => updateSpecifics());
|
||||
SelectedMods.BindValueChanged(onSelectedModsChanged);
|
||||
}
|
||||
|
||||
private void onRoomUpdated()
|
||||
{
|
||||
if (client.Room == null)
|
||||
return;
|
||||
|
||||
SelectedItem.Value = new PlaylistItem(client.Room.CurrentPlaylistItem);
|
||||
}
|
||||
|
||||
private void onSelectedModsChanged(ValueChangedEvent<IReadOnlyList<Mod>> mods)
|
||||
{
|
||||
modSettingChangeTracker?.Dispose();
|
||||
|
||||
if (client.Room == null)
|
||||
return;
|
||||
|
||||
client.ChangeUserMods(mods.NewValue).FireAndForget();
|
||||
|
||||
modSettingChangeTracker = new ModSettingChangeTracker(mods.NewValue);
|
||||
modSettingChangeTracker.SettingChanged += _ =>
|
||||
{
|
||||
// Debounce changes to mod settings so as to not thrash the network.
|
||||
debouncedModSettingsUpdate?.Cancel();
|
||||
debouncedModSettingsUpdate = Scheduler.AddDelayed(() =>
|
||||
{
|
||||
if (client.Room == null)
|
||||
return;
|
||||
|
||||
client.ChangeUserMods(SelectedMods.Value).FireAndForget();
|
||||
}, 500);
|
||||
};
|
||||
}
|
||||
|
||||
private void updateSpecifics()
|
||||
{
|
||||
if (client.Room == null || client.LocalUser == null)
|
||||
return;
|
||||
|
||||
MultiplayerPlaylistItem currentItem = client.Room.CurrentPlaylistItem;
|
||||
Ruleset ruleset = rulesets.GetRuleset(client.LocalUser.RulesetId ?? currentItem.RulesetID)!.CreateInstance();
|
||||
Mod[] allowedMods = currentItem.Freestyle
|
||||
? ruleset.AllMods.OfType<Mod>().Where(m => ModUtils.IsValidFreeModForMatchType(m, client.Room.Settings.MatchType)).ToArray()
|
||||
: currentItem.AllowedMods.Select(m => m.ToMod(ruleset)).ToArray();
|
||||
|
||||
// Update the mod panels to reflect the ones which are valid for selection.
|
||||
IsValidMod = allowedMods.Length > 0
|
||||
? m => allowedMods.Any(a => a.GetType() == m.GetType())
|
||||
: _ => false;
|
||||
|
||||
// Remove any mods that are no longer allowed.
|
||||
Mod[] newUserMods = SelectedMods.Value.Where(m => allowedMods.Any(a => m.GetType() == a.GetType())).ToArray();
|
||||
if (!newUserMods.SequenceEqual(SelectedMods.Value))
|
||||
SelectedMods.Value = newUserMods;
|
||||
}
|
||||
|
||||
protected override void Dispose(bool isDisposing)
|
||||
{
|
||||
base.Dispose(isDisposing);
|
||||
|
||||
if (client.IsNotNull())
|
||||
client.RoomUpdated -= onRoomUpdated;
|
||||
|
||||
modSettingChangeTracker?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
||||
// See the LICENCE file in the repository root for full licence text.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Allocation;
|
||||
@@ -11,9 +10,7 @@ using osu.Framework.Graphics;
|
||||
using osu.Framework.Graphics.Containers;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Framework.Screens;
|
||||
using osu.Framework.Threading;
|
||||
using osu.Game.Beatmaps;
|
||||
using osu.Game.Configuration;
|
||||
using osu.Game.Graphics.Cursor;
|
||||
using osu.Game.Online;
|
||||
using osu.Game.Online.API;
|
||||
@@ -23,7 +20,6 @@ using osu.Game.Online.Rooms;
|
||||
using osu.Game.Overlays;
|
||||
using osu.Game.Overlays.Dialog;
|
||||
using osu.Game.Rulesets;
|
||||
using osu.Game.Rulesets.Mods;
|
||||
using osu.Game.Screens.OnlinePlay.Components;
|
||||
using osu.Game.Screens.OnlinePlay.Match;
|
||||
using osu.Game.Screens.OnlinePlay.Match.Components;
|
||||
@@ -64,7 +60,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
base.LoadComplete();
|
||||
|
||||
BeatmapAvailability.BindValueChanged(updateBeatmapAvailability, true);
|
||||
UserMods.BindValueChanged(onUserModsChanged);
|
||||
|
||||
client.LoadRequested += onLoadRequested;
|
||||
client.RoomUpdated += onRoomUpdated;
|
||||
@@ -306,35 +301,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
|
||||
protected override void PartRoom() => client.LeaveRoom();
|
||||
|
||||
private ModSettingChangeTracker? modSettingChangeTracker;
|
||||
private ScheduledDelegate? debouncedModSettingsUpdate;
|
||||
|
||||
private void onUserModsChanged(ValueChangedEvent<IReadOnlyList<Mod>> mods)
|
||||
{
|
||||
modSettingChangeTracker?.Dispose();
|
||||
|
||||
if (client.Room == null)
|
||||
return;
|
||||
|
||||
client.ChangeUserMods(mods.NewValue).FireAndForget();
|
||||
|
||||
modSettingChangeTracker = new ModSettingChangeTracker(mods.NewValue);
|
||||
modSettingChangeTracker.SettingChanged += onModSettingsChanged;
|
||||
}
|
||||
|
||||
private void onModSettingsChanged(Mod mod)
|
||||
{
|
||||
// Debounce changes to mod settings so as to not thrash the network.
|
||||
debouncedModSettingsUpdate?.Cancel();
|
||||
debouncedModSettingsUpdate = Scheduler.AddDelayed(() =>
|
||||
{
|
||||
if (client.Room == null)
|
||||
return;
|
||||
|
||||
client.ChangeUserMods(UserMods.Value).FireAndForget();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
private void updateBeatmapAvailability(ValueChangedEvent<BeatmapAvailability> availability)
|
||||
{
|
||||
if (client.Room == null)
|
||||
@@ -462,8 +428,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||
client.RoomUpdated -= onRoomUpdated;
|
||||
client.LoadRequested -= onLoadRequested;
|
||||
}
|
||||
|
||||
modSettingChangeTracker?.Dispose();
|
||||
}
|
||||
|
||||
public partial class AddItemButton : PurpleRoundedButton
|
||||
|
||||
Reference in New Issue
Block a user