IndieGame/client/Assets/Scripts/System/Save/SaveSystem.cs

251 lines
9.9 KiB
C#
Raw Normal View History

2024-10-11 10:12:15 +08:00

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using UnityEngine;
using static Animancer.Validate;
using static Unity.VisualScripting.Member;
namespace Ether
{
public abstract class SaveBase<T> : Singleton<T> where T : new()
{
public SaveBase()
{
SaveSystem.Inst.Regist(this);
}
}
public abstract class SaveBase
{
public SaveBase()
{
SaveSystem.Inst.Regist(this);
}
}
public class SaveSystem : Singleton<SaveSystem>
{
public int SaveArchiveNum = 5;
public Dictionary<int, ArchiveData> AllSaveArchive
{
get
{
Dictionary<int, ArchiveData> allSaveArchive = new Dictionary<int, ArchiveData>();
for (int i = 0; i < SaveArchiveNum; i++)
{
string path = string.Format(PathConst.SaveArchiveDataPath, i);
if (!ES3.FileExists(string.Format(PathConst.SaveArchiveDataPath, i)))
{
continue;
}
ArchiveData archiveData = ES3.Load<ArchiveData>("SaveArchive", string.Format(PathConst.SaveArchiveDataPath, i));
if (archiveData != null)
{
allSaveArchive.Add(i, archiveData);
}
}
return allSaveArchive;
}
}
private List<object> allSaveInst = new List<object>();
public void Regist(object savaBase)
{
allSaveInst.Add(savaBase);
}
public void UnRegist(object savaBase)
{
allSaveInst.Remove(savaBase);
}
public bool LoadArchive(int saveIndex, Action<bool> callback = null)
{
if (AllSaveArchive.TryGetValue(saveIndex, out ArchiveData archiveData))
{
foreach (object source in allSaveInst)
{// 获取对象的类型
Type type = source.GetType();
// 存储字段、属性和方法的值
var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(f => f.GetCustomAttribute<SaveAttribute>() != null);
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(p => p.GetCustomAttribute<SaveAttribute>() != null);
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(m => m.GetCustomAttribute<SaveAttribute>() != null);
// 打印出带有Attribute的成员的名称和值
foreach (var field in fields)
{
//object value = field.GetValue(source);
//Debug.LogError($"Field: {field.Name}, Value: {value}");
// 存储field.GetValue(source)的值
object value = archiveData.ArchiveDic[field.Name];
Type tempType = field.FieldType;
if (value is JObject valueObj)
{
if (tempType.IsGenericType && tempType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
// 直接调用 ToObject 方法,并指定目标泛型类型
var deserializedValue = valueObj.ToObject(tempType, JsonSerializer.CreateDefault());
field.SetValue(source, deserializedValue);
}
else
{
field.SetValue(source, valueObj.ToObject(tempType));
}
}
else
{
if (tempType == typeof(int) && value.GetType() == typeof(long))
{
value = Convert.ToInt32(value);
}
field.SetValue(source, value);
}
}
foreach (var property in properties)
{
object value = archiveData.ArchiveDic[property.Name];
Type tempType = property.PropertyType;
if (value is JObject valueObj)
{
if (tempType.IsGenericType && tempType.GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
// 直接调用 ToObject 方法,并指定目标泛型类型
var deserializedValue = valueObj.ToObject(tempType, JsonSerializer.CreateDefault());
property.SetValue(source, deserializedValue);
}
else
{
property.SetValue(source, valueObj.ToObject(tempType));
}
}
else
{
if (tempType == typeof(int) && value.GetType() == typeof(long))
{
value = Convert.ToInt32(value);
}
property.SetValue(source, value);
}
}
foreach (var method in methods)
{
//Debug.LogError($"Method: {method.Name}");
// 存储方法的引用或返回值
// 注意:方法的调用可能需要参数,这里只是获取方法的引用
}
}
string sceneSavePath = string.Format(PathConst.SaveArchiveScenePath, saveIndex);
ES3.DeleteFile("TempSceneSave.es3");
ES3.CopyFile(sceneSavePath, "TempSceneSave.es3");
callback?.Invoke(true);
return true;
}
callback?.Invoke(false);
return false;
}
public bool SaveArchive(int saveIndex, Action<bool> callback = null)
{
ArchiveData archiveData = saveIndex < AllSaveArchive.Count ? AllSaveArchive[saveIndex] : new ArchiveData() { Id = saveIndex, Time = DateTime.Now };
foreach (object source in allSaveInst)
{
// 获取对象的类型
Type type = source.GetType();
// 存储字段、属性和方法的值
var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(f => f.GetCustomAttribute<SaveAttribute>() != null);
var properties = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(p => p.GetCustomAttribute<SaveAttribute>() != null);
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Where(m => m.GetCustomAttribute<SaveAttribute>() != null);
// 打印出带有Attribute的成员的名称和值
foreach (var field in fields)
{
object value = field.GetValue(source);
//Debug.LogError($"Field: {field.Name}, Value: {value}");
// 存储field.GetValue(source)的值
if (!archiveData.ArchiveDic.TryAdd(field.Name, value))
{
archiveData.ArchiveDic[field.Name] = value;
}
}
foreach (var property in properties)
{
object value = property.GetValue(source);
//Debug.LogError($"Property: {property.Name}, Value: {value}");
// 存储property.GetValue(source)的值
if (!archiveData.ArchiveDic.TryAdd(property.Name, value))
{
archiveData.ArchiveDic[property.Name] = value;
}
}
foreach (var method in methods)
{
//Debug.LogError($"Method: {method.Name}");
// 存储方法的引用或返回值
// 注意:方法的调用可能需要参数,这里只是获取方法的引用
}
}
ES3.Save("SaveArchive", archiveData, string.Format(PathConst.SaveArchiveDataPath, saveIndex));
string sceneSavePath = string.Format(PathConst.SaveArchiveScenePath, saveIndex);
ES3.DeleteFile(sceneSavePath);
ES3.CopyFile("TempSceneSave.es3", sceneSavePath);
//Debug.LogError(JsonTools.ToJson(archiveData));
//FileTools.WriteFileForJson(string.Format(PathConst.SaveArchivePath, saveIndex), archiveData, isFormat: true);
callback?.Invoke(true);
return true;
}
}
public class ArchiveData
{
public int Id;
public DateTime Time;
public Dictionary<object, object> ArchiveDic = new Dictionary<object, object>();
public void SaveData(object key, object value)
{
ArchiveDic.TryAdd(key, value);
}
public object GetData(object key)
{
if (ArchiveDic.ContainsKey(key))
{
return ArchiveDic[key];
}
return null;
}
}
}