Browse Source

Fix a better way to pick-up logged in user.

Dominique Louis 1 week ago
parent
commit
581f0a46b8

+ 218 - 1
MonoGame.Xna.Framework.Net/GamerServices/SignedInGamer.cs

@@ -1,3 +1,10 @@
+#if __ANDROID__
+using Android.OS;
+#endif
+#if __IOS__
+using UIKit;
+#endif
+
 namespace Microsoft.Xna.Framework.GamerServices
 {
 	/// <summary>
@@ -17,13 +24,223 @@ namespace Microsoft.Xna.Framework.GamerServices
                 if (current == null)
                 {
                     current = new SignedInGamer();
-                    current.SetGamertag(Environment.UserName);
+                    current.SetGamertag(GetPlatformUsername());
                 }
                 return current;
             }
             internal set => current = value;
         }
 
+        /// <summary>
+        /// Gets a platform-appropriate username for the device.
+        /// Attempts to retrieve the actual user identity on each platform with appropriate fallbacks.
+        /// </summary>
+        private static string GetPlatformUsername()
+        {
+            // Desktop platforms: Use OS username (most reliable)
+            if (OperatingSystem.IsWindows() || OperatingSystem.IsMacOS() || OperatingSystem.IsLinux())
+            {
+                return GetDesktopUsername();
+            }
+
+            // Mobile platforms: Use device-specific methods
+            if (OperatingSystem.IsAndroid())
+            {
+                return GetAndroidUsername();
+            }
+
+            if (OperatingSystem.IsIOS())
+            {
+                return GetIOSUsername();
+            }
+
+            // Ultimate fallback
+            return "Player";
+        }
+
+        /// <summary>
+        /// Gets username on desktop platforms (Windows, macOS, Linux).
+        /// </summary>
+        private static string GetDesktopUsername()
+        {
+            try
+            {
+                // Try Environment.UserName first (most reliable)
+                string userName = Environment.UserName;
+                if (!string.IsNullOrWhiteSpace(userName) && !IsSystemUID(userName))
+                {
+                    return userName;
+                }
+
+                // Fallback to USER environment variable (macOS/Linux)
+                string envUser = Environment.GetEnvironmentVariable("USER");
+                if (!string.IsNullOrWhiteSpace(envUser) && !IsSystemUID(envUser))
+                {
+                    return envUser;
+                }
+
+                // Windows alternative: USERNAME environment variable
+                string envUsername = Environment.GetEnvironmentVariable("USERNAME");
+                if (!string.IsNullOrWhiteSpace(envUsername))
+                {
+                    return envUsername;
+                }
+            }
+            catch { }
+
+            return "Player";
+        }
+
+        /// <summary>
+        /// Gets username on Android.
+        /// Tries device name (user-configurable), then brand+model, then Android ID hash.
+        /// </summary>
+        private static string GetAndroidUsername()
+        {
+#if __ANDROID__
+            try
+            {
+                // Try 1: Device name from Settings (user-configurable, most meaningful)
+                try
+                {
+                    string deviceName = Android.Provider.Settings.Secure.GetString(
+                        Android.App.Application.Context.ContentResolver,
+                        Android.Provider.Settings.Secure.AndroidDeviceName
+                    );
+                    if (!string.IsNullOrWhiteSpace(deviceName))
+                    {
+                        return deviceName;
+                    }
+                }
+                catch { }
+
+                // Try 2: Brand + Model (e.g., "Samsung Galaxy S21")
+                try
+                {
+                    string brand = Android.OS.Build.Brand ?? "";
+                    string model = Android.OS.Build.Model ?? "";
+
+                    if (!string.IsNullOrWhiteSpace(model))
+                    {
+                        if (!string.IsNullOrWhiteSpace(brand) && !model.StartsWith(brand, StringComparison.OrdinalIgnoreCase))
+                        {
+                            return $"{brand} {model}".Trim();
+                        }
+                        return model;
+                    }
+                }
+                catch { }
+
+                // Try 3: Android ID (unique but less user-friendly)
+                try
+                {
+                    string androidId = Android.Provider.Settings.Secure.GetString(
+                        Android.App.Application.Context.ContentResolver,
+                        Android.Provider.Settings.Secure.AndroidId
+                    );
+                    if (!string.IsNullOrWhiteSpace(androidId) && androidId.Length >= 8)
+                    {
+                        return $"Device_{androidId.Substring(0, 8).ToUpperInvariant()}";
+                    }
+                }
+                catch { }
+            }
+            catch { }
+#endif
+
+            return "AndroidPlayer";
+        }
+
+        /// <summary>
+        /// Gets username on iOS.
+        /// Tries device name (user-configurable), then creates/retrieves persistent UUID.
+        /// </summary>
+        private static string GetIOSUsername()
+        {
+#if __IOS__
+            try
+            {
+                // Try 1: Device name (user-configured in Settings > General > About > Name)
+                try
+                {
+                    string deviceName = UIKit.UIDevice.CurrentDevice.Name;
+                    if (!string.IsNullOrWhiteSpace(deviceName) && deviceName != "iPhone" && deviceName != "iPad")
+                    {
+                        return deviceName;
+                    }
+                }
+                catch { }
+
+                // Try 2: Persistent UUID stored in UserDefaults (survives reinstalls if iCloud synced)
+                try
+                {
+                    var defaults = Foundation.NSUserDefaults.StandardUserDefaults;
+                    string uuid = defaults.StringForKey("game_player_uuid");
+
+                    if (string.IsNullOrEmpty(uuid))
+                    {
+                        // Generate new UUID if not present
+                        uuid = Foundation.NSProcessInfo.ProcessInfo.GloballyUniqueString;
+                        defaults.SetString(uuid, "game_player_uuid");
+                        defaults.Synchronize();
+                    }
+
+                    if (!string.IsNullOrWhiteSpace(uuid) && uuid.Length >= 8)
+                    {
+                        return $"Player_{uuid.Substring(0, 8).ToUpperInvariant()}";
+                    }
+                }
+                catch { }
+
+                // Try 3: UIDevice model as fallback
+                try
+                {
+                    string model = UIKit.UIDevice.CurrentDevice.Model;
+                    if (!string.IsNullOrWhiteSpace(model))
+                    {
+                        return model;
+                    }
+                }
+                catch { }
+            }
+            catch { }
+#endif
+
+            return "iOSPlayer";
+        }
+
+        /// <summary>
+        /// Checks if a username represents a system user rather than a real person.
+        /// </summary>
+        private static bool IsSystemUID(string name)
+        {
+            if (string.IsNullOrWhiteSpace(name))
+                return true;
+
+            // Android app UID format (e.g., "U0_A123" or "u0_a123")
+            if (name.StartsWith("U0_A", StringComparison.OrdinalIgnoreCase) ||
+                name.StartsWith("u0_a", StringComparison.OrdinalIgnoreCase))
+            {
+                return true;
+            }
+
+            // Linux system UIDs (typically < 1000)
+            if (int.TryParse(name, out int uid) && uid < 1000)
+            {
+                return true;
+            }
+
+            // Common system users across Unix-like systems
+            string[] systemUsers = new[]
+            {
+                "root", "bin", "sys", "daemon", "adm", "lp", "sync", "shutdown",
+                "halt", "mail", "news", "uucp", "operator", "nobody", "games",
+                "postgres", "mysql", "www-data", "apache", "nginx"
+            };
+
+            return Array.Exists(systemUsers, user => user.Equals(name, StringComparison.OrdinalIgnoreCase));
+        }
+
         private string gamertag;
 
         /// <summary>

+ 1 - 1
MonoGame.Xna.Framework.Net/MonoGame.Xna.Framework.Net.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>net8.0</TargetFramework>
+    <TargetFramework>net9.0</TargetFramework>
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>disable</Nullable>
     <RootNamespace>Microsoft.Xna.Framework</RootNamespace>