TH1/Unity/Assets/Scripts/TH1_Logic/Config/ConfigManager.cs
2026-03-11 20:45:29 +08:00

281 lines
8.6 KiB
C#

/*
* @Author: 白哉
* @Description:
* @Date: 2025年07月24日 星期四 11:07:37
* @Modify:
*/
using System;
using System.IO;
using System.Linq;
using ExcelConfig;
using Logic.Config;
using Logic.CrashSight;
using Logic.Multilingual;
using TH1_Logic.Tools;
using UnityEngine;
namespace TH1_Logic.Config
{
public class ConfigManager
{
public static ConfigManager Instance = new ConfigManager();
public GameConfig Config;
public VersionConfig VersionCfg;
private static ColorConfig _colorConfig;
public static ColorConfig ColorConfig
{
get
{
if (_colorConfig == null)
{
_colorConfig = Resources.Load<ColorConfig>("TH1Config/ColorConfig");
}
return _colorConfig;
}
}
public void Init()
{
if (Config == null)
{
string path = Application.persistentDataPath + "/../Config/game_cfg.json";
string backupPath = path + ".bak";
// 尝试读取主文件
Config = TryReadGameConfig(path);
// 主文件损坏,尝试从备份恢复
if (Config == null && File.Exists(backupPath))
{
LogSystem.LogInfo("[ConfigManager] 主文件损坏,尝试从备份恢复...");
Config = TryReadGameConfig(backupPath);
if (Config != null)
{
LogSystem.LogInfo("[ConfigManager] 从备份恢复成功");
try
{
string json = JsonUtility.ToJson(Config);
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(json);
FileTools.SafeWriteFile(path, bytes);
}
catch (Exception e)
{
LogSystem.LogError($"[ConfigManager] 恢复写入主文件失败: {e.Message}");
}
}
else
{
LogSystem.LogError("[ConfigManager] 备份文件也已损坏,将重置数据");
}
}
Config ??= new GameConfig();
}
if (!VersionCfg)
{
VersionCfg = Resources.Load<VersionConfig>("Export/VersionConfig");
}
CrashSightAgent.SetAppVersion(VersionCfg.CurVersionInfo.FullVersion);
}
public void InitExcelConfig()
{
// 获取当前程序集中所有实现 IExcelConfig 接口的类
var excelConfigTypes = System.Reflection.Assembly.GetExecutingAssembly().GetTypes()
.Where(t => typeof(ExcelConfigBase).IsAssignableFrom(t)
&& t.IsClass
&& !t.IsAbstract);
foreach (var type in excelConfigTypes)
{
try
{
// 创建实例
var instance = (ExcelConfigBase)Activator.CreateInstance(type);
// 这里可以根据需要加载对应的配置数据
// 例如:从 Resources 或其他路径加载 byte[] 数据
byte[] configData = LoadConfigData(type.Name);
// 调用 Init 方法
instance.Init(configData);
instance.AfterInit();
}
catch (Exception ex)
{
LogSystem.LogError($"初始化配置失败: {type.Name}, 错误: {ex.Message}");
}
}
}
private byte[] LoadConfigData(string typeName)
{
string configName = typeName.Replace("Category", "");
TextAsset asset = Resources.Load<TextAsset>($"ExcelConfig/GenerateBytes/{configName}");
if (asset == null || asset.bytes == null || asset.bytes.Length == 0)
{
LogSystem.LogError($"[ConfigManager] 加载配置数据失败: {configName}");
return Array.Empty<byte>();
}
return asset.bytes;
}
private GameConfig TryReadGameConfig(string path)
{
if (!File.Exists(path)) return null;
try
{
string json = File.ReadAllText(path);
if (string.IsNullOrEmpty(json))
{
LogSystem.LogError($"[ConfigManager] 文件为空: {path}");
return null;
}
var config = JsonUtility.FromJson<GameConfig>(json);
if (config == null)
{
LogSystem.LogError($"[ConfigManager] 反序列化结果无效: {path}");
return null;
}
return config;
}
catch (Exception e)
{
LogSystem.LogError($"[ConfigManager] 读取文件失败: {path} | 错误: {e.Message}");
return null;
}
}
private float _lastSaveTime;
private const float SaveInterval = 1f; // 最少间隔1秒写一次
public void Update()
{
if (Config == null || !Config.IsChanged) return;
if (Time.time - _lastSaveTime < SaveInterval) return;
try
{
string json = JsonUtility.ToJson(Config);
byte[] bytes = System.Text.Encoding.UTF8.GetBytes(json);
string path = Application.persistentDataPath + "/../Config/game_cfg.json";
FileTools.SafeWriteFile(path, bytes);
Config.MarkSaved();
_lastSaveTime = Time.time;
}
catch (Exception e)
{
LogSystem.LogError($"[ConfigManager] 保存配置失败: {e.Message}");
}
}
}
[Serializable]
public class GameConfig
{
[SerializeField]
private MultilingualType _multilingualType;
[SerializeField]
private float _musicVolume;
[SerializeField]
private float _audioVolume;
[SerializeField]
private bool _showReminder;
[SerializeField]
private bool _keyMomentEnabled;
[SerializeField]
private bool _bgmContinuousPlay;
private bool _isChanged;
public bool IsChanged => _isChanged;
public void MarkSaved()
{
_isChanged = false;
}
public MultilingualType MultilingualType
{
get => _multilingualType;
set
{
if (_multilingualType == value) return;
_isChanged = true;
_multilingualType = value;
}
}
public float MusicVolume
{
get => _musicVolume;
set
{
if (Math.Abs(_musicVolume - value) < 0.01f) return;
_isChanged = true;
_musicVolume = value;
}
}
public float AudioVolume
{
get => _audioVolume;
set
{
if (Math.Abs(_audioVolume - value) < 0.01f) return;
_isChanged = true;
_audioVolume = value;
}
}
public bool BgmContinuousPlay
{
get => _bgmContinuousPlay;
set
{
if (_bgmContinuousPlay == value) return;
_isChanged = true;
_bgmContinuousPlay = value;
}
}
public bool ShowReminder
{
get => _showReminder;
set
{
if (_showReminder == value) return;
_isChanged = true;
_showReminder = value;
}
}
public bool KeyMomentEnabled
{
get => _keyMomentEnabled;
set
{
if (_keyMomentEnabled == value) return;
_isChanged = true;
_keyMomentEnabled = value;
}
}
public GameConfig()
{
_multilingualType = MultilingualType.None;
_musicVolume = 0.5f;
_audioVolume = 0.5f;
_showReminder = true;
_keyMomentEnabled = true;
_bgmContinuousPlay = false;
}
}
}