using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Security.Cryptography; using System.Text; using UnityEngine; using System.Threading; [XLua.LuaCallCSharp] public class Config : Singleton { bool isPlaying = true; bool m_Inited = false; public bool inited { get { return m_Inited; } private set { m_Inited = value; } } Dictionary> configDictionary = new Dictionary>(); public void RegisterGlobalEvent() { SnxxzGame.Instance.RemoveApplicationOutAction(OnApplicationOut); SnxxzGame.Instance.AddApplicationOutAction(OnApplicationOut); } public void LoadPriorBundleConfig() { StartSyncTask(); } public void PreLoadConfigs() { StartSyncTask(); StartSyncTask(); StartSyncTask(); StartSyncTask(); StartSyncTask(); } List configTasks = new List(); public IEnumerator Co_LoadConfigs() { StartSyncTask(); StartSyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask();//检查断线原因 AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); //装备套装属性 AddAsyncTask(); //装备套装锻造需要材料 AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); AddAsyncTask(); while (!AllCompleted()) { var completedCount = 0; for (int i = 0; i < configTasks.Count; i++) { var task = configTasks[i]; if (task.state == TaskState.ParseSuccess) { completedCount++; } } var allowTaskCount = completedCount <= 8 ? GetMinWorkingTaskCount() : GetMaxWorkingTaskCount(); var workingCount = 0; for (int i = 0; i < configTasks.Count; i++) { var task = configTasks[i]; if (task.state > TaskState.None && task.state < TaskState.ParseSuccess) { workingCount++; } } if (workingCount < allowTaskCount) { var leisureCount = allowTaskCount - workingCount; var startedTasksCount = 0; for (int i = 0; i < configTasks.Count; i++) { var task = configTasks[i]; if (task.state == TaskState.None) { StartAsyncTask(task); startedTasksCount++; } if (startedTasksCount >= leisureCount) { break; } } } yield return null; } } public void SyncLoadConfigs() { StartSyncTask(); StartSyncTask(); StartSyncTask(); StartSyncTask(); StartSyncTask(); StartSyncTask(); } public bool AllCompleted() { foreach (var task in configTasks) { if (task.state != TaskState.ParseSuccess) { // DesignDebug.LogFormat("未完成是配置解析任务:{0},当前状态:{1}", task.taskName, task.state); return false; } } return true; } public float GetProgress() { var count = 0; foreach (var task in configTasks) { if (task.state == TaskState.ParseSuccess) { count++; } } return (float)count / configTasks.Count; } public int GetTaskCount() { return configTasks.Count; } public void ConfigParsePostProcess() { foreach (var task in configTasks) { configDictionary[task.token] = task.container; } inited = true; } int GetMinWorkingTaskCount() { switch (Application.platform) { case RuntimePlatform.Android: if (DeviceUtility.cpu >= 4 && DeviceUtility.memory > 3.2f * 1024) { return 4; } else if (DeviceUtility.cpu >= 4 && DeviceUtility.memory > 2.5f * 1024) { return 2; } else { return 1; } case RuntimePlatform.IPhonePlayer: if (DeviceUtility.cpu > 1 && DeviceUtility.memory > 1.5f * 1024) { return 4; } else { return 1; } case RuntimePlatform.WindowsEditor: return 4; default: return 1; } } int GetMaxWorkingTaskCount() { switch (Application.platform) { case RuntimePlatform.Android: if (DeviceUtility.cpu >= 4 && DeviceUtility.memory > 3.2f * 1024) { return 20; } else if (DeviceUtility.cpu >= 4 && DeviceUtility.memory > 2.5f * 1024) { return 10; } else if (DeviceUtility.cpu > 1 && DeviceUtility.memory > 1.5f * 1024) { return 4; } else { return 1; } case RuntimePlatform.IPhonePlayer: if (DeviceUtility.cpu > 1 && DeviceUtility.memory > 1.5f * 1024) { return 10; } else { return 1; } case RuntimePlatform.WindowsEditor: return 20; default: return 5; } } ConfigTask AddAsyncTask() where T : ConfigBase, new() { var typeName = typeof(T).Name; var path = string.Empty; var fileName = typeName.Substring(0, typeName.Length - 6); if (AssetSource.refdataFromEditor) { path = ResourcesPath.CONFIG_FODLER + "/" + fileName + ".txt"; } else { path = AssetVersionUtility.GetAssetFilePath(StringUtility.Contact("config/", fileName, ".txt")); } var task = new ConfigTask(typeof(T), path); Action launch = (ConfigTask _task) => { ReadFile(_task, OnEndReadFile); }; task.launch = launch; configTasks.Add(task); return task; } void StartAsyncTask(ConfigTask _task) { _task.state = TaskState.Working; _task.launch(_task); } void ReadFile(ConfigTask _task, Action _callBack) { ThreadPool.QueueUserWorkItem( (object _obj) => { string[] lines = null; try { lines = File.ReadAllLines(_task.filePath, Encoding.UTF8); _task.state = TaskState.ReadFileSuccess; } catch (Exception ex) { _task.state = TaskState.ReadFileFailure; DebugEx.Log(ex); } finally { _task.contentLines = lines; if (_callBack != null) { _callBack(_task); } } } ); } void AsyncParseConfig(ConfigTask _task, Action _callBack) where T : ConfigBase, new() { ThreadPool.QueueUserWorkItem( (object _obj) => { try { var count = 0; var container = _task.container as Dictionary; for (int i = 3; i < _task.contentLines.Length; i++) { var newConfig = new T(); newConfig.Parse(_task.contentLines[i]); if (newConfig is IConfigPostProcess) { (newConfig as IConfigPostProcess).OnConfigParseCompleted(); } container[newConfig.getKey()] = newConfig; count++; if (count >= 500) { count = 0; Thread.Sleep(30); } } _task.state = TaskState.ParseSuccess; } catch (Exception ex) { _task.state = TaskState.ParseFailure; DebugEx.Log(ex); } finally { if (_callBack != null) { _callBack(_task); } } } ); } private void OnEndReadFile(ConfigTask _task) where T : ConfigBase, new() { if (isPlaying && _task.state == TaskState.ReadFileFailure) { Thread.Sleep(30); ReadFile(_task, OnEndReadFile); } else { _task.capacity = Mathf.Max(_task.contentLines.Length - 3, 0); _task.container = new Dictionary(_task.capacity); AsyncParseConfig(_task, OnEndParse); } } private void OnEndParse(ConfigTask _task) where T : ConfigBase, new() { if (isPlaying && _task.state == TaskState.ParseFailure) { Debug.LogFormat("配置表解析失败:{0}", _task.taskName); Thread.Sleep(30); ReadFile(_task, OnEndReadFile); } } private void StartSyncTask() where T : ConfigBase, new() { var typeName = typeof(T).Name; var fileName = typeName.Substring(0, typeName.Length - 6); var path = string.Empty; if (Application.isEditor || AssetSource.refdataFromEditor) { path = ResourcesPath.CONFIG_FODLER + "/" + fileName + ".txt"; } else { path = AssetVersionUtility.GetAssetFilePath(StringUtility.Contact("config/", fileName, ".txt")); } var task = new ConfigTask(typeof(T), path); task.contentLines = File.ReadAllLines(path, Encoding.UTF8); if (task.contentLines != null && task.contentLines.Length > 3) { var length = Mathf.Max(task.contentLines.Length - 3, 0); task.capacity = length; task.container = new Dictionary(length); task.state = TaskState.ReadFileSuccess; SyncParseConfig(task); } else { task.state = TaskState.ReadFileFailure; } } private void SyncParseConfig(ConfigTask _task) where T : ConfigBase, new() { try { for (int i = 3; i < _task.contentLines.Length; i++) { var newConfig = new T(); newConfig.Parse(_task.contentLines[i]); if (newConfig is IConfigPostProcess) { (newConfig as IConfigPostProcess).OnConfigParseCompleted(); } _task.container[newConfig.getKey()] = newConfig; } } catch (Exception ex) { DebugEx.Log(ex); } finally { _task.state = TaskState.ParseSuccess; configDictionary[_task.token] = _task.container; } } public T Get(string _dwTemplateID) where T : ConfigBase, new() { if (string.IsNullOrEmpty(_dwTemplateID)) { return null; } var token = typeof(T).MetadataToken; if (configDictionary.ContainsKey(token) == false) { DebugEx.LogErrorFormat("not find the config:{0}", token); return null; } ConfigBase config = null; var dic = configDictionary[token]; if (!dic.ContainsKey(_dwTemplateID)) { DebugEx.LogFormat("not find the config:{0},ID:{1}", typeof(T).Name, _dwTemplateID); } else { config = dic[_dwTemplateID]; } return config as T; } public T Get(int _dwTemplateID) where T : ConfigBase, new() { return Get(_dwTemplateID.ToString()); } public bool ContainKey(int _id) { return ContainKey(_id.ToString()); } public bool ContainKey(string _key) { if (string.IsNullOrEmpty(_key)) { return false; } var token = typeof(T).MetadataToken; if (configDictionary.ContainsKey(token) == false) { return false; } var dic = configDictionary[token]; return dic.ContainsKey(_key); } public List GetAllKeys() where T : ConfigBase { var token = typeof(T).MetadataToken; if (!configDictionary.ContainsKey(token)) { DebugEx.LogErrorFormat("not find the dic of config: {0}", typeof(T).Name); return null; } var dicTemplate = configDictionary[token]; return new List(dicTemplate.Keys); } public List GetAllValues() where T : ConfigBase, new() { var token = typeof(T).MetadataToken; if (!configDictionary.ContainsKey(token)) { DebugEx.LogErrorFormat("not find the dic of config: {0}", typeof(T).Name); return null; } var configs = new List(); var dicTemplate = configDictionary[token]; foreach (var value in dicTemplate.Values) { configs.Add(value as T); } return configs; } class ConfigTask { public readonly Type type; public readonly int token; public readonly string taskName; public readonly string filePath; public Action launch; public int capacity = 0; public string[] contentLines; public Dictionary container; public TaskState state = TaskState.None; public ConfigTask(Type _type, string _filePath) { type = _type; taskName = type.Name; token = type.MetadataToken; filePath = _filePath; } } public enum TaskState { None = 0, Working = 1, ReadFileSuccess = 2, ReadFileFailure = 3, ParseFailure = 4, ParseSuccess = 5, } private void OnApplicationOut() { isPlaying = false; } }