Added trace logging to client

This commit is contained in:
Pat Hartl 2023-08-21 18:44:20 -05:00
parent b30bb0de44
commit 4574dea6f9
7 changed files with 160 additions and 26 deletions

View file

@ -1,4 +1,5 @@
using System; using Playnite.SDK;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -8,6 +9,8 @@ namespace LANCommander.PlaynitePlugin.Helpers
{ {
internal static class RetryHelper internal static class RetryHelper
{ {
internal static readonly ILogger Logger = LogManager.GetLogger();
internal static T RetryOnException<T>(int maxAttempts, TimeSpan delay, T @default, Func<T> action) internal static T RetryOnException<T>(int maxAttempts, TimeSpan delay, T @default, Func<T> action)
{ {
int attempts = 0; int attempts = 0;
@ -16,11 +19,15 @@ namespace LANCommander.PlaynitePlugin.Helpers
{ {
try try
{ {
Logger.Trace($"Attempt #{attempts + 1}/{maxAttempts}...");
attempts++; attempts++;
return action(); return action();
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Error(ex, $"Attempt failed!");
if (attempts >= maxAttempts) if (attempts >= maxAttempts)
return @default; return @default;

View file

@ -17,6 +17,8 @@ namespace LANCommander.PlaynitePlugin
{ {
public class LANCommanderInstallController : InstallController public class LANCommanderInstallController : InstallController
{ {
public static readonly ILogger Logger = LogManager.GetLogger();
private LANCommanderLibraryPlugin Plugin; private LANCommanderLibraryPlugin Plugin;
private PowerShellRuntime PowerShellRuntime; private PowerShellRuntime PowerShellRuntime;
private Playnite.SDK.Models.Game PlayniteGame; private Playnite.SDK.Models.Game PlayniteGame;
@ -31,16 +33,23 @@ namespace LANCommander.PlaynitePlugin
public override void Install(InstallActionArgs args) public override void Install(InstallActionArgs args)
{ {
Logger.Trace("Game install triggered, checking connection...");
while (!Plugin.ValidateConnection()) while (!Plugin.ValidateConnection())
{ {
Logger.Trace("User not authenticated. Opening auth window...");
Plugin.ShowAuthenticationWindow(); Plugin.ShowAuthenticationWindow();
} }
var gameId = Guid.Parse(Game.GameId); var gameId = Guid.Parse(Game.GameId);
var game = Plugin.LANCommander.GetGame(gameId); var game = Plugin.LANCommander.GetGame(gameId);
Logger.Trace($"Installing game {game.Title} ({game.Id})...");
var installDirectory = RetryHelper.RetryOnException(10, TimeSpan.FromMilliseconds(500), "", () => var installDirectory = RetryHelper.RetryOnException(10, TimeSpan.FromMilliseconds(500), "", () =>
{ {
Logger.Trace("Attempting to download and extract game...");
return DownloadAndExtract(game); return DownloadAndExtract(game);
}); });
@ -58,6 +67,8 @@ namespace LANCommander.PlaynitePlugin
var writeManifestSuccess = RetryHelper.RetryOnException(10, TimeSpan.FromSeconds(1), false, () => var writeManifestSuccess = RetryHelper.RetryOnException(10, TimeSpan.FromSeconds(1), false, () =>
{ {
Logger.Trace("Attempting to get game manifest...");
manifest = Plugin.LANCommander.GetGameManifest(gameId); manifest = Plugin.LANCommander.GetGameManifest(gameId);
WriteManifest(manifest, installDirectory); WriteManifest(manifest, installDirectory);
@ -68,6 +79,8 @@ namespace LANCommander.PlaynitePlugin
if (!writeManifestSuccess) if (!writeManifestSuccess)
throw new Exception("Could not get or write the manifest file. Retry the install or check your connection."); throw new Exception("Could not get or write the manifest file. Retry the install or check your connection.");
Logger.Trace("Saving scripts...");
SaveScript(game, installDirectory, ScriptType.Install); SaveScript(game, installDirectory, ScriptType.Install);
SaveScript(game, installDirectory, ScriptType.Uninstall); SaveScript(game, installDirectory, ScriptType.Uninstall);
SaveScript(game, installDirectory, ScriptType.NameChange); SaveScript(game, installDirectory, ScriptType.NameChange);
@ -95,11 +108,15 @@ namespace LANCommander.PlaynitePlugin
{ {
if (game == null) if (game == null)
{ {
Logger.Trace("Game failed to download! No game was specified!");
throw new Exception("Game failed to download!"); throw new Exception("Game failed to download!");
} }
var destination = Path.Combine(Plugin.Settings.InstallDirectory, game.Title.SanitizeFilename()); var destination = Path.Combine(Plugin.Settings.InstallDirectory, game.Title.SanitizeFilename());
Logger.Trace($"Downloading and extracting \"{game}\" to path {destination}");
Plugin.PlayniteApi.Dialogs.ActivateGlobalProgress(progress => Plugin.PlayniteApi.Dialogs.ActivateGlobalProgress(progress =>
{ {
try try
@ -127,8 +144,12 @@ namespace LANCommander.PlaynitePlugin
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Error(ex, $"Could not extract to path {destination}");
if (Directory.Exists(destination)) if (Directory.Exists(destination))
{ {
Logger.Trace("Directory at install path already exists. Deleting...");
Directory.Delete(destination, true); Directory.Delete(destination, true);
} }
} }
@ -139,6 +160,8 @@ namespace LANCommander.PlaynitePlugin
Cancelable = false, Cancelable = false,
}); });
Logger.Trace($"Game successfully downloaded and extracted to {destination}");
return destination; return destination;
} }
@ -217,13 +240,19 @@ namespace LANCommander.PlaynitePlugin
private void WriteManifest(SDK.GameManifest manifest, string installDirectory) private void WriteManifest(SDK.GameManifest manifest, string installDirectory)
{ {
var destination = Path.Combine(installDirectory, "_manifest.yml");
Logger.Trace($"Attempting to write manifest to path {destination}");
var serializer = new SerializerBuilder() var serializer = new SerializerBuilder()
.WithNamingConvention(new PascalCaseNamingConvention()) .WithNamingConvention(new PascalCaseNamingConvention())
.Build(); .Build();
Logger.Trace("Serializing manifest...");
var yaml = serializer.Serialize(manifest); var yaml = serializer.Serialize(manifest);
File.WriteAllText(Path.Combine(installDirectory, "_manifest.yml"), yaml); Logger.Trace("Writing manifest file...");
File.WriteAllText(destination, yaml);
} }
private void SaveScript(LANCommander.SDK.Models.Game game, string installationDirectory, ScriptType type) private void SaveScript(LANCommander.SDK.Models.Game game, string installationDirectory, ScriptType type)
@ -241,6 +270,8 @@ namespace LANCommander.PlaynitePlugin
if (File.Exists(filename)) if (File.Exists(filename))
File.Delete(filename); File.Delete(filename);
Logger.Trace($"Writing {type} script to {filename}");
File.WriteAllText(filename, script.Contents); File.WriteAllText(filename, script.Contents);
} }
} }

View file

@ -1,5 +1,6 @@
using LANCommander.SDK; using LANCommander.SDK;
using LANCommander.SDK.Models; using LANCommander.SDK.Models;
using Playnite.SDK;
using RestSharp; using RestSharp;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -14,6 +15,8 @@ namespace LANCommander.PlaynitePlugin
{ {
internal class LANCommanderClient internal class LANCommanderClient
{ {
public static readonly ILogger Logger = LogManager.GetLogger();
public readonly RestClient Client; public readonly RestClient Client;
public AuthToken Token; public AuthToken Token;
@ -142,17 +145,32 @@ namespace LANCommander.PlaynitePlugin
public bool ValidateToken(AuthToken token) public bool ValidateToken(AuthToken token)
{ {
Logger.Trace("Validating token...");
if (token == null) if (token == null)
{
Logger.Trace("Token is null!");
return false; return false;
}
var request = new RestRequest("/api/Auth/Validate") var request = new RestRequest("/api/Auth/Validate")
.AddHeader("Authorization", $"Bearer {token.AccessToken}"); .AddHeader("Authorization", $"Bearer {token.AccessToken}");
if (String.IsNullOrEmpty(token.AccessToken) || String.IsNullOrEmpty(token.RefreshToken)) if (String.IsNullOrEmpty(token.AccessToken) || String.IsNullOrEmpty(token.RefreshToken))
{
Logger.Trace("Token is empty!");
return false; return false;
}
var response = Client.Post(request); var response = Client.Post(request);
var valid = response.StatusCode == HttpStatusCode.OK;
if (valid)
Logger.Trace("Token is valid!");
else
Logger.Trace("Token is invalid!");
return response.StatusCode == HttpStatusCode.OK; return response.StatusCode == HttpStatusCode.OK;
} }
@ -198,6 +216,8 @@ namespace LANCommander.PlaynitePlugin
public GameSave UploadSave(string gameId, byte[] data) public GameSave UploadSave(string gameId, byte[] data)
{ {
Logger.Trace("Uploading save...");
var request = new RestRequest($"/api/Saves/Upload/{gameId}", Method.POST) var request = new RestRequest($"/api/Saves/Upload/{gameId}", Method.POST)
.AddHeader("Authorization", $"Bearer {Token.AccessToken}"); .AddHeader("Authorization", $"Bearer {Token.AccessToken}");
@ -210,6 +230,8 @@ namespace LANCommander.PlaynitePlugin
public string GetKey(Guid id) public string GetKey(Guid id)
{ {
Logger.Trace("Requesting key allocation...");
var macAddress = GetMacAddress(); var macAddress = GetMacAddress();
var request = new KeyRequest() var request = new KeyRequest()
@ -227,6 +249,8 @@ namespace LANCommander.PlaynitePlugin
public string GetAllocatedKey(Guid id) public string GetAllocatedKey(Guid id)
{ {
Logger.Trace("Requesting allocated key...");
var macAddress = GetMacAddress(); var macAddress = GetMacAddress();
var request = new KeyRequest() var request = new KeyRequest()
@ -247,6 +271,8 @@ namespace LANCommander.PlaynitePlugin
public string GetNewKey(Guid id) public string GetNewKey(Guid id)
{ {
Logger.Trace("Requesting new key allocation...");
var macAddress = GetMacAddress(); var macAddress = GetMacAddress();
var request = new KeyRequest() var request = new KeyRequest()

View file

@ -55,6 +55,7 @@ namespace LANCommander.PlaynitePlugin
{ {
if (LANCommander.Token == null || LANCommander.Client == null || !LANCommander.ValidateToken(LANCommander.Token)) if (LANCommander.Token == null || LANCommander.Client == null || !LANCommander.ValidateToken(LANCommander.Token))
{ {
Logger.Trace("No valid authentication token exists. Showing auth window...");
ShowAuthenticationWindow(); ShowAuthenticationWindow();
} }
} }
@ -70,10 +71,10 @@ namespace LANCommander.PlaynitePlugin
while (!ValidateConnection()) while (!ValidateConnection())
{ {
Logger.Trace("Authentication invalid, showing auth window...");
ShowAuthenticationWindow(); ShowAuthenticationWindow();
} }
var games = LANCommander var games = LANCommander
.GetGames() .GetGames()
.Where(g => g.Archives != null && g.Archives.Count() > 0); .Where(g => g.Archives != null && g.Archives.Count() > 0);
@ -82,16 +83,24 @@ namespace LANCommander.PlaynitePlugin
{ {
try try
{ {
Logger.Trace($"Importing/updating metadata for game \"{game.Title}\"...");
var manifest = LANCommander.GetGameManifest(game.Id); var manifest = LANCommander.GetGameManifest(game.Id);
Logger.Trace("Successfully grabbed game manifest");
var existingGame = PlayniteApi.Database.Games.FirstOrDefault(g => g.GameId == game.Id.ToString() && g.PluginId == Id && g.IsInstalled); var existingGame = PlayniteApi.Database.Games.FirstOrDefault(g => g.GameId == game.Id.ToString() && g.PluginId == Id && g.IsInstalled);
if (existingGame != null) if (existingGame != null)
{ {
Logger.Trace("Game already exists in library, updating metadata...");
UpdateGame(manifest, game.Id); UpdateGame(manifest, game.Id);
continue; continue;
} }
Logger.Trace("Game does not exist in the library, importing metadata...");
var metadata = new GameMetadata() var metadata = new GameMetadata()
{ {
IsInstalled = false, IsInstalled = false,
@ -142,7 +151,7 @@ namespace LANCommander.PlaynitePlugin
} }
catch (Exception ex) catch (Exception ex)
{ {
Logger.Error(ex, $"Could not update game \"{game.Title}\" in library");
} }
}; };
@ -167,6 +176,8 @@ namespace LANCommander.PlaynitePlugin
public override IEnumerable<GameMenuItem> GetGameMenuItems(GetGameMenuItemsArgs args) public override IEnumerable<GameMenuItem> GetGameMenuItems(GetGameMenuItemsArgs args)
{ {
Logger.Trace("Populating game menu items...");
if (args.Games.Count == 1 && args.Games.First().IsInstalled && !String.IsNullOrWhiteSpace(args.Games.First().InstallDirectory)) if (args.Games.Count == 1 && args.Games.First().IsInstalled && !String.IsNullOrWhiteSpace(args.Games.First().InstallDirectory))
{ {
var nameChangeScriptPath = PowerShellRuntime.GetScriptFilePath(args.Games.First(), SDK.Enums.ScriptType.NameChange); var nameChangeScriptPath = PowerShellRuntime.GetScriptFilePath(args.Games.First(), SDK.Enums.ScriptType.NameChange);
@ -174,6 +185,9 @@ namespace LANCommander.PlaynitePlugin
var installScriptPath = PowerShellRuntime.GetScriptFilePath(args.Games.First(), SDK.Enums.ScriptType.Install); var installScriptPath = PowerShellRuntime.GetScriptFilePath(args.Games.First(), SDK.Enums.ScriptType.Install);
if (File.Exists(nameChangeScriptPath)) if (File.Exists(nameChangeScriptPath))
{
Logger.Trace($"Name change script found at path {nameChangeScriptPath}");
yield return new GameMenuItem yield return new GameMenuItem
{ {
Description = "Change Player Name", Description = "Change Player Name",
@ -187,8 +201,12 @@ namespace LANCommander.PlaynitePlugin
PowerShellRuntime.RunScript(nameChangeArgs.Games.First(), SDK.Enums.ScriptType.NameChange, $@"""{result.SelectedString}"" ""{oldName}"""); PowerShellRuntime.RunScript(nameChangeArgs.Games.First(), SDK.Enums.ScriptType.NameChange, $@"""{result.SelectedString}"" ""{oldName}""");
} }
}; };
}
if (File.Exists(keyChangeScriptPath)) if (File.Exists(keyChangeScriptPath))
{
Logger.Trace($"Key change script found at path {keyChangeScriptPath}");
yield return new GameMenuItem yield return new GameMenuItem
{ {
Description = "Change Game Key", Description = "Change Game Key",
@ -212,8 +230,12 @@ namespace LANCommander.PlaynitePlugin
} }
} }
}; };
}
if (File.Exists(installScriptPath)) if (File.Exists(installScriptPath))
{
Logger.Trace($"Install script found at path {installScriptPath}");
yield return new GameMenuItem yield return new GameMenuItem
{ {
Description = "Run Install Script", Description = "Run Install Script",
@ -231,6 +253,7 @@ namespace LANCommander.PlaynitePlugin
} }
} }
}; };
}
} }
} }
@ -304,28 +327,41 @@ namespace LANCommander.PlaynitePlugin
public void ShowNameChangeWindow() public void ShowNameChangeWindow()
{ {
Logger.Trace("Showing name change dialog!");
var result = PlayniteApi.Dialogs.SelectString("Enter your new player name. This will change your name across all installed games!", "Enter Name", Settings.PlayerName); var result = PlayniteApi.Dialogs.SelectString("Enter your new player name. This will change your name across all installed games!", "Enter Name", Settings.PlayerName);
if (result.Result == true) if (result.Result == true)
{ {
Logger.Trace($"New name entered was \"{result.SelectedString}\"");
// Check to make sure they're staying in ASCII encoding // Check to make sure they're staying in ASCII encoding
if (String.IsNullOrEmpty(result.SelectedString) || result.SelectedString.Any(c => c > sbyte.MaxValue)) if (String.IsNullOrEmpty(result.SelectedString) || result.SelectedString.Any(c => c > sbyte.MaxValue))
{ {
PlayniteApi.Dialogs.ShowErrorMessage("The name you supplied is invalid. Try again."); PlayniteApi.Dialogs.ShowErrorMessage("The name you supplied is invalid. Try again.");
Logger.Trace("An invalid name was specified. Showing the name dialog again...");
ShowNameChangeWindow(); ShowNameChangeWindow();
} }
else else
{ {
Settings.PlayerName = result.SelectedString; Settings.PlayerName = result.SelectedString;
Logger.Trace($"New player name of \"{Settings.PlayerName}\" has been set!");
Logger.Trace("Saving plugin settings!");
SavePluginSettings(Settings); SavePluginSettings(Settings);
var games = PlayniteApi.Database.Games.Where(g => g.IsInstalled).ToList(); var games = PlayniteApi.Database.Games.Where(g => g.IsInstalled).ToList();
Logger.Trace($"Running name change scripts across {games.Count} installed game(s)");
PowerShellRuntime.RunScripts(games, SDK.Enums.ScriptType.NameChange, Settings.PlayerName); PowerShellRuntime.RunScripts(games, SDK.Enums.ScriptType.NameChange, Settings.PlayerName);
} }
} }
else
Logger.Trace("Name change was cancelled");
} }
public Window ShowAuthenticationWindow() public Window ShowAuthenticationWindow()

View file

@ -1,4 +1,5 @@
using LANCommander.SDK.Enums; using LANCommander.SDK.Enums;
using Playnite.SDK;
using Playnite.SDK.Models; using Playnite.SDK.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -15,6 +16,8 @@ namespace LANCommander.PlaynitePlugin
{ {
internal class PowerShellRuntime internal class PowerShellRuntime
{ {
public static readonly ILogger Logger = LogManager.GetLogger();
[DllImport("kernel32.dll", SetLastError = true)] [DllImport("kernel32.dll", SetLastError = true)]
static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr); static extern bool Wow64DisableWow64FsRedirection(ref IntPtr ptr);
@ -23,8 +26,12 @@ namespace LANCommander.PlaynitePlugin
public void RunCommand(string command, bool asAdmin = false) public void RunCommand(string command, bool asAdmin = false)
{ {
Logger.Trace($"Executing command `{command}` | Admin: {asAdmin}");
var tempScript = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".ps1"); var tempScript = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".ps1");
Logger.Trace($"Creating temp script at path {tempScript}");
File.WriteAllText(tempScript, command); File.WriteAllText(tempScript, command);
RunScript(tempScript, asAdmin); RunScript(tempScript, asAdmin);
@ -34,8 +41,11 @@ namespace LANCommander.PlaynitePlugin
public void RunScript(string path, bool asAdmin = false, string arguments = null) public void RunScript(string path, bool asAdmin = false, string arguments = null)
{ {
Logger.Trace($"Executing script at path {path} | Admin: {asAdmin} | Arguments: {arguments}");
var wow64Value = IntPtr.Zero; var wow64Value = IntPtr.Zero;
// Disable Wow64 redirection so we can hit areas of the registry absolutely
Wow64DisableWow64FsRedirection(ref wow64Value); Wow64DisableWow64FsRedirection(ref wow64Value);
var process = new Process(); var process = new Process();
@ -49,7 +59,10 @@ namespace LANCommander.PlaynitePlugin
process.StartInfo.Arguments += " " + arguments; process.StartInfo.Arguments += " " + arguments;
if (asAdmin) if (asAdmin)
{
process.StartInfo.Verb = "runas"; process.StartInfo.Verb = "runas";
process.StartInfo.UseShellExecute = true;
}
process.Start(); process.Start();
process.WaitForExit(); process.WaitForExit();
@ -57,28 +70,6 @@ namespace LANCommander.PlaynitePlugin
Wow64RevertWow64FsRedirection(ref wow64Value); Wow64RevertWow64FsRedirection(ref wow64Value);
} }
public void RunScriptsAsAdmin(IEnumerable<string> paths, string arguments = null)
{
// Concatenate scripts
var sb = new StringBuilder();
foreach (var path in paths)
{
var contents = File.ReadAllText(path);
sb.AppendLine(contents);
}
if (sb.Length > 0)
{
var scriptPath = Path.GetTempFileName();
File.WriteAllText(scriptPath, sb.ToString());
RunScript(scriptPath, true, arguments);
}
}
public void RunScript(Game game, ScriptType type, string arguments = null) public void RunScript(Game game, ScriptType type, string arguments = null)
{ {
var path = GetScriptFilePath(game, type); var path = GetScriptFilePath(game, type);
@ -94,6 +85,36 @@ namespace LANCommander.PlaynitePlugin
} }
} }
public void RunScriptsAsAdmin(IEnumerable<string> paths, string arguments = null)
{
// Concatenate scripts
var sb = new StringBuilder();
Logger.Trace("Concatenating scripts...");
foreach (var path in paths)
{
var contents = File.ReadAllText(path);
sb.AppendLine(contents);
Logger.Trace($"Added {path}!");
}
Logger.Trace("Done concatenating!");
if (sb.Length > 0)
{
var scriptPath = Path.GetTempFileName();
Logger.Trace($"Creating temp script at path {scriptPath}");
File.WriteAllText(scriptPath, sb.ToString());
RunScript(scriptPath, true, arguments);
}
}
public void RunScripts(IEnumerable<Game> games, ScriptType type, string arguments = null) public void RunScripts(IEnumerable<Game> games, ScriptType type, string arguments = null)
{ {
List<string> scripts = new List<string>(); List<string> scripts = new List<string>();

View file

@ -1,4 +1,5 @@
using LANCommander.SDK.Enums; using LANCommander.SDK.Enums;
using Playnite.SDK;
using Playnite.SDK.Models; using Playnite.SDK.Models;
using Playnite.SDK.Plugins; using Playnite.SDK.Plugins;
using System; using System;
@ -8,6 +9,8 @@ namespace LANCommander.PlaynitePlugin
{ {
public class LANCommanderUninstallController : UninstallController public class LANCommanderUninstallController : UninstallController
{ {
public static readonly ILogger Logger = LogManager.GetLogger();
private LANCommanderLibraryPlugin Plugin; private LANCommanderLibraryPlugin Plugin;
private PowerShellRuntime PowerShellRuntime; private PowerShellRuntime PowerShellRuntime;
@ -26,9 +29,13 @@ namespace LANCommander.PlaynitePlugin
} }
catch { } catch { }
Logger.Trace("Attempting to delete install directory...");
if (!String.IsNullOrWhiteSpace(Game.InstallDirectory) && Directory.Exists(Game.InstallDirectory)) if (!String.IsNullOrWhiteSpace(Game.InstallDirectory) && Directory.Exists(Game.InstallDirectory))
Directory.Delete(Game.InstallDirectory, true); Directory.Delete(Game.InstallDirectory, true);
Logger.Trace("Deleted!");
InvokeOnUninstalled(new GameUninstalledEventArgs()); InvokeOnUninstalled(new GameUninstalledEventArgs());
} }
} }

View file

@ -21,6 +21,8 @@ namespace LANCommander.PlaynitePlugin.Views
{ {
public partial class Authentication : UserControl public partial class Authentication : UserControl
{ {
public static readonly ILogger Logger = LogManager.GetLogger();
private LANCommanderLibraryPlugin Plugin; private LANCommanderLibraryPlugin Plugin;
private ViewModels.Authentication Context { get { return (ViewModels.Authentication)DataContext; } } private ViewModels.Authentication Context { get { return (ViewModels.Authentication)DataContext; } }
@ -32,6 +34,8 @@ namespace LANCommander.PlaynitePlugin.Views
var probe = new Probe("LANCommander"); var probe = new Probe("LANCommander");
Logger.Trace("Attempting to find a LANCommander server on the local network...");
probe.BeaconsUpdated += beacons => Dispatcher.BeginInvoke((System.Action)(() => probe.BeaconsUpdated += beacons => Dispatcher.BeginInvoke((System.Action)(() =>
{ {
var beacon = beacons.First(); var beacon = beacons.First();
@ -40,6 +44,8 @@ namespace LANCommander.PlaynitePlugin.Views
this.ServerAddress.Text = Context.ServerAddress; this.ServerAddress.Text = Context.ServerAddress;
Logger.Trace($"The beacons have been lit! LANCommander calls for aid! {Context.ServerAddress}");
probe.Stop(); probe.Stop();
})); }));