Compare commits

..

2 commits

Author SHA1 Message Date
Mark Joshwel 9db2f1a1db game: the sdk hates me 2024-11-15 04:15:58 +08:00
Mark Joshwel 2a7a720348 scripts: backend foundation/shape 2024-11-15 04:15:45 +08:00
3 changed files with 280 additions and 0 deletions

View file

@ -0,0 +1,261 @@
using System;
using System.Threading.Tasks;
using Firebase;
using Firebase.Auth;
using Firebase.Database;
using UnityEngine;
/// <summary>
/// the general managing class for handling communication with the firebase backend
/// (to be initialised by GameManager)
/// </summary>
public class Backend : MonoBehaviour
{
/// <summary>
/// whether the backend is connected to the firebase backend
/// </summary>
public bool connected;
/// <summary>
/// the firebase authentication object
/// </summary>
private FirebaseAuth _auth;
/// <summary>
/// the firebase database reference
/// </summary>
private DatabaseReference _db;
/// <summary>
/// callback function to be invoked when the user signs in
/// </summary>
private Action<FirebaseUser> _onSignInCallback = user => { Debug.Log("signed in as" + user.UserId); };
/// <summary>
/// callback function to be invoked when the user signs out
/// </summary>
private Action<FirebaseUser> _onSignOutCallback = user => { Debug.Log("signed out" + user.UserId); };
/// <summary>
/// the current user object, if authenticated
/// </summary>
private FirebaseUser _user;
/// <summary>
/// script load function
/// </summary>
private void Awake()
{
Debug.Log("firing firebase Initialise() invocation");
Initialise();
}
/// <summary>
/// deferred cleanup function
/// </summary>
private void OnDestroy()
{
SignOutUser();
}
/// <summary>
/// variable initialisation function
/// </summary>
private void Initialise()
{
FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
{
switch (task.Result)
{
case DependencyStatus.Available:
var app = FirebaseApp.DefaultInstance;
_auth = FirebaseAuth.GetAuth(app);
_auth.StateChanged += AuthStateChanged;
_db = FirebaseDatabase.DefaultInstance.RootReference;
connected = true;
Debug.Log("firebase initialised");
break;
case DependencyStatus.UnavailableDisabled:
case DependencyStatus.UnavailableInvalid:
case DependencyStatus.UnavilableMissing:
case DependencyStatus.UnavailablePermission:
Debug.LogError("firebase error outside of our control");
break;
case DependencyStatus.UnavailableUpdaterequired:
case DependencyStatus.UnavailableUpdating:
Debug.LogError("firebase is updating");
RetryInitialiseAfterDelay();
break;
case DependencyStatus.UnavailableOther:
default:
Debug.LogError("firebase ??? blew up or something," + task.Result);
break;
}
});
}
/// <summary>
/// function to handle the authentication state change event
/// </summary>
/// <param name="sender">the object that triggered the event</param>
/// <param name="eventArgs">the event arguments</param>
private void AuthStateChanged(object sender, EventArgs eventArgs)
{
if (_auth.CurrentUser == _user) return;
var signedIn = _user != _auth.CurrentUser && _auth.CurrentUser != null;
switch (signedIn)
{
case false when _user != null:
_onSignOutCallback(_user);
break;
case true:
_onSignInCallback(_auth.CurrentUser);
break;
}
}
/// <summary>
/// function to register a callback for when the user signs in
/// </summary>
/// <param name="callback">callback function that takes in a FirebaseUser argument</param>
private void RegisterOnSignInCallback(Action<FirebaseUser> callback)
{
_onSignInCallback = callback;
}
/// <summary>
/// function to register a callback for when the user signs out
/// </summary>
/// <param name="callback">callback function that takes in a FirebaseUser argument</param>
private void RegisterOnSignOutCallback(Action<FirebaseUser> callback)
{
_onSignOutCallback = callback;
}
/// <summary>
/// async function to retry initialisation after a delay
/// </summary>
private async void RetryInitialiseAfterDelay()
{
await Task.Delay(TimeSpan.FromSeconds(10));
Initialise();
}
/// <summary>
/// abstraction function to authenticate the user
/// </summary>
/// <param name="username">user name string</param>
/// <param name="password">user raw password string</param>
/// <param name="callback">callback function that takes in an AuthenticationResult argument</param>
/// <param name="registerUser">whether to treat authentication as registration</param>
private void AuthenticateUser(
string username,
string password,
Action<AuthenticationResult> callback,
bool registerUser = false)
{
throw new NotImplementedException();
}
/// <summary>
/// abstraction function to retrieve the user
/// </summary>
/// <returns>the firebase user object</returns>
private FirebaseUser GetUser()
{
return _user;
}
/// <summary>
/// abstraction function to sign out the user
/// </summary>
private void SignOutUser()
{
_auth.SignOut();
}
/// <summary>
/// abstraction function to submit a play to the database
/// </summary>
/// <param name="averageMatchAccuracy">the float percentage (0-100) of how accurate the user was when colour matching</param>
/// <param name="callback">callback function that takes in one DatabaseTransactionResult argument</param>
private void SubmitPlay(
float averageMatchAccuracy,
Action<DatabaseTransactionResult> callback)
{
throw new NotImplementedException();
}
/// <summary>
/// abstraction function to get and calculate the user's rating from the database
/// calculation is done locally, call UpdateUserRating to update the user's rating in the database
/// </summary>
/// <param name="callback">callback function that takes in a DatabaseTransactionResult and float (user rating) argument</param>
private void CalculateUserRating(
Action<DatabaseTransactionResult, float> callback)
{
throw new NotImplementedException();
}
/// <summary>
/// abstraction function to update the user's rating in the database
/// </summary>
/// <param name="newRating">new user rating value as a float</param>
/// <param name="callback">callback function that takes in one DatabaseTransactionResult argument</param>
private void UpdateUserRating(
float newRating,
Action<DatabaseTransactionResult> callback)
{
throw new NotImplementedException();
}
/// <summary>
/// abstraction function to get the leaderboard from the database
/// </summary>
/// <param name="callback"></param>
/// <exception cref="NotImplementedException"></exception>
private void GetLeaderboard(
Action<DatabaseTransactionResult, LeaderboardEntry[]> callback)
{
throw new NotImplementedException();
}
/// <summary>
/// struct for a leaderboard entry
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
public struct LeaderboardEntry
{
public string Username;
public float Rating;
public int PlayCount;
}
/// <summary>
/// enum for the result of the authentication process
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
public enum AuthenticationResult
{
Ok,
AlreadyAuthenticated,
NonExistentUser,
AlreadyExistingUser,
InvalidCredentials,
GenericError
}
/// <summary>
/// generic enum for the result of a database transaction
/// </summary>
// ReSharper disable once MemberCanBePrivate.Global
public enum DatabaseTransactionResult
{
Ok,
Unauthenticated,
Error
}
}

View file

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e377ac89b8e57264d9a53a33902d1e07
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 907afaa291af0c24e9b8dac8089593e1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant: