From 2805263a633fc3da8b8bd59ad6f3ac57bcbb3264 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Wed, 4 Sep 2024 17:47:58 +0100 Subject: [PATCH 1/3] Fix remaining activity tracker related bugs --- Bloxstrap/Integrations/ActivityWatcher.cs | 13 +++++++++++-- .../ContextMenu/ServerHistoryViewModel.cs | 3 +-- .../UI/ViewModels/Installer/WelcomeViewModel.cs | 1 - 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Bloxstrap/Integrations/ActivityWatcher.cs b/Bloxstrap/Integrations/ActivityWatcher.cs index 914493b..c772397 100644 --- a/Bloxstrap/Integrations/ActivityWatcher.cs +++ b/Bloxstrap/Integrations/ActivityWatcher.cs @@ -125,7 +125,6 @@ namespace Bloxstrap.Integrations } } - // TODO: i need to double check how this handles failed game joins (connection error, invalid permissions, etc) private void ReadLogEntry(string entry) { const string LOG_IDENT = "ActivityWatcher::ReadLogEntry"; @@ -142,7 +141,17 @@ namespace Bloxstrap.Integrations App.Logger.WriteLine(LOG_IDENT, $"Read {_logEntriesRead} log entries"); if (entry.Contains(GameLeavingEntry)) - OnAppClose?.Invoke(this, new EventArgs()); + { + App.Logger.WriteLine(LOG_IDENT, "User is back into the desktop app"); + + OnAppClose?.Invoke(this, EventArgs.Empty); + + if (Data.PlaceId != 0 && !InGame) + { + App.Logger.WriteLine(LOG_IDENT, "User appears to be leaving from a cancelled/errored join"); + Data = new(); + } + } if (!InGame && Data.PlaceId == 0) { diff --git a/Bloxstrap/UI/ViewModels/ContextMenu/ServerHistoryViewModel.cs b/Bloxstrap/UI/ViewModels/ContextMenu/ServerHistoryViewModel.cs index bea9d61..f48e534 100644 --- a/Bloxstrap/UI/ViewModels/ContextMenu/ServerHistoryViewModel.cs +++ b/Bloxstrap/UI/ViewModels/ContextMenu/ServerHistoryViewModel.cs @@ -36,8 +36,7 @@ namespace Bloxstrap.UI.ViewModels.ContextMenu if (entries.Any()) { - // TODO: this will duplicate universe ids - string universeIds = String.Join(',', entries.Select(x => x.UniverseId)); + string universeIds = String.Join(',', entries.GroupBy(x => x.UniverseId).Select(x => x.First())); try { diff --git a/Bloxstrap/UI/ViewModels/Installer/WelcomeViewModel.cs b/Bloxstrap/UI/ViewModels/Installer/WelcomeViewModel.cs index 41190d8..025b84a 100644 --- a/Bloxstrap/UI/ViewModels/Installer/WelcomeViewModel.cs +++ b/Bloxstrap/UI/ViewModels/Installer/WelcomeViewModel.cs @@ -1,6 +1,5 @@ namespace Bloxstrap.UI.ViewModels.Installer { - // TODO: administrator check? public class WelcomeViewModel : NotifyPropertyChangedViewModel { // formatting is done here instead of in xaml, it's just a bit easier From 0d5be93616b6b978af4eeb59f9bbba5c5a7ede17 Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Thu, 5 Sep 2024 11:14:46 +0100 Subject: [PATCH 2/3] Fix some other things --- Bloxstrap/Installer.cs | 2 +- Bloxstrap/Integrations/ActivityWatcher.cs | 2 +- .../ContextMenu/MenuContainer.xaml.cs | 21 ++++++++++++++----- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/Bloxstrap/Installer.cs b/Bloxstrap/Installer.cs index c08c45f..e807455 100644 --- a/Bloxstrap/Installer.cs +++ b/Bloxstrap/Installer.cs @@ -494,7 +494,7 @@ namespace Bloxstrap string oldStartPath = Path.Combine(Paths.WindowsStartMenu, "Bloxstrap"); if (File.Exists(oldDesktopPath)) - File.Move(oldDesktopPath, DesktopShortcut); + File.Move(oldDesktopPath, DesktopShortcut, true); if (Directory.Exists(oldStartPath)) { diff --git a/Bloxstrap/Integrations/ActivityWatcher.cs b/Bloxstrap/Integrations/ActivityWatcher.cs index c772397..78a927d 100644 --- a/Bloxstrap/Integrations/ActivityWatcher.cs +++ b/Bloxstrap/Integrations/ActivityWatcher.cs @@ -226,7 +226,7 @@ namespace Bloxstrap.Integrations { var lastActivity = History.First(); - if (lastActivity is not null && Data.UniverseId == lastActivity.UniverseId && Data.IsTeleport) + if (Data.UniverseId == lastActivity.UniverseId && Data.IsTeleport) Data.RootActivity = lastActivity.RootActivity ?? lastActivity; } } diff --git a/Bloxstrap/UI/Elements/ContextMenu/MenuContainer.xaml.cs b/Bloxstrap/UI/Elements/ContextMenu/MenuContainer.xaml.cs index 25f1d68..388752e 100644 --- a/Bloxstrap/UI/Elements/ContextMenu/MenuContainer.xaml.cs +++ b/Bloxstrap/UI/Elements/ContextMenu/MenuContainer.xaml.cs @@ -28,6 +28,8 @@ namespace Bloxstrap.UI.Elements.ContextMenu private ServerInformation? _serverInformationWindow; + private ServerHistory? _gameHistoryWindow; + public MenuContainer(Watcher watcher) { InitializeComponent(); @@ -51,14 +53,14 @@ namespace Bloxstrap.UI.Elements.ContextMenu { if (_serverInformationWindow is null) { - _serverInformationWindow = new ServerInformation(_watcher); + _serverInformationWindow = new(_watcher); _serverInformationWindow.Closed += (_, _) => _serverInformationWindow = null; } if (!_serverInformationWindow.IsVisible) - _serverInformationWindow.Show(); - - _serverInformationWindow.Activate(); + _serverInformationWindow.ShowDialog(); + else + _serverInformationWindow.Activate(); } public void ActivityWatcher_OnLogOpen(object? sender, EventArgs e) => @@ -135,7 +137,16 @@ namespace Bloxstrap.UI.Elements.ContextMenu if (_activityWatcher is null) throw new ArgumentNullException(nameof(_activityWatcher)); - new ServerHistory(_activityWatcher).ShowDialog(); + if (_gameHistoryWindow is null) + { + _gameHistoryWindow = new(_activityWatcher); + _gameHistoryWindow.Closed += (_, _) => _gameHistoryWindow = null; + } + + if (!_gameHistoryWindow.IsVisible) + _gameHistoryWindow.ShowDialog(); + else + _gameHistoryWindow.Activate(); } } } From 15dc2dfbfe6e1fbf1f4943f21a03fb1d8f08c7ac Mon Sep 17 00:00:00 2001 From: pizzaboxer Date: Thu, 5 Sep 2024 12:53:33 +0100 Subject: [PATCH 3/3] Improvements to server location querying --- Bloxstrap/GlobalCache.cs | 9 ++++ Bloxstrap/Integrations/ActivityWatcher.cs | 54 ++++--------------- Bloxstrap/Models/ActivityData.cs | 52 ++++++++++++++++++ Bloxstrap/Resources/Strings.Designer.cs | 47 +++++++--------- Bloxstrap/Resources/Strings.resx | 13 ++--- .../ContextMenu/ServerInformation.xaml | 6 +-- .../ContextMenu/ServerInformation.xaml.cs | 6 +-- .../Settings/Pages/IntegrationsPage.xaml | 7 +-- Bloxstrap/UI/NotifyIconWrapper.cs | 7 +-- .../ContextMenu/ServerInformationViewModel.cs | 21 ++++---- 10 files changed, 119 insertions(+), 103 deletions(-) create mode 100644 Bloxstrap/GlobalCache.cs diff --git a/Bloxstrap/GlobalCache.cs b/Bloxstrap/GlobalCache.cs new file mode 100644 index 0000000..fcd6ede --- /dev/null +++ b/Bloxstrap/GlobalCache.cs @@ -0,0 +1,9 @@ +namespace Bloxstrap +{ + public static class GlobalCache + { + public static readonly Dictionary PendingTasks = new(); + + public static readonly Dictionary ServerLocation = new(); + } +} diff --git a/Bloxstrap/Integrations/ActivityWatcher.cs b/Bloxstrap/Integrations/ActivityWatcher.cs index 78a927d..41acd93 100644 --- a/Bloxstrap/Integrations/ActivityWatcher.cs +++ b/Bloxstrap/Integrations/ActivityWatcher.cs @@ -190,6 +190,9 @@ namespace Bloxstrap.Integrations Data.JobId = match.Groups[1].Value; Data.MachineAddress = match.Groups[3].Value; + if (App.Settings.Prop.ShowServerDetails && Data.MachineAddressValid) + _ = Data.QueryServerLocation(); + if (_teleportMarker) { Data.IsTeleport = true; @@ -202,7 +205,7 @@ namespace Bloxstrap.Integrations _reservedTeleportMarker = false; } - App.Logger.WriteLine(LOG_IDENT, $"Joining Game ({Data.PlaceId}/{Data.JobId}/{Data.MachineAddress})"); + App.Logger.WriteLine(LOG_IDENT, $"Joining Game ({Data})"); } } else if (!InGame && Data.PlaceId != 0) @@ -243,7 +246,10 @@ namespace Bloxstrap.Integrations Data.MachineAddress = match.Groups[1].Value; - App.Logger.WriteLine(LOG_IDENT, $"Server is UDMUX protected ({Data.PlaceId}/{Data.JobId}/{Data.MachineAddress})"); + if (App.Settings.Prop.ShowServerDetails) + _ = Data.QueryServerLocation(); + + App.Logger.WriteLine(LOG_IDENT, $"Server is UDMUX protected ({Data})"); } else if (entry.Contains(GameJoinedEntry)) { @@ -256,7 +262,7 @@ namespace Bloxstrap.Integrations return; } - App.Logger.WriteLine(LOG_IDENT, $"Joined Game ({Data.PlaceId}/{Data.JobId}/{Data.MachineAddress})"); + App.Logger.WriteLine(LOG_IDENT, $"Joined Game ({Data})"); InGame = true; Data.TimeJoined = DateTime.Now; @@ -270,7 +276,7 @@ namespace Bloxstrap.Integrations if (entry.Contains(GameDisconnectedEntry)) { - App.Logger.WriteLine(LOG_IDENT, $"Disconnected from Game ({Data.PlaceId}/{Data.JobId}/{Data.MachineAddress})"); + App.Logger.WriteLine(LOG_IDENT, $"Disconnected from Game ({Data})"); Data.TimeLeft = DateTime.Now; History.Insert(0, Data); @@ -283,7 +289,7 @@ namespace Bloxstrap.Integrations } else if (entry.Contains(GameTeleportingEntry)) { - App.Logger.WriteLine(LOG_IDENT, $"Initiating teleport to server ({Data.PlaceId}/{Data.JobId}/{Data.MachineAddress})"); + App.Logger.WriteLine(LOG_IDENT, $"Initiating teleport to server ({Data})"); _teleportMarker = true; } else if (_teleportMarker && entry.Contains(GameJoiningReservedServerEntry)) @@ -371,44 +377,6 @@ namespace Bloxstrap.Integrations } } - public async Task GetServerLocation() - { - const string LOG_IDENT = "ActivityWatcher::GetServerLocation"; - - if (GeolocationCache.ContainsKey(Data.MachineAddress)) - return GeolocationCache[Data.MachineAddress]; - - try - { - string location = ""; - var ipInfo = await Http.GetJson($"https://ipinfo.io/{Data.MachineAddress}/json"); - - if (String.IsNullOrEmpty(ipInfo.City)) - throw new InvalidHTTPResponseException("Reported city was blank"); - - if (ipInfo.City == ipInfo.Region) - location = $"{ipInfo.Region}, {ipInfo.Country}"; - else - location = $"{ipInfo.City}, {ipInfo.Region}, {ipInfo.Country}"; - - GeolocationCache[Data.MachineAddress] = location; - - if (!InGame) - return ""; - - return location; - } - catch (Exception ex) - { - App.Logger.WriteLine(LOG_IDENT, $"Failed to get server location for {Data.MachineAddress}"); - App.Logger.WriteException(LOG_IDENT, ex); - - Frontend.ShowMessageBox($"{Strings.ActivityWatcher_LocationQueryFailed}\n\n{ex.Message}", MessageBoxImage.Warning); - - return "?"; - } - } - public void Dispose() { IsDisposed = true; diff --git a/Bloxstrap/Models/ActivityData.cs b/Bloxstrap/Models/ActivityData.cs index 394be4f..69c9499 100644 --- a/Bloxstrap/Models/ActivityData.cs +++ b/Bloxstrap/Models/ActivityData.cs @@ -1,4 +1,5 @@ using System.Web; +using System.Windows; using System.Windows.Input; using CommunityToolkit.Mvvm.Input; @@ -36,6 +37,8 @@ namespace Bloxstrap.Models public string MachineAddress { get; set; } = String.Empty; + public bool MachineAddressValid => !String.IsNullOrEmpty(MachineAddress) && !MachineAddress.StartsWith("10."); + public bool IsTeleport { get; set; } = false; public ServerType ServerType { get; set; } = ServerType.Public; @@ -83,6 +86,55 @@ namespace Bloxstrap.Models return deeplink; } + public async Task QueryServerLocation() + { + const string LOG_IDENT = "ActivityData::QueryServerLocation"; + + if (!MachineAddressValid) + throw new InvalidOperationException($"Machine address is invalid ({MachineAddress})"); + + if (GlobalCache.PendingTasks.TryGetValue(MachineAddress, out Task? task)) + await task; + + if (GlobalCache.ServerLocation.TryGetValue(MachineAddress, out string? location)) + return location; + + try + { + location = ""; + var ipInfoTask = Http.GetJson($"https://ipinfo.io/{MachineAddress}/json"); + + GlobalCache.PendingTasks.Add(MachineAddress, ipInfoTask); + + var ipInfo = await ipInfoTask; + + GlobalCache.PendingTasks.Remove(MachineAddress); + + if (String.IsNullOrEmpty(ipInfo.City)) + throw new InvalidHTTPResponseException("Reported city was blank"); + + if (ipInfo.City == ipInfo.Region) + location = $"{ipInfo.Region}, {ipInfo.Country}"; + else + location = $"{ipInfo.City}, {ipInfo.Region}, {ipInfo.Country}"; + + GlobalCache.ServerLocation[MachineAddress] = location; + + return location; + } + catch (Exception ex) + { + App.Logger.WriteLine(LOG_IDENT, $"Failed to get server location for {MachineAddress}"); + App.Logger.WriteException(LOG_IDENT, ex); + + Frontend.ShowMessageBox($"{Strings.ActivityWatcher_LocationQueryFailed}\n\n{ex.Message}", MessageBoxImage.Warning); + + return "?"; + } + } + + public override string ToString() => $"{PlaceId}/{JobId}"; + private void RejoinServer() { string playerPath = Path.Combine(Paths.Versions, App.State.Prop.PlayerVersionGuid, "RobloxPlayerBeta.exe"); diff --git a/Bloxstrap/Resources/Strings.Designer.cs b/Bloxstrap/Resources/Strings.Designer.cs index bf9ae72..0d863f5 100644 --- a/Bloxstrap/Resources/Strings.Designer.cs +++ b/Bloxstrap/Resources/Strings.Designer.cs @@ -719,15 +719,6 @@ namespace Bloxstrap.Resources { } } - /// - /// Looks up a localized string similar to Loading, please wait.... - /// - public static string ContextMenu_ServerInformation_Loading { - get { - return ResourceManager.GetString("ContextMenu.ServerInformation.Loading", resourceCulture); - } - } - /// /// Looks up a localized string similar to Location. /// @@ -2709,7 +2700,25 @@ namespace Bloxstrap.Resources { } /// - /// Looks up a localized string similar to This feature requires activity tracking to be enabled and the Discord desktop app to be installed and running.. + /// Looks up a localized string similar to When in-game, you'll be able to see where your server is located via [ipinfo.io]({0}).. + /// + public static string Menu_Integrations_QueryServerLocation_Description { + get { + return ResourceManager.GetString("Menu.Integrations.QueryServerLocation.Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Query server location. + /// + public static string Menu_Integrations_QueryServerLocation_Title { + get { + return ResourceManager.GetString("Menu.Integrations.QueryServerLocation.Title", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to This feature requires activity tracking to be enabled and the Discord desktop app to be installed and running. [Find out more]({0}).. /// public static string Menu_Integrations_RequiresActivityTracking { get { @@ -2735,24 +2744,6 @@ namespace Bloxstrap.Resources { } } - /// - /// Looks up a localized string similar to When you join a game, you'll be notified of where your server's located. Won't show in fullscreen.. - /// - public static string Menu_Integrations_ShowServerDetails_Description { - get { - return ResourceManager.GetString("Menu.Integrations.ShowServerDetails.Description", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to See server location when joining a game. - /// - public static string Menu_Integrations_ShowServerDetails_Title { - get { - return ResourceManager.GetString("Menu.Integrations.ShowServerDetails.Title", resourceCulture); - } - } - /// /// Looks up a localized string similar to Integrations. /// diff --git a/Bloxstrap/Resources/Strings.resx b/Bloxstrap/Resources/Strings.resx index 85bd332..3301be8 100644 --- a/Bloxstrap/Resources/Strings.resx +++ b/Bloxstrap/Resources/Strings.resx @@ -268,9 +268,6 @@ Your ReShade configuration files will still be saved, and you can locate them by Instance ID - - Loading, please wait... - Location @@ -755,7 +752,7 @@ Selecting 'No' will ignore this warning and continue installation. Enable activity tracking - This feature requires activity tracking to be enabled and the Discord desktop app to be installed and running. + This feature requires activity tracking to be enabled and the Discord desktop app to be installed and running. [Find out more]({0}). The Roblox game you're playing will be shown on your Discord profile. [Not working?]({0}) @@ -763,11 +760,11 @@ Selecting 'No' will ignore this warning and continue installation. Show game activity - - When you join a game, you'll be notified of where your server's located. Won't show in fullscreen. + + When in-game, you'll be able to see where your server is located via [ipinfo.io]({0}). - - See server location when joining a game + + Query server location Integrations diff --git a/Bloxstrap/UI/Elements/ContextMenu/ServerInformation.xaml b/Bloxstrap/UI/Elements/ContextMenu/ServerInformation.xaml index 381215c..3f12302 100644 --- a/Bloxstrap/UI/Elements/ContextMenu/ServerInformation.xaml +++ b/Bloxstrap/UI/Elements/ContextMenu/ServerInformation.xaml @@ -46,14 +46,14 @@ - - + +