game: I FIXED THE CALLBACK FIRING?

This commit is contained in:
Mark Joshwel 2024-11-17 23:17:24 +08:00
parent 30c82d77f6
commit e8091632c4
3 changed files with 140 additions and 102 deletions

View file

@ -65,7 +65,7 @@ public enum UserAccountDetailTargetEnum
/// <summary> /// <summary>
/// callback functions to be invoked when the user signs out /// callback functions to be invoked when the user signs out
/// </summary> /// </summary>
private readonly List<Action<FirebaseUser>> _onSignOutCallback = new(); private readonly List<Action> _onSignOutCallback = new();
/// <summary> /// <summary>
/// the firebase authentication object /// the firebase authentication object
@ -81,6 +81,11 @@ public enum UserAccountDetailTargetEnum
/// the current user object, if authenticated /// the current user object, if authenticated
/// </summary> /// </summary>
private FirebaseUser _user; private FirebaseUser _user;
/// <summary>
/// whether the user is signed in
/// </summary>
public bool IsSignedIn;
/// <summary> /// <summary>
/// the current user's username, if authenticated /// the current user's username, if authenticated
@ -135,6 +140,44 @@ public void Initialise()
Debug.Log("firebase status is" + Status); Debug.Log("firebase status is" + Status);
}); });
} }
/// <summary>
/// function to fire all on sign in callbacks
/// </summary>
private void FireOnSignInCallbacks()
{
Debug.Log($"firing on sign in callbacks ({_onSignInCallback.Count})");
foreach (var callback in _onSignInCallback)
{
try
{
callback.Invoke(_user);
}
catch (Exception e)
{
Debug.LogError(e);
}
}
}
/// <summary>
/// function to fire all on sign out callbacks
/// </summary>
private void FireOnSignOutCallbacks()
{
Debug.Log($"firing on sign out callbacks ({_onSignOutCallback.Count})");
foreach (var callback in _onSignOutCallback)
{
try
{
callback.Invoke();
}
catch (Exception e)
{
Debug.LogError(e);
}
}
}
/// <summary> /// <summary>
/// async function to retry initialisation after a delay /// async function to retry initialisation after a delay
@ -166,44 +209,44 @@ private void AuthStateChanged(object sender, EventArgs eventArgs)
if (_auth.CurrentUser == _user) return; if (_auth.CurrentUser == _user) return;
// if the user has changed, check if they've signed in or out // if the user has changed, check if they've signed in or out
var signedIn = _user != _auth.CurrentUser && _auth.CurrentUser != null; IsSignedIn = _user != _auth.CurrentUser && _auth.CurrentUser != null;
// if we're not signed in, but we still hold _user locally, we've signed out // if we're not signed in, but we still hold _user locally, we've signed out
if (!signedIn && _user != null) if (!IsSignedIn && _user != null)
{ {
Debug.Log($"signed out successfully as {_user.UserId}"); Debug.Log("moi-moi");
foreach (var callback in _onSignOutCallback) FireOnSignOutCallbacks();
callback(_user);
} }
// they have signed in, update _user // they have signed in, update _user
_user = _auth.CurrentUser; _user = _auth.CurrentUser;
if (!signedIn) return; if (!IsSignedIn) return;
Debug.Log($"signed in successfully as {_user.UserId}"); Debug.Log($"signed in successfully as {_user?.UserId}");
RetrieveUsernameWithCallback((_, _) => RetrieveUsernameWithCallback((_, _) =>
{ {
foreach (var callback in _onSignInCallback) callback(_user); FireOnSignInCallbacks();
}); });
} }
/// <summary> /// <summary>
/// function to register a callback for when the user signs in /// function to register a callback for when the user signs in
/// </summary> /// </summary>
/// <param name="callback">callback function that takes in a FirebaseUser argument</param> /// <param name="callback">callback function that takes in a <c>FirebaseUser</c> object</param>
public void RegisterOnSignInCallback(Action<FirebaseUser> callback) public void RegisterOnSignInCallback(Action<FirebaseUser> callback)
{ {
Debug.Log("registering on sign in callback");
_onSignInCallback.Add(callback); _onSignInCallback.Add(callback);
} }
/// <summary> // /// <summary>
/// function to register a callback for when the user signs out // /// function to register a callback for when the user signs out
/// </summary> // /// </summary>
/// <param name="callback">callback function that takes in a FirebaseUser argument</param> // /// <param name="callback">callback function</param>
public void RegisterOnSignOutCallback(Action<FirebaseUser> callback) // public void RegisterOnSignOutCallback(Action callback)
{ // {
_onSignOutCallback.Add(callback); // _onSignOutCallback.Add(callback);
} // }
/// <summary> /// <summary>
/// abstraction function to authenticate the user /// abstraction function to authenticate the user
@ -345,7 +388,7 @@ public void RegisterOnSignOutCallback(Action<FirebaseUser> callback)
/// </summary> /// </summary>
private void RetrieveUsername() private void RetrieveUsername()
{ {
RetrieveUsernameWithCallback((result, username) => { }); RetrieveUsernameWithCallback((_, _) => { });
} }
/// <summary> /// <summary>

