201 lines
No EOL
6.1 KiB
C#
201 lines
No EOL
6.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using ShiroginSDK.Runtime.Modules.IAP.Enums;
|
|
using UnityEngine;
|
|
|
|
namespace ShiroginSDK.Runtime.Modules.Data.Scripts
|
|
{
|
|
[Serializable]
|
|
public class ProductPurchase
|
|
{
|
|
public string ProductId;
|
|
public int PurchaseCount;
|
|
public long LastPurchaseUnix;
|
|
public StoreCategory StoreCategory;
|
|
|
|
public ProductPurchase(string id, int count, long unix, StoreCategory type = StoreCategory.UnknownPacks)
|
|
{
|
|
ProductId = id;
|
|
PurchaseCount = count;
|
|
LastPurchaseUnix = unix;
|
|
StoreCategory = type;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public class LimitedOfferState
|
|
{
|
|
public string OfferId;
|
|
public bool Seen;
|
|
public bool Purchased;
|
|
public long ExpireUnix; // 0 = unlimited
|
|
|
|
public bool IsActive(long nowUnix)
|
|
{
|
|
return ExpireUnix == 0 || nowUnix < ExpireUnix;
|
|
}
|
|
}
|
|
|
|
[Serializable]
|
|
public class StoreData : BaseData
|
|
{
|
|
public const string REMOVE_ADS_PRODUCT_ID = "remove_ads";
|
|
|
|
public List<ProductPurchase> Purchases = new();
|
|
public List<LimitedOfferState> LimitedOffers = new();
|
|
public long DailyShopNextRefreshUnix;
|
|
protected override string PrefsKey => "STORE_DATA";
|
|
|
|
// --------------------------------------------------------------------
|
|
// 🚫 REMOVE ADS
|
|
// --------------------------------------------------------------------
|
|
public bool HasRemovedAds => HasPurchased(REMOVE_ADS_PRODUCT_ID);
|
|
|
|
private static long NowUnix()
|
|
{
|
|
return DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
|
}
|
|
|
|
private ProductPurchase FindPurchase(string pid)
|
|
{
|
|
return Purchases.Find(p => p.ProductId == pid);
|
|
}
|
|
|
|
private LimitedOfferState FindOffer(string oid)
|
|
{
|
|
return LimitedOffers.Find(o => o.OfferId == oid);
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// 🧾 PURCHASE MANAGEMENT
|
|
// --------------------------------------------------------------------
|
|
public void MarkPurchased(string productId, int count = 1, StoreCategory type = StoreCategory.UnknownPacks)
|
|
{
|
|
if (string.IsNullOrEmpty(productId))
|
|
{
|
|
Debug.LogWarning("[StoreData] Tried to mark a purchase with null/empty productId.");
|
|
return;
|
|
}
|
|
|
|
var existing = FindPurchase(productId);
|
|
|
|
if (existing == null)
|
|
{
|
|
Purchases.Add(new ProductPurchase(productId, Mathf.Max(1, count), NowUnix(), type));
|
|
}
|
|
else
|
|
{
|
|
existing.PurchaseCount += Mathf.Max(1, count);
|
|
existing.LastPurchaseUnix = NowUnix();
|
|
existing.StoreCategory = type;
|
|
}
|
|
|
|
Save();
|
|
Debug.Log($"[StoreData] ✅ Purchase marked → {productId} ({type})");
|
|
}
|
|
|
|
public int GetPurchaseCount(string productId)
|
|
{
|
|
return FindPurchase(productId)?.PurchaseCount ?? 0;
|
|
}
|
|
|
|
public bool HasPurchased(string productId)
|
|
{
|
|
return GetPurchaseCount(productId) > 0;
|
|
}
|
|
|
|
public int GetTotalPurchased(StoreCategory type)
|
|
{
|
|
var total = 0;
|
|
foreach (var p in Purchases)
|
|
if (p.StoreCategory == type)
|
|
total += p.PurchaseCount;
|
|
return total;
|
|
}
|
|
|
|
public bool HasPurchasedType(StoreCategory type)
|
|
{
|
|
return Purchases.Exists(p => p.StoreCategory == type);
|
|
}
|
|
|
|
public void ResetPurchases(StoreCategory type)
|
|
{
|
|
Purchases.RemoveAll(p => p.StoreCategory == type);
|
|
Save();
|
|
Debug.Log($"[StoreData] 🔄 Reset purchases of type {type}");
|
|
}
|
|
|
|
public void SetRemoveAds(bool purchased)
|
|
{
|
|
if (purchased)
|
|
MarkPurchased(REMOVE_ADS_PRODUCT_ID, 1, StoreCategory.RemoveAdsPacks);
|
|
else
|
|
Purchases.RemoveAll(p => p.ProductId == REMOVE_ADS_PRODUCT_ID);
|
|
|
|
Save();
|
|
Debug.Log($"[StoreData] 🧩 Remove Ads state updated → {purchased}");
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// 🕒 DAILY SHOP
|
|
// --------------------------------------------------------------------
|
|
public void SetDailyShopRefresh(long nextUnix)
|
|
{
|
|
DailyShopNextRefreshUnix = nextUnix;
|
|
Save();
|
|
}
|
|
|
|
public bool NeedsDailyShopRefresh(long nowUnix)
|
|
{
|
|
return nowUnix >= DailyShopNextRefreshUnix;
|
|
}
|
|
|
|
public void ForceRefreshNow(int hoursToNext = 24)
|
|
{
|
|
DailyShopNextRefreshUnix = NowUnix() + hoursToNext * 3600L;
|
|
Save();
|
|
}
|
|
|
|
// --------------------------------------------------------------------
|
|
// 🎁 LIMITED OFFERS
|
|
// --------------------------------------------------------------------
|
|
public void UpsertOffer(string offerId, long expireUnix = 0)
|
|
{
|
|
var offer = FindOffer(offerId);
|
|
if (offer == null)
|
|
LimitedOffers.Add(new LimitedOfferState
|
|
{
|
|
OfferId = offerId,
|
|
Seen = false,
|
|
Purchased = false,
|
|
ExpireUnix = expireUnix
|
|
});
|
|
else
|
|
offer.ExpireUnix = expireUnix;
|
|
|
|
Save();
|
|
}
|
|
|
|
public void MarkOfferSeen(string offerId)
|
|
{
|
|
var offer = FindOffer(offerId);
|
|
if (offer == null) return;
|
|
offer.Seen = true;
|
|
Save();
|
|
}
|
|
|
|
public bool IsOfferActive(string offerId)
|
|
{
|
|
var offer = FindOffer(offerId);
|
|
return offer != null && offer.IsActive(NowUnix());
|
|
}
|
|
|
|
public void MarkOfferPurchased(string offerId)
|
|
{
|
|
var offer = FindOffer(offerId);
|
|
if (offer == null) return;
|
|
offer.Purchased = true;
|
|
Save();
|
|
}
|
|
}
|
|
} |