using System; using System.IO; using UnityEngine; using UnityEngine.Networking; using Supabase.Gotrue; using Supabase.Gotrue.Exceptions; using Client = Supabase.Client; using Cysharp.Threading.Tasks; using TMPro; // Dieses Script wickelt die gesamte Kommunikation mit der Datenbank ab. Das Skript enthält noch einige Verbindungstests (z.B. zu Google), die bei Bedarf zum Debuggen verwendet // werden können. namespace GhostSystem { public class SupabaseManager : MonoBehaviour { public static SupabaseManager instance { get; private set; } public const string subabaseUrl = "https://cezghxztvyggwgunyhmq.supabase.co"; public const string supabaseAnonKey = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImNlemdoeHp0dnlnZ3dndW55aG1xIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDcyMTk5MzcsImV4cCI6MjA2Mjc5NTkzN30.vr6-3X3Ux_DjcCiw_CqG-VKP8BiBXtmCzAXjYTiA_vY"; public Client supabase { get; private set; } public string userId = "09321725-0150-4df0-92a7-029005cc75eb"; private string email; private string password; private const string authFileName = "auth.txt"; public static event Action OnSuperbaseReady; public TMP_Text textbox; private void Start() { Initialize().Forget(); } private async UniTask Initialize() { if (instance == null) // Zuerst wird sichergestellt, dass nur eine Instanz des Supabase-Managers existiert und beim Szenenwechsel mitgenommen wird. { instance = this; DontDestroyOnLoad(gameObject); } else { Destroy(gameObject); return; } Debug.Log("Starting Supabase setup..."); await RunDiagnostics(); // Dann wird geprüft, ob die Supabase-Instanz erreichbar ist. await InitSupabaseAsync(); // Eigentlicher Verbindungsaufbau. OnSuperbaseReady?.Invoke(); // Wenn erfolgreich eine Verbindung zu Supabase aufgebaut wurde, wird das als Event gemeldet. } private async UniTask InitSupabaseAsync() // Wird aufgerufen, um die Verbindung zu Supabase zu initialisieren. { if (supabase != null) return; string path = Path.Combine(Application.persistentDataPath, authFileName); if (File.Exists(path)) // Ist bereits eine Datei mit Email und Passwort auf dem VR-Headset hinterlegt, wird diese ausgelesen. { string[] lines = await UniTask.Run(() => File.ReadAllLines(path)); email = lines[0]; password = lines[1]; } else { // Falls nicht, werden neue Anmeldedaten erstellt. email = string.IsNullOrEmpty(SystemInfo.deviceUniqueIdentifier) // Fake-Email-Adresse wird aus der GUID des Gerätes generiert. ? $"{Guid.NewGuid()}@device.local" // Fallback, generiert theoretisch bei jeder Neuinstallation der App einen anderen User. : $"{SystemInfo.deviceUniqueIdentifier}@device.local"; password = email; // selbe GUID, damit das Passwort sich nicht pro App-Version verändern kann. await UniTask.Run(() => File.WriteAllLines(path, new[] { email, password })); } Debug.Log($"Using Email: {email}, Password: {password}"); supabase = new Client(subabaseUrl, supabaseAnonKey); try { await supabase.InitializeAsync(); textbox.text += "\n\rSupabase initialized."; Debug.Log("Supabase initialized."); } catch (Exception ex) { Debug.LogError($"Initialization failed: {ex}"); textbox.text += "\n\rInitialization failed"; } await AuthenticateAsync(email, password); Debug.Log($"Authenticated user ID: {userId}"); } public async UniTask AuthenticateAsync(string email, string password) // Diese Methode übernimmt die Anmeldung als User bei der Supabase-Instanz. { try { await supabase.Auth.SignIn(email, password); // Nutzt die übergebene Mail-Adresse und das Passwort, um den Unser anzumelden. textbox.text += "\n\rSign-in successful"; Debug.Log("Sign-in successful"); } catch (Exception authEx) // Funktioniert die Anmeldung nicht, wird versucht, einen neuen User mit der übergebenen Mail-Adresse und dem { // Passwort zu registrieren. Debug.LogWarning($"Sign-in failed, trying sign-up: {authEx.Message}"); try { await supabase.Auth.SignUp(email, password); textbox.text += "\n\rSign-up successful"; Debug.Log("Sign-up successful"); } catch (Exception ex) { textbox.text += "\n\rAuthentication failed"; Debug.LogError($"Authentication failed: {ex}"); } } } private async UniTask RunDiagnostics() { await UniTask.WhenAll(CheckSupabaseHealthAsync(), CheckGoogleConnectionAsync()); } private async UniTask CheckSupabaseHealthAsync() // Prüft, ob Supabase erreichbar ist. { using var www = UnityWebRequest.Get($"{subabaseUrl}/auth/v1/health"); www.SetRequestHeader("apikey", supabaseAnonKey); await www.SendWebRequest(); if (www.result == UnityWebRequest.Result.Success) { //textbox.text += $"\n\rSupabase health: {www.downloadHandler.text}"; Debug.Log($"Supabase health: {www.downloadHandler.text}"); } else { //textbox.text += $"\n\rSupabase health check failed: {www.error}"; Debug.LogError($"Supabase health check failed: {www.error}"); } } private async UniTask CheckGoogleConnectionAsync() // Testet, ob grundsätzlich eine Internetverbindung besteht. { using var www = UnityWebRequest.Get("https://www.google.com"); await www.SendWebRequest(); if (www.result == UnityWebRequest.Result.Success) { //textbox.text += "\n\rGoogle request succeeded."; Debug.Log("Google request succeeded."); } else { textbox.text += $"\n\rGoogle connection failed: {www.error}"; Debug.LogError($"Google connection failed: {www.error}"); } } private async UniTask CheckApacheConnectionAsync() { using var www = UnityWebRequest.Get("http://192.168.0.85/test/index.html"); await www.SendWebRequest(); if (www.result == UnityWebRequest.Result.Success) { textbox.text += "\n\rApache request succeeded."; Debug.Log("Apache request succeeded."); } else { textbox.text += $"\n\rApache connection failed: {www.error}"; Debug.LogError($"❌ Apache connection failed: {www.error}"); } } } }