You've already forked taptap2024_GJ_chidouren
init
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 263939c973da4ba78fe5d43131ab5bfa
|
||||
timeCreated: 1716804995
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: caf09ddb7d054bb6a13286dcbb868301
|
||||
timeCreated: 1716882147
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace Framework.Save
|
||||
{
|
||||
public interface ISaveData
|
||||
{
|
||||
public string SaveKey { get; }
|
||||
void Save ();
|
||||
bool Load ();
|
||||
void Delete ();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2417200c5fe4d7f944ee29585b174b7
|
||||
timeCreated: 1716805005
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Framework.Save
|
||||
{
|
||||
public interface ISaveGroup : ISaveData
|
||||
{
|
||||
public string GroupKey { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 887bb4869230464ea1aea6c91361aec9
|
||||
timeCreated: 1716806649
|
||||
@@ -0,0 +1,120 @@
|
||||
using FJson;
|
||||
using Framework.Utils.SingletonTemplate;
|
||||
|
||||
namespace Framework.Save
|
||||
{
|
||||
public class SaveDataController : MgrBase<SaveDataController>
|
||||
{
|
||||
private LiteDictionary<string , SaveGroup> _saveGroups = new LiteDictionary<string , SaveGroup> ();
|
||||
private string _userID;
|
||||
|
||||
protected override void OnCreateMge ()
|
||||
{
|
||||
SaveConfig config = SaveConfig.CreateConfig ();
|
||||
#if UNITY_EDITOR
|
||||
config._saveSerializer = new SaveSerializerJson ();
|
||||
config._saveHandler = new SaveHandlerFileStream ();
|
||||
config.hasHashName = false;
|
||||
#else
|
||||
config._saveSerializer = new SaveSerializerJsonEncrypt ();
|
||||
config._saveHandler = new SaveHandlerQuickFileStream ();
|
||||
#endif
|
||||
config._saveHandler.Init ();
|
||||
this.SetConfig (config);
|
||||
}
|
||||
|
||||
public void SetConfig (SaveConfig config)
|
||||
{
|
||||
SaveManager.Instance.SetConfig (Save.SaveData.PersistentData , config);
|
||||
}
|
||||
|
||||
public void SetUserID (string userID)
|
||||
{
|
||||
this._userID = userID;
|
||||
this._saveGroups = new LiteDictionary<string, SaveGroup> ();
|
||||
}
|
||||
|
||||
public bool HasSave (ISaveData saveData)
|
||||
{
|
||||
return SaveManager.Instance.HasSave (Save.SaveData.PersistentData , this._userID + saveData.SaveKey);
|
||||
}
|
||||
|
||||
public void DeleteData (ISaveData saveData)
|
||||
{
|
||||
if (HasSave (saveData))
|
||||
{
|
||||
SaveManager.Instance.DeleteSave (Save.SaveData.PersistentData , this._userID + saveData.SaveKey);
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveData (ISaveData saveData)
|
||||
{
|
||||
SaveManager.Instance.Save (Save.SaveData.PersistentData , saveData , this._userID + saveData.SaveKey);
|
||||
}
|
||||
|
||||
public T LoadData<T> (string saveKey)
|
||||
{
|
||||
if (SaveManager.Instance.HasSave (Save.SaveData.PersistentData , this._userID + saveKey))
|
||||
{
|
||||
return SaveManager.Instance.Load<T> (Save.SaveData.PersistentData , this._userID + saveKey);
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public object LoadData (ISaveData saveData)
|
||||
{
|
||||
if (SaveManager.Instance.HasSave (Save.SaveData.PersistentData , this._userID + saveData.SaveKey))
|
||||
{
|
||||
return SaveManager.Instance.Load<object> (Save.SaveData.PersistentData , this._userID + saveData.SaveKey);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
|
||||
internal void SaveDataToGroup (ISaveGroup saveGroup)
|
||||
{
|
||||
CheckSaveGroup (saveGroup.GroupKey);
|
||||
var group = this._saveGroups[saveGroup.GroupKey];
|
||||
group.SaveData (saveGroup);
|
||||
SaveData (group);
|
||||
}
|
||||
|
||||
internal bool LoadDataFromGroup<T> (ISaveGroup saveGroup) where T : ISaveGroup
|
||||
{
|
||||
if (this._saveGroups.ContainsKey (saveGroup.GroupKey))
|
||||
this._saveGroups.Remove (saveGroup.GroupKey);
|
||||
var group = CheckSaveGroup (saveGroup.GroupKey);
|
||||
return group.LoadData (saveGroup.SaveKey , (T)saveGroup);
|
||||
}
|
||||
|
||||
private SaveGroup CheckSaveGroup (string groupName)
|
||||
{
|
||||
if (!this._saveGroups.ContainsKey (groupName))
|
||||
{
|
||||
var group = new SaveGroup ();
|
||||
if (SaveManager.Instance.HasSave (Save.SaveData.PersistentData , this._userID + groupName))
|
||||
{
|
||||
var saveGroup = LoadData<object> (groupName);
|
||||
FJsonUtility.Convert<SaveGroup> (saveGroup , group);
|
||||
}
|
||||
|
||||
group._saveKey = groupName;
|
||||
this._saveGroups[groupName] = group;
|
||||
}
|
||||
|
||||
return this._saveGroups[groupName];
|
||||
}
|
||||
|
||||
public void DeleteGroupData <T> (GroupPersistentData<T> groupPersistentData) where T : ISaveGroup, new ()
|
||||
{
|
||||
var groupName = groupPersistentData.GroupKey;
|
||||
if (this._saveGroups.ContainsKey (groupName))
|
||||
{
|
||||
var group = this._saveGroups[groupName];
|
||||
group.DeleteData(groupPersistentData);
|
||||
this._saveGroups[groupName] = group;
|
||||
SaveData (group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 56ef41d5cf924813aa83980b88a2f801
|
||||
timeCreated: 1716805437
|
||||
@@ -0,0 +1,66 @@
|
||||
using FJson;
|
||||
using FJson.Core;
|
||||
|
||||
namespace Framework.Save
|
||||
{
|
||||
internal class SaveGroup : ISaveGroup
|
||||
{
|
||||
[FSerialize] internal LiteDictionary<string, JsonObject> _saveDataArray = new LiteDictionary<string, JsonObject> ();
|
||||
|
||||
[FSerialize] internal string _saveKey;
|
||||
string ISaveData. SaveKey => this._saveKey;
|
||||
public string GroupKey => this._saveKey;
|
||||
|
||||
public SaveGroup ()
|
||||
{
|
||||
}
|
||||
|
||||
public void Save ()
|
||||
{
|
||||
SaveDataController.Instance.SaveData (this);
|
||||
}
|
||||
|
||||
public bool Load ()
|
||||
{
|
||||
var data = SaveDataController.Instance.LoadData (this);
|
||||
if (data != null)
|
||||
{
|
||||
FJsonUtility.Convert<SaveGroup> ( data,this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void SaveData (ISaveData saveData)
|
||||
{
|
||||
if (this._saveDataArray == null)
|
||||
{
|
||||
this._saveDataArray = new LiteDictionary<string, JsonObject> ();
|
||||
}
|
||||
this._saveDataArray[saveData.SaveKey] = FJsonUtility.ToJsonObject(saveData);
|
||||
}
|
||||
|
||||
public bool LoadData<T> (string saveKey , T target) where T : ISaveData
|
||||
{
|
||||
if (_saveDataArray != null && this._saveDataArray.TryGetValue ( saveKey, out var data))
|
||||
{
|
||||
FJsonUtility.Convert<T> (data , target);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Delete ()
|
||||
{
|
||||
this._saveDataArray?.Clear ();
|
||||
}
|
||||
|
||||
public void DeleteData (ISaveData saveData)
|
||||
{
|
||||
if (this._saveDataArray != null && this._saveDataArray.ContainsKey (saveData.SaveKey))
|
||||
{
|
||||
this._saveDataArray.Remove (saveData.SaveKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 60a74de868394b8799ee3e60fb2cb32f
|
||||
timeCreated: 1716805718
|
||||
@@ -0,0 +1,22 @@
|
||||
|
||||
namespace Framework.Save
|
||||
{
|
||||
/// <summary>
|
||||
/// 按组持久化单元(按组读写)
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public abstract class GroupPersistentData<T> : ISaveGroup where T : ISaveGroup , new()
|
||||
{
|
||||
public virtual string SaveKey => this.GetType ().FullName;
|
||||
public abstract string GroupKey { get; }
|
||||
|
||||
public void Save () => SaveDataController.Instance.SaveDataToGroup (this);
|
||||
|
||||
public bool Load ()
|
||||
{
|
||||
return SaveDataController.Instance.LoadDataFromGroup<T> (this);
|
||||
}
|
||||
|
||||
public void Delete () => SaveDataController.Instance.DeleteGroupData (this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 76ed2d42b79142d5862db90f5415cfb1
|
||||
timeCreated: 1716812696
|
||||
@@ -0,0 +1,28 @@
|
||||
using FJson;
|
||||
|
||||
namespace Framework.Save
|
||||
{
|
||||
/// <summary>
|
||||
/// 持久化单元(单独读写存储)
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public abstract class SinglePersistentData<T> : ISaveData where T : ISaveData , new()
|
||||
{
|
||||
public virtual string SaveKey => this.GetType ().FullName;
|
||||
|
||||
public virtual void Save () => SaveDataController.Instance.SaveData (this);
|
||||
|
||||
public virtual bool Load ()
|
||||
{
|
||||
var data = SaveDataController.Instance.LoadData (this);
|
||||
if (data != null)
|
||||
{
|
||||
FJsonUtility.Convert<T> (data , this);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public void Delete () => SaveDataController.Instance.DeleteData (this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 05079d1c84134b67ba6d8af1e1e75939
|
||||
timeCreated: 1716805144
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44eacfb08d634af3ad80597933c5f792
|
||||
timeCreated: 1581932615
|
||||
@@ -0,0 +1,12 @@
|
||||
|
||||
namespace Framework.Save.Interface
|
||||
{
|
||||
public interface ISaveHandler
|
||||
{
|
||||
void Init();
|
||||
void WriteData(string path , string name, byte[] bytes);
|
||||
byte[] ReadData(string path , string name);
|
||||
bool HasPath(string path , string name);
|
||||
void Dispose();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e593669ea2b2443084b9e25bd0b848b9
|
||||
timeCreated: 1581932538
|
||||
@@ -0,0 +1,10 @@
|
||||
using System;
|
||||
|
||||
namespace Framework.Save.Interface
|
||||
{
|
||||
public interface ISaveSerializer
|
||||
{
|
||||
byte[] Serialize(object obj);
|
||||
T Deserialize<T>(byte[] value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 75dae824b16e4dd692b110363a40de21
|
||||
timeCreated: 1581932348
|
||||
@@ -0,0 +1,67 @@
|
||||
using System.Collections.Generic;
|
||||
using Framework.Save.Interface;
|
||||
using Framework.Utils;
|
||||
|
||||
|
||||
namespace Framework.Save
|
||||
{
|
||||
public class SaveConfig
|
||||
{
|
||||
public bool hasHashName = true;
|
||||
|
||||
/// <summary>
|
||||
/// 存储根目录
|
||||
/// </summary>
|
||||
public string RootPath;
|
||||
|
||||
internal ISaveHandler _saveHandler;
|
||||
internal ISaveSerializer _saveSerializer;
|
||||
|
||||
private SaveConfig() { }
|
||||
|
||||
public static SaveConfig CreateConfig(string rootPath = null , bool hasHashName = true)
|
||||
{
|
||||
if (string.IsNullOrEmpty(rootPath))
|
||||
rootPath = FileHelper.UnityRootPath + "/save";
|
||||
var config = new SaveConfig();
|
||||
config.RootPath = rootPath;
|
||||
config.hasHashName = hasHashName;
|
||||
config._saveHandler = new SaveHandlerFileStream();
|
||||
config._saveSerializer = new SaveSerializerJson();
|
||||
#if !UNITY_EDITOR
|
||||
config._saveSerializer = new SaveSerializerCommonJson();
|
||||
#endif
|
||||
return config;
|
||||
}
|
||||
|
||||
public SaveConfig SetDataHandler(ISaveHandler saveHandler)
|
||||
{
|
||||
_saveHandler?.Dispose();
|
||||
this._saveHandler = saveHandler;
|
||||
this._saveHandler?.Init();
|
||||
return this;
|
||||
}
|
||||
|
||||
public SaveConfig SetSerializer(ISaveSerializer serializer)
|
||||
{
|
||||
this._saveSerializer = serializer;
|
||||
return this;
|
||||
}
|
||||
|
||||
public string HashName(object saveGroup, string table = "")
|
||||
{
|
||||
if (hasHashName)
|
||||
{
|
||||
var name = saveGroup + table;
|
||||
return name.GetHashCode().ToString();
|
||||
}
|
||||
|
||||
return saveGroup.ToString() + $"_{table}";
|
||||
}
|
||||
|
||||
public void Release()
|
||||
{
|
||||
_saveHandler?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc6b2aaf5e7e6e949a7a2e9905e2e084
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,241 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Framework.Save.Interface;
|
||||
using Framework.Utils;
|
||||
using UnityEngine;
|
||||
using Object = System.Object;
|
||||
|
||||
namespace Framework.Save
|
||||
{
|
||||
public class SaveControl<SaveType> where SaveType : Enum
|
||||
{
|
||||
public SaveConfig BaseConfig { get; private set; }
|
||||
|
||||
public Dictionary<SaveType, SaveConfig> SaveConfigs;
|
||||
|
||||
private Dictionary<SaveType, Dictionary<string, byte[]>> _bytesCaches;
|
||||
|
||||
public SaveControl()
|
||||
{
|
||||
SaveConfigs = new Dictionary<SaveType, SaveConfig>();
|
||||
this._bytesCaches = new Dictionary<SaveType, Dictionary<string, byte[]>>();
|
||||
this.BaseConfig = SaveConfig.CreateConfig();
|
||||
}
|
||||
|
||||
public void SetConfig(SaveType saveType, SaveConfig saveConfig)
|
||||
{
|
||||
if (SaveConfigs.TryGetValue(saveType, out var config))
|
||||
{
|
||||
config.Release();
|
||||
}
|
||||
SaveConfigs[saveType] = saveConfig;
|
||||
}
|
||||
|
||||
public bool HasConfig(SaveType saveType)
|
||||
{
|
||||
return SaveConfigs.ContainsKey(saveType);
|
||||
}
|
||||
|
||||
#region 基础数据操作 ---------------------------------------------------------------
|
||||
|
||||
/// <summary>
|
||||
/// 是否有指定存档
|
||||
/// </summary>
|
||||
/// <param name="saveGroup"></param>
|
||||
/// <param name="table"></param>
|
||||
/// <returns></returns>
|
||||
public bool HasSave(SaveType saveGroup, string table = "")
|
||||
{
|
||||
var config = GetConfig(saveGroup);
|
||||
return config._saveHandler.HasPath(config.RootPath, config.HashName(saveGroup.ToString(), table));
|
||||
}
|
||||
|
||||
|
||||
public SaveConfig GetConfig(SaveType saveType)
|
||||
{
|
||||
if (SaveConfigs.TryGetValue(saveType, out var config))
|
||||
{
|
||||
return config;
|
||||
}
|
||||
return this.BaseConfig;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 删除指定存档文件
|
||||
/// </summary>
|
||||
/// <param name="saveGroup"></param>
|
||||
/// <param name="table"></param>
|
||||
public void DeleteSave(SaveType saveGroup, string table = "")
|
||||
{
|
||||
var config = GetConfig(saveGroup);
|
||||
FileHelper.DeleteFile(config.RootPath, config.HashName(saveGroup.ToString(), table));
|
||||
this.ClearCache(saveGroup, table);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 数据存档
|
||||
/// </summary>
|
||||
/// <param name="saveGroup"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="table"></param>
|
||||
public void Save(SaveType saveGroup, object value, string table = "")
|
||||
{
|
||||
var config = GetConfig(saveGroup);
|
||||
//序列化数据
|
||||
var bytes = config._saveSerializer.Serialize(value);
|
||||
if (this._bytesCaches.ContainsKey(saveGroup) && this._bytesCaches[saveGroup].ContainsKey(table))
|
||||
this._bytesCaches[saveGroup][table] = bytes;
|
||||
config._saveHandler.WriteData(config.RootPath, config.HashName(saveGroup.ToString(), table), bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 数据加载
|
||||
/// </summary>
|
||||
/// <param name="saveGroup"></param>
|
||||
/// <param name="table"></param>
|
||||
public T Load<T>(SaveType saveGroup, string table = "")
|
||||
{
|
||||
try
|
||||
{
|
||||
var config = GetConfig(saveGroup);
|
||||
var bytes = config._saveHandler.ReadData(config.RootPath, config.HashName(saveGroup.ToString(), table));
|
||||
if (bytes != null)
|
||||
{
|
||||
return config._saveSerializer.Deserialize<T>(bytes);
|
||||
}
|
||||
return default;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogError($"数据加载失败: {saveGroup}_{table}" + e);
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 快速存储,只会将数据序列化到缓存中(内存),需要手动调用Flush方法将数据写入到磁盘
|
||||
/// </summary>
|
||||
/// <param name="saveGroup"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <param name="table"></param>
|
||||
/// <param name="serializer"></param>
|
||||
public void QuickSave(SaveType saveGroup, object value, string table = "")
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this._bytesCaches.ContainsKey(saveGroup))
|
||||
{
|
||||
this._bytesCaches[saveGroup] = new Dictionary<string, byte[]>();
|
||||
}
|
||||
var config = GetConfig(saveGroup);
|
||||
var bytes = config._saveSerializer.Serialize(value);
|
||||
this._bytesCaches[saveGroup][table] = bytes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 快速加载,将会优先从缓存读取数据,如果缓存区没有数据则尝试从磁盘中读取指定数据并缓存
|
||||
/// </summary>
|
||||
/// <param name="saveGroup"></param>
|
||||
/// <param name="table"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public T QuickLoad<T>(SaveType saveGroup, string table = "")
|
||||
{
|
||||
byte[] obytes = null;
|
||||
var config = GetConfig(saveGroup);
|
||||
|
||||
if (!this._bytesCaches.ContainsKey(saveGroup) || !this._bytesCaches[saveGroup].ContainsKey(table))
|
||||
{
|
||||
this._bytesCaches[saveGroup] = new Dictionary<string, byte[]>();
|
||||
obytes = config._saveHandler.ReadData(config.RootPath, config.HashName(saveGroup.ToString(), table));
|
||||
this._bytesCaches[saveGroup][table] = obytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
obytes = this._bytesCaches[saveGroup][table];
|
||||
}
|
||||
|
||||
byte[] bytes = new byte[obytes.Length];
|
||||
obytes.CopyTo(bytes, 0);
|
||||
|
||||
return config._saveSerializer.Deserialize<T>(bytes);
|
||||
// return default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将指定缓存写入到磁盘
|
||||
/// </summary>
|
||||
/// <param name="saveType"></param>
|
||||
public void Flush(SaveType saveType)
|
||||
{
|
||||
if (this._bytesCaches.TryGetValue(saveType, out var bytesMap))
|
||||
{
|
||||
var keys = bytesMap.Keys;
|
||||
foreach (var key in keys)
|
||||
{
|
||||
this.Flush(saveType, key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将指定缓存内容写入到磁盘
|
||||
/// </summary>
|
||||
/// <param name="saveType"></param>
|
||||
/// <param name="table"></param>
|
||||
public void Flush(SaveType saveType, string table )
|
||||
{
|
||||
|
||||
if (this._bytesCaches.ContainsKey(saveType) && this._bytesCaches[saveType].ContainsKey(table))
|
||||
{
|
||||
var config = GetConfig(saveType);
|
||||
Debug.Log("写入数据: " + saveType + table);
|
||||
config._saveHandler.WriteData(config.RootPath, config.HashName(saveType, table),
|
||||
this._bytesCaches[saveType][table]);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 将缓存区所有数据写入到磁盘
|
||||
/// </summary>
|
||||
public void FlushAll()
|
||||
{
|
||||
foreach (var cachesKey in this._bytesCaches.Keys)
|
||||
{
|
||||
this.Flush(cachesKey);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearCache(SaveType saveType)
|
||||
{
|
||||
this._bytesCaches.Remove(saveType);
|
||||
}
|
||||
|
||||
public void ClearCache(SaveType saveType, string table)
|
||||
{
|
||||
if (this._bytesCaches.TryGetValue(saveType, out var cach))
|
||||
{
|
||||
cach.Remove(table);
|
||||
}
|
||||
}
|
||||
|
||||
public void ClearCacheAll()
|
||||
{
|
||||
this._bytesCaches.Clear();
|
||||
}
|
||||
|
||||
public void Release()
|
||||
{
|
||||
this.FlushAll();
|
||||
this.ClearCacheAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: efbc7eba16e542f9b91246d9050db5b8
|
||||
timeCreated: 1581935135
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Framework.Save
|
||||
{
|
||||
public enum SaveData
|
||||
{
|
||||
Game,
|
||||
System,
|
||||
GM,
|
||||
Temp1,
|
||||
Temp2,
|
||||
Scene,
|
||||
Data,
|
||||
PersistentData,
|
||||
Cache
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86ca46d8fcfb4d6ebdbf683c9f22d589
|
||||
timeCreated: 1582121860
|
||||
@@ -0,0 +1,39 @@
|
||||
using Framework.Save.Interface;
|
||||
using Framework.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Framework.Save
|
||||
{
|
||||
/// <summary>
|
||||
/// 基于FileStream的方式读写数据
|
||||
/// </summary>
|
||||
public class SaveHandlerFileStream : ISaveHandler
|
||||
{
|
||||
public void Init()
|
||||
{
|
||||
}
|
||||
|
||||
public void WriteData(string path, string name, byte[] value)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
FileHelper.WriteFile(path , name , value);
|
||||
}
|
||||
}
|
||||
public byte[] ReadData(string path, string name)
|
||||
{
|
||||
var bytes = FileHelper.ReadFile(path, name);
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public bool HasPath(string path, string name)
|
||||
{
|
||||
return FileHelper.CheckPath(path + "/" + name);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 43f86d69ccc9478a9e8e697277b3b2ee
|
||||
timeCreated: 1582041404
|
||||
@@ -0,0 +1,135 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Framework.Save.Interface;
|
||||
using Framework.Utils;
|
||||
|
||||
namespace Framework.Save
|
||||
{
|
||||
/// <summary>
|
||||
/// 快速存储,适用于数据文件数量少,但对数据文件读写频繁的情况。
|
||||
/// </summary>
|
||||
public class SaveHandlerQuickFileStream : ISaveHandler
|
||||
{
|
||||
private class FileNode
|
||||
{
|
||||
public byte[] Cache;
|
||||
public readonly string Path;
|
||||
public readonly string Name;
|
||||
|
||||
public string FullName => Path + "/" + Name;
|
||||
public string FullNameTemp => Path + "/" + Name + ".temp";
|
||||
|
||||
|
||||
public FileNode(string path, string name)
|
||||
{
|
||||
this.Path = path;
|
||||
this.Name = name;
|
||||
FileHelper.CreateDirectory(Path);
|
||||
}
|
||||
|
||||
public void Close()
|
||||
{
|
||||
File.Delete(FullNameTemp);
|
||||
}
|
||||
|
||||
public byte[] Read()
|
||||
{
|
||||
if (Cache != null)
|
||||
{
|
||||
return Cache;
|
||||
}
|
||||
|
||||
if (HasPath())
|
||||
{
|
||||
using ( var stream = new FileStream(this.Path + "/" + this.Name, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite))
|
||||
{
|
||||
var length = (int) stream.Length;
|
||||
Cache = new byte[length];
|
||||
var read = stream.Read(Cache, 0, length);
|
||||
if (read == length) return Cache;
|
||||
}
|
||||
Cache = null;
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Write(byte[] bytes)
|
||||
{
|
||||
Cache = bytes;
|
||||
try
|
||||
{
|
||||
var stream = new FileStream(FullNameTemp, FileMode.Create, FileAccess.ReadWrite,
|
||||
FileShare.ReadWrite);
|
||||
stream.Write(Cache, 0, Cache.Length);
|
||||
stream.Flush();
|
||||
stream.Close();
|
||||
stream.Dispose();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (File.Exists(FullNameTemp))
|
||||
{
|
||||
File.Delete(FullNameTemp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
File.Copy(FullNameTemp , FullName , true);
|
||||
}
|
||||
|
||||
public bool HasPath()
|
||||
{
|
||||
return FileHelper.CheckPath(Path + "/" + Name);
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string,FileNode> _fileNodes ;
|
||||
|
||||
public void Init()
|
||||
{
|
||||
_fileNodes = new Dictionary<string, FileNode>();
|
||||
}
|
||||
|
||||
public void WriteData(string path, string name, byte[] bytes)
|
||||
{
|
||||
var fileNode = GetFileNode(path, name);
|
||||
fileNode.Write(bytes);
|
||||
}
|
||||
|
||||
public byte[] ReadData(string path, string name)
|
||||
{
|
||||
var fileNode = GetFileNode(path, name);
|
||||
return fileNode.Read();
|
||||
}
|
||||
|
||||
public bool HasPath(string path, string name)
|
||||
{
|
||||
var fileNode = GetFileNode(path, name);
|
||||
return fileNode.HasPath();
|
||||
}
|
||||
|
||||
private FileNode GetFileNode(string path, string name)
|
||||
{
|
||||
var key = path + "/" + name;
|
||||
if (_fileNodes.TryGetValue(key, out var node))
|
||||
{
|
||||
return node;
|
||||
}
|
||||
node = new FileNode(path, name);
|
||||
_fileNodes.Add(key, node);
|
||||
return node;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var fileNodesValue in _fileNodes.Values)
|
||||
{
|
||||
fileNodesValue.Close();
|
||||
}
|
||||
_fileNodes.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26e4f710c926423e93bd930f024c1853
|
||||
timeCreated: 1684242182
|
||||
@@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using Framework.Utils;
|
||||
using Framework.Utils.SingletonTemplate;
|
||||
|
||||
namespace Framework.Save
|
||||
{
|
||||
public class SaveManager : SingletonBase<SaveControl<SaveData>, SaveManager>
|
||||
{
|
||||
protected override void OnInit()
|
||||
{
|
||||
_instance.BaseConfig.RootPath = FileHelper.UnityRootPath + "/system";
|
||||
// _instance.Config.SetSerializer(new SaveSerializerJson());
|
||||
// return;
|
||||
#if UNITY_EDITOR
|
||||
_instance.BaseConfig.hasHashName = false;
|
||||
_instance.BaseConfig.SetSerializer(new SaveSerializerJson());
|
||||
// _instance.Config.SetSerializer(new SaveSerializerCommonJson());
|
||||
#else
|
||||
_instance.BaseConfig.SetSerializer(new SaveSerializerCommonJson());
|
||||
#endif
|
||||
|
||||
_instance.SetConfig(SaveData.Cache,
|
||||
SaveConfig.CreateConfig($"{FileHelper.UnityRootPath}/cache", false)
|
||||
.SetSerializer(new SaveSerializerBytes()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8cc730ace44947d48537651e656eae43
|
||||
timeCreated: 1582120542
|
||||
@@ -0,0 +1,21 @@
|
||||
using Framework.Save.Interface;
|
||||
|
||||
namespace Framework.Save
|
||||
{
|
||||
public class SaveSerializerBytes : ISaveSerializer
|
||||
{
|
||||
public byte[] Serialize(object obj)
|
||||
{
|
||||
if (obj is byte[])
|
||||
{
|
||||
return (byte[])obj;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public T Deserialize<T>(byte[] value)
|
||||
{
|
||||
return (T)((object)value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 871953917f7e47c880476525f5378d11
|
||||
timeCreated: 1681737518
|
||||
@@ -0,0 +1,35 @@
|
||||
using System;
|
||||
using FJson;
|
||||
using Framework.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Framework.Save
|
||||
{
|
||||
public class SaveSerializerCommonJson : SaveSerializerJsonEncrypt
|
||||
{
|
||||
public override T Deserialize<T>(byte[] value)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
//尝试直接解析
|
||||
var json = FileHelper.ArrayByteUtf8ToString(value);
|
||||
//如果解析成功
|
||||
var op = FJsonUtility.ToObject<T>(json);
|
||||
if (op != null)
|
||||
{
|
||||
// // 重新写入,并转换为加密数据
|
||||
// this.Serialize(op);
|
||||
return op;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
return base.Deserialize<T>(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ecd4585823154347bef6b0d2efe1ae47
|
||||
timeCreated: 1658738774
|
||||
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using FJson;
|
||||
using Framework.Save.Interface;
|
||||
using Framework.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Framework.Save
|
||||
{
|
||||
public class SaveSerializerJson : ISaveSerializer
|
||||
{
|
||||
|
||||
public byte[] Serialize(object obj)
|
||||
{
|
||||
var json = FJsonUtility.ToJson(obj);
|
||||
return FileHelper.StringToArrayByteUtf8(json);
|
||||
}
|
||||
|
||||
public T Deserialize<T>(byte[] value)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
var json = FileHelper.ArrayByteUtf8ToString(value);
|
||||
var op = FJsonUtility.ToObject<T>(json);
|
||||
return op;
|
||||
}
|
||||
return default;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d1a9eb41984e4407ba71af8f23452ef9
|
||||
timeCreated: 1581933052
|
||||
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using FJson;
|
||||
using Framework.Save.Interface;
|
||||
using Framework.Utils;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Framework.Save
|
||||
{
|
||||
public class SaveSerializerJsonEncrypt : ISaveSerializer
|
||||
{
|
||||
private static readonly byte[] EncryptMaps = {0x16 , 0x12 , 0x15 , 0xf1 , 0xd5 , 0x01 , 0x18 , 0x00, 0xf2 , 0x10 , 0xf6 , 0xf7 , 0xf9};
|
||||
public virtual byte[] Serialize(object obj)
|
||||
{
|
||||
var json = FJsonUtility.ToJson(obj);
|
||||
var tBytes = FileHelper.StringToArrayByteUtf8(json);
|
||||
this.reverseBytes(0 , tBytes);
|
||||
return tBytes;
|
||||
}
|
||||
|
||||
public virtual T Deserialize<T>(byte[] value)
|
||||
{
|
||||
if (value == null)
|
||||
return default;
|
||||
this.reverseBytes(0 , value);
|
||||
var json = FileHelper.ArrayByteUtf8ToString(value);
|
||||
var deserialize = FJsonUtility.ToObject<T>(json);
|
||||
return deserialize;
|
||||
}
|
||||
|
||||
|
||||
public void reverseBytes(int index, byte[] arr) {
|
||||
int j = arr.Length - 1;
|
||||
int el = EncryptMaps.Length;
|
||||
byte temp;
|
||||
while (index<j) {
|
||||
//替换
|
||||
temp = arr[index];
|
||||
arr[index] = (byte)(arr[j] ^ EncryptMaps[index % el]);
|
||||
arr[j] = (byte)(temp ^ EncryptMaps[index % el]);
|
||||
index++;
|
||||
j--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f5019769583c4c68ade7e68d1f0d4ba8
|
||||
timeCreated: 1582122140
|
||||
Reference in New Issue
Block a user