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

214 lines
9.6 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using UniRx;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameDataObserver : SingletonMonoBehaviour<GameDataObserver>
{
[SerializeField] private FloatReactiveProperty checkInterval = new FloatReactiveProperty(.2f);
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 Subject<Unit> updateMissionProgress = new Subject<Unit>();
private readonly BoolReactiveProperty updateMissionAchieved = new BoolReactiveProperty();
public IReadOnlyReactiveProperty<bool> UpdateMissionAchieved => updateMissionAchieved;
public IObservable<int> HeartObserver => heartObserver;
public IObservable<int> SceneCounter => sceneCounter.DistinctUntilChanged();
public IObservable<int> ShopLevelObserver => shopLevelObserver.AddTo(this);
private GameData globalGameData;
private GameData cityGameData;
private List<MissionData> missionDataList;
private List<MissionData> latestNormalMissions;
private List<MissionData> normalMissionList;
private static readonly MissionCondition[] StaticMissionConditions = {
MissionCondition.UseFertilizer,
MissionCondition.UseAdWalker,
MissionCondition.UseAutoCook,
};
private void Start()
{
checkInterval.AddTo(this);
updateMissionAchieved.AddTo(this);
ResetGameData();
var levelList = SpreadsheetDataManager.Instance.GetBaseDataList<ShopLevelData>(Const.ShopLevelDataSheet);
levelList = levelList.Where(data => data.shopLevel != Const.SpecialShopLevel).ToList();
checkInterval
.Select(x => Observable.Interval(TimeSpan.FromSeconds(x))).Switch()
.Subscribe(_ =>
{
heartObserver.OnNext(GameDataUtils.GetTotalHeart());
sceneCounter.OnNext(SceneManager.sceneCount);
shopLevelObserver.OnNext(globalGameData.ViewedShopLevel);
achievedMissionObserver.OnNext(cityGameData.AchievedMission.Count);
// addCoinObserver.OnNext(cityGameData.TotalAddCoin);
subCoinObserver.OnNext(cityGameData.TotalSubCoin);
addCornObserver.OnNext(cityGameData.TotalAddCornSeed);
addCustomerObserver.OnNext(cityGameData.TotalCustomerCount);
addSalesObserver.OnNext(cityGameData.TotalSales);
addRareSalesObserver.OnNext(cityGameData.RareTotalSales);
hasRecipeObserver.OnNext(cityGameData.MyRecipes.Length);
deliveredBulkOrderObserver.OnNext(cityGameData.BulkOrderDeliveredCount);
}).AddTo(this);
// ミッション達成チェッカー
missionDataList = SpreadsheetDataManager.Instance.GetBaseDataList<MissionData>(Const.MissionDataSheet);
normalMissionList = missionDataList.Where(data => data.Category == MissionCategory.Normal).ToList();
UpdateLatestNormalMissions();
// 店舗レベルアップorミッション達成でリスト更新して達成チェック
shopLevelObserver.DistinctUntilChanged().Merge(achievedMissionObserver.DistinctUntilChanged(),
updateMissionProgress.Select(_ => 0))
.Subscribe(_ =>
{
// リスト更新
UpdateLatestNormalMissions();
// ここで達成を確認
CheckNormalMissionNewAchieved();
CheckDailyMissionNewAchieved();
CheckDailyCompleteMission();
});
// 各種ポップコーン以外の達成を確認
subCoinObserver.DistinctUntilChanged().Select(_ => MissionCondition.CoinConsumeCount).Merge(addCornObserver.DistinctUntilChanged().Select(_ => MissionCondition.CornCount),
addCustomerObserver.DistinctUntilChanged().Select(_ => MissionCondition.CustomerCount),
hasRecipeObserver.DistinctUntilChanged().Select(_ => MissionCondition.RecipeCount),
deliveredBulkOrderObserver.DistinctUntilChanged().Select(_ => MissionCondition.BulkOrderDeliveredCount))
.Subscribe(condition =>
{
CheckNormalMissionNewAchieved(condition);
CheckDailyMissionNewAchieved();
});
// ポップコーン販売達成確認
addSalesObserver.DistinctUntilChanged().Merge(addRareSalesObserver.DistinctUntilChanged())
.Subscribe(_ =>
{
CheckNormalMissionNewAchieved();
CheckDailyMissionNewAchieved();
});
// デイリーミッション日付チェック
sceneCounter
.Where(x => x <= 1)
.Subscribe(x =>
{
if (globalGameData.ViewedShopLevel == 0) return;
var lastSetDateUtc = DateTime.FromBinary(globalGameData.lastDailyMissionSetTime);
// 現時刻が最後にデイリーミッションを設定した日より前の場合無視(時間操作対策)
if (lastSetDateUtc > DateTime.UtcNow)
{
#if UNITY_EDITOR
Debug.Log($"不正な時刻 {lastSetDateUtc:s}");
#endif
return;
}
// ミッションリセットチェック(0時)
if (globalGameData.GetDailyMissionLimitTime().TotalSeconds > 0) return;
#if UNITY_EDITOR
Debug.Log("reset daily mission");
#endif
// ミッション実績リセット
globalGameData.dailyMissionAchievedIdArray = Array.Empty<int>();
globalGameData.dailyMissionCompleted = false;
globalGameData.ResetDailyTotalCount();
// 新ミッション登録
var targetList = missionDataList
.Where(data => data.Category == MissionCategory.Daily && data.shopLevel <= globalGameData.ViewedShopLevel)
.Where(data => MissionManager.CheckAvailableMission(data, globalGameData.MyRecipes))
.ToList();
var staticMissionList = targetList
.Where(data => StaticMissionConditions.Contains(data.Condition))
.ToList();
globalGameData.dailyMissionIdArray = targetList
.Where(data => !StaticMissionConditions.Contains(data.Condition))
.ToList()
.RandomChoose(2)
.Append(staticMissionList.RandomChoose()) // 固定ミッション広告視聴
.Select(data => data.id)
.ToArray();
globalGameData.lastDailyMissionSetTime = DateTime.UtcNow.ToBinary();
globalGameData.dailyLoginCount++;
GameDataManager.SaveGameData();
});
}
private void UpdateLatestNormalMissions()
{
// 各条件の最前の未達成のミッションのみにフィルタ
latestNormalMissions = normalMissionList
.Where(data => data.shopLevel <= cityGameData.ViewedShopLevel)
.Where(data => !cityGameData.AchievedMission.Contains(data.id))
.GroupBy(data => data.Condition, (_, list) => list.FirstOrDefault()).ToList();
}
private void CheckNormalMissionNewAchieved(MissionCondition condition)
{
if (latestNormalMissions
.Where(data => data.Condition == condition)
.Any(data => data.count <= MissionManager.GetProgressValue(data)))
{
updateMissionAchieved.Value = true;
}
}
private void CheckNormalMissionNewAchieved()
{
updateMissionAchieved.Value = latestNormalMissions
.Any(data => data.count <= MissionManager.GetProgressValue(data));
}
private void CheckDailyMissionNewAchieved()
{
var ids = globalGameData.dailyMissionIdArray
.Except(globalGameData.dailyMissionAchievedIdArray);
if (missionDataList
.Where(data => ids.Contains(data.id))
.Any(missionData => missionData.count <= MissionManager.GetDailyProgressValue(missionData)))
{
updateMissionAchieved.Value = true;
}
}
private void CheckDailyCompleteMission()
{
if (globalGameData.dailyMissionCompleted) return;
if (globalGameData.dailyMissionIdArray.Length <= globalGameData.dailyMissionAchievedIdArray.Length)
{
updateMissionAchieved.Value = true;
}
}
public void CheckMissionProgress(){
updateMissionProgress.OnNext(Unit.Default);
}
public void ChangeCity(int cityId)
{
// 監視対象リセット
cityGameData = GameDataManager.GetCityGameData(cityId);
}
public void ResetGameData()
{
globalGameData = GameDataManager.GameData;
cityGameData = GameDataManager.GetCurrentCityGameData();
}
}