ShopStorage에서 catalog별 typed storage data를 저장/복원할 때 사용한다.
Status: ACTIVE AppliesTo: v10
ShopStorage는 Shop catalog runtime 상태의 저장 컨테이너다.
[Serializable]
public sealed class ShopStorage
DevianDevian.Samples.MobilePackageShopManager[Serializable]
public abstract class ShopCatalogStorageDataBase
{
public abstract SHOP_CATALOG_TYPE CatalogType { get; }
}
[Serializable]
public abstract class ShopCatalogProductRemainStorageDataBase : ShopCatalogStorageDataBase
{
public Dictionary<string, int> productRemainCounts = new();
}
[Serializable]
public sealed class ShopCatalogDailyStorageData : ShopCatalogStorageDataBase
{
public override SHOP_CATALOG_TYPE CatalogType => SHOP_CATALOG_TYPE.DAILY;
public long autoRefreshUtcMs;
public long adsRefreshUtcMs;
public long manualRefreshUtcMs;
public int manualRefreshRemainCount;
public List<ShopDailyProductState> dailyCatalogProducts = new();
}
[Serializable]
public sealed class ShopCatalogChestStorageData : ShopCatalogProductRemainStorageDataBase
{
public override SHOP_CATALOG_TYPE CatalogType => SHOP_CATALOG_TYPE.CHEST;
public long adsRefreshUtcMs;
public int level;
public int currentExp;
}
[Serializable]
public sealed class ShopCatalogPurchaseStorageData : ShopCatalogStorageDataBase
{
public override SHOP_CATALOG_TYPE CatalogType => SHOP_CATALOG_TYPE.PURCHASE;
}
[Serializable]
public sealed class ShopCatalogGoldStorageData : ShopCatalogProductRemainStorageDataBase
{
public override SHOP_CATALOG_TYPE CatalogType => SHOP_CATALOG_TYPE.GOLD;
public long adsRefreshUtcMs;
}
[Serializable]
public sealed class ShopCatalogEventStorageData : ShopCatalogStorageDataBase
{
public override SHOP_CATALOG_TYPE CatalogType => SHOP_CATALOG_TYPE.EVENT;
public long autoRefreshUtcMs;
}
보조 타입:
ShopDailyProductState = { shopId, discountType, remainCount, amount }ShopStorage 필드:
schemaVersion (현재 14)daily: ShopCatalogDailyStorageDatachest: ShopCatalogChestStorageDatapurchase: ShopCatalogPurchaseStorageDatagold: ShopCatalogGoldStorageDataeventCatalog: ShopCatalogEventStorageData_legacyPurchaseCounts: Dictionary<string, int> (직렬화 안 함)DAILY
autoRefreshUtcMsadsRefreshUtcMsmanualRefreshUtcMsmanualRefreshRemainCountdailyCatalogProductsCHEST
adsRefreshUtcMsproductRemainCountslevelcurrentExpGOLD
adsRefreshUtcMsproductRemainCountsPURCHASE
EVENT
autoRefreshUtcMs규칙:
dailyCatalogProducts는 DAILY 최종 snapshot 전체를 저장한다.FREE, ADS, 비고정 5개가 모두 포함된다.remainCount/discountType/amount 저장 위치는 dailyCatalogProducts 하나뿐이다.max_count=-1)은 CHEST/GOLD.productRemainCounts에 저장하지 않는다.PURCHASE와 EVENT에 필요 없는 상태를 미리 넣지 않는다.currentExp=0으로 저장/복원한다.ShopCatalogFactory.CreateRuntimeCatalogs(storage)는 catalog 생성 시 해당 catalog type의 storage data를 같이 전달한다.productRemainCounts를 직접 적용한다.DAILY는 storage의 dailyCatalogProducts가 valid하면 snapshot 전체를 복원하고, invalid/empty면 FREE/ADS 고정 + 비고정 5개 선택으로 새 snapshot을 생성한다.autoRefreshUtcMs는 시작 시각이 아니라 다음 refresh 시각이다.EVENT.autoRefreshUtcMs는 주기값이 아니라 다음 start_time/end_time 경계 시각이다.adsRefreshUtcMs는 ADS/FREE 구매 성공 시 serverNow + 1day로 기록한다.CHEST.level 기본값은 1이다.CHEST.currentExp 기본값은 0이다.CHEST가 최대 레벨이면 currentExp=0으로 정규화한다.manualRefreshUtcMs는 ShopCatalogDaily.RefreshByAdsAsync() 성공 시 serverNow + 1day로 기록한다.manualRefreshRemainCount는 rolling 24시간 남은 횟수다.manualRefreshRemainCount는 5다.manualRefreshRemainCount를 1 감소시킨다.productRemainCounts는 deserialize 시 dailyCatalogProducts로 병합 복원하고, 신규 저장에서는 사용하지 않는다.purchaseCounts/purchaseLimits는 _legacyPurchaseCounts로만 1회 마이그레이션한다.ShopStorage는 SaveData JSON의 shop 섹션으로 직렬화한다.
SaveDataJsonCodecShop.Serialize(ShopStorage)SaveDataJsonCodecShop.DeserializeInto(JObject, ShopStorage)schemaVersion=13catalogs 하위에 catalog 단위로 묶어 저장한다.DAILY는 adsRefreshUtcMs, autoRefreshUtcMs, manualRefreshUtcMs, manualRefreshRemainCount, dailyCatalogProducts(shopId, discountType, remainCount, amount)를 저장한다.CHEST는 adsRefreshUtcMs, productRemainCounts, level, currentExp를 저장한다.GOLD는 adsRefreshUtcMs, productRemainCounts를 저장한다.EVENT는 autoRefreshUtcMs를 저장한다.PURCHASE는 현재 직렬화할 catalog 전용 상태가 없다.ShopManager.Initialize()는 SaveData에서 복원된 ShopStorage를 읽어 runtime catalog를 생성한다.ShopCatalogFactory가 ShopStorage.GetCatalogData(...)로 catalog-specific storage data를 주입한다.ShopManager.synchronizeProductIndexFromCatalogs()는 product index rebuild만 한다. storage 복원 책임은 없다.ShopManager.InvalidateRuntimeState()를 호출한다.framework-cs/upm/com.devian.foundation/Samples~/MobilePackage/Runtime/Shop/ShopStorage.csframework-cs/apps/UnityExample/Packages/com.devian.foundation/Samples~/MobilePackage/Runtime/Shop/ShopStorage.csframework-cs/apps/UnityExample/Assets/Samples/Devian Foundation/0.1.0/MobilePackage/Runtime/Shop/ShopStorage.cs