TH1/Unity/Assets/Scripts/TH1_Logic/Achievement/AchievementDataManager.cs

260 lines
8.8 KiB
C#

/*
* @Author: 白哉
* @Description: 成就数据管理
* @Date: 2025年05月14日 星期三 21:05:54
* @Modify:
*/
using System;
using System.Collections.Generic;
using System.IO;
using Logic.Achievement;
using Logic.CrashSight;
using TH1_Logic.Tools;
using UnityEngine;
namespace RuntimeData
{
public class AchievementDataManager
{
public static AchievementDataManager Instance = new AchievementDataManager();
public AchievementData Achievement;
public List<uint> FinishedCache;
public void OnGameStart(MapData map)
{
LoadAchievement();
BindMapData(map);
ReCheckAchievementDataNotComplete();
}
public void Init()
{
LoadAchievement();
ReCheckAchievementDataNotComplete();
}
public void LoadAchievement()
{
var asset = Resources.Load<AchievementAsset>("Export/Achievement");
string path = Application.persistentDataPath + "/achievement.json";
string backupPath = path + ".bak";
// 尝试读取主文件
Achievement = TryReadAchievementData(path);
// 主文件损坏,尝试从备份恢复
if (Achievement == null && File.Exists(backupPath))
{
LogSystem.LogInfo("[Achievement] 主文件损坏,尝试从备份恢复...");
Achievement = TryReadAchievementData(backupPath);
if (Achievement != null)
{
LogSystem.LogInfo("[Achievement] 从备份恢复成功");
try
{
string json = JsonUtility.ToJson(Achievement);
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(json);
FileTools.SafeWriteFile(path, bytes);
}
catch (Exception e)
{
LogSystem.LogError($"[Achievement] 恢复写入主文件失败: {e.Message}");
}
}
else
{
LogSystem.LogError("[Achievement] 备份文件也已损坏,将重置数据");
}
}
if (Achievement == null)
{
Achievement = asset.Data;
Achievement.ClearAchievementFinishedInfo();
}
else
{
// 移除无效成就
var removeList = new List<AchievementItem>();
foreach (var item in Achievement.AchievementList)
{
var target = asset.Data.GetAchievementItem(item.BigID, item.SmallID, item.InternalID);
if (target != null && !item.CheckChanged(target)) continue;
removeList.Add(item);
}
foreach (var item in removeList)
{
Achievement.RemoveAchievementItem(item.BigID, item.SmallID, item.InternalID);
}
// 添加新增成就
foreach (var item in asset.Data.AchievementList)
{
if (Achievement.GetAchievementItem(item.BigID, item.SmallID, item.InternalID) != null)
continue;
item.IsFinished = false;
Achievement.AchievementList.Add(item);
}
Achievement.RefreshAchievementDict();
}
FinishedCache ??= new List<uint>();
FinishedCache.Clear();
}
private AchievementData TryReadAchievementData(string path)
{
if (!File.Exists(path)) return null;
try
{
string json = File.ReadAllText(path);
if (string.IsNullOrEmpty(json))
{
LogSystem.LogError($"[Achievement] 文件为空: {path}");
return null;
}
var data = JsonUtility.FromJson<AchievementData>(json);
if (data == null)
{
LogSystem.LogError($"[Achievement] 反序列化结果无效: {path}");
return null;
}
return data;
}
catch (Exception e)
{
LogSystem.LogError($"[Achievement] 读取文件失败: {path} | 错误: {e.Message}");
return null;
}
}
public void SaveAchievementData()
{
if (Achievement == null) return;
string json = JsonUtility.ToJson(Achievement);
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(json);
FileTools.SafeWriteFile(Application.persistentDataPath + "/achievement.json", bytes);
}
public void BindMapData(MapData mapData)
{
foreach (var item in Achievement.AchievementList) item.BindMapData(mapData);
}
public void ReCheckAchievementDataNotComplete()
{
foreach (var item in Achievement.AchievementList)
item.ReCheckConditionsNotComplete();
}
public void OnTurnStart(MapData map, PlayerData player)
{
if (map.Net.Mode == NetMode.Spectator) return;
foreach (var item in Achievement.AchievementList)
item.OnTurnStart(map, player);
}
public void OnTrainUnit(MapData map, PlayerData player, CityData city, UnitData newUnit)
{
if (map.Net.Mode == NetMode.Spectator) return;
foreach (var item in Achievement.AchievementList)
item.OnTrainUnit(map, player, city, newUnit);
}
public void OnBuildWonder(MapData map, PlayerData player, CityData city, GridData grid)
{
if (map.Net.Mode == NetMode.Spectator) return;
foreach (var item in Achievement.AchievementList)
item.OnBuildWonder(map, player, city, grid);
}
public void OnKillUnit(MapData map, UnitData origin, UnitData target)
{
if (map.Net.Mode == NetMode.Spectator) return;
foreach (var item in Achievement.AchievementList)
item.OnKillUnit(map, origin, target);
}
public void OnUnitMove(MapData map, UnitData unit, GridData gridData)
{
if (map.Net.Mode == NetMode.Spectator) return;
foreach (var item in Achievement.AchievementList)
item.OnUnitMove(map, unit, gridData);
}
public void OnGameEnd(MapData map, bool isWin)
{
if (map.Net.Mode == NetMode.Spectator) return;
foreach (var item in Achievement.AchievementList)
item.OnGameEnd(map, isWin);
}
public bool IsFinished(uint bigId, uint smallId, uint internalID)
{
var item = Achievement.GetAchievementItem(bigId, smallId, internalID);
if (item == null) return false;
return item.IsFinished;
}
public string GetNoFinishDescription(uint bigId, uint smallId, uint internalID)
{
var item = Achievement.GetAchievementItem(bigId, smallId, internalID);
if (item == null) return "";
if (item.IsFinished) return "";
return item.GetConditionDescription();
}
// ------------------------------- 查询辅助类方法
private bool GetSmallIdByChessType(ChessType chessType, out uint part_smallid)
{
part_smallid = chessType switch
{
ChessType.Rook => 5,
ChessType.Knight => 4,
ChessType.Bishop => 3,
ChessType.Queen => 2,
ChessType.King => 1,
_ => 0
};
return part_smallid != 0;
}
public bool GetSmallIdByGiantType(GiantType giantType, out uint smallid)
{
smallid = 0;
if (!Table.Instance.UnitTypeDataAssets.GetGiantTypeChessType(giantType, out ChessType chessType))
return false;
if (!Table.Instance.LibraryDataAssets.GetLibraryInfoByGiant(giantType, out var libInfo)) return false;
smallid = (uint)libInfo.AchivePreId % 100;
return true;
}
public bool GetSmallIdByWonderAndEmpire(Empire empire ,WonderTypeEnum wonder, out uint smallid)
{
smallid = 0;
int tmp = -1;
if (empire.Civ == CivEnum.Egyptian)
tmp = 0;
if (empire.Civ == CivEnum.French)
tmp = 1;
if (empire.Civ == CivEnum.Germany)
tmp = 2;
if (tmp == -1) return false;
smallid = (uint)tmp * 7 + (uint)wonder;
return true;
}
}
}