Files
tankwar_proj/js/managers/CurrencyManager.js
2026-04-10 22:59:39 +08:00

173 lines
3.9 KiB
JavaScript

/**
* CurrencyManager.js
* Manages the single in-game currency: Gold.
* Simplified from the original multi-currency system (monetization-lite).
* Provides add/spend/get operations with EventBus notifications,
* StorageManager persistence, and overflow protection.
*/
/** Maximum gold cap to prevent overflow. */
const MAX_GOLD = 999999;
class CurrencyManager {
constructor() {
this._gold = 0;
this._load();
}
// ============================================================
// Persistence
// ============================================================
/**
* Load currency data from StorageManager.
* @private
*/
_load() {
try {
if (GameGlobal && GameGlobal.storageManager) {
const data = GameGlobal.storageManager.get('currency', null);
if (data) {
this._gold = data.gold || 0;
}
}
} catch (e) {
console.warn('[CurrencyManager] Failed to load currency data:', e);
}
}
/**
* Save currency data to StorageManager.
* @private
*/
_save() {
try {
if (GameGlobal && GameGlobal.storageManager) {
GameGlobal.storageManager.set('currency', {
gold: this._gold,
});
}
} catch (e) {
console.warn('[CurrencyManager] Failed to save currency data:', e);
}
}
/**
* Emit a currency change event via EventBus.
* @private
*/
_emitGoldChanged() {
try {
if (GameGlobal && GameGlobal.eventBus) {
GameGlobal.eventBus.emit('currency:gold:changed', this._gold);
}
} catch (e) {}
}
// ============================================================
// Gold
// ============================================================
/**
* Get current gold amount.
* @returns {number}
*/
getGold() {
return this._gold;
}
/**
* Add gold (capped at MAX_GOLD).
* @param {number} amount - Must be positive.
* @returns {number} Actual amount added (may be less if capped).
*/
addGold(amount) {
if (amount <= 0) return 0;
const before = this._gold;
this._gold = Math.min(this._gold + Math.floor(amount), MAX_GOLD);
const added = this._gold - before;
if (added > 0) {
this._save();
this._emitGoldChanged();
}
return added;
}
/**
* Spend gold.
* @param {number} amount - Must be positive.
* @returns {boolean} True if successful, false if insufficient.
*/
spendGold(amount) {
if (amount <= 0) return true;
if (this._gold < amount) {
// Emit insufficient event for UI to handle
try {
if (GameGlobal && GameGlobal.eventBus) {
GameGlobal.eventBus.emit('currency:gold:insufficient', { required: amount, current: this._gold });
}
} catch (e) {}
return false;
}
this._gold -= Math.floor(amount);
this._save();
this._emitGoldChanged();
return true;
}
/**
* Check if player has enough gold.
* @param {number} amount
* @returns {boolean}
*/
hasGold(amount) {
return this._gold >= amount;
}
/**
* Check if gold is at maximum cap.
* @returns {boolean}
*/
isGoldFull() {
return this._gold >= MAX_GOLD;
}
/**
* Get the maximum gold cap.
* @returns {number}
*/
getMaxGold() {
return MAX_GOLD;
}
// ============================================================
// Cloud Sync
// ============================================================
/**
* Get currency data for cloud sync.
* @returns {object}
*/
getCloudSyncData() {
return {
gold: this._gold,
};
}
/**
* Restore currency data from cloud (merge: keep higher values).
* @param {object} cloudData
*/
restoreFromCloud(cloudData) {
if (!cloudData) return;
if (cloudData.gold !== undefined && cloudData.gold > this._gold) {
this._gold = Math.min(cloudData.gold, MAX_GOLD);
this._save();
this._emitGoldChanged();
}
}
}
module.exports = CurrencyManager;