Skip to content

Commit 17dc715

Browse files
committed
Update the RPC on pressing the "Play" button
1 parent 2b23b04 commit 17dc715

File tree

4 files changed

+72
-70
lines changed

4 files changed

+72
-70
lines changed

src/NexusMods.App.UI/LeftMenu/Items/ApplyControl/LaunchButtonViewModel.cs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
using NexusMods.Telemetry;
1616
using ReactiveUI;
1717
using ReactiveUI.Fody.Helpers;
18+
using NexusMods.Discord;
19+
using NexusMods.Abstractions.Loadouts.Extensions;
1820

1921
namespace NexusMods.App.UI.LeftMenu.Items;
2022

@@ -36,16 +38,18 @@ public class LaunchButtonViewModel : AViewModel<ILaunchButtonViewModel>, ILaunch
3638
private readonly IJobMonitor _monitor;
3739
private readonly IServiceProvider _serviceProvider;
3840
private readonly GameRunningTracker _gameRunningTracker;
41+
private readonly DiscordRpcService _discordRpcService;
3942

40-
public LaunchButtonViewModel(ILogger<ILaunchButtonViewModel> logger, IToolManager toolManager, IConnection conn, IJobMonitor monitor, IServiceProvider serviceProvider, GameRunningTracker gameRunningTracker)
43+
public LaunchButtonViewModel(ILogger<ILaunchButtonViewModel> logger, IToolManager toolManager, IConnection conn, IJobMonitor monitor, IServiceProvider serviceProvider, GameRunningTracker gameRunningTracker, DiscordRpcService discordRpcService)
4144
{
4245
_logger = logger;
4346
_toolManager = toolManager;
4447
_conn = conn;
4548
_monitor = monitor;
4649
_serviceProvider = serviceProvider;
4750
_gameRunningTracker = gameRunningTracker;
48-
51+
_discordRpcService = discordRpcService;
52+
4953
this.WhenActivated(cd =>
5054
{
5155
_gameRunningTracker.GetWithCurrentStateAsStarting().Subscribe(isRunning =>
@@ -73,13 +77,38 @@ await Task.Run(async () =>
7377
var sw = Stopwatch.StartNew();
7478
try
7579
{
80+
try
81+
{
82+
_logger.LogDebug("Stopping Discord RPC before launching game");
83+
await _discordRpcService.StopAsync(token);
84+
}
85+
catch
86+
{
87+
_logger.LogWarning("Failed to stop Discord RPC before launching game, continuing anyway.");
88+
}
7689
Tracking.AddEvent(Events.Game.LaunchGame, new EventMetadata(name: $"{installation.Game.Name} - {installation.Store}"));
7790
await _toolManager.RunTool(tool, marker, _monitor, token: token);
7891
}
7992
finally
8093
{
8194
var duration = sw.Elapsed;
8295
Tracking.AddEvent(Events.Game.ExitGame, EventMetadata.Create(name: $"{installation.Game.Name} - {installation.Store}", value: duration.TotalSeconds));
96+
try
97+
{
98+
_logger.LogDebug("Starting Discord RPC after launching game");
99+
await _discordRpcService.StartAsync(token);
100+
var mods = marker.Items.OfType<LoadoutItem.ReadOnly>().Where(item => item.IsValid() && item.IsEnabled() && item.HasParent());
101+
var modCount = mods.Count();
102+
foreach (var mod in mods)
103+
{
104+
_logger.LogDebug("Adding mod to Discord RPC presence: {ModName}", mod.Name);
105+
}
106+
_discordRpcService.SetGamePresence(installation.Game.Name, "stardewvalley", modCount);
107+
}
108+
catch
109+
{
110+
_logger.LogWarning("Failed to start Discord RPC after launching game, continuing anyway.");
111+
}
83112
}
84113
}, token);
85114
}

src/NexusMods.App.UI/NexusMods.App.UI.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<Project Sdk="Microsoft.NET.Sdk">
1+
<Project Sdk="Microsoft.NET.Sdk">
22
<PropertyGroup>
33
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
44
<ApplicationManifest>app.manifest</ApplicationManifest>
@@ -107,6 +107,7 @@
107107
<ProjectReference Include="..\NexusMods.Networking.GitHub\NexusMods.Networking.GitHub.csproj" />
108108
<ProjectReference Include="..\NexusMods.Telemetry\NexusMods.Telemetry.csproj" />
109109
<ProjectReference Include="..\NexusMods.UI.Sdk\NexusMods.UI.Sdk.csproj" />
110+
<ProjectReference Include="..\NexusMods.Discord\NexusMods.Discord.csproj" />
110111
</ItemGroup>
111112

112113
<ItemGroup>

src/NexusMods.Discord/DiscordRpcService.cs

Lines changed: 39 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,19 @@
22
using DiscordRPC;
33
using Microsoft.Extensions.Hosting;
44
using Microsoft.Extensions.Logging;
5-
using NexusMods.App.UI.Settings;
65
using NexusMods.Abstractions.Settings;
76
using NexusMods.Sdk;
8-
using ReactiveUI;
97

108
namespace NexusMods.Discord
119
{
1210
public class DiscordRpcService : IHostedService
1311
{
14-
private readonly DiscordRpcClient _client;
12+
private DiscordRpcClient _client;
1513
private readonly string _applicationId = "1393166557101691101";
1614
private readonly ILogger<DiscordRpcService> _logger;
1715
private readonly ISettingsManager _settings;
18-
private bool _isEnabled;
19-
// Temporary for testing
20-
private CancellationTokenSource? _periodicUpdateTokenSource;
21-
private string _lastGameName = "";
16+
private bool _isEnabled = true;
17+
private bool _isInitialized = false;
2218

2319
private readonly IReadOnlyDictionary<string, string> _assetKeys = new ReadOnlyDictionary<string, string>(
2420
new Dictionary<string, string>
@@ -37,16 +33,16 @@ public DiscordRpcService(ILogger<DiscordRpcService> logger, ISettingsManager set
3733

3834
public Task StartAsync(CancellationToken cancellationToken)
3935
{
40-
var settings = _settings.Get<DiscordSettings>();
41-
_isEnabled = settings.EnableRichPresence;
36+
//var settings = _settings.Get<DiscordSettings>();
37+
//_isEnabled = settings.EnableRichPresence;
4238

4339
if (!_isEnabled)
4440
{
4541
_logger.LogInformation("Discord RPC is disabled in settings and was not started.");
46-
return Task.CompletedTask;
42+
return Task.CompletedTask;
4743
}
48-
49-
44+
45+
5046
_client.OnReady += (_, e) =>
5147
{
5248
_logger.LogDebug($"Connected to Discord as {e.User.Username}");
@@ -62,10 +58,15 @@ public Task StartAsync(CancellationToken cancellationToken)
6258
_logger.LogError($"Discord RPC Error: {e.Message}");
6359
};
6460

61+
if (_client.IsDisposed) {
62+
_client = new DiscordRpcClient(_applicationId);
63+
_logger.LogDebug("Recreated Discord RPC client due to previous disposal.");
64+
}
65+
6566
try
6667
{
6768
_client.Initialize();
68-
SetDefaultPresence();
69+
_isInitialized = true;
6970
}
7071
catch (Exception ex)
7172
{
@@ -74,57 +75,21 @@ public Task StartAsync(CancellationToken cancellationToken)
7475

7576
_logger.LogTrace("Discord RPC service started successfully.");
7677

77-
_periodicUpdateTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
78-
79-
_ = Task.Run(async () =>
80-
{
81-
try
82-
{
83-
while (!_periodicUpdateTokenSource.Token.IsCancellationRequested)
84-
{
85-
if (_lastGameName != "")
86-
{
87-
if (_lastGameName == "Stardew Valley")
88-
{
89-
_logger.LogInformation("Discord RPC set to Cyberpunk");
90-
SetGamePresence("Cyberpunk 2077", "cyberpunk2077", 9);
91-
_lastGameName = "Cyberpunk 2077";
92-
}
93-
else
94-
{
95-
_logger.LogInformation("Discord RPC set to Unknown");
96-
SetGamePresence("Unknown Game", "unknown", 0);
97-
_lastGameName = "";
98-
}
99-
}
100-
else
101-
{
102-
_logger.LogInformation("Discord RPC set to Stardew");
103-
SetGamePresence("Stardew Valley", "stardewvalley", 222);
104-
_lastGameName = "Stardew Valley";
105-
}
106-
107-
await Task.Delay(TimeSpan.FromSeconds(15), _periodicUpdateTokenSource.Token);
108-
}
109-
}
110-
catch (OperationCanceledException)
111-
{
112-
_logger.LogInformation("Discord RPC periodic update task cancelled.");
113-
}
114-
catch (Exception ex)
115-
{
116-
_logger.LogError($"Discord RPC periodic update task failed: {ex.Message}");
117-
}
118-
}, _periodicUpdateTokenSource.Token
119-
);
120-
12178
return Task.CompletedTask;
12279
}
12380

12481
public Task StopAsync(CancellationToken cancellationToken)
12582
{
126-
_client.Dispose();
127-
_logger.LogInformation("Discord RPC service stopped.");
83+
if (!_isInitialized)
84+
{
85+
_logger.LogWarning("Discord RPC service was not initialized, skipping stop.");
86+
}
87+
else
88+
{
89+
_client.ClearPresence();
90+
_client.Dispose();
91+
_logger.LogInformation("Discord RPC service stopped.");
92+
}
12893
return Task.CompletedTask;
12994
}
13095

@@ -154,14 +119,21 @@ public void SetDefaultPresence()
154119

155120
public void SetGamePresence(string gameName, string gameDomain, int modCount)
156121
{
157-
if (!_isEnabled) return;
122+
if (!_isInitialized || !_isEnabled)
123+
{
124+
_logger.LogWarning("Discord RPC is not initialized or enabled, cannot set game presence.");
125+
return;
126+
}
158127

159128
var largeImageKey = "nexusmods_logo";
160129

161130
if (_assetKeys.TryGetValue(gameDomain, out var gameArtKey))
162131
{
163132
largeImageKey = gameArtKey;
164133
}
134+
135+
_logger.LogInformation($"Setting Discord presence for game: {gameName}, Domain: {gameDomain}, Mods: {modCount}");
136+
165137
_client.SetPresence(new RichPresence
166138
{
167139
Details = $"Modding {gameName}",
@@ -175,16 +147,17 @@ public void SetGamePresence(string gameName, string gameDomain, int modCount)
175147
},
176148
});
177149
}
178-
179-
public void ClearPresence()
180-
{
181-
_client.ClearPresence();
182-
_logger.LogInformation("Discord presence cleared.");
183-
}
184150
}
185151
}
186152

187153
public interface IDiscordRpcService
188154
{
189155
void SetGamePresence(string gameName, string gameDomain, int modCount);
156+
157+
void SetCustomPresence(RichPresence presence);
158+
159+
void SetDefaultPresence();
160+
161+
Task StartAsync(CancellationToken cancellationToken);
162+
Task StopAsync(CancellationToken cancellationToken);
190163
}

src/NexusMods.Discord/NexusMods.Discord.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
<ItemGroup>
1717
<ProjectReference Include="..\NexusMods.Sdk\NexusMods.Sdk.csproj" />
18-
<ProjectReference Include="..\NexusMods.App.UI\NexusMods.App.UI.csproj" />
1918
<ProjectReference Include="..\NexusMods.Abstractions.Settings\NexusMods.Abstractions.Settings.csproj" />
2019
</ItemGroup>
2120

0 commit comments

Comments
 (0)