Files
bansonic_beta_main/Assets/scripts/_runtimecache/PlayerEconomyLedger.cs
T

223 lines
4.6 KiB
C#

using System;
using UnityEngine;
public sealed class PlayerEconomyLedger : MonoBehaviour
{
public static PlayerEconomyLedger Instance { get; private set; }
public event Action<int> OnCoinsChanged;
public event Action<int> OnMaterialChanged;
private PlayerEconomyPayload payload;
private bool initialized;
private bool loadedFromSave;
private Player_SO boundPlayerData;
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
private static void Bootstrap()
{
EnsureInstance();
}
public static PlayerEconomyLedger EnsureInstance()
{
if (Instance != null)
{
return Instance;
}
var host = new GameObject("__runtime_wallet_bridge");
host.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;
DontDestroyOnLoad(host);
Instance = host.AddComponent<PlayerEconomyLedger>();
return Instance;
}
private void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
Instance = this;
DontDestroyOnLoad(gameObject);
InitializeIfNeeded();
}
private void OnApplicationPause(bool pauseStatus)
{
if (pauseStatus)
{
SaveNow();
}
}
private void OnApplicationQuit()
{
SaveNow();
}
public void InitializeIfNeeded()
{
if (initialized)
{
return;
}
PlayerEconomyPayload loadedPayload;
loadedFromSave = PlayerEconomyStorage.TryLoad(out loadedPayload);
payload = loadedPayload;
initialized = true;
SaveNow();
}
public void AttachPlayerData(Player_SO playerData)
{
if (playerData == null)
{
return;
}
InitializeIfNeeded();
boundPlayerData = playerData;
if (!loadedFromSave)
{
payload.coins = Mathf.Max(0, playerData.Coins);
payload.material = Mathf.Max(0, playerData.Material);
SaveNow();
loadedFromSave = true;
}
SyncToPlayerData();
NotifyEconomyChanged();
}
public int GetCoins()
{
InitializeIfNeeded();
return payload.coins;
}
public int GetMaterial()
{
InitializeIfNeeded();
return payload.material;
}
public bool HasEnoughCoins(long amount)
{
if (amount <= 0)
{
return true;
}
InitializeIfNeeded();
return payload.coins >= amount;
}
public void AddCoins(int amount)
{
if (amount <= 0)
{
return;
}
InitializeIfNeeded();
long next = (long)payload.coins + amount;
payload.coins = next > int.MaxValue ? int.MaxValue : (int)next;
SaveNow();
}
public void AddMaterial(int amount)
{
if (amount <= 0)
{
return;
}
InitializeIfNeeded();
long next = (long)payload.material + amount;
payload.material = next > int.MaxValue ? int.MaxValue : (int)next;
SaveNow();
}
public bool TrySpendCoins(int amount)
{
if (amount <= 0)
{
return true;
}
InitializeIfNeeded();
if (payload.coins < amount)
{
return false;
}
payload.coins -= amount;
SaveNow();
DailyTaskEventHub.ReportSpendCoins(amount);
return true;
}
public void SetCoins(int value)
{
InitializeIfNeeded();
payload.coins = Mathf.Max(0, value);
SaveNow();
}
public void SaveNow()
{
InitializeIfNeededForSave();
PlayerEconomyStorage.TrySave(payload);
SyncToPlayerData();
NotifyEconomyChanged();
}
private void InitializeIfNeededForSave()
{
if (!initialized)
{
InitializeIfNeeded();
}
if (payload == null)
{
payload = PlayerEconomyStorage.CreateDefaultPayload();
}
}
private void SyncToPlayerData()
{
if (boundPlayerData == null || payload == null)
{
return;
}
boundPlayerData.SetCoins(payload.coins);
boundPlayerData.SetMaterial(payload.material);
}
private void NotifyEconomyChanged()
{
if (payload == null)
{
return;
}
if (OnCoinsChanged != null)
{
OnCoinsChanged(payload.coins);
}
if (OnMaterialChanged != null)
{
OnMaterialChanged(payload.material);
}
}
}