View file

@ -1,3 +1,4 @@
using System;
using UnityEngine; using UnityEngine;
using UnityEngine.UIElements; using UnityEngine.UIElements;
@ -52,9 +53,24 @@ private void Start()
_localPlayerData = new LocalPlayerData(); _localPlayerData = new LocalPlayerData();
_localPlayerData.LoadFromTheWorld(); _localPlayerData.LoadFromTheWorld();
PopulateFields(); PopulateFields();
try
{
RenderFromPlayerData();
}
catch (Exception)
{
// TODO: remove this once the bug is fixed
Debug.LogWarning("handling known exception, remove this once the bug is fixed");
}
// register a callback to refresh the ui when the player signs in // register a callback to refresh the ui when the player signs in
Backend.RegisterOnSignInCallback(_ => { _localPlayerData.LoadFromTheWorld(); }); Backend.RegisterOnSignInCallback(_ =>
{
Debug.Log("sign in callback, refreshing GameManager-controlled SideView UI");
_localPlayerData.LoadFromTheWorld();
PopulateFields();
RenderFromPlayerData();
});
} }
/// <summary> /// <summary>
@ -82,7 +98,68 @@ private void OnApplicationQuit()
/// </summary> /// </summary>
public void PopulateFields() public void PopulateFields()
{ {
Debug.Log(
$"populating AccountView fields with lkUsername={_localPlayerData.LastKnownUsername} and lkEmail={_localPlayerData.LastKnownEmail}");
ui.UI.Q<TextField>("UsernameField").value = _localPlayerData.LastKnownUsername; ui.UI.Q<TextField>("UsernameField").value = _localPlayerData.LastKnownUsername;
ui.UI.Q<TextField>("EmailField").value = _localPlayerData.LastKnownEmail; ui.UI.Q<TextField>("EmailField").value = _localPlayerData.LastKnownEmail;
} }
/// <summary>
/// function to update the ui with the latest data
/// </summary>
private void RenderFromPlayerData()
{
// calculate averages from both recent local scores and online scores
var totalLightnessAcc = 0f;
var totalChromaAcc = 0f;
var totalHueAcc = 0f;
var totalRounds = 0;
// average out all the scores we have to get a stable-ish average
foreach (var localScore in _localPlayerData.RecentLocalScores)
{
totalLightnessAcc += localScore.AvgLightnessAccuracy;
totalChromaAcc += localScore.AvgChromaAccuracy;
totalHueAcc += localScore.AvgHueAccuracy;
totalRounds += localScore.NoOfRounds;
}
foreach (var onlineScore in _localPlayerData.RecentOnlineScores)
{
totalLightnessAcc += onlineScore.AvgLightnessAccuracy;
totalChromaAcc += onlineScore.AvgChromaAccuracy;
totalHueAcc += onlineScore.AvgHueAccuracy;
totalRounds += onlineScore.NoOfRounds;
}
foreach (var onlineScore in _localPlayerData.BestOnlineScores)
{
totalLightnessAcc += onlineScore.AvgLightnessAccuracy;
totalChromaAcc += onlineScore.AvgChromaAccuracy;
totalHueAcc += onlineScore.AvgHueAccuracy;
totalRounds += onlineScore.NoOfRounds;
}
Debug.Log($"tL={totalLightnessAcc} tC={totalChromaAcc} tH={totalHueAcc} tR={totalRounds}");
if (totalRounds == 0) totalRounds = 1;
var lightnessAcc = totalLightnessAcc / totalRounds;
var chromaAcc = totalChromaAcc / totalRounds;
var hueAcc = totalHueAcc / totalRounds;
var playerText = Backend.IsSignedIn ? _localPlayerData.LastKnownUsername : $"{_localPlayerData.LastKnownUsername} (Not Signed In)";
// finally, set the labels
ui.UI.Q<Label>("PlayerText").text = playerText;
ui.UI.Q<Label>("LightnessAccuracyText").text = $"{lightnessAcc:F}";
ui.UI.Q<Label>("ChromaAccuracyText").text = $"{chromaAcc:F}";
ui.UI.Q<Label>("HueAccuracyText").text = $"{hueAcc:F}";
// and set the player rating, but after we get it from the backend
// (god I LOVE async (I am LYING out of my teeth))
Backend.CalculateUserRating((dtr, rating) =>
{
if (dtr != Backend.DatabaseTransactionResult.Ok) return;
ui.UI.Q<Label>("RatingText").text = $"{rating:F}";
});
}
} }

