mirror of
https://github.com/ppy/osu.git
synced 2025-01-14 20:13:22 +08:00
Merge branch 'master' into lounge-redesign
This commit is contained in:
commit
0246e6f850
@ -52,7 +52,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.803.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.803.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.804.0" />
|
<PackageReference Include="ppy.osu.Framework.Android" Version="2021.805.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Transitive Dependencies">
|
<ItemGroup Label="Transitive Dependencies">
|
||||||
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
<!-- Realm needs to be directly referenced in all Xamarin projects, as it will not pull in its transitive dependencies otherwise. -->
|
||||||
|
@ -8,6 +8,7 @@ using osu.Framework.Allocation;
|
|||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
using osu.Framework.Graphics.UserInterface;
|
using osu.Framework.Graphics.UserInterface;
|
||||||
|
using osu.Framework.Input;
|
||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Framework.Screens;
|
using osu.Framework.Screens;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
@ -88,6 +89,28 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
// used to test the flow of multiplayer from visual tests.
|
// used to test the flow of multiplayer from visual tests.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCreateRoomViaKeyboard()
|
||||||
|
{
|
||||||
|
// create room dialog
|
||||||
|
AddStep("Press new document", () => InputManager.Keys(PlatformAction.DocumentNew));
|
||||||
|
AddUntilStep("wait for settings", () => InputManager.ChildrenOfType<MultiplayerMatchSettingsOverlay>().FirstOrDefault() != null);
|
||||||
|
|
||||||
|
// edit playlist item
|
||||||
|
AddStep("Press select", () => InputManager.Key(Key.Enter));
|
||||||
|
AddUntilStep("wait for song select", () => InputManager.ChildrenOfType<MultiplayerMatchSongSelect>().FirstOrDefault() != null);
|
||||||
|
|
||||||
|
// select beatmap
|
||||||
|
AddStep("Press select", () => InputManager.Key(Key.Enter));
|
||||||
|
AddUntilStep("wait for return to screen", () => InputManager.ChildrenOfType<MultiplayerMatchSongSelect>().FirstOrDefault() == null);
|
||||||
|
|
||||||
|
// create room
|
||||||
|
AddStep("Press select", () => InputManager.Key(Key.Enter));
|
||||||
|
|
||||||
|
AddUntilStep("wait for room open", () => this.ChildrenOfType<MultiplayerMatchSubScreen>().FirstOrDefault()?.IsLoaded == true);
|
||||||
|
AddUntilStep("wait for join", () => client.Room != null);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestCreateRoomWithoutPassword()
|
public void TestCreateRoomWithoutPassword()
|
||||||
{
|
{
|
||||||
|
191
osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs
Normal file
191
osu.Game.Tests/Visual/Multiplayer/TestSceneTeamVersus.cs
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
// 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;
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Audio;
|
||||||
|
using osu.Framework.Platform;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Database;
|
||||||
|
using osu.Game.Online.Multiplayer;
|
||||||
|
using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus;
|
||||||
|
using osu.Game.Online.Rooms;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Osu;
|
||||||
|
using osu.Game.Screens;
|
||||||
|
using osu.Game.Screens.OnlinePlay.Components;
|
||||||
|
using osu.Game.Screens.OnlinePlay.Multiplayer;
|
||||||
|
using osu.Game.Screens.OnlinePlay.Multiplayer.Match;
|
||||||
|
using osu.Game.Screens.OnlinePlay.Multiplayer.Participants;
|
||||||
|
using osu.Game.Tests.Resources;
|
||||||
|
using osuTK.Input;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.Multiplayer
|
||||||
|
{
|
||||||
|
public class TestSceneTeamVersus : ScreenTestScene
|
||||||
|
{
|
||||||
|
private BeatmapManager beatmaps;
|
||||||
|
private RulesetStore rulesets;
|
||||||
|
private BeatmapSetInfo importedSet;
|
||||||
|
|
||||||
|
private DependenciesScreen dependenciesScreen;
|
||||||
|
private TestMultiplayer multiplayerScreen;
|
||||||
|
private TestMultiplayerClient client;
|
||||||
|
|
||||||
|
[Cached(typeof(UserLookupCache))]
|
||||||
|
private UserLookupCache lookupCache = new TestUserLookupCache();
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load(GameHost host, AudioManager audio)
|
||||||
|
{
|
||||||
|
Dependencies.Cache(rulesets = new RulesetStore(ContextFactory));
|
||||||
|
Dependencies.Cache(beatmaps = new BeatmapManager(LocalStorage, ContextFactory, rulesets, null, audio, Resources, host, Beatmap.Default));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void SetUpSteps()
|
||||||
|
{
|
||||||
|
base.SetUpSteps();
|
||||||
|
|
||||||
|
AddStep("import beatmap", () =>
|
||||||
|
{
|
||||||
|
beatmaps.Import(TestResources.GetQuickTestBeatmapForImport()).Wait();
|
||||||
|
importedSet = beatmaps.GetAllUsableBeatmapSetsEnumerable(IncludedDetails.All).First();
|
||||||
|
});
|
||||||
|
|
||||||
|
AddStep("create multiplayer screen", () => multiplayerScreen = new TestMultiplayer());
|
||||||
|
|
||||||
|
AddStep("load dependencies", () =>
|
||||||
|
{
|
||||||
|
client = new TestMultiplayerClient(multiplayerScreen.RoomManager);
|
||||||
|
|
||||||
|
// The screen gets suspended so it stops receiving updates.
|
||||||
|
Child = client;
|
||||||
|
|
||||||
|
LoadScreen(dependenciesScreen = new DependenciesScreen(client));
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("wait for dependencies to load", () => dependenciesScreen.IsLoaded);
|
||||||
|
|
||||||
|
AddStep("load multiplayer", () => LoadScreen(multiplayerScreen));
|
||||||
|
AddUntilStep("wait for multiplayer to load", () => multiplayerScreen.IsLoaded);
|
||||||
|
AddUntilStep("wait for lounge to load", () => this.ChildrenOfType<MultiplayerLoungeSubScreen>().FirstOrDefault()?.IsLoaded == true);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestCreateWithType()
|
||||||
|
{
|
||||||
|
createRoom(() => new Room
|
||||||
|
{
|
||||||
|
Name = { Value = "Test Room" },
|
||||||
|
Type = { Value = MatchType.TeamVersus },
|
||||||
|
Playlist =
|
||||||
|
{
|
||||||
|
new PlaylistItem
|
||||||
|
{
|
||||||
|
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.RulesetID == 0)).BeatmapInfo },
|
||||||
|
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("room type is team vs", () => client.Room?.Settings.MatchType == MatchType.TeamVersus);
|
||||||
|
AddAssert("user state arrived", () => client.Room?.Users.FirstOrDefault()?.MatchState is TeamVersusUserState);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestChangeTeamsViaButton()
|
||||||
|
{
|
||||||
|
createRoom(() => new Room
|
||||||
|
{
|
||||||
|
Name = { Value = "Test Room" },
|
||||||
|
Type = { Value = MatchType.TeamVersus },
|
||||||
|
Playlist =
|
||||||
|
{
|
||||||
|
new PlaylistItem
|
||||||
|
{
|
||||||
|
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.RulesetID == 0)).BeatmapInfo },
|
||||||
|
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("user on team 0", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0);
|
||||||
|
|
||||||
|
AddStep("press button", () =>
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(multiplayerScreen.ChildrenOfType<TeamDisplay>().First());
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
AddAssert("user on team 1", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 1);
|
||||||
|
|
||||||
|
AddStep("press button", () => InputManager.Click(MouseButton.Left));
|
||||||
|
AddAssert("user on team 0", () => (client.Room?.Users.FirstOrDefault()?.MatchState as TeamVersusUserState)?.TeamID == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestChangeTypeViaMatchSettings()
|
||||||
|
{
|
||||||
|
createRoom(() => new Room
|
||||||
|
{
|
||||||
|
Name = { Value = "Test Room" },
|
||||||
|
Playlist =
|
||||||
|
{
|
||||||
|
new PlaylistItem
|
||||||
|
{
|
||||||
|
Beatmap = { Value = beatmaps.GetWorkingBeatmap(importedSet.Beatmaps.First(b => b.RulesetID == 0)).BeatmapInfo },
|
||||||
|
Ruleset = { Value = new OsuRuleset().RulesetInfo },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("room type is head to head", () => client.Room?.Settings.MatchType == MatchType.HeadToHead);
|
||||||
|
|
||||||
|
AddStep("change to team vs", () => client.ChangeSettings(matchType: MatchType.TeamVersus));
|
||||||
|
|
||||||
|
AddAssert("room type is team vs", () => client.Room?.Settings.MatchType == MatchType.TeamVersus);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createRoom(Func<Room> room)
|
||||||
|
{
|
||||||
|
AddStep("open room", () =>
|
||||||
|
{
|
||||||
|
multiplayerScreen.OpenNewRoom(room());
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("wait for room open", () => this.ChildrenOfType<MultiplayerMatchSubScreen>().FirstOrDefault()?.IsLoaded == true);
|
||||||
|
AddWaitStep("wait for transition", 2);
|
||||||
|
|
||||||
|
AddStep("create room", () =>
|
||||||
|
{
|
||||||
|
InputManager.MoveMouseTo(this.ChildrenOfType<MultiplayerMatchSettingsOverlay.CreateOrUpdateButton>().Single());
|
||||||
|
InputManager.Click(MouseButton.Left);
|
||||||
|
});
|
||||||
|
|
||||||
|
AddUntilStep("wait for join", () => client.Room != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used for the sole purpose of adding <see cref="TestMultiplayerClient"/> as a resolvable dependency.
|
||||||
|
/// </summary>
|
||||||
|
private class DependenciesScreen : OsuScreen
|
||||||
|
{
|
||||||
|
[Cached(typeof(MultiplayerClient))]
|
||||||
|
public readonly TestMultiplayerClient Client;
|
||||||
|
|
||||||
|
public DependenciesScreen(TestMultiplayerClient client)
|
||||||
|
{
|
||||||
|
Client = client;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TestMultiplayer : Screens.OnlinePlay.Multiplayer.Multiplayer
|
||||||
|
{
|
||||||
|
public new TestRequestHandlingMultiplayerRoomManager RoomManager { get; private set; }
|
||||||
|
|
||||||
|
protected override RoomManager CreateRoomManager() => RoomManager = new TestRequestHandlingMultiplayerRoomManager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -7,6 +7,7 @@ using System.IO;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Audio;
|
using osu.Framework.Audio;
|
||||||
|
using osu.Framework.Audio.Mixing;
|
||||||
using osu.Framework.Audio.Track;
|
using osu.Framework.Audio.Track;
|
||||||
using osu.Framework.Bindables;
|
using osu.Framework.Bindables;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
@ -30,11 +31,11 @@ namespace osu.Game.Audio
|
|||||||
private readonly BindableNumber<double> globalTrackVolumeAdjust = new BindableNumber<double>(OsuGameBase.GLOBAL_TRACK_VOLUME_ADJUST);
|
private readonly BindableNumber<double> globalTrackVolumeAdjust = new BindableNumber<double>(OsuGameBase.GLOBAL_TRACK_VOLUME_ADJUST);
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load(AudioManager audioManager)
|
||||||
{
|
{
|
||||||
// this is a temporary solution to get around muting ourselves.
|
// this is a temporary solution to get around muting ourselves.
|
||||||
// todo: update this once we have a BackgroundTrackManager or similar.
|
// todo: update this once we have a BackgroundTrackManager or similar.
|
||||||
trackStore = new PreviewTrackStore(new OnlineStore());
|
trackStore = new PreviewTrackStore(audioManager.Mixer, new OnlineStore());
|
||||||
|
|
||||||
audio.AddItem(trackStore);
|
audio.AddItem(trackStore);
|
||||||
trackStore.AddAdjustment(AdjustableProperty.Volume, globalTrackVolumeAdjust);
|
trackStore.AddAdjustment(AdjustableProperty.Volume, globalTrackVolumeAdjust);
|
||||||
@ -118,10 +119,12 @@ namespace osu.Game.Audio
|
|||||||
|
|
||||||
private class PreviewTrackStore : AudioCollectionManager<AdjustableAudioComponent>, ITrackStore
|
private class PreviewTrackStore : AudioCollectionManager<AdjustableAudioComponent>, ITrackStore
|
||||||
{
|
{
|
||||||
|
private readonly AudioMixer defaultMixer;
|
||||||
private readonly IResourceStore<byte[]> store;
|
private readonly IResourceStore<byte[]> store;
|
||||||
|
|
||||||
internal PreviewTrackStore(IResourceStore<byte[]> store)
|
internal PreviewTrackStore(AudioMixer defaultMixer, IResourceStore<byte[]> store)
|
||||||
{
|
{
|
||||||
|
this.defaultMixer = defaultMixer;
|
||||||
this.store = store;
|
this.store = store;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,8 +148,12 @@ namespace osu.Game.Audio
|
|||||||
if (dataStream == null)
|
if (dataStream == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
// Todo: This is quite unsafe. TrackBass shouldn't be exposed as public.
|
||||||
Track track = new TrackBass(dataStream);
|
Track track = new TrackBass(dataStream);
|
||||||
|
|
||||||
|
defaultMixer.Add(track);
|
||||||
AddItem(track);
|
AddItem(track);
|
||||||
|
|
||||||
return track;
|
return track;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,6 +142,8 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
APIRoom = room;
|
APIRoom = room;
|
||||||
foreach (var user in joinedRoom.Users)
|
foreach (var user in joinedRoom.Users)
|
||||||
updateUserPlayingState(user.UserID, user.State);
|
updateUserPlayingState(user.UserID, user.State);
|
||||||
|
|
||||||
|
OnRoomJoined();
|
||||||
}, cancellationSource.Token).ConfigureAwait(false);
|
}, cancellationSource.Token).ConfigureAwait(false);
|
||||||
|
|
||||||
// Update room settings.
|
// Update room settings.
|
||||||
@ -149,6 +151,13 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
}, cancellationSource.Token).ConfigureAwait(false);
|
}, cancellationSource.Token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fired when the room join sequence is complete
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void OnRoomJoined()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Joins the <see cref="MultiplayerRoom"/> with a given ID.
|
/// Joins the <see cref="MultiplayerRoom"/> with a given ID.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -192,8 +201,9 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
/// </remarks>
|
/// </remarks>
|
||||||
/// <param name="name">The new room name, if any.</param>
|
/// <param name="name">The new room name, if any.</param>
|
||||||
/// <param name="password">The new password, if any.</param>
|
/// <param name="password">The new password, if any.</param>
|
||||||
|
/// <param name="matchType">The type of the match, if any.</param>
|
||||||
/// <param name="item">The new room playlist item, if any.</param>
|
/// <param name="item">The new room playlist item, if any.</param>
|
||||||
public Task ChangeSettings(Optional<string> name = default, Optional<string> password = default, Optional<PlaylistItem> item = default)
|
public Task ChangeSettings(Optional<string> name = default, Optional<string> password = default, Optional<MatchType> matchType = default, Optional<PlaylistItem> item = default)
|
||||||
{
|
{
|
||||||
if (Room == null)
|
if (Room == null)
|
||||||
throw new InvalidOperationException("Must be joined to a match to change settings.");
|
throw new InvalidOperationException("Must be joined to a match to change settings.");
|
||||||
@ -219,6 +229,7 @@ namespace osu.Game.Online.Multiplayer
|
|||||||
BeatmapID = item.GetOr(existingPlaylistItem).BeatmapID,
|
BeatmapID = item.GetOr(existingPlaylistItem).BeatmapID,
|
||||||
BeatmapChecksum = item.GetOr(existingPlaylistItem).Beatmap.Value.MD5Hash,
|
BeatmapChecksum = item.GetOr(existingPlaylistItem).Beatmap.Value.MD5Hash,
|
||||||
RulesetID = item.GetOr(existingPlaylistItem).RulesetID,
|
RulesetID = item.GetOr(existingPlaylistItem).RulesetID,
|
||||||
|
MatchType = matchType.GetOr(Room.Settings.MatchType),
|
||||||
RequiredMods = item.HasValue ? item.Value.AsNonNull().RequiredMods.Select(m => new APIMod(m)).ToList() : Room.Settings.RequiredMods,
|
RequiredMods = item.HasValue ? item.Value.AsNonNull().RequiredMods.Select(m => new APIMod(m)).ToList() : Room.Settings.RequiredMods,
|
||||||
AllowedMods = item.HasValue ? item.Value.AsNonNull().AllowedMods.Select(m => new APIMod(m)).ToList() : Room.Settings.AllowedMods,
|
AllowedMods = item.HasValue ? item.Value.AsNonNull().AllowedMods.Select(m => new APIMod(m)).ToList() : Room.Settings.AllowedMods,
|
||||||
});
|
});
|
||||||
|
@ -9,7 +9,7 @@ namespace osu.Game.Screens.OnlinePlay.Components
|
|||||||
{
|
{
|
||||||
public abstract class DisableableTabControl<T> : TabControl<T>
|
public abstract class DisableableTabControl<T> : TabControl<T>
|
||||||
{
|
{
|
||||||
public readonly BindableBool Enabled = new BindableBool();
|
public readonly BindableBool Enabled = new BindableBool(true);
|
||||||
|
|
||||||
protected override void AddTabItem(TabItem<T> tab, bool addToDropdown = true)
|
protected override void AddTabItem(TabItem<T> tab, bool addToDropdown = true)
|
||||||
{
|
{
|
||||||
|
@ -0,0 +1,39 @@
|
|||||||
|
// 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 osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Input;
|
||||||
|
using osu.Framework.Input.Bindings;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.OnlinePlay.Match.Components
|
||||||
|
{
|
||||||
|
public abstract class CreateRoomButton : PurpleTriangleButton, IKeyBindingHandler<PlatformAction>
|
||||||
|
{
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
Triangles.TriangleScale = 1.5f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool OnPressed(PlatformAction action)
|
||||||
|
{
|
||||||
|
if (!Enabled.Value)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case PlatformAction.DocumentNew:
|
||||||
|
// might as well also handle new tab. it's a bit of an undefined flow on this screen.
|
||||||
|
case PlatformAction.TabNew:
|
||||||
|
TriggerClick();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnReleased(PlatformAction action)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,15 +4,17 @@
|
|||||||
using osu.Framework.Allocation;
|
using osu.Framework.Allocation;
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Graphics.Containers;
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Input.Bindings;
|
||||||
using osu.Game.Graphics;
|
using osu.Game.Graphics;
|
||||||
using osu.Game.Graphics.Sprites;
|
using osu.Game.Graphics.Sprites;
|
||||||
using osu.Game.Graphics.UserInterface;
|
using osu.Game.Graphics.UserInterface;
|
||||||
|
using osu.Game.Input.Bindings;
|
||||||
using osuTK;
|
using osuTK;
|
||||||
using osuTK.Graphics;
|
using osuTK.Graphics;
|
||||||
|
|
||||||
namespace osu.Game.Screens.OnlinePlay.Match.Components
|
namespace osu.Game.Screens.OnlinePlay.Match.Components
|
||||||
{
|
{
|
||||||
public abstract class MatchSettingsOverlay : FocusedOverlayContainer
|
public abstract class MatchSettingsOverlay : FocusedOverlayContainer, IKeyBindingHandler<GlobalAction>
|
||||||
{
|
{
|
||||||
protected const float TRANSITION_DURATION = 350;
|
protected const float TRANSITION_DURATION = 350;
|
||||||
protected const float FIELD_PADDING = 45;
|
protected const float FIELD_PADDING = 45;
|
||||||
@ -21,6 +23,10 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
|
|||||||
|
|
||||||
protected override bool BlockScrollInput => false;
|
protected override bool BlockScrollInput => false;
|
||||||
|
|
||||||
|
protected abstract OsuButton SubmitButton { get; }
|
||||||
|
|
||||||
|
protected abstract bool IsLoading { get; }
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
@ -29,6 +35,8 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
|
|||||||
Add(Settings = CreateSettings());
|
Add(Settings = CreateSettings());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract void SelectBeatmap();
|
||||||
|
|
||||||
protected abstract OnlinePlayComposite CreateSettings();
|
protected abstract OnlinePlayComposite CreateSettings();
|
||||||
|
|
||||||
protected override void PopIn()
|
protected override void PopIn()
|
||||||
@ -41,6 +49,33 @@ namespace osu.Game.Screens.OnlinePlay.Match.Components
|
|||||||
Settings.MoveToY(-1, TRANSITION_DURATION, Easing.InSine);
|
Settings.MoveToY(-1, TRANSITION_DURATION, Easing.InSine);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool OnPressed(GlobalAction action)
|
||||||
|
{
|
||||||
|
switch (action)
|
||||||
|
{
|
||||||
|
case GlobalAction.Select:
|
||||||
|
if (IsLoading)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (SubmitButton.Enabled.Value)
|
||||||
|
{
|
||||||
|
SubmitButton.TriggerClick();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SelectBeatmap();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnReleased(GlobalAction action)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
protected class SettingsTextBox : OsuTextBox
|
protected class SettingsTextBox : OsuTextBox
|
||||||
{
|
{
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
|
@ -8,7 +8,7 @@ using osu.Game.Screens.OnlinePlay.Match.Components;
|
|||||||
|
|
||||||
namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
||||||
{
|
{
|
||||||
public class CreateMultiplayerMatchButton : PurpleTriangleButton
|
public class CreateMultiplayerMatchButton : CreateRoomButton
|
||||||
{
|
{
|
||||||
private IBindable<bool> isConnected;
|
private IBindable<bool> isConnected;
|
||||||
private IBindable<bool> operationInProgress;
|
private IBindable<bool> operationInProgress;
|
||||||
@ -22,9 +22,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
|||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
Triangles.TriangleScale = 1.5f;
|
|
||||||
SpriteText.Font = SpriteText.Font.With(size: 14);
|
SpriteText.Font = SpriteText.Font.With(size: 14);
|
||||||
|
|
||||||
Text = "Create room";
|
Text = "Create room";
|
||||||
|
|
||||||
isConnected = multiplayerClient.IsConnected.GetBoundCopy();
|
isConnected = multiplayerClient.IsConnected.GetBoundCopy();
|
||||||
|
@ -47,7 +47,11 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
|||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Height = 40,
|
Height = 40,
|
||||||
Text = "Select beatmap",
|
Text = "Select beatmap",
|
||||||
Action = () => matchSubScreen.Push(new MultiplayerMatchSongSelect()),
|
Action = () =>
|
||||||
|
{
|
||||||
|
if (matchSubScreen.IsCurrentScreen())
|
||||||
|
matchSubScreen.Push(new MultiplayerMatchSongSelect());
|
||||||
|
},
|
||||||
Alpha = 0
|
Alpha = 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -68,6 +72,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
|||||||
}, true);
|
}, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void BeginSelection() => selectButton.TriggerClick();
|
||||||
|
|
||||||
private void updateBeatmap()
|
private void updateBeatmap()
|
||||||
{
|
{
|
||||||
if (SelectedItem.Value == null)
|
if (SelectedItem.Value == null)
|
||||||
|
@ -28,8 +28,19 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
|||||||
{
|
{
|
||||||
public class MultiplayerMatchSettingsOverlay : MatchSettingsOverlay
|
public class MultiplayerMatchSettingsOverlay : MatchSettingsOverlay
|
||||||
{
|
{
|
||||||
|
private MatchSettings settings;
|
||||||
|
|
||||||
|
protected override OsuButton SubmitButton => settings.ApplyButton;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OngoingOperationTracker ongoingOperationTracker { get; set; }
|
||||||
|
|
||||||
|
protected override bool IsLoading => ongoingOperationTracker.InProgress.Value;
|
||||||
|
|
||||||
|
protected override void SelectBeatmap() => settings.SelectBeatmap();
|
||||||
|
|
||||||
protected override OnlinePlayComposite CreateSettings()
|
protected override OnlinePlayComposite CreateSettings()
|
||||||
=> new MatchSettings
|
=> settings = new MatchSettings
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
RelativePositionAxes = Axes.Y,
|
RelativePositionAxes = Axes.Y,
|
||||||
@ -54,6 +65,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
|||||||
private LoadingLayer loadingLayer;
|
private LoadingLayer loadingLayer;
|
||||||
private BeatmapSelectionControl initialBeatmapControl;
|
private BeatmapSelectionControl initialBeatmapControl;
|
||||||
|
|
||||||
|
public void SelectBeatmap() => initialBeatmapControl.BeginSelection();
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private IRoomManager manager { get; set; }
|
private IRoomManager manager { get; set; }
|
||||||
|
|
||||||
@ -149,7 +162,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
|||||||
},
|
},
|
||||||
new Section("Game type")
|
new Section("Game type")
|
||||||
{
|
{
|
||||||
Alpha = disabled_alpha,
|
|
||||||
Child = new FillFlowContainer
|
Child = new FillFlowContainer
|
||||||
{
|
{
|
||||||
AutoSizeAxes = Axes.Y,
|
AutoSizeAxes = Axes.Y,
|
||||||
@ -161,7 +173,6 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
|||||||
TypePicker = new MatchTypePicker
|
TypePicker = new MatchTypePicker
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Enabled = { Value = false }
|
|
||||||
},
|
},
|
||||||
typeLabel = new OsuSpriteText
|
typeLabel = new OsuSpriteText
|
||||||
{
|
{
|
||||||
@ -305,7 +316,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match
|
|||||||
// Otherwise, update the room directly in preparation for it to be submitted to the API on match creation.
|
// Otherwise, update the room directly in preparation for it to be submitted to the API on match creation.
|
||||||
if (client.Room != null)
|
if (client.Room != null)
|
||||||
{
|
{
|
||||||
client.ChangeSettings(name: NameField.Text, password: PasswordTextBox.Text).ContinueWith(t => Schedule(() =>
|
client.ChangeSettings(name: NameField.Text, password: PasswordTextBox.Text, matchType: TypePicker.Current.Value).ContinueWith(t => Schedule(() =>
|
||||||
{
|
{
|
||||||
if (t.IsCompletedSuccessfully)
|
if (t.IsCompletedSuccessfully)
|
||||||
onSuccess(currentRoom.Value);
|
onSuccess(currentRoom.Value);
|
||||||
|
@ -28,7 +28,8 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer
|
|||||||
protected override Room CreateNewRoom() => new Room
|
protected override Room CreateNewRoom() => new Room
|
||||||
{
|
{
|
||||||
Name = { Value = $"{api.LocalUser}'s awesome room" },
|
Name = { Value = $"{api.LocalUser}'s awesome room" },
|
||||||
Category = { Value = RoomCategory.Realtime }
|
Category = { Value = RoomCategory.Realtime },
|
||||||
|
Type = { Value = MatchType.HeadToHead },
|
||||||
};
|
};
|
||||||
|
|
||||||
protected override RoomSubScreen CreateRoomSubScreen(Room room) => new MultiplayerMatchSubScreen(room);
|
protected override RoomSubScreen CreateRoomSubScreen(Room room) => new MultiplayerMatchSubScreen(room);
|
||||||
|
@ -37,6 +37,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
|
|||||||
private RulesetStore rulesets { get; set; }
|
private RulesetStore rulesets { get; set; }
|
||||||
|
|
||||||
private SpriteIcon crown;
|
private SpriteIcon crown;
|
||||||
|
|
||||||
private OsuSpriteText userRankText;
|
private OsuSpriteText userRankText;
|
||||||
private ModDisplay userModsDisplay;
|
private ModDisplay userModsDisplay;
|
||||||
private StateDisplay userStateDisplay;
|
private StateDisplay userStateDisplay;
|
||||||
@ -56,99 +57,108 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
|
|||||||
|
|
||||||
var backgroundColour = Color4Extensions.FromHex("#33413C");
|
var backgroundColour = Color4Extensions.FromHex("#33413C");
|
||||||
|
|
||||||
InternalChildren = new Drawable[]
|
InternalChild = new GridContainer
|
||||||
{
|
{
|
||||||
crown = new SpriteIcon
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
ColumnDimensions = new[]
|
||||||
{
|
{
|
||||||
Anchor = Anchor.CentreLeft,
|
new Dimension(GridSizeMode.Absolute, 18),
|
||||||
Origin = Anchor.CentreLeft,
|
new Dimension(GridSizeMode.AutoSize),
|
||||||
Icon = FontAwesome.Solid.Crown,
|
new Dimension()
|
||||||
Size = new Vector2(14),
|
|
||||||
Colour = Color4Extensions.FromHex("#F7E65D"),
|
|
||||||
Alpha = 0
|
|
||||||
},
|
},
|
||||||
new Container
|
Content = new[]
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
new Drawable[]
|
||||||
Padding = new MarginPadding { Left = 24 },
|
|
||||||
Child = new Container
|
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
crown = new SpriteIcon
|
||||||
Masking = true,
|
|
||||||
CornerRadius = 5,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
{
|
||||||
new Box
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Icon = FontAwesome.Solid.Crown,
|
||||||
|
Size = new Vector2(14),
|
||||||
|
Colour = Color4Extensions.FromHex("#F7E65D"),
|
||||||
|
Alpha = 0
|
||||||
|
},
|
||||||
|
new TeamDisplay(user),
|
||||||
|
new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Masking = true,
|
||||||
|
CornerRadius = 5,
|
||||||
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
new Box
|
||||||
Colour = backgroundColour
|
|
||||||
},
|
|
||||||
new UserCoverBackground
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreRight,
|
|
||||||
Origin = Anchor.CentreRight,
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Width = 0.75f,
|
|
||||||
User = user,
|
|
||||||
Colour = ColourInfo.GradientHorizontal(Color4.White.Opacity(0), Color4.White.Opacity(0.25f))
|
|
||||||
},
|
|
||||||
new FillFlowContainer
|
|
||||||
{
|
|
||||||
RelativeSizeAxes = Axes.Both,
|
|
||||||
Spacing = new Vector2(10),
|
|
||||||
Direction = FillDirection.Horizontal,
|
|
||||||
Children = new Drawable[]
|
|
||||||
{
|
{
|
||||||
new UpdateableAvatar
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Colour = backgroundColour
|
||||||
|
},
|
||||||
|
new UserCoverBackground
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreRight,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Width = 0.75f,
|
||||||
|
User = user,
|
||||||
|
Colour = ColourInfo.GradientHorizontal(Color4.White.Opacity(0), Color4.White.Opacity(0.25f))
|
||||||
|
},
|
||||||
|
new FillFlowContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Spacing = new Vector2(10),
|
||||||
|
Direction = FillDirection.Horizontal,
|
||||||
|
Children = new Drawable[]
|
||||||
{
|
{
|
||||||
Anchor = Anchor.CentreLeft,
|
new UpdateableAvatar
|
||||||
Origin = Anchor.CentreLeft,
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
Anchor = Anchor.CentreLeft,
|
||||||
FillMode = FillMode.Fit,
|
Origin = Anchor.CentreLeft,
|
||||||
User = user
|
RelativeSizeAxes = Axes.Both,
|
||||||
},
|
FillMode = FillMode.Fit,
|
||||||
new UpdateableFlag
|
User = user
|
||||||
{
|
},
|
||||||
Anchor = Anchor.CentreLeft,
|
new UpdateableFlag
|
||||||
Origin = Anchor.CentreLeft,
|
{
|
||||||
Size = new Vector2(30, 20),
|
Anchor = Anchor.CentreLeft,
|
||||||
Country = user?.Country
|
Origin = Anchor.CentreLeft,
|
||||||
},
|
Size = new Vector2(30, 20),
|
||||||
new OsuSpriteText
|
Country = user?.Country
|
||||||
{
|
},
|
||||||
Anchor = Anchor.CentreLeft,
|
new OsuSpriteText
|
||||||
Origin = Anchor.CentreLeft,
|
{
|
||||||
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 18),
|
Anchor = Anchor.CentreLeft,
|
||||||
Text = user?.Username
|
Origin = Anchor.CentreLeft,
|
||||||
},
|
Font = OsuFont.GetFont(weight: FontWeight.Bold, size: 18),
|
||||||
userRankText = new OsuSpriteText
|
Text = user?.Username
|
||||||
{
|
},
|
||||||
Anchor = Anchor.CentreLeft,
|
userRankText = new OsuSpriteText
|
||||||
Origin = Anchor.CentreLeft,
|
{
|
||||||
Font = OsuFont.GetFont(size: 14),
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Origin = Anchor.CentreLeft,
|
||||||
|
Font = OsuFont.GetFont(size: 14),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
new Container
|
||||||
new Container
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreRight,
|
|
||||||
Origin = Anchor.CentreRight,
|
|
||||||
AutoSizeAxes = Axes.Both,
|
|
||||||
Margin = new MarginPadding { Right = 70 },
|
|
||||||
Child = userModsDisplay = new ModDisplay
|
|
||||||
{
|
{
|
||||||
Scale = new Vector2(0.5f),
|
Anchor = Anchor.CentreRight,
|
||||||
ExpansionMode = ExpansionMode.AlwaysContracted,
|
Origin = Anchor.CentreRight,
|
||||||
|
AutoSizeAxes = Axes.Both,
|
||||||
|
Margin = new MarginPadding { Right = 70 },
|
||||||
|
Child = userModsDisplay = new ModDisplay
|
||||||
|
{
|
||||||
|
Scale = new Vector2(0.5f),
|
||||||
|
ExpansionMode = ExpansionMode.AlwaysContracted,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
userStateDisplay = new StateDisplay
|
||||||
|
{
|
||||||
|
Anchor = Anchor.CentreRight,
|
||||||
|
Origin = Anchor.CentreRight,
|
||||||
|
Margin = new MarginPadding { Right = 10 },
|
||||||
}
|
}
|
||||||
},
|
|
||||||
userStateDisplay = new StateDisplay
|
|
||||||
{
|
|
||||||
Anchor = Anchor.CentreRight,
|
|
||||||
Origin = Anchor.CentreRight,
|
|
||||||
Margin = new MarginPadding { Right = 10 },
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,134 @@
|
|||||||
|
// 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.Linq;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics;
|
||||||
|
using osu.Framework.Graphics.Colour;
|
||||||
|
using osu.Framework.Graphics.Containers;
|
||||||
|
using osu.Framework.Graphics.Shapes;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Graphics.Containers;
|
||||||
|
using osu.Game.Online.Multiplayer;
|
||||||
|
using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus;
|
||||||
|
using osu.Game.Users;
|
||||||
|
using osuTK;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Screens.OnlinePlay.Multiplayer.Participants
|
||||||
|
{
|
||||||
|
internal class TeamDisplay : MultiplayerRoomComposite
|
||||||
|
{
|
||||||
|
private readonly User user;
|
||||||
|
private Drawable box;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuColour colours { get; set; }
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private MultiplayerClient client { get; set; }
|
||||||
|
|
||||||
|
public TeamDisplay(User user)
|
||||||
|
{
|
||||||
|
this.user = user;
|
||||||
|
|
||||||
|
RelativeSizeAxes = Axes.Y;
|
||||||
|
Width = 15;
|
||||||
|
|
||||||
|
Margin = new MarginPadding { Horizontal = 3 };
|
||||||
|
|
||||||
|
Alpha = 0;
|
||||||
|
Scale = new Vector2(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[BackgroundDependencyLoader]
|
||||||
|
private void load()
|
||||||
|
{
|
||||||
|
box = new Container
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
CornerRadius = 5,
|
||||||
|
Masking = true,
|
||||||
|
Scale = new Vector2(0, 1),
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
Child = new Box
|
||||||
|
{
|
||||||
|
Colour = Color4.White,
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
Anchor = Anchor.Centre,
|
||||||
|
Origin = Anchor.Centre,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (user.Id == client.LocalUser?.UserID)
|
||||||
|
{
|
||||||
|
InternalChild = new OsuClickableContainer
|
||||||
|
{
|
||||||
|
RelativeSizeAxes = Axes.Both,
|
||||||
|
TooltipText = "Change team",
|
||||||
|
Action = changeTeam,
|
||||||
|
Child = box
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
InternalChild = box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void changeTeam()
|
||||||
|
{
|
||||||
|
client.SendMatchRequest(new ChangeTeamRequest
|
||||||
|
{
|
||||||
|
TeamID = ((client.LocalUser?.MatchState as TeamVersusUserState)?.TeamID + 1) % 2 ?? 0,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private int? displayedTeam;
|
||||||
|
|
||||||
|
protected override void OnRoomUpdated()
|
||||||
|
{
|
||||||
|
base.OnRoomUpdated();
|
||||||
|
|
||||||
|
// we don't have a way of knowing when an individual user's state has updated, so just handle on RoomUpdated for now.
|
||||||
|
|
||||||
|
var userRoomState = Room?.Users.FirstOrDefault(u => u.UserID == user.Id)?.MatchState;
|
||||||
|
|
||||||
|
const double duration = 400;
|
||||||
|
|
||||||
|
int? newTeam = (userRoomState as TeamVersusUserState)?.TeamID;
|
||||||
|
|
||||||
|
if (newTeam == displayedTeam)
|
||||||
|
return;
|
||||||
|
|
||||||
|
displayedTeam = newTeam;
|
||||||
|
|
||||||
|
if (displayedTeam != null)
|
||||||
|
{
|
||||||
|
box.FadeColour(getColourForTeam(displayedTeam.Value), duration, Easing.OutQuint);
|
||||||
|
box.ScaleTo(new Vector2(box.Scale.X < 0 ? 1 : -1, 1), duration, Easing.OutQuint);
|
||||||
|
|
||||||
|
this.ScaleTo(Vector2.One, duration, Easing.OutQuint);
|
||||||
|
this.FadeIn(duration);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.ScaleTo(new Vector2(0, 1), duration, Easing.OutQuint);
|
||||||
|
this.FadeOut(duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ColourInfo getColourForTeam(int id)
|
||||||
|
{
|
||||||
|
switch (id)
|
||||||
|
{
|
||||||
|
default:
|
||||||
|
return colours.Red;
|
||||||
|
|
||||||
|
case 1:
|
||||||
|
return colours.Blue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,14 +6,12 @@ using osu.Game.Screens.OnlinePlay.Match.Components;
|
|||||||
|
|
||||||
namespace osu.Game.Screens.OnlinePlay.Playlists
|
namespace osu.Game.Screens.OnlinePlay.Playlists
|
||||||
{
|
{
|
||||||
public class CreatePlaylistsRoomButton : PurpleTriangleButton
|
public class CreatePlaylistsRoomButton : CreateRoomButton
|
||||||
{
|
{
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
private void load()
|
private void load()
|
||||||
{
|
{
|
||||||
Triangles.TriangleScale = 1.5f;
|
|
||||||
SpriteText.Font = SpriteText.Font.With(size: 14);
|
SpriteText.Font = SpriteText.Font.With(size: 14);
|
||||||
|
|
||||||
Text = "Create playlist";
|
Text = "Create playlist";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,11 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
|||||||
|
|
||||||
protected override Room CreateNewRoom()
|
protected override Room CreateNewRoom()
|
||||||
{
|
{
|
||||||
return new Room { Name = { Value = $"{api.LocalUser}'s awesome playlist" } };
|
return new Room
|
||||||
|
{
|
||||||
|
Name = { Value = $"{api.LocalUser}'s awesome playlist" },
|
||||||
|
Type = { Value = MatchType.Playlists }
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override RoomSubScreen CreateRoomSubScreen(Room room) => new PlaylistsRoomSubScreen(room);
|
protected override RoomSubScreen CreateRoomSubScreen(Room room) => new PlaylistsRoomSubScreen(room);
|
||||||
|
@ -26,8 +26,16 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
|||||||
{
|
{
|
||||||
public Action EditPlaylist;
|
public Action EditPlaylist;
|
||||||
|
|
||||||
|
private MatchSettings settings;
|
||||||
|
|
||||||
|
protected override OsuButton SubmitButton => settings.ApplyButton;
|
||||||
|
|
||||||
|
protected override bool IsLoading => settings.IsLoading; // should probably be replaced with an OngoingOperationTracker.
|
||||||
|
|
||||||
|
protected override void SelectBeatmap() => settings.SelectBeatmap();
|
||||||
|
|
||||||
protected override OnlinePlayComposite CreateSettings()
|
protected override OnlinePlayComposite CreateSettings()
|
||||||
=> new MatchSettings
|
=> settings = new MatchSettings
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
RelativePositionAxes = Axes.Y,
|
RelativePositionAxes = Axes.Y,
|
||||||
@ -45,12 +53,16 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
|||||||
public RoomAvailabilityPicker AvailabilityPicker;
|
public RoomAvailabilityPicker AvailabilityPicker;
|
||||||
public TriangleButton ApplyButton;
|
public TriangleButton ApplyButton;
|
||||||
|
|
||||||
|
public bool IsLoading => loadingLayer.State.Value == Visibility.Visible;
|
||||||
|
|
||||||
public OsuSpriteText ErrorText;
|
public OsuSpriteText ErrorText;
|
||||||
|
|
||||||
private LoadingLayer loadingLayer;
|
private LoadingLayer loadingLayer;
|
||||||
private DrawableRoomPlaylist playlist;
|
private DrawableRoomPlaylist playlist;
|
||||||
private OsuSpriteText playlistLength;
|
private OsuSpriteText playlistLength;
|
||||||
|
|
||||||
|
private PurpleTriangleButton editPlaylistButton;
|
||||||
|
|
||||||
[Resolved(CanBeNull = true)]
|
[Resolved(CanBeNull = true)]
|
||||||
private IRoomManager manager { get; set; }
|
private IRoomManager manager { get; set; }
|
||||||
|
|
||||||
@ -199,7 +211,7 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
|||||||
},
|
},
|
||||||
new Drawable[]
|
new Drawable[]
|
||||||
{
|
{
|
||||||
new PurpleTriangleButton
|
editPlaylistButton = new PurpleTriangleButton
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.X,
|
RelativeSizeAxes = Axes.X,
|
||||||
Height = 40,
|
Height = 40,
|
||||||
@ -292,6 +304,8 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
|||||||
ApplyButton.Enabled.Value = hasValidSettings;
|
ApplyButton.Enabled.Value = hasValidSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SelectBeatmap() => editPlaylistButton.TriggerClick();
|
||||||
|
|
||||||
private void onPlaylistChanged(object sender, NotifyCollectionChangedEventArgs e) =>
|
private void onPlaylistChanged(object sender, NotifyCollectionChangedEventArgs e) =>
|
||||||
playlistLength.Text = $"Length: {Playlist.GetTotalDuration()}";
|
playlistLength.Text = $"Length: {Playlist.GetTotalDuration()}";
|
||||||
|
|
||||||
|
@ -230,7 +230,11 @@ namespace osu.Game.Screens.OnlinePlay.Playlists
|
|||||||
settingsOverlay = new PlaylistsMatchSettingsOverlay
|
settingsOverlay = new PlaylistsMatchSettingsOverlay
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both,
|
RelativeSizeAxes = Axes.Both,
|
||||||
EditPlaylist = () => this.Push(new PlaylistsSongSelect()),
|
EditPlaylist = () =>
|
||||||
|
{
|
||||||
|
if (this.IsCurrentScreen())
|
||||||
|
this.Push(new PlaylistsSongSelect());
|
||||||
|
},
|
||||||
State = { Value = roomId.Value == null ? Visibility.Visible : Visibility.Hidden }
|
State = { Value = roomId.Value == null ? Visibility.Visible : Visibility.Hidden }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -61,8 +61,6 @@ namespace osu.Game.Screens.Play
|
|||||||
protected GameplayMenuOverlay()
|
protected GameplayMenuOverlay()
|
||||||
{
|
{
|
||||||
RelativeSizeAxes = Axes.Both;
|
RelativeSizeAxes = Axes.Both;
|
||||||
|
|
||||||
State.ValueChanged += s => InternalButtons.Deselect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[BackgroundDependencyLoader]
|
[BackgroundDependencyLoader]
|
||||||
@ -142,6 +140,8 @@ namespace osu.Game.Screens.Play
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
State.ValueChanged += s => InternalButtons.Deselect();
|
||||||
|
|
||||||
updateRetryCount();
|
updateRetryCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ using osu.Framework.Bindables;
|
|||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Online.API;
|
using osu.Game.Online.API;
|
||||||
using osu.Game.Online.Multiplayer;
|
using osu.Game.Online.Multiplayer;
|
||||||
|
using osu.Game.Online.Multiplayer.MatchTypes.TeamVersus;
|
||||||
using osu.Game.Online.Rooms;
|
using osu.Game.Online.Rooms;
|
||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using osu.Game.Users;
|
using osu.Game.Users;
|
||||||
@ -132,6 +133,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
Settings =
|
Settings =
|
||||||
{
|
{
|
||||||
Name = apiRoom.Name.Value,
|
Name = apiRoom.Name.Value,
|
||||||
|
MatchType = apiRoom.Type.Value,
|
||||||
BeatmapID = apiRoom.Playlist.Last().BeatmapID,
|
BeatmapID = apiRoom.Playlist.Last().BeatmapID,
|
||||||
RulesetID = apiRoom.Playlist.Last().RulesetID,
|
RulesetID = apiRoom.Playlist.Last().RulesetID,
|
||||||
BeatmapChecksum = apiRoom.Playlist.Last().Beatmap.Value.MD5Hash,
|
BeatmapChecksum = apiRoom.Playlist.Last().Beatmap.Value.MD5Hash,
|
||||||
@ -151,6 +153,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
return Task.FromResult(room);
|
return Task.FromResult(room);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnRoomJoined()
|
||||||
|
{
|
||||||
|
Debug.Assert(Room != null);
|
||||||
|
|
||||||
|
// emulate the server sending this after the join room. scheduler required to make sure the join room event is fired first (in Join).
|
||||||
|
changeMatchType(Room.Settings.MatchType).Wait();
|
||||||
|
}
|
||||||
|
|
||||||
protected override Task LeaveRoomInternal() => Task.CompletedTask;
|
protected override Task LeaveRoomInternal() => Task.CompletedTask;
|
||||||
|
|
||||||
public override Task TransferHost(int userId) => ((IMultiplayerClient)this).HostChanged(userId);
|
public override Task TransferHost(int userId) => ((IMultiplayerClient)this).HostChanged(userId);
|
||||||
@ -163,6 +173,8 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
foreach (var user in Room.Users.Where(u => u.State == MultiplayerUserState.Ready))
|
foreach (var user in Room.Users.Where(u => u.State == MultiplayerUserState.Ready))
|
||||||
ChangeUserState(user.UserID, MultiplayerUserState.Idle);
|
ChangeUserState(user.UserID, MultiplayerUserState.Idle);
|
||||||
|
|
||||||
|
await changeMatchType(settings.MatchType).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task ChangeState(MultiplayerUserState newState)
|
public override Task ChangeState(MultiplayerUserState newState)
|
||||||
@ -192,7 +204,30 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Task SendMatchRequest(MatchUserRequest request) => Task.CompletedTask;
|
public override async Task SendMatchRequest(MatchUserRequest request)
|
||||||
|
{
|
||||||
|
Debug.Assert(Room != null);
|
||||||
|
Debug.Assert(LocalUser != null);
|
||||||
|
|
||||||
|
switch (request)
|
||||||
|
{
|
||||||
|
case ChangeTeamRequest changeTeam:
|
||||||
|
|
||||||
|
TeamVersusRoomState roomState = (TeamVersusRoomState)Room.MatchState!;
|
||||||
|
TeamVersusUserState userState = (TeamVersusUserState)LocalUser.MatchState!;
|
||||||
|
|
||||||
|
var targetTeam = roomState.Teams.FirstOrDefault(t => t.ID == changeTeam.TeamID);
|
||||||
|
|
||||||
|
if (targetTeam != null)
|
||||||
|
{
|
||||||
|
userState.TeamID = targetTeam.ID;
|
||||||
|
|
||||||
|
await ((IMultiplayerClient)this).MatchUserStateChanged(LocalUser.UserID, userState).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public override Task StartMatch()
|
public override Task StartMatch()
|
||||||
{
|
{
|
||||||
@ -218,5 +253,27 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
return Task.FromResult(set);
|
return Task.FromResult(set);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task changeMatchType(MatchType type)
|
||||||
|
{
|
||||||
|
Debug.Assert(Room != null);
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case MatchType.HeadToHead:
|
||||||
|
await ((IMultiplayerClient)this).MatchRoomStateChanged(null).ConfigureAwait(false);
|
||||||
|
|
||||||
|
foreach (var user in Room.Users)
|
||||||
|
await ((IMultiplayerClient)this).MatchUserStateChanged(user.UserID, null).ConfigureAwait(false);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MatchType.TeamVersus:
|
||||||
|
await ((IMultiplayerClient)this).MatchRoomStateChanged(TeamVersusRoomState.CreateDefault()).ConfigureAwait(false);
|
||||||
|
|
||||||
|
foreach (var user in Room.Users)
|
||||||
|
await ((IMultiplayerClient)this).MatchUserStateChanged(user.UserID, new TeamVersusUserState()).ConfigureAwait(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@
|
|||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Realm" Version="10.3.0" />
|
<PackageReference Include="Realm" Version="10.3.0" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2021.804.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2021.805.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.803.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.803.0" />
|
||||||
<PackageReference Include="Sentry" Version="3.8.3" />
|
<PackageReference Include="Sentry" Version="3.8.3" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.28.3" />
|
<PackageReference Include="SharpCompress" Version="0.28.3" />
|
||||||
|
@ -70,7 +70,7 @@
|
|||||||
<Reference Include="System.Net.Http" />
|
<Reference Include="System.Net.Http" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup Label="Package References">
|
<ItemGroup Label="Package References">
|
||||||
<PackageReference Include="ppy.osu.Framework.iOS" Version="2021.804.0" />
|
<PackageReference Include="ppy.osu.Framework.iOS" Version="2021.805.0" />
|
||||||
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.803.0" />
|
<PackageReference Include="ppy.osu.Game.Resources" Version="2021.803.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
|
<!-- See https://github.com/dotnet/runtime/issues/35988 (can be removed after Xamarin uses net5.0 / net6.0) -->
|
||||||
@ -93,7 +93,7 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="2.2.6" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite.Core" Version="2.2.6" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="ppy.osu.Framework" Version="2021.804.0" />
|
<PackageReference Include="ppy.osu.Framework" Version="2021.805.0" />
|
||||||
<PackageReference Include="SharpCompress" Version="0.28.3" />
|
<PackageReference Include="SharpCompress" Version="0.28.3" />
|
||||||
<PackageReference Include="NUnit" Version="3.13.2" />
|
<PackageReference Include="NUnit" Version="3.13.2" />
|
||||||
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
<PackageReference Include="SharpRaven" Version="2.4.0" />
|
||||||
|
Loading…
Reference in New Issue
Block a user