popcorn/popcorn/Assets/MyGame/Scripts/GameDataObserver.cs

190 lines
9.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UniRx;
using UnityEngine;
public class GameDataObserver : SingletonMonoBehaviour<GameDataObserver>
{
[SerializeField] private FloatReactiveProperty checkInterval = new FloatReactiveProperty(.1f);
private readonly Subject<int> heartObserver = new Subject<int>();
private readonly Subject<int> sceneCounter = new Subject<int>();
private readonly Subject<int> shopLevelObserver = new Subject<int>();
private readonly Subject<int> achievedMissionObserver = new Subject<int>();
private readonly Subject<int> addCoinObserver = new Subject<int>();
private readonly Subject<int> subCoinObserver = new Subject<int>();
private readonly Subject<int> addCornObserver = new Subject<int>();
private readonly Subject<int> addCustomerObserver = new Subject<int>();
private readonly Subject<int> addSalesObserver = new Subject<int>();
private readonly Subject<int> addRareSalesObserver = new Subject<int>();
private readonly Subject<int> hasRecipeObserver = new Subject<int>();
private readonly Subject<int> deliveredBulkOrderObserver = new Subject<int>();
private readonly BoolReactiveProperty updateMissionAchieved = new BoolReactiveProperty();
public IReadOnlyReactiveProperty<bool> UpdateMissionAchieved => updateMissionAchieved;
public IObservable<bool> ShopLevelUpdate { get; private set; }
private void Start()
{
checkInterval.AddTo(this);
updateMissionAchieved.AddTo(this);
var levelList = SpreadsheetDataManager.Instance.GetBaseDataList<ShopLevelData>(Const.ShopLevelDataSheet);
checkInterval.Select(x => Observable.Interval(TimeSpan.FromSeconds(x))).Switch().Subscribe(_ =>
{
var gameData = GameDataManager.GameData;
heartObserver.OnNext(gameData.Heart);
sceneCounter.OnNext(UnityEngine.SceneManagement.SceneManager.sceneCount);
shopLevelObserver.OnNext(gameData.ViewedShopLevel);
achievedMissionObserver.OnNext(gameData.AchievedMission.Count);
// addCoinObserver.OnNext(gameData.TotalAddCoin);
subCoinObserver.OnNext(gameData.TotalSubCoin);
addCornObserver.OnNext(gameData.TotalAddCornSeed);
addCustomerObserver.OnNext(gameData.TotalCustomerCount);
addSalesObserver.OnNext(gameData.TotalSales);
addRareSalesObserver.OnNext(gameData.RareTotalSales);
hasRecipeObserver.OnNext(gameData.MyRecipes.Length);
deliveredBulkOrderObserver.OnNext(gameData.BulkOrderDeliveredCount);
}).AddTo(this);
ShopLevelUpdate = Observable.CombineLatest(
heartObserver.DistinctUntilChanged(),
sceneCounter.DistinctUntilChanged().Delay(TimeSpan.FromSeconds(.4f)),
(heart, sceneCount) =>
{
var viewedLevel = GameDataManager.GameData.ViewedShopLevel;
if (viewedLevel == 0 && GameDataManager.GameData.isFirstPlay)
{
return false;
}
var currentLevel = levelList.LastOrDefault(data => data.heart <= heart)?.shopLevel ?? 1;
return currentLevel > viewedLevel && sceneCount == 1;
})
.DistinctUntilChanged()
.Publish(false)
.RefCount();
#if UNITY_EDITOR
// ShopLevelUpdate.Subscribe(x => { Debug.Log($"change:{x}"); });
#endif
// ミッション達成チェッカー
var missionList = SpreadsheetDataManager.Instance.GetBaseDataList<MissionData>(Const.MissionDataSheet);
var normalMissionList = missionList.Where(data => data.Category == MissionCategory.Normal).ToList();
var latestMissionList = GetLatestMissionList();
// 各条件の最前の未達成のミッションのみにフィルタ
List<MissionData> GetLatestMissionList() => normalMissionList
.Where(data => data.shopLevel <= GameDataManager.GameData.ViewedShopLevel)
.Where(data => !GameDataManager.GameData.AchievedMission.Contains(data.id))
.GroupBy(data => data.Condition, (_, list) => list.FirstOrDefault()).ToList();
// 店舗レベルアップorミッション達成でリスト更新して達成チェック
Observable.Merge(
shopLevelObserver.DistinctUntilChanged(),
achievedMissionObserver.DistinctUntilChanged())
.Subscribe(_ =>
{
latestMissionList = GetLatestMissionList();
// ここで達成を再確認
updateMissionAchieved.Value = latestMissionList
.Any(data => data.count <= MissionManager.GetProgressValue(data));
// CheckDailyCompleteMission
if (!GameDataManager.GameData.dailyMissionCompleted)
{
if (GameDataManager.GameData.dailyMissionIdArray.Length <= GameDataManager.GameData.dailyMissionAchievedIdArray.Length)
{
updateMissionAchieved.Value = true;
}
}
});
// 各種ポップコーン以外の達成を確認
Observable.Merge(
subCoinObserver.DistinctUntilChanged().Select(_ => MissionCondition.CoinConsumeCount),
addCornObserver.DistinctUntilChanged().Select(_ => MissionCondition.CornCount),
addCustomerObserver.DistinctUntilChanged().Select(_ => MissionCondition.CustomerCount),
hasRecipeObserver.DistinctUntilChanged().Select(_ => MissionCondition.RecipeCount),
deliveredBulkOrderObserver.DistinctUntilChanged().Select(_ => MissionCondition.BulkOrderDeliveredCount))
.Subscribe(condition =>
{
if (latestMissionList
.Where(data => data.Condition == condition)
.Any(data => data.count <= MissionManager.GetProgressValue(data)))
{
updateMissionAchieved.Value = true;
}
// dailyMission
var ids = GameDataManager.GameData.dailyMissionIdArray.Except(GameDataManager.GameData.dailyMissionAchievedIdArray);
if (missionList
.Where(data => ids.Contains(data.id))
.Any(missionData => missionData.count <= MissionManager.GetDailyProgressValue(missionData)))
{
updateMissionAchieved.Value = true;
}
});
// ポップコーン達成確認
Observable.Merge(
addSalesObserver.DistinctUntilChanged(),
addRareSalesObserver.DistinctUntilChanged())
.Subscribe(_ =>
{
if (latestMissionList
.Any(data => data.count <= MissionManager.GetProgressValue(data)))
{
updateMissionAchieved.Value = true;
}
// dailyMission
var ids = GameDataManager.GameData.dailyMissionIdArray.Except(GameDataManager.GameData.dailyMissionAchievedIdArray);
if (missionList
.Where(data => ids.Contains(data.id))
.Any(missionData => missionData.count <= MissionManager.GetDailyProgressValue(missionData)))
{
updateMissionAchieved.Value = true;
}
});
// デイリーミッション日付チェック
sceneCounter
.Where(x => x <= 1)
.Subscribe(x =>
{
var gameData = GameDataManager.GameData;
if (gameData.ViewedShopLevel == 0)
{
return;
}
var lastSetDateUtc = DateTime.FromBinary(gameData.lastDailyMissionSetTime);
// 現時刻が最後にデイリーミッションを設定した日より前の場合無視(時間操作対策)
if (lastSetDateUtc > DateTime.UtcNow)
{
#if UNITY_EDITOR
Debug.Log($"不正な時刻 {lastSetDateUtc:s}");
#endif
return;
}
// ミッションリセットチェック(0時)
if (gameData.GetDailyMissionLimitTime().TotalSeconds > 0)
{
return;
}
#if UNITY_EDITOR
Debug.Log($"reset daily mission");
#endif
// ミッション実績リセット
gameData.dailyMissionAchievedIdArray = new int[0];
gameData.dailyMissionCompleted = false;
gameData.ResetDailyTotalCount();
// 新ミッション登録
var targetList = missionList.Where(data =>
data.Category == MissionCategory.Daily && data.shopLevel <= gameData.ViewedShopLevel);
gameData.dailyMissionIdArray = targetList.ToList().RandomChoose(3).Select(data => data.id).ToArray();
gameData.lastDailyMissionSetTime = DateTime.UtcNow.ToBinary();
gameData.dailyLoginCount++;
GameDataManager.SaveGameData();
});
}
}