253 lines
6.1 KiB
C#
253 lines
6.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public sealed class EquipmentConsumableLedger : MonoBehaviour
|
|
{
|
|
public static EquipmentConsumableLedger Instance { get; private set; }
|
|
|
|
public event Action<EquipmentConsumableKind, int> OnCountChanged;
|
|
|
|
private readonly Dictionary<string, int> countsByKey = new Dictionary<string, int>(StringComparer.Ordinal);
|
|
private bool initialized;
|
|
|
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
|
private static void Bootstrap()
|
|
{
|
|
EnsureInstance();
|
|
}
|
|
|
|
public static EquipmentConsumableLedger EnsureInstance()
|
|
{
|
|
if (Instance != null)
|
|
{
|
|
return Instance;
|
|
}
|
|
|
|
var host = new GameObject("__runtime_equipment_consumable_bridge");
|
|
host.hideFlags = HideFlags.HideInHierarchy | HideFlags.HideInInspector;
|
|
DontDestroyOnLoad(host);
|
|
Instance = host.AddComponent<EquipmentConsumableLedger>();
|
|
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;
|
|
}
|
|
|
|
EquipmentConsumableLedgerPayload payload;
|
|
EquipmentConsumableLedgerStorage.TryLoad(out payload);
|
|
RebuildFromPayload(payload);
|
|
initialized = true;
|
|
SyncMirrorCounts();
|
|
SaveNow();
|
|
}
|
|
|
|
public int GetCount(EquipmentConsumableKind kind)
|
|
{
|
|
return GetCountByKey(EquipmentConsumableCatalog.GetKey(kind));
|
|
}
|
|
|
|
public void Add(EquipmentConsumableKind kind, int amount)
|
|
{
|
|
if (amount <= 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
ChangeCount(EquipmentConsumableCatalog.GetKey(kind), amount);
|
|
}
|
|
|
|
public bool TryConsume(EquipmentConsumableKind kind, int amount)
|
|
{
|
|
if (amount <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
string key = EquipmentConsumableCatalog.GetKey(kind);
|
|
int current = GetCountByKey(key);
|
|
if (current < amount)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
ChangeCount(key, -amount);
|
|
DailyTaskEventHub.ReportUseItem(amount);
|
|
return true;
|
|
}
|
|
|
|
public void ResetAllToZero()
|
|
{
|
|
InitializeIfNeeded();
|
|
|
|
for (int i = 0; i < EquipmentConsumableCatalog.All.Count; i++)
|
|
{
|
|
countsByKey[EquipmentConsumableCatalog.All[i].Key] = 0;
|
|
}
|
|
|
|
SaveNow();
|
|
NotifyAllCountsChanged();
|
|
}
|
|
|
|
public void SaveNow()
|
|
{
|
|
if (!initialized)
|
|
{
|
|
InitializeIfNeeded();
|
|
}
|
|
|
|
SyncMirrorCounts();
|
|
EquipmentConsumableLedgerStorage.TrySave(BuildPayload());
|
|
}
|
|
|
|
private void SyncMirrorCounts()
|
|
{
|
|
equipmentConsumableSO[] definitions = Resources.FindObjectsOfTypeAll<equipmentConsumableSO>();
|
|
for (int i = 0; i < definitions.Length; i++)
|
|
{
|
|
equipmentConsumableSO definition = definitions[i];
|
|
if (definition == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
definition.runtimeOwnedCount = GetCount(definition.consumableKind);
|
|
}
|
|
}
|
|
|
|
private int GetCountByKey(string key)
|
|
{
|
|
InitializeIfNeeded();
|
|
|
|
if (!countsByKey.TryGetValue(key, out int count))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
private void ChangeCount(string key, int delta)
|
|
{
|
|
InitializeIfNeeded();
|
|
|
|
int current = GetCountByKey(key);
|
|
long next = (long)current + delta;
|
|
if (next < 0)
|
|
{
|
|
next = 0;
|
|
}
|
|
else if (next > int.MaxValue)
|
|
{
|
|
next = int.MaxValue;
|
|
}
|
|
|
|
SetCountByKey(key, (int)next);
|
|
}
|
|
|
|
private void SetCountByKey(string key, int value)
|
|
{
|
|
int safeValue = Mathf.Max(0, value);
|
|
int current = GetCountByKey(key);
|
|
if (current == safeValue)
|
|
{
|
|
return;
|
|
}
|
|
|
|
countsByKey[key] = safeValue;
|
|
SaveNow();
|
|
|
|
if (EquipmentConsumableCatalog.TryGetKind(key, out EquipmentConsumableKind kind) && OnCountChanged != null)
|
|
{
|
|
OnCountChanged(kind, safeValue);
|
|
}
|
|
}
|
|
|
|
private void RebuildFromPayload(EquipmentConsumableLedgerPayload payload)
|
|
{
|
|
countsByKey.Clear();
|
|
for (int i = 0; i < EquipmentConsumableCatalog.All.Count; i++)
|
|
{
|
|
countsByKey[EquipmentConsumableCatalog.All[i].Key] = 0;
|
|
}
|
|
|
|
if (payload == null || payload.entries == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < payload.entries.Count; i++)
|
|
{
|
|
var entry = payload.entries[i];
|
|
if (entry == null || string.IsNullOrEmpty(entry.key))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
countsByKey[entry.key] = Mathf.Max(0, entry.count);
|
|
}
|
|
}
|
|
|
|
private EquipmentConsumableLedgerPayload BuildPayload()
|
|
{
|
|
var payload = EquipmentConsumableLedgerStorage.CreateDefaultPayload();
|
|
payload.entries.Clear();
|
|
|
|
for (int i = 0; i < EquipmentConsumableCatalog.All.Count; i++)
|
|
{
|
|
var descriptor = EquipmentConsumableCatalog.All[i];
|
|
payload.entries.Add(new EquipmentConsumableEntry
|
|
{
|
|
key = descriptor.Key,
|
|
count = GetCountByKey(descriptor.Key)
|
|
});
|
|
}
|
|
|
|
return payload;
|
|
}
|
|
|
|
private void NotifyAllCountsChanged()
|
|
{
|
|
if (OnCountChanged == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
for (int i = 0; i < EquipmentConsumableCatalog.All.Count; i++)
|
|
{
|
|
var descriptor = EquipmentConsumableCatalog.All[i];
|
|
OnCountChanged(descriptor.Kind, GetCountByKey(descriptor.Key));
|
|
}
|
|
}
|
|
}
|