View file

@ -11,41 +11,16 @@ public class SideViewUI : MonoBehaviour
/// </summary> /// </summary>
private Button _accountButton; private Button _accountButton;
/// <summary>
/// settings button for showing the settings menu
/// </summary>
private Label _chromaAccuracyText;
/// <summary>
/// settings button for showing the settings menu
/// </summary>
private Label _hueAccuracyText;
/// <summary> /// <summary>
/// leaderboard button for showing the leaderboard /// leaderboard button for showing the leaderboard
/// </summary> /// </summary>
private Button _leaderboardButton; private Button _leaderboardButton;
/// <summary>
/// settings button for showing the settings menu
/// </summary>
private Label _lightnessAccuracyText;
/// <summary> /// <summary>
/// play button for starting the game /// play button for starting the game
/// </summary> /// </summary>
private Button _playButton; private Button _playButton;
/// <summary>
/// settings button for showing the settings menu
/// </summary>
private Label _playerNameText;
/// <summary>
/// settings button for showing the settings menu
/// </summary>
private Label _playerRatingText;
/// <summary> /// <summary>
/// function to subscribe button events to their respective functions /// function to subscribe button events to their respective functions
/// </summary> /// </summary>
@ -61,63 +36,6 @@ private void OnEnable()
_accountButton = ui.Q<Button>("AccountButton"); _accountButton = ui.Q<Button>("AccountButton");
_accountButton.clicked += OnAccountButtonClicked; _accountButton.clicked += OnAccountButtonClicked;
_lightnessAccuracyText = ui.Q<Label>("LightnessAccuracyText");
_hueAccuracyText = ui.Q<Label>("HueAccuracyText");
_chromaAccuracyText = ui.Q<Label>("ChromaAccuracyText");
}
/// <summary>
/// function to update the ui with the latest data
/// </summary>
/// <param name="localPlayerData"></param>
private void RenderFromPlayerData(LocalPlayerData localPlayerData)
{
// calculate averages from both recent local scores and online scores
var totalLightnessAcc = 0f;
var totalChromaAcc = 0f;
var totalHueAcc = 0f;
var totalRounds = 0;
// average out all the scores we have to get a stable-ish average
foreach (var localScore in localPlayerData.RecentLocalScores)
{
totalLightnessAcc += localScore.AvgLightnessAccuracy;
totalChromaAcc += localScore.AvgChromaAccuracy;
totalHueAcc += localScore.AvgHueAccuracy;
totalRounds += localScore.NoOfRounds;
}
foreach (var onlineScore in localPlayerData.RecentOnlineScores)
{
totalLightnessAcc += onlineScore.AvgLightnessAccuracy;
totalChromaAcc += onlineScore.AvgChromaAccuracy;
totalHueAcc += onlineScore.AvgHueAccuracy;
totalRounds += onlineScore.NoOfRounds;
}
foreach (var onlineScore in localPlayerData.BestOnlineScores)
{
totalLightnessAcc += onlineScore.AvgLightnessAccuracy;
totalChromaAcc += onlineScore.AvgChromaAccuracy;
totalHueAcc += onlineScore.AvgHueAccuracy;
totalRounds += onlineScore.NoOfRounds;
}
// finally, set the labels
_playerNameText.text = GameManager.Instance.Backend.GetUsername();
_lightnessAccuracyText.text = $"{totalLightnessAcc / totalRounds:F}";
_hueAccuracyText.text = $"{totalHueAcc / totalRounds:F}";
_chromaAccuracyText.text = $"{totalChromaAcc / totalRounds:F}";
// and set the player rating, but after we get it from the backend
// (god I LOVE async (I am LYING out of my teeth))
GameManager.Instance.Backend.CalculateUserRating((dtr, rating) =>
{
if (dtr != Backend.DatabaseTransactionResult.Ok) return;
_playerRatingText.text = $"{rating:F}";
});
} }
/// <summary> /// <summary>