diff --git a/Bloxstrap/GlobalCache.cs b/Bloxstrap/GlobalCache.cs new file mode 100644 index 00000000..fcd6edee --- /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 78a927df..41acd93a 100644 --- a/Bloxstrap/Integrations/ActivityWatcher.cs +++ b/Bloxstrap/Integrations/ActivityWatcher.cs @@ -190,6 +190,9 @@ private void ReadLogEntry(string entry) 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 @@ private void ReadLogEntry(string entry) _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 @@ private void ReadLogEntry(string entry) 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 @@ private void ReadLogEntry(string entry) 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 @@ private void ReadLogEntry(string entry) 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 @@ private void ReadLogEntry(string entry) } 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 @@ private void ReadLogEntry(string entry) } } - 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 394be4f1..69c94999 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 @@ public long UniverseId 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 @@ public string GetInviteDeeplink(bool launchData = true) 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 bf9ae723..0d863f50 100644 --- a/Bloxstrap/Resources/Strings.Designer.cs +++ b/Bloxstrap/Resources/Strings.Designer.cs @@ -719,15 +719,6 @@ public static string ContextMenu_ServerInformation_InstanceId { } } - /// - /// 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,47 +2700,47 @@ public static string Menu_Integrations_EnableActivityTracking_Title { } /// - /// 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_RequiresActivityTracking { + public static string Menu_Integrations_QueryServerLocation_Description { get { - return ResourceManager.GetString("Menu.Integrations.RequiresActivityTracking", resourceCulture); + return ResourceManager.GetString("Menu.Integrations.QueryServerLocation.Description", resourceCulture); } } /// - /// Looks up a localized string similar to The Roblox game you're playing will be shown on your Discord profile. [Not working?]({0}). + /// Looks up a localized string similar to Query server location. /// - public static string Menu_Integrations_ShowGameActivity_Description { + public static string Menu_Integrations_QueryServerLocation_Title { get { - return ResourceManager.GetString("Menu.Integrations.ShowGameActivity.Description", resourceCulture); + return ResourceManager.GetString("Menu.Integrations.QueryServerLocation.Title", resourceCulture); } } /// - /// Looks up a localized string similar to Show game activity. + /// 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_ShowGameActivity_Title { + public static string Menu_Integrations_RequiresActivityTracking { get { - return ResourceManager.GetString("Menu.Integrations.ShowGameActivity.Title", resourceCulture); + return ResourceManager.GetString("Menu.Integrations.RequiresActivityTracking", resourceCulture); } } /// - /// 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.. + /// Looks up a localized string similar to The Roblox game you're playing will be shown on your Discord profile. [Not working?]({0}). /// - public static string Menu_Integrations_ShowServerDetails_Description { + public static string Menu_Integrations_ShowGameActivity_Description { get { - return ResourceManager.GetString("Menu.Integrations.ShowServerDetails.Description", resourceCulture); + return ResourceManager.GetString("Menu.Integrations.ShowGameActivity.Description", resourceCulture); } } /// - /// Looks up a localized string similar to See server location when joining a game. + /// Looks up a localized string similar to Show game activity. /// - public static string Menu_Integrations_ShowServerDetails_Title { + public static string Menu_Integrations_ShowGameActivity_Title { get { - return ResourceManager.GetString("Menu.Integrations.ShowServerDetails.Title", resourceCulture); + return ResourceManager.GetString("Menu.Integrations.ShowGameActivity.Title", resourceCulture); } } diff --git a/Bloxstrap/Resources/Strings.resx b/Bloxstrap/Resources/Strings.resx index 85bd3321..3301be8c 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 381215c1..3f123020 100644 --- a/Bloxstrap/UI/Elements/ContextMenu/ServerInformation.xaml +++ b/Bloxstrap/UI/Elements/ContextMenu/ServerInformation.xaml @@ -46,14 +46,14 @@ - - + +