Skip to content

Commit

Permalink
refactor activities and add lobby joining support
Browse files Browse the repository at this point in the history
  • Loading branch information
flustix committed Aug 22, 2024
1 parent b0e89bf commit 60d3182
Show file tree
Hide file tree
Showing 25 changed files with 426 additions and 85 deletions.
99 changes: 73 additions & 26 deletions fluXis.Desktop/DiscordActivity.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,36 @@
using System;
using System.Linq;
using DiscordRPC;
using DiscordRPC.Message;
using fluXis.Game;
using fluXis.Game.Online.Activity;
using fluXis.Game.Integration;
using fluXis.Game.Online.Fluxel;
using osu.Framework.Bindables;
using fluXis.Shared.Utils;
using Newtonsoft.Json;
using osu.Framework.Logging;
using EventType = DiscordRPC.EventType;

namespace fluXis.Desktop;

public class DiscordActivity
{
private IAPIClient api;
private FluXisGame game;
private DiscordRpcClient client;

public void Initialize(IAPIClient api, Bindable<UserActivity> bind)
public void Initialize(FluXisGame game, IAPIClient api)
{
client = new DiscordRpcClient("975141679583604767");
this.game = game;

var secondPipe = Program.Args.Contains("--rpc-pipe-2");

client = new DiscordRpcClient("975141679583604767", pipe: secondPipe ? 1 : -1);

client.RegisterUriScheme();
client.Subscribe(EventType.Join);
client.OnJoin += onJoin;

client.OnConnectionEstablished += (_, args) => Logger.Log($"RPC is on pipe {args.ConnectedPipe}", LoggingTarget.Network, LogLevel.Debug);
client.OnError += (_, args) => Logger.Log($"Discord RPC error: {args.Message}.", LoggingTarget.Network, LogLevel.Error);
var success = client.Initialize();

if (!success)
Expand All @@ -24,44 +39,76 @@ public void Initialize(IAPIClient api, Bindable<UserActivity> bind)
return;
}

this.api = api;

bind.BindValueChanged(e =>
api.Activity.BindValueChanged(e =>
{
var activity = e.NewValue;
if (activity == null) return;
activity.API = api;
update(activity.Details, activity.Status, activity.Icon);
client?.SetPresence(build(activity.CreateDiscord()));
}, true);
}

private void update(string state = "", string details = "", string largeImageKey = "")
private void onJoin(object sender, JoinMessage args)
{
var secret = args.Secret.Deserialize<LobbySecret>();
game.JoinMultiplayerRoom(secret.ID, secret.Password);
}

private static RichPresence build(DiscordRichPresence rpc)
{
Assets assets = new Assets
var discord = new RichPresence
{
LargeImageKey = largeImageKey,
LargeImageText = $"fluXis {FluXisGameBase.VersionString}"
State = rpc.State[..Math.Min(rpc.State.Length, 128)],
Details = rpc.Details[..Math.Min(rpc.Details.Length, 128)],
Assets = new Assets
{
LargeImageKey = rpc.LargeImage,
LargeImageText = rpc.LargeImageText,
SmallImageKey = rpc.SmallImage,
SmallImageText = rpc.SmallImageText
},
Timestamps = new Timestamps()
};

var user = api?.User.Value;
if (rpc.StartTime > 0)
discord.Timestamps.StartUnixMilliseconds = rpc.StartTime;
if (rpc.EndTime > 0)
discord.Timestamps.EndUnixMilliseconds = rpc.EndTime;

if (user != null)
if (rpc.PartyID > 0)
{
assets.SmallImageKey = $"{api.Endpoint.AssetUrl}/avatar/{user.ID}";
assets.SmallImageText = user.Username;
}
discord.Party = new Party
{
Privacy = Party.PrivacySetting.Public,
ID = $"multiplayer:{rpc.PartyID}",
Size = rpc.PartySize,
Max = rpc.PartyMax
};

client?.SetPresence(new RichPresence
{
Details = details.Substring(0, Math.Min(128, details.Length)),
State = state.Substring(0, Math.Min(128, state.Length)),
Assets = assets
});
discord.Secrets = new Secrets
{
JoinSecret = new LobbySecret
{
ID = rpc.PartyID,
Password = rpc.PartySecret
}.Serialize()
};
}
else if (rpc.Buttons is not null)
discord.Buttons = rpc.Buttons.Select(b => new Button { Label = b.Label, Url = b.Url }).ToArray();

Logger.Log($"Discord Rich Presence updated: {getOrEmpty(state)}, {getOrEmpty(details)}, {getOrEmpty(largeImageKey)}!", LoggingTarget.Network, LogLevel.Debug);
Logger.Log($"Setting Discord RPC to: {discord.Serialize()}", LoggingTarget.Network, LogLevel.Debug);
return discord;
}

