260 lines
8.8 KiB
C#
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;
|
|
|
|
}
|
|
}
|
|
} |