This repository has been archived on 2024-11-20. You can view files and clone it, but cannot push or open issues or pull requests.
colourmeok/ColourMeOKGame/Assets/Scripts/GameManager.cs

150 lines
5.4 KiB
C#
Raw Normal View History

2024-11-17 23:17:24 +08:00
using System;
using System.Collections.Generic;
2024-11-15 07:54:43 +08:00
using UnityEngine;
2024-11-17 22:31:03 +08:00
using UnityEngine.UIElements;
2024-11-15 07:54:43 +08:00
/// <summary>
/// singleton for a single source of truth game state and flow management
/// </summary>
public class GameManager : MonoBehaviour
{
/// <summary>
/// singleton pattern: define instance field for accessing the singleton elsewhere
/// </summary>
public static GameManager Instance;
2024-11-17 22:31:03 +08:00
/// <summary>
/// ui manager object for handling ui state and flow
/// </summary>
public UIManager ui;
2024-11-17 07:29:22 +08:00
/// <summary>
2024-11-17 22:05:04 +08:00
/// the local player data object for storing player data
2024-11-17 21:32:14 +08:00
/// </summary>
private LocalPlayerData _data;
/// <summary>
/// read-only property for accessing the local player data outside of this class
/// </summary>
public LocalPlayerData Data => _data;
/// <summary>
/// list of callbacks to call when the local player data changes
/// </summary>
private readonly List<Action<LocalPlayerData>> _onLocalPlayerDataChangeCallbacks = new List<Action<LocalPlayerData>>();
2024-11-17 21:32:14 +08:00
/// <summary>
/// backend object for handling communication with the firebase backend
/// </summary>
public Backend Backend;
2024-11-17 22:05:04 +08:00
2024-11-15 07:54:43 +08:00
/// <summary>
/// enforces singleton behaviour; sets doesn't destroy on load and checks for multiple instances
/// </summary>
private void Awake()
{
// check if instance hasn't been set yet
if (Instance == null)
{
Debug.Log("awake as singleton instance, setting self as the forever-alive instance");
Instance = this;
DontDestroyOnLoad(gameObject);
}
// check if instance is already set and it's not this instance
else if (Instance != null && Instance != this)
{
Debug.Log("awake as non-singleton instance, destroying self");
Destroy(gameObject);
}
2024-11-17 22:31:03 +08:00
}
/// <summary>
/// called when the game object is enabled, initialises variables
/// </summary>
private void OnEnable()
2024-11-17 22:31:03 +08:00
{
ui = UIManager.Instance;
2024-11-17 22:31:03 +08:00
// load the local player data and refresh the ui
_data = new LocalPlayerData();
2024-11-17 07:29:22 +08:00
Backend = new Backend();
Backend.Initialise(status =>
{
Debug.Log("initialised backend, setting connection status text");
ui.UI.Q<Label>("ConnectionStatusText").text = status switch
{
Backend.FirebaseConnectionStatus.Connected => "Status: Connected",
Backend.FirebaseConnectionStatus.Updating => "Status: Updating... (Retrying in a bit!)",
Backend.FirebaseConnectionStatus.NotConnected => "Status: Disconnected",
Backend.FirebaseConnectionStatus.UpdateRequired =>
"Status: Disconnected (Device Component Update Required)",
Backend.FirebaseConnectionStatus.ExternalError => "Status: Disconnected (External/Device Error)",
Backend.FirebaseConnectionStatus.InternalError => "Status: Disconnected (Internal Error)",
_ => "Status: Disconnected (unknown fcs state, this is unreachable and a bug)"
};
if (status == Backend.FirebaseConnectionStatus.Connected) return;
// if we're not connected, hide any online 'features'
ui.UI.Q<Button>("LeaderboardButton").style.display = DisplayStyle.None;
ui.UI.Q<Button>("AccountButton").style.display = DisplayStyle.None;
});
2024-11-17 22:31:03 +08:00
// register a callback to refresh the ui when the player signs in
2024-11-17 23:17:24 +08:00
Backend.RegisterOnSignInCallback(_ =>
{
Debug.Log("sign in callback, refreshing GameManager-controlled SideView UI");
_data.LoadFromTheWorld(FireLocalPlayerDataChangeCallbacks);
2024-11-17 23:17:24 +08:00
});
2024-11-17 19:10:01 +08:00
}
2024-11-17 07:29:22 +08:00
/// <summary>
/// load in stuff
2024-11-17 07:29:22 +08:00
/// </summary>
private void Start()
2024-11-17 07:29:22 +08:00
{
Debug.Log("GameManager starts here");
_data.LoadFromTheWorld(FireLocalPlayerDataChangeCallbacks);
2024-11-17 07:29:22 +08:00
}
2024-11-17 22:31:03 +08:00
/// <summary>
/// called when the application is quitting, saves the local player data
/// </summary>
private void OnApplicationQuit()
2024-11-17 07:29:22 +08:00
{
2024-11-17 22:31:03 +08:00
Debug.Log("running deferred cleanup/save functions");
Backend.Cleanup();
_data.SaveToTheWorld();
2024-11-17 07:29:22 +08:00
}
2024-11-17 19:10:01 +08:00
/// <summary>
/// function to register a callback to be called when the local player data changes
2024-11-17 19:10:01 +08:00
/// </summary>
/// <param name="callback">callback function that takes a <c>LocalPlayerData</c> object</param>
public void RegisterOnLocalPlayerDataChangeCallback(Action<LocalPlayerData> callback)
2024-11-17 19:10:01 +08:00
{
_onLocalPlayerDataChangeCallbacks.Add(callback);
Debug.Log($"registering LocalPlayerDataChangeCallback ({_onLocalPlayerDataChangeCallbacks.Count})");
2024-11-17 19:10:01 +08:00
}
2024-11-17 23:17:24 +08:00
/// <summary>
/// function to fire all local player data change callbacks
2024-11-17 23:17:24 +08:00
/// </summary>
private void FireLocalPlayerDataChangeCallbacks(LocalPlayerData data)
2024-11-17 23:17:24 +08:00
{
Debug.Log($"firing LocalPlayerDataChangeCallbacks ({_onLocalPlayerDataChangeCallbacks.Count})");
foreach (var callback in _onLocalPlayerDataChangeCallbacks)
2024-11-17 23:17:24 +08:00
{
try
{
callback.Invoke(data);
}
catch (Exception e)
{
Debug.LogError($"error invoking LocalPlayerDataChangeCallback: {e.Message}");
}
2024-11-17 23:17:24 +08:00
}
}
2024-11-15 07:54:43 +08:00
}