private string getOrEmpty(string str) => string.IsNullOrEmpty(str) ? "<empty>" : str;
public class LobbySecret
{
[JsonProperty("id")]
public long ID { get; set; }

[JsonProperty("password")]
public string Password { get; set; }
}
}
11 changes: 10 additions & 1 deletion fluXis.Desktop/FluXisGameDesktop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using fluXis.Game.Integration;
using fluXis.Game.IPC;
using fluXis.Game.Updater;
using fluXis.Game.Utils;
using osu.Framework.Allocation;
using osu.Framework.Platform;

Expand Down Expand Up @@ -35,9 +36,17 @@ private void load()
protected override void LoadComplete()
{
base.LoadComplete();
new DiscordActivity().Initialize(APIClient, Activity);
new DiscordActivity().Initialize(this, APIClient);

var args = Program.Args.ToList();

if (args.Contains("--debug-join-multi"))
{
var idx = args.IndexOf("--debug-join-multi");
var id = args[idx + 1];
JoinMultiplayerRoom(id.ToIntInvariant(), "");
}

args.RemoveAll(a => a.StartsWith('-'));
WaitForReady(() => HandleDragDrop(args.ToArray()));
}
Expand Down
4 changes: 4 additions & 0 deletions fluXis.Game.Tests/TestAPIClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System;
using System.Threading.Tasks;
using fluXis.Game.Online;
using fluXis.Game.Online.Activity;
using fluXis.Game.Online.API;
using fluXis.Game.Online.Fluxel;
using fluXis.Shared.API;
Expand All @@ -22,6 +23,9 @@ public class TestAPIClient : IAPIClient
});

public Bindable<ConnectionStatus> Status { get; } = new(ConnectionStatus.Online);

public Bindable<UserActivity> Activity { get; } = new();

public string AccessToken => "token";
public string MultifactorToken { get; set; } = "mfa-token";
public APIEndpointConfig Endpoint => new();
Expand Down
24 changes: 22 additions & 2 deletions fluXis.Game/FluXisGame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,15 @@
using fluXis.Game.Overlay.User;
using fluXis.Game.Overlay.Volume;
using fluXis.Game.Screens;
using fluXis.Game.Screens.Intro;
using fluXis.Game.Screens.Loading;
using fluXis.Game.Screens.Menu;
using fluXis.Game.Screens.Multiplayer;
using fluXis.Game.Screens.Result;
using fluXis.Game.Screens.Select;
using fluXis.Game.Screens.Skinning;
using fluXis.Game.Utils;
using fluXis.Game.Utils.Extensions;
using fluXis.Game.Utils.Sentry;
using fluXis.Shared.API.Packets.Other;
using fluXis.Shared.API.Packets.User;
Expand Down Expand Up @@ -116,7 +119,7 @@ private void load()

loadComponent(globalBackground = new GlobalBackground { InitialDim = 1 }, buffer.Add, true);
loadComponent(screenContainer = new Container { RelativeSizeAxes = Axes.Both }, buffer.Add);
loadComponent(screenStack = new FluXisScreenStack(Activity, allowOverlays), screenContainer.Add, true);
loadComponent(screenStack = new FluXisScreenStack(APIClient.Activity, allowOverlays), screenContainer.Add, true);

loadComponent(overlayContainer = new Container<VisibilityContainer> { RelativeSizeAxes = Axes.Both }, buffer.Add);
loadComponent(dashboard = new Dashboard(), overlayContainer.Add, true);
Expand Down Expand Up @@ -210,7 +213,7 @@ private void loadNext()

public void WaitForReady(Action action)
{
if (screenStack?.CurrentScreen is null or LoadingScreen)
if (screenStack?.CurrentScreen is null or LoadingScreen or IntroAnimation)
Schedule(() => WaitForReady(action));
else
action();
Expand Down Expand Up @@ -356,6 +359,23 @@ public override void ShowMap(RealmMapSet set)
}
}

public void JoinMultiplayerRoom(long id, string password) => Scheduler.ScheduleIfNeeded(() => WaitForReady(() =>
{
Logger.Log($"joining multi room [{id}, {password}]");
MenuScreen.MakeCurrent();
MenuScreen.CanPlayAnimation();
if (MenuScreen.IsCurrentScreen())
{
MenuScreen.Push(new MultiplayerScreen
{
TargetLobby = id,
LobbyPassword = password
});
}
}));

public bool OnPressed(KeyBindingPressEvent<FluXisGlobalKeybind> e)
{
if (e.Repeat) return false;
Expand Down
2 changes: 0 additions & 2 deletions fluXis.Game/FluXisGameBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
using fluXis.Game.Localization;
using fluXis.Game.Map;
using fluXis.Game.Online;
using fluXis.Game.Online.Activity;
using fluXis.Game.Online.API.Models.Chat;
using fluXis.Game.Online.API.Models.Groups;
using fluXis.Game.Online.API.Models.Multi;
Expand Down Expand Up @@ -97,7 +96,6 @@ public partial class FluXisGameBase : osu.Framework.Game

public Storage ExportStorage => exportStorage ??= Host.Storage.GetStorageForDirectory("export");

protected Bindable<UserActivity> Activity { get; } = new();
public Season CurrentSeason { get; private set; }

public static string VersionString
Expand Down
12 changes: 8 additions & 4 deletions fluXis.Game/Graphics/UserInterface/Panel/Panel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@ public partial class Panel : Container
public bool IsDangerous { get; init; }

public new Container Content { get; }
public bool ShowOnCreate { get; set; } = true;

private Container loadingOverlay { get; }
private Box flashBox { get; }

protected bool Loading { get; private set; }

private Visibility state = Visibility.Hidden;
private Visibility state = Visibility.Visible;
private bool initial = true;

public Panel()
{
Expand Down Expand Up @@ -73,7 +73,11 @@ public Panel()

protected override void LoadComplete()
{
if (ShowOnCreate) Show();
if (state == Visibility.Hidden)
return;

Show();
initial = true;
}

public void Flash()
Expand All @@ -95,7 +99,7 @@ public override void Hide()

public override void Show()
{
if (state == Visibility.Visible)
if (state == Visibility.Visible && !initial)
return;

state = Visibility.Visible;
Expand Down
35 changes: 35 additions & 0 deletions fluXis.Game/Integration/DiscordRichPresence.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
namespace fluXis.Game.Integration;

public class DiscordRichPresence
{
public string State { get; set; } = "";
public string Details { get; set; } = "";

public string LargeImage { get; set; } = "";
public string LargeImageText { get; set; } = "";

public string SmallImage { get; set; } = "";
public string SmallImageText { get; set; } = "";

public long PartyID { get; set; }
public string PartySecret { get; set; }
public int PartySize { get; set; }
public int PartyMax { get; set; }

public ulong StartTime { get; set; }
public ulong EndTime { get; set; }

public Button[] Buttons { get; set; }

public class Button
{
public string Label { get; }
public string Url { get; }

public Button(string label, string url)
{
Label = label;
Url = url;
}
}
}
Loading

0 comments on commit 60d3182

Please sign in to comment.