| | |
| | | using System; |
| | | using System.Collections; |
| | | using System.Collections.Generic; |
| | | using System.IO; |
| | | using System.Security.Cryptography; |
| | | using System.Text; |
| | | using TableConfig; |
| | | using UnityEngine; |
| | | using System.Threading; |
| | | |
| | | public class ConfigManager : Singleton<ConfigManager> |
| | | { |
| | | public static string CustomIV = "4vHKRj3yfzU="; |
| | | public static string CustomKey = "xhVs6DRXLfUGxw+AhtfQdpQGoa+8SA9d"; |
| | | |
| | | protected string[] lineStep = new string[] { "\r\n" }; //行间隔体 |
| | | protected string[] rowStep = new string[] { "\t" }; //段间隔体 |
| | | |
| | | bool isPlaying = true; |
| | | |
| | | bool m_Inited = false; |
| | | public bool inited { |
| | | get { return m_Inited; } |
| | | private set { m_Inited = value; } |
| | | } |
| | | |
| | | Dictionary<int, Dictionary<string, ConfigBase>> configDictionary = new Dictionary<int, Dictionary<string, ConfigBase>>(); |
| | | |
| | | public void RegisterGlobalEvent() |
| | | { |
| | | SnxxzGame.Instance.RemoveApplicationOutAction(OnApplicationOut); |
| | | SnxxzGame.Instance.AddApplicationOutAction(OnApplicationOut); |
| | | } |
| | | |
| | | public void PreLoadConfigs() |
| | | { |
| | | StartSyncTask<PriorBundleConfig>(AssetPath.Resource); |
| | | StartSyncTask<PriorLanguageConfig>(AssetPath.Resource); |
| | | } |
| | | |
| | | List<ConfigTask> configTasks = new List<ConfigTask>(); |
| | | |
| | | public IEnumerator Co_LoadConfigs() |
| | | { |
| | | AddAsyncTask<IconConfig>(); |
| | | AddAsyncTask<ItemConfig>(); |
| | | AddAsyncTask<SkillConfig>(); |
| | | AddAsyncTask<mapnpcConfig>(); |
| | | AddAsyncTask<LoginSeverListConfig>(); |
| | | AddAsyncTask<DienstgradConfig>(); |
| | | AddAsyncTask<PlayerPropertyConfig>(); |
| | | AddAsyncTask<RealmConfig>(); |
| | | AddAsyncTask<ItemCompoundConfig>(); |
| | | AddAsyncTask<FuncConfigConfig>(); |
| | | AddAsyncTask<GodWeaponConfig>(); |
| | | AddAsyncTask<FuncOpenLVConfig>(); |
| | | AddAsyncTask<RichTextMsgReplaceConfig>(); |
| | | AddAsyncTask<SysInfoConfig>(); |
| | | AddAsyncTask<ItemPlusConfig>(); |
| | | AddAsyncTask<ItemPlusMaxConfig>(); |
| | | AddAsyncTask<PyTaskConfig>(); |
| | | AddAsyncTask<TASKINFOConfig>(); |
| | | AddAsyncTask<MailConfig>(); |
| | | AddAsyncTask<RuneTowerConfig>(); |
| | | AddAsyncTask<EquipWashConfig>(); |
| | | AddAsyncTask<EquipWashSpecConfig>(); |
| | | AddAsyncTask<AttrFruitConfig>(); |
| | | AddAsyncTask<RuneConfig>(); |
| | | AddAsyncTask<MapConfig>(); |
| | | AddAsyncTask<PlayerLVConfig>(); |
| | | AddAsyncTask<PetEatEquipConfig>(); |
| | | AddAsyncTask<PetInfoConfig>(); |
| | | AddAsyncTask<RandomNameConfig>(); |
| | | AddAsyncTask<PetClassCostConfig>(); |
| | | AddAsyncTask<NPCConfig>(); |
| | | AddAsyncTask<KickOutReasonConfig>();//检查断线原因 |
| | | AddAsyncTask<HorseConfig>(); |
| | | AddAsyncTask<HorseUpConfig>(); |
| | | AddAsyncTask<RankListConfig>(); |
| | | AddAsyncTask<OccupationNameConfig>(); |
| | | AddAsyncTask<EquipSuitAttrConfig>(); //装备套装属性 |
| | | AddAsyncTask<EquipSuitCompoundConfig>(); //装备套装锻造需要材料 |
| | | AddAsyncTask<DirtyWordConfig>(); |
| | | AddAsyncTask<EffectConfig>(); |
| | | AddAsyncTask<WingRefineAttrConfig>(); |
| | | AddAsyncTask<FamilyTechConfig>(); |
| | | AddAsyncTask<FamilyConfig>(); |
| | | AddAsyncTask<IconConfig>(); |
| | | AddAsyncTask<LanguageConfig>(); |
| | | AddAsyncTask<CreateRoleConfig>(); |
| | | AddAsyncTask<DamageNumConfig>(); |
| | | AddAsyncTask<DungeonConfig>(); |
| | | AddAsyncTask<JobSetupConfig>(); |
| | | AddAsyncTask<ModelResConfig>(); |
| | | AddAsyncTask<DailyQuestConfig>(); |
| | | AddAsyncTask<FaceConfig>(); |
| | | AddAsyncTask<DailyLivenessRewardConfig>(); |
| | | AddAsyncTask<JobNameConfig>(); |
| | | AddAsyncTask<MarketConfig>(); |
| | | AddAsyncTask<maptransportConfig>(); |
| | | AddAsyncTask<ItemPlusSumAttrConfig>(); |
| | | AddAsyncTask<RoleEquipStarsConfig>(); |
| | | AddAsyncTask<MonsterNameColorConfig>(); |
| | | AddAsyncTask<TreasureConfig>(); |
| | | AddAsyncTask<SuccessConfig>(); |
| | | AddAsyncTask<TreasureSkillConfig>(); |
| | | AddAsyncTask<mapAreaConfig>(); |
| | | AddAsyncTask<EquipDeComposeConfig>(); |
| | | AddAsyncTask<WindowSearchConfig>(); |
| | | AddAsyncTask<SignInConfig>(); |
| | | AddAsyncTask<ContinueSignInConfig>(); |
| | | AddAsyncTask<DungeonHintConfig>(); |
| | | AddAsyncTask<MapEventPointConfig>(); |
| | | AddAsyncTask<VIPAwardConfig>(); |
| | | AddAsyncTask<VipPrivilegeConfig>(); |
| | | AddAsyncTask<DailyQuestOpenTimeConfig>(); |
| | | AddAsyncTask<DungeonOpenTimeConfig>(); |
| | | AddAsyncTask<AppointItemConfig>(); |
| | | AddAsyncTask<EquipGSParamConfig>(); |
| | | AddAsyncTask<StoreConfig>(); |
| | | AddAsyncTask<WorldBossConfig>(); |
| | | AddAsyncTask<BossHomeConfig>(); |
| | | AddAsyncTask<PersonalBossConfig>(); |
| | | AddAsyncTask<ElderGodAreaConfig>(); |
| | | AddAsyncTask<RuneTowerFloorConfig>(); |
| | | AddAsyncTask<TreasureRefineConfig>(); |
| | | AddAsyncTask<AlchemyConfig>(); |
| | | AddAsyncTask<BlastFurnaceLVConfig>(); |
| | | AddAsyncTask<AlchemySpecConfig>(); |
| | | AddAsyncTask<QuestionBankConfig>(); |
| | | AddAsyncTask<WingRefineExpConfig>(); |
| | | AddAsyncTask<UnionLivenConfig>(); |
| | | AddAsyncTask<ActorShowConfig>(); |
| | | AddAsyncTask<FunctionForecastConfig>(); |
| | | AddAsyncTask<GmCmdConfig>(); |
| | | AddAsyncTask<GetItemWaysConfig>(); |
| | | AddAsyncTask<GuideConfig>(); |
| | | AddAsyncTask<ViewRoleFuncConfig>(); |
| | | AddAsyncTask<RoleStrongerConfig>(); |
| | | AddAsyncTask<RoleResourceConfig>(); |
| | | AddAsyncTask<AudioConfig>(); |
| | | AddAsyncTask<AreaCameraConfig>(); |
| | | AddAsyncTask<NPCDialogueConfig>(); |
| | | AddAsyncTask<TaskListConfig>(); |
| | | AddAsyncTask<DemonJarConfig>(); |
| | | AddAsyncTask<StoryMissionsConfig>(); |
| | | AddAsyncTask<DungeonStateTimeConfig>(); |
| | | AddAsyncTask<DungeonInspireConfig>(); |
| | | AddAsyncTask<RuneComposeConfig>(); |
| | | AddAsyncTask<BossInfoConfig>(); |
| | | AddAsyncTask<DialogConfig>(); |
| | | AddAsyncTask<SceneShadowConfig>(); |
| | | AddAsyncTask<ResourcesBackConfig>(); |
| | | AddAsyncTask<WeatherConfig>(); |
| | | AddAsyncTask<RuleConfig>(); |
| | | AddAsyncTask<MonsterRefreshPointConfig>(); |
| | | AddAsyncTask<DogzConfig>(); |
| | | AddAsyncTask<ChestsConfig>(); |
| | | AddAsyncTask<ChestsAwardConfig>(); |
| | | AddAsyncTask<NPCDropItemConfig>(); |
| | | AddAsyncTask<TeamTargetConfig>(); |
| | | AddAsyncTask<OSCBillRankAwardConfig>(); |
| | | AddAsyncTask<OSCBillTagAwardConfig>(); |
| | | AddAsyncTask<InSevenDaysConfig>(); |
| | | AddAsyncTask<OnlineAwardConfig>(); |
| | | AddAsyncTask<LVAawrdConfig>(); |
| | | AddAsyncTask<DemonRecommondPropertyConfig>(); |
| | | AddAsyncTask<InvestConfig>(); |
| | | AddAsyncTask<SuitEffectConfig>(); |
| | | AddAsyncTask<RefineStoveConfig>(); |
| | | AddAsyncTask<VIPKillNPCConfig>(); |
| | | AddAsyncTask<LoadingTipConfig>(); |
| | | AddAsyncTask<XMZZAchievementConfig>(); |
| | | AddAsyncTask<XBGetItemConfig>(); |
| | | AddAsyncTask<bossSkillTipsConfig>(); |
| | | AddAsyncTask<OSRedAchieveConfig>(); |
| | | AddAsyncTask<RedPackConfig>(); |
| | | AddAsyncTask<TreasureFindHostConfig>(); |
| | | AddAsyncTask<TreasureUpConfig>(); |
| | | AddAsyncTask<TreasurePrivilegeConfig>(); |
| | | AddAsyncTask<CTGConfig>(); |
| | | AddAsyncTask<MapResourcesConfig>(); |
| | | AddAsyncTask<FightPowerParamConfig>(); |
| | | AddAsyncTask<LoadingFunctionConfig>(); |
| | | AddAsyncTask<LoginAdConfig>(); |
| | | AddAsyncTask<FreeGoodsConfig>(); |
| | | AddAsyncTask<BossRebornConfig>(); |
| | | AddAsyncTask<UniquenessArriveConfig>(); |
| | | AddAsyncTask<AllPeoplePartyConfig>(); |
| | | AddAsyncTask<AllPeoplePartyAwardConfig>(); |
| | | AddAsyncTask<OrderInfoConfig>(); |
| | | AddAsyncTask<TrialExchangeConfig>(); |
| | | |
| | | 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 <= 7 ? 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<NPCConfig>(AssetPath.ResourceOut); |
| | | StartSyncTask<ModelResConfig>(AssetPath.ResourceOut); |
| | | StartSyncTask<ActorShowConfig>(AssetPath.ResourceOut); |
| | | StartSyncTask<IconConfig>(AssetPath.ResourceOut); |
| | | StartSyncTask<SysInfoConfig>(AssetPath.ResourceOut); |
| | | StartSyncTask<LanguageConfig>(AssetPath.ResourceOut); |
| | | } |
| | | |
| | | 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.5f * 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 50; |
| | | default: |
| | | return 1; |
| | | } |
| | | } |
| | | |
| | | int GetMaxWorkingTaskCount() |
| | | { |
| | | switch (Application.platform) |
| | | { |
| | | case RuntimePlatform.Android: |
| | | if (DeviceUtility.cpu >= 4 && DeviceUtility.memory > 3.5f * 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 50; |
| | | default: |
| | | return 5; |
| | | } |
| | | } |
| | | |
| | | ConfigTask AddAsyncTask<T>() 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 |
| | | { |
| | | var assetVersion = AssetVersionUtility.GetAssetVersion(StringUtility.Contact("config/", fileName, ".bytes")); |
| | | path = StringUtility.Contact(ResourcesPath.Instance.ExternalStorePath, assetVersion.relativePath); |
| | | } |
| | | |
| | | var task = new ConfigTask(typeof(T), AssetSource.refdataFromEditor ? AssetPath.ResourceOut : AssetPath.External, path); |
| | | Action<ConfigTask> launch = (ConfigTask _task) => { ReadFile(_task, OnEndReadFile<T>); }; |
| | | task.launch = launch; |
| | | configTasks.Add(task); |
| | | |
| | | return task; |
| | | } |
| | | |
| | | void StartAsyncTask(ConfigTask _task) |
| | | { |
| | | _task.state = TaskState.Working; |
| | | _task.launch(_task); |
| | | } |
| | | |
| | | void ReadFile(ConfigTask _task, Action<ConfigTask> _callBack) |
| | | { |
| | | ThreadPool.QueueUserWorkItem( |
| | | (object _obj) => |
| | | { |
| | | string[] lines = null; |
| | | StreamReader sr = null; |
| | | |
| | | try |
| | | { |
| | | if (_task.assetPath == AssetPath.ResourceOut) |
| | | { |
| | | var fileInfo = new FileInfo(_task.filePath); |
| | | var fs = fileInfo.OpenRead(); |
| | | sr = new StreamReader(fs, Encoding.UTF8); |
| | | var content = sr.ReadToEnd(); |
| | | lines = content.Split(lineStep, StringSplitOptions.None); |
| | | } |
| | | else if (_task.assetPath == AssetPath.External) |
| | | { |
| | | var tripleDESCryptoServiceProvider = new TripleDESCryptoServiceProvider(); |
| | | tripleDESCryptoServiceProvider.Key = Convert.FromBase64String(CustomKey); |
| | | tripleDESCryptoServiceProvider.IV = Convert.FromBase64String(CustomIV); |
| | | tripleDESCryptoServiceProvider.Mode = CipherMode.CBC; |
| | | tripleDESCryptoServiceProvider.Padding = PaddingMode.PKCS7; |
| | | var decryptor = tripleDESCryptoServiceProvider.CreateDecryptor(); |
| | | |
| | | var expectedSteam = new FileStream(_task.filePath, FileMode.Open, FileAccess.Read, FileShare.Read); |
| | | var bytes = new byte[expectedSteam.Length]; |
| | | expectedSteam.Read(bytes, 0, bytes.Length); |
| | | var tableMs = new MemoryStream(bytes); |
| | | |
| | | var crypS = new CryptoStream(tableMs, decryptor, CryptoStreamMode.Read); |
| | | sr = new StreamReader(crypS, Encoding.UTF8); |
| | | var content = sr.ReadToEnd(); |
| | | lines = content.Split(lineStep, StringSplitOptions.None); |
| | | } |
| | | |
| | | _task.state = TaskState.ReadFileSuccess; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _task.state = TaskState.ReadFileFailure; |
| | | DesignDebug.Log(ex); |
| | | } |
| | | finally |
| | | { |
| | | _task.contentLines = lines; |
| | | if (_callBack != null) |
| | | { |
| | | _callBack(_task); |
| | | } |
| | | } |
| | | } |
| | | ); |
| | | |
| | | } |
| | | |
| | | void AsyncParseConfig<T>(ConfigTask _task, Action<ConfigTask> _callBack) where T : ConfigBase, new() |
| | | { |
| | | ThreadPool.QueueUserWorkItem( |
| | | (object _obj) => |
| | | { |
| | | try |
| | | { |
| | | var count = 0; |
| | | |
| | | var container = _task.container as Dictionary<string, ConfigBase>; |
| | | for (int i = 3; i < _task.contentLines.Length; i++) |
| | | { |
| | | var contents = _task.contentLines[i].Split(rowStep, StringSplitOptions.None); |
| | | if (contents.Length <= 1) |
| | | { |
| | | continue; |
| | | } |
| | | |
| | | var newConfig = new T(); |
| | | newConfig.SetRawContent(contents); |
| | | |
| | | newConfig.Parse(); |
| | | newConfig.PostProcess(); |
| | | if (newConfig is IConfigPostProcess) |
| | | { |
| | | (newConfig as IConfigPostProcess).OnConfigParseCompleted(); |
| | | } |
| | | |
| | | newConfig.parsed = true; |
| | | container[contents[0]] = newConfig; |
| | | |
| | | count++; |
| | | if (count >= 500) |
| | | { |
| | | count = 0; |
| | | Thread.Sleep(30); |
| | | } |
| | | } |
| | | |
| | | _task.state = TaskState.ParseSuccess; |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | _task.state = TaskState.ParseFailure; |
| | | DesignDebug.Log(ex); |
| | | } |
| | | finally |
| | | { |
| | | if (_callBack != null) |
| | | { |
| | | _callBack(_task); |
| | | } |
| | | } |
| | | } |
| | | ); |
| | | } |
| | | |
| | | private void OnEndReadFile<T>(ConfigTask _task) where T : ConfigBase, new() |
| | | { |
| | | if (isPlaying && _task.state == TaskState.ReadFileFailure) |
| | | { |
| | | ReadFile(_task, OnEndReadFile<T>); |
| | | } |
| | | else |
| | | { |
| | | _task.capacity = Mathf.Max(_task.contentLines.Length - 3, 0); |
| | | _task.container = new Dictionary<string, ConfigBase>(_task.capacity); |
| | | AsyncParseConfig<T>(_task, OnEndParse<T>); |
| | | } |
| | | } |
| | | |
| | | private void OnEndParse<T>(ConfigTask _task) where T : ConfigBase, new() |
| | | { |
| | | if (isPlaying && _task.state == TaskState.ParseFailure) |
| | | { |
| | | Debug.LogFormat("配置表解析失败:{0}", _task.taskName); |
| | | ReadFile(_task, OnEndReadFile<T>); |
| | | } |
| | | } |
| | | |
| | | private void StartSyncTask<T>(AssetPath _assetPath) where T : ConfigBase, new() |
| | | { |
| | | var typeName = typeof(T).Name; |
| | | var fileName = typeName.Substring(0, typeName.Length - 6); |
| | | string[] lines = null; |
| | | var path = string.Empty; |
| | | |
| | | switch (_assetPath) |
| | | { |
| | | case AssetPath.Resource: |
| | | path = StringUtility.Contact("Config/", fileName); |
| | | var textAsset = Resources.Load<TextAsset>(path); |
| | | lines = textAsset.text.Split(lineStep, StringSplitOptions.None); |
| | | break; |
| | | case AssetPath.ResourceOut: |
| | | path = StringUtility.Contact(ResourcesPath.CONFIG_FODLER, "/", fileName, ".txt"); |
| | | lines = File.ReadAllLines(path, Encoding.UTF8); |
| | | break; |
| | | case AssetPath.External: |
| | | var assetVersion = AssetVersionUtility.GetAssetVersion(StringUtility.Contact("config/", fileName, ".bytes")); |
| | | path = StringUtility.Contact(ResourcesPath.Instance.ExternalStorePath, assetVersion.relativePath); |
| | | |
| | | var provider = new TripleDESCryptoServiceProvider(); |
| | | provider.Key = Convert.FromBase64String(CustomKey); |
| | | provider.IV = Convert.FromBase64String(CustomIV); |
| | | provider.Mode = CipherMode.CBC; |
| | | provider.Padding = PaddingMode.PKCS7; |
| | | var decryptor = provider.CreateDecryptor(); |
| | | |
| | | var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); |
| | | var bytes = new byte[fs.Length]; |
| | | fs.Read(bytes, 0, bytes.Length); |
| | | var ms = new MemoryStream(bytes); |
| | | |
| | | var crypS = new CryptoStream(ms, decryptor, CryptoStreamMode.Read); |
| | | var sr = new StreamReader(crypS, Encoding.UTF8); |
| | | var content = sr.ReadToEnd(); |
| | | lines = content.Split(lineStep, StringSplitOptions.None); |
| | | |
| | | break; |
| | | } |
| | | |
| | | var task = new ConfigTask(typeof(T), _assetPath, path); |
| | | configTasks.Add(task); |
| | | |
| | | task.contentLines = lines; |
| | | if (lines != null && lines.Length > 3) |
| | | { |
| | | var length = Mathf.Max(lines.Length - 3, 0); |
| | | task.capacity = length; |
| | | task.container = new Dictionary<string, ConfigBase>(length); |
| | | task.state = TaskState.ReadFileSuccess; |
| | | SyncParseConfig<T>(task); |
| | | } |
| | | else |
| | | { |
| | | task.state = TaskState.ReadFileFailure; |
| | | } |
| | | } |
| | | |
| | | private void SyncParseConfig<T>(ConfigTask _task) where T : ConfigBase, new() |
| | | { |
| | | try |
| | | { |
| | | for (int i = 3; i < _task.contentLines.Length; i++) |
| | | { |
| | | var contents = _task.contentLines[i].Split(rowStep, StringSplitOptions.None); |
| | | if (contents.Length <= 1) |
| | | { |
| | | continue; |
| | | } |
| | | |
| | | var newConfig = new T(); |
| | | newConfig.SetRawContent(contents); |
| | | |
| | | newConfig.Parse(); |
| | | newConfig.PostProcess(); |
| | | |
| | | if (newConfig is IConfigPostProcess) |
| | | { |
| | | (newConfig as IConfigPostProcess).OnConfigParseCompleted(); |
| | | } |
| | | |
| | | newConfig.parsed = true; |
| | | |
| | | _task.container[contents[0]] = newConfig; |
| | | } |
| | | } |
| | | catch (Exception ex) |
| | | { |
| | | DesignDebug.Log(ex); |
| | | } |
| | | finally |
| | | { |
| | | _task.state = TaskState.ParseSuccess; |
| | | configDictionary[_task.token] = _task.container; |
| | | } |
| | | |
| | | } |
| | | |
| | | public T GetTemplate<T>(string _dwTemplateID) where T : ConfigBase, new() |
| | | { |
| | | if (string.IsNullOrEmpty(_dwTemplateID)) |
| | | { |
| | | return null; |
| | | } |
| | | |
| | | var token = typeof(T).MetadataToken; |
| | | if (configDictionary.ContainsKey(token) == false) |
| | | { |
| | | DesignDebug.LogErrorFormat("not find the config:{0}", token); |
| | | return null; |
| | | } |
| | | |
| | | ConfigBase config = null; |
| | | var dic = configDictionary[token]; |
| | | if (!dic.ContainsKey(_dwTemplateID)) |
| | | { |
| | | DesignDebug.LogFormat("not find the config:{0},<color=#ff0000ff>ID:{1}</color>", typeof(T).Name, _dwTemplateID); |
| | | } |
| | | else |
| | | { |
| | | config = dic[_dwTemplateID]; |
| | | } |
| | | |
| | | if (config != null && !config.parsed) |
| | | { |
| | | config.Parse(); |
| | | config.PostProcess(); |
| | | config.parsed = true; |
| | | } |
| | | |
| | | return config as T; |
| | | } |
| | | |
| | | public T GetTemplate<T>(int _dwTemplateID) where T : ConfigBase, new() |
| | | { |
| | | return GetTemplate<T>(_dwTemplateID.ToString()); |
| | | } |
| | | |
| | | public bool ContainKey<T>(int _id) |
| | | { |
| | | return ContainKey<T>(_id.ToString()); |
| | | } |
| | | |
| | | public bool ContainKey<T>(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<string> GetAllKeys<T>() where T : ConfigBase |
| | | { |
| | | var token = typeof(T).MetadataToken; |
| | | if (!configDictionary.ContainsKey(token)) |
| | | { |
| | | DesignDebug.LogErrorFormat("not find the dic of config: {0}", typeof(T).Name); |
| | | return null; |
| | | } |
| | | |
| | | var dicTemplate = configDictionary[token]; |
| | | return new List<string>(dicTemplate.Keys); |
| | | } |
| | | |
| | | public List<T> GetAllValues<T>() where T : ConfigBase, new() |
| | | { |
| | | var token = typeof(T).MetadataToken; |
| | | if (!configDictionary.ContainsKey(token)) |
| | | { |
| | | DesignDebug.LogErrorFormat("not find the dic of config: {0}", typeof(T).Name); |
| | | return null; |
| | | } |
| | | |
| | | var configs = new List<T>(); |
| | | var dicTemplate = configDictionary[token]; |
| | | foreach (var value in dicTemplate.Values) |
| | | { |
| | | if (value != null && !value.parsed) |
| | | { |
| | | value.Parse(); |
| | | value.PostProcess(); |
| | | value.parsed = true; |
| | | } |
| | | |
| | | configs.Add(value as T); |
| | | } |
| | | |
| | | return configs; |
| | | } |
| | | |
| | | class ConfigTask |
| | | { |
| | | public readonly Type type; |
| | | public readonly int token; |
| | | public readonly string taskName; |
| | | public readonly AssetPath assetPath; |
| | | public readonly string filePath; |
| | | |
| | | public Action<ConfigTask> launch; |
| | | public int capacity = 0; |
| | | public string[] contentLines; |
| | | public Dictionary<string, ConfigBase> container; |
| | | public TaskState state = TaskState.None; |
| | | |
| | | public ConfigTask(Type _type, AssetPath _assetPath, string _filePath) |
| | | { |
| | | type = _type; |
| | | assetPath = _assetPath; |
| | | taskName = type.Name; |
| | | token = type.MetadataToken; |
| | | |
| | | filePath = _filePath; |
| | | } |
| | | } |
| | | |
| | | public enum TaskState |
| | | { |
| | | None = 0, |
| | | Working = 1, |
| | | ReadFileSuccess = 2, |
| | | ReadFileFailure = 3, |
| | | ParseFailure = 4, |
| | | ParseSuccess = 5, |
| | | } |
| | | |
| | | public enum AssetPath |
| | | { |
| | | Resource, |
| | | ResourceOut, |
| | | External, |
| | | } |
| | | |
| | | private void OnApplicationOut() |
| | | { |
| | | isPlaying = false; |
| | | } |
| | | |
| | | } |
| | | using System;
|
| | | using System.Collections;
|
| | | using System.Collections.Generic;
|
| | | using System.IO;
|
| | | using System.Security.Cryptography;
|
| | | using System.Text;
|
| | | using TableConfig;
|
| | | using UnityEngine;
|
| | | using System.Threading;
|
| | |
|
| | | public class ConfigManager : Singleton<ConfigManager>
|
| | | {
|
| | | public readonly static string CustomIV = "4vHKRj3yfzU=";
|
| | | public readonly static string CustomKey = "xhVs6DRXLfUGxw+AhtfQdpQGoa+8SA9d";
|
| | |
|
| | | bool isPlaying = true;
|
| | |
|
| | | bool m_Inited = false;
|
| | | public bool inited {
|
| | | get { return m_Inited; }
|
| | | private set { m_Inited = value; }
|
| | | }
|
| | |
|
| | | Dictionary<int, Dictionary<string, ConfigBase>> configDictionary = new Dictionary<int, Dictionary<string, ConfigBase>>();
|
| | |
|
| | | public void RegisterGlobalEvent()
|
| | | {
|
| | | SnxxzGame.Instance.RemoveApplicationOutAction(OnApplicationOut);
|
| | | SnxxzGame.Instance.AddApplicationOutAction(OnApplicationOut);
|
| | | }
|
| | |
|
| | | public void PreLoadConfigs()
|
| | | {
|
| | | StartSyncTask<PriorBundleConfig>(AssetPath.Resource);
|
| | | StartSyncTask<PriorLanguageConfig>(AssetPath.Resource);
|
| | | }
|
| | |
|
| | | List<ConfigTask> configTasks = new List<ConfigTask>();
|
| | |
|
| | | public IEnumerator Co_LoadConfigs()
|
| | | {
|
| | | AddAsyncTask<IconConfig>();
|
| | | AddAsyncTask<ItemConfig>();
|
| | | AddAsyncTask<SkillConfig>();
|
| | | AddAsyncTask<TASKINFOConfig>();
|
| | | AddAsyncTask<mapnpcConfig>();
|
| | | AddAsyncTask<LoginSeverListConfig>();
|
| | | AddAsyncTask<DienstgradConfig>();
|
| | | AddAsyncTask<PlayerPropertyConfig>();
|
| | | AddAsyncTask<RealmConfig>();
|
| | | AddAsyncTask<ItemCompoundConfig>();
|
| | | AddAsyncTask<FuncConfigConfig>();
|
| | | AddAsyncTask<GodWeaponConfig>();
|
| | | AddAsyncTask<FuncOpenLVConfig>();
|
| | | AddAsyncTask<RichTextMsgReplaceConfig>();
|
| | | AddAsyncTask<SysInfoConfig>();
|
| | | AddAsyncTask<ItemPlusConfig>();
|
| | | AddAsyncTask<ItemPlusMaxConfig>();
|
| | | AddAsyncTask<PyTaskConfig>();
|
| | | AddAsyncTask<MailConfig>();
|
| | | AddAsyncTask<RuneTowerConfig>();
|
| | | AddAsyncTask<EquipWashConfig>();
|
| | | AddAsyncTask<EquipWashSpecConfig>();
|
| | | AddAsyncTask<AttrFruitConfig>();
|
| | | AddAsyncTask<RuneConfig>();
|
| | | AddAsyncTask<MapConfig>();
|
| | | AddAsyncTask<PlayerLVConfig>();
|
| | | AddAsyncTask<PetEatEquipConfig>();
|
| | | AddAsyncTask<PetInfoConfig>();
|
| | | AddAsyncTask<RandomNameConfig>();
|
| | | AddAsyncTask<PetClassCostConfig>();
|
| | | AddAsyncTask<NPCConfig>();
|
| | | AddAsyncTask<KickOutReasonConfig>();//检查断线原因
|
| | | AddAsyncTask<HorseConfig>();
|
| | | AddAsyncTask<HorseUpConfig>();
|
| | | AddAsyncTask<RankListConfig>();
|
| | | AddAsyncTask<OccupationNameConfig>();
|
| | | AddAsyncTask<EquipSuitAttrConfig>(); //装备套装属性
|
| | | AddAsyncTask<EquipSuitCompoundConfig>(); //装备套装锻造需要材料
|
| | | AddAsyncTask<DirtyWordConfig>();
|
| | | AddAsyncTask<EffectConfig>();
|
| | | AddAsyncTask<WingRefineAttrConfig>();
|
| | | AddAsyncTask<FamilyTechConfig>();
|
| | | AddAsyncTask<FamilyConfig>();
|
| | | AddAsyncTask<IconConfig>();
|
| | | AddAsyncTask<LanguageConfig>();
|
| | | AddAsyncTask<CreateRoleConfig>();
|
| | | AddAsyncTask<DamageNumConfig>();
|
| | | AddAsyncTask<DungeonConfig>();
|
| | | AddAsyncTask<JobSetupConfig>();
|
| | | AddAsyncTask<ModelResConfig>();
|
| | | AddAsyncTask<DailyQuestConfig>();
|
| | | AddAsyncTask<FaceConfig>();
|
| | | AddAsyncTask<DailyLivenessRewardConfig>();
|
| | | AddAsyncTask<JobNameConfig>();
|
| | | AddAsyncTask<MarketConfig>();
|
| | | AddAsyncTask<maptransportConfig>();
|
| | | AddAsyncTask<ItemPlusSumAttrConfig>();
|
| | | AddAsyncTask<RoleEquipStarsConfig>();
|
| | | AddAsyncTask<MonsterNameColorConfig>();
|
| | | AddAsyncTask<TreasureConfig>();
|
| | | AddAsyncTask<SuccessConfig>();
|
| | | AddAsyncTask<TreasureSkillConfig>();
|
| | | AddAsyncTask<mapAreaConfig>();
|
| | | AddAsyncTask<EquipDeComposeConfig>();
|
| | | AddAsyncTask<WindowSearchConfig>();
|
| | | AddAsyncTask<SignInConfig>();
|
| | | AddAsyncTask<ContinueSignInConfig>();
|
| | | AddAsyncTask<DungeonHintConfig>();
|
| | | AddAsyncTask<MapEventPointConfig>();
|
| | | AddAsyncTask<VIPAwardConfig>();
|
| | | AddAsyncTask<VipPrivilegeConfig>();
|
| | | AddAsyncTask<DailyQuestOpenTimeConfig>();
|
| | | AddAsyncTask<DungeonOpenTimeConfig>();
|
| | | AddAsyncTask<AppointItemConfig>();
|
| | | AddAsyncTask<EquipGSParamConfig>();
|
| | | AddAsyncTask<StoreConfig>();
|
| | | AddAsyncTask<WorldBossConfig>();
|
| | | AddAsyncTask<BossHomeConfig>();
|
| | | AddAsyncTask<PersonalBossConfig>();
|
| | | AddAsyncTask<ElderGodAreaConfig>();
|
| | | AddAsyncTask<RuneTowerFloorConfig>();
|
| | | AddAsyncTask<TreasureRefineConfig>();
|
| | | AddAsyncTask<AlchemyConfig>();
|
| | | AddAsyncTask<BlastFurnaceLVConfig>();
|
| | | AddAsyncTask<AlchemySpecConfig>();
|
| | | AddAsyncTask<QuestionBankConfig>();
|
| | | AddAsyncTask<WingRefineExpConfig>();
|
| | | AddAsyncTask<UnionLivenConfig>();
|
| | | AddAsyncTask<ActorShowConfig>();
|
| | | AddAsyncTask<FunctionForecastConfig>();
|
| | | AddAsyncTask<GmCmdConfig>();
|
| | | AddAsyncTask<GetItemWaysConfig>();
|
| | | AddAsyncTask<GuideConfig>();
|
| | | AddAsyncTask<ViewRoleFuncConfig>();
|
| | | AddAsyncTask<RoleStrongerConfig>();
|
| | | AddAsyncTask<RoleResourceConfig>();
|
| | | AddAsyncTask<AudioConfig>();
|
| | | AddAsyncTask<AreaCameraConfig>();
|
| | | AddAsyncTask<NPCDialogueConfig>();
|
| | | AddAsyncTask<TaskListConfig>();
|
| | | AddAsyncTask<DemonJarConfig>();
|
| | | AddAsyncTask<StoryMissionsConfig>();
|
| | | AddAsyncTask<DungeonStateTimeConfig>();
|
| | | AddAsyncTask<DungeonInspireConfig>();
|
| | | AddAsyncTask<RuneComposeConfig>();
|
| | | AddAsyncTask<BossInfoConfig>();
|
| | | AddAsyncTask<DialogConfig>();
|
| | | AddAsyncTask<SceneShadowConfig>();
|
| | | AddAsyncTask<ResourcesBackConfig>();
|
| | | AddAsyncTask<WeatherConfig>();
|
| | | AddAsyncTask<RuleConfig>();
|
| | | AddAsyncTask<MonsterRefreshPointConfig>();
|
| | | AddAsyncTask<DogzConfig>();
|
| | | AddAsyncTask<ChestsConfig>();
|
| | | AddAsyncTask<ChestsAwardConfig>();
|
| | | AddAsyncTask<NPCDropItemConfig>();
|
| | | AddAsyncTask<TeamTargetConfig>();
|
| | | AddAsyncTask<OSCBillRankAwardConfig>();
|
| | | AddAsyncTask<OSCBillTagAwardConfig>();
|
| | | AddAsyncTask<InSevenDaysConfig>();
|
| | | AddAsyncTask<OnlineAwardConfig>();
|
| | | AddAsyncTask<LVAawrdConfig>();
|
| | | AddAsyncTask<DemonRecommondPropertyConfig>();
|
| | | AddAsyncTask<InvestConfig>();
|
| | | AddAsyncTask<SuitEffectConfig>();
|
| | | AddAsyncTask<RefineStoveConfig>();
|
| | | AddAsyncTask<VIPKillNPCConfig>();
|
| | | AddAsyncTask<LoadingTipConfig>();
|
| | | AddAsyncTask<XMZZAchievementConfig>();
|
| | | AddAsyncTask<XBGetItemConfig>();
|
| | | AddAsyncTask<bossSkillTipsConfig>();
|
| | | AddAsyncTask<OSRedAchieveConfig>();
|
| | | AddAsyncTask<RedPackConfig>();
|
| | | AddAsyncTask<TreasureFindHostConfig>();
|
| | | AddAsyncTask<TreasureUpConfig>();
|
| | | AddAsyncTask<TreasurePrivilegeConfig>();
|
| | | AddAsyncTask<CTGConfig>();
|
| | | AddAsyncTask<MapResourcesConfig>();
|
| | | AddAsyncTask<FightPowerParamConfig>();
|
| | | AddAsyncTask<LoadingFunctionConfig>();
|
| | | AddAsyncTask<LoginAdConfig>();
|
| | | AddAsyncTask<FreeGoodsConfig>();
|
| | | AddAsyncTask<BossRebornConfig>();
|
| | | AddAsyncTask<UniquenessArriveConfig>();
|
| | | AddAsyncTask<AllPeoplePartyConfig>();
|
| | | AddAsyncTask<AllPeoplePartyAwardConfig>();
|
| | | AddAsyncTask<OrderInfoConfig>();
|
| | | AddAsyncTask<TrialExchangeConfig>();
|
| | |
|
| | | 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 <= 7 ? 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<NPCConfig>(AssetPath.ResourceOut);
|
| | | StartSyncTask<ModelResConfig>(AssetPath.ResourceOut);
|
| | | StartSyncTask<ActorShowConfig>(AssetPath.ResourceOut);
|
| | | StartSyncTask<IconConfig>(AssetPath.ResourceOut);
|
| | | StartSyncTask<SysInfoConfig>(AssetPath.ResourceOut);
|
| | | StartSyncTask<LanguageConfig>(AssetPath.ResourceOut);
|
| | | }
|
| | |
|
| | | 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.5f * 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 50;
|
| | | default:
|
| | | return 1;
|
| | | }
|
| | | }
|
| | |
|
| | | int GetMaxWorkingTaskCount()
|
| | | {
|
| | | switch (Application.platform)
|
| | | {
|
| | | case RuntimePlatform.Android:
|
| | | if (DeviceUtility.cpu >= 4 && DeviceUtility.memory > 3.5f * 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 50;
|
| | | default:
|
| | | return 5;
|
| | | }
|
| | | }
|
| | |
|
| | | ConfigTask AddAsyncTask<T>() 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 = StringUtility.Contact(ResourcesPath.Instance.ExternalStorePath, "config/", fileName, ".bytes");
|
| | | }
|
| | |
|
| | | var task = new ConfigTask(typeof(T), AssetSource.refdataFromEditor ? AssetPath.ResourceOut : AssetPath.External, path);
|
| | | Action<ConfigTask> launch = (ConfigTask _task) => { ReadFile(_task, OnEndReadFile<T>); };
|
| | | task.launch = launch;
|
| | | configTasks.Add(task);
|
| | |
|
| | | return task;
|
| | | }
|
| | |
|
| | | void StartAsyncTask(ConfigTask _task)
|
| | | {
|
| | | _task.state = TaskState.Working;
|
| | | _task.launch(_task);
|
| | | }
|
| | |
|
| | | void ReadFile(ConfigTask _task, Action<ConfigTask> _callBack)
|
| | | {
|
| | | ThreadPool.QueueUserWorkItem(
|
| | | (object _obj) =>
|
| | | {
|
| | | string[] lines = null;
|
| | | StreamReader sr = null;
|
| | |
|
| | | try
|
| | | {
|
| | | if (_task.assetPath == AssetPath.ResourceOut)
|
| | | {
|
| | | lines = File.ReadAllLines(_task.filePath, Encoding.UTF8);
|
| | | }
|
| | | else if (_task.assetPath == AssetPath.External)
|
| | | {
|
| | | var tripleDESCryptoServiceProvider = new TripleDESCryptoServiceProvider();
|
| | | tripleDESCryptoServiceProvider.Key = Convert.FromBase64String(CustomKey);
|
| | | tripleDESCryptoServiceProvider.IV = Convert.FromBase64String(CustomIV);
|
| | | tripleDESCryptoServiceProvider.Mode = CipherMode.CBC;
|
| | | tripleDESCryptoServiceProvider.Padding = PaddingMode.PKCS7;
|
| | | var decryptor = tripleDESCryptoServiceProvider.CreateDecryptor();
|
| | |
|
| | | var expectedSteam = new FileStream(_task.filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
|
| | | var bytes = new byte[expectedSteam.Length];
|
| | | expectedSteam.Read(bytes, 0, bytes.Length);
|
| | | var tableMs = new MemoryStream(bytes);
|
| | |
|
| | | var crypS = new CryptoStream(tableMs, decryptor, CryptoStreamMode.Read);
|
| | | sr = new StreamReader(crypS, Encoding.UTF8);
|
| | | var content = sr.ReadToEnd();
|
| | |
|
| | | lines = content.Split(new string[] { "\r\n" }, StringSplitOptions.None);
|
| | | }
|
| | |
|
| | | _task.state = TaskState.ReadFileSuccess;
|
| | | }
|
| | | catch (Exception ex)
|
| | | {
|
| | | _task.state = TaskState.ReadFileFailure;
|
| | | DesignDebug.Log(ex);
|
| | | }
|
| | | finally
|
| | | {
|
| | | _task.contentLines = lines;
|
| | | if (_callBack != null)
|
| | | {
|
| | | _callBack(_task);
|
| | | }
|
| | | }
|
| | | }
|
| | | );
|
| | |
|
| | | }
|
| | |
|
| | | void AsyncParseConfig<T>(ConfigTask _task, Action<ConfigTask> _callBack) where T : ConfigBase, new()
|
| | | {
|
| | | ThreadPool.QueueUserWorkItem(
|
| | | (object _obj) =>
|
| | | {
|
| | | try
|
| | | {
|
| | | var count = 0;
|
| | |
|
| | | var container = _task.container as Dictionary<string, ConfigBase>;
|
| | | for (int i = 3; i < _task.contentLines.Length; i++)
|
| | | {
|
| | | var contents = _task.contentLines[i].Split(new string[] { "\t" }, StringSplitOptions.None);
|
| | | if (contents.Length <= 1)
|
| | | {
|
| | | continue;
|
| | | }
|
| | |
|
| | | var newConfig = new T();
|
| | | newConfig.SetRawContent(contents);
|
| | |
|
| | | newConfig.Parse();
|
| | | newConfig.PostProcess();
|
| | | if (newConfig is IConfigPostProcess)
|
| | | {
|
| | | (newConfig as IConfigPostProcess).OnConfigParseCompleted();
|
| | | }
|
| | |
|
| | | newConfig.parsed = true;
|
| | | container[contents[0]] = newConfig;
|
| | |
|
| | | count++;
|
| | | if (count >= 500)
|
| | | {
|
| | | count = 0;
|
| | | Thread.Sleep(30);
|
| | | }
|
| | | }
|
| | |
|
| | | _task.state = TaskState.ParseSuccess;
|
| | | }
|
| | | catch (Exception ex)
|
| | | {
|
| | | _task.state = TaskState.ParseFailure;
|
| | | DesignDebug.Log(ex);
|
| | | }
|
| | | finally
|
| | | {
|
| | | if (_callBack != null)
|
| | | {
|
| | | _callBack(_task);
|
| | | }
|
| | | }
|
| | | }
|
| | | );
|
| | | }
|
| | |
|
| | | private void OnEndReadFile<T>(ConfigTask _task) where T : ConfigBase, new()
|
| | | {
|
| | | if (isPlaying && _task.state == TaskState.ReadFileFailure)
|
| | | {
|
| | | ReadFile(_task, OnEndReadFile<T>);
|
| | | }
|
| | | else
|
| | | {
|
| | | _task.capacity = Mathf.Max(_task.contentLines.Length - 3, 0);
|
| | | _task.container = new Dictionary<string, ConfigBase>(_task.capacity);
|
| | | AsyncParseConfig<T>(_task, OnEndParse<T>);
|
| | | }
|
| | | }
|
| | |
|
| | | private void OnEndParse<T>(ConfigTask _task) where T : ConfigBase, new()
|
| | | {
|
| | | if (isPlaying && _task.state == TaskState.ParseFailure)
|
| | | {
|
| | | Debug.LogFormat("配置表解析失败:{0}", _task.taskName);
|
| | | ReadFile(_task, OnEndReadFile<T>);
|
| | | }
|
| | | }
|
| | |
|
| | | private void StartSyncTask<T>(AssetPath _assetPath) where T : ConfigBase, new()
|
| | | {
|
| | | var typeName = typeof(T).Name;
|
| | | var fileName = typeName.Substring(0, typeName.Length - 6);
|
| | | string[] lines = null;
|
| | | var path = string.Empty;
|
| | |
|
| | | switch (_assetPath)
|
| | | {
|
| | | case AssetPath.Resource:
|
| | | path = StringUtility.Contact("Config/", fileName);
|
| | | var textAsset = Resources.Load<TextAsset>(path);
|
| | | lines = textAsset.text.Split(new string[] { "\r\n" }, StringSplitOptions.None);
|
| | | break;
|
| | | case AssetPath.ResourceOut:
|
| | | path = StringUtility.Contact(ResourcesPath.CONFIG_FODLER, "/", fileName, ".txt");
|
| | | lines = File.ReadAllLines(path, Encoding.UTF8);
|
| | | break;
|
| | | case AssetPath.External:
|
| | | var assetVersion = AssetVersionUtility.GetAssetVersion(StringUtility.Contact("config/", fileName, ".bytes"));
|
| | | path = StringUtility.Contact(ResourcesPath.Instance.ExternalStorePath, assetVersion.relativePath);
|
| | |
|
| | | var provider = new TripleDESCryptoServiceProvider();
|
| | | provider.Key = Convert.FromBase64String(CustomKey);
|
| | | provider.IV = Convert.FromBase64String(CustomIV);
|
| | | provider.Mode = CipherMode.CBC;
|
| | | provider.Padding = PaddingMode.PKCS7;
|
| | | var decryptor = provider.CreateDecryptor();
|
| | |
|
| | | var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
|
| | | var bytes = new byte[fs.Length];
|
| | | fs.Read(bytes, 0, bytes.Length);
|
| | | var ms = new MemoryStream(bytes);
|
| | |
|
| | | var crypS = new CryptoStream(ms, decryptor, CryptoStreamMode.Read);
|
| | | var sr = new StreamReader(crypS, Encoding.UTF8);
|
| | | var content = sr.ReadToEnd();
|
| | | lines = content.Split(new string[] { "\r\n" }, StringSplitOptions.None);
|
| | |
|
| | | break;
|
| | | }
|
| | |
|
| | | var task = new ConfigTask(typeof(T), _assetPath, path);
|
| | | configTasks.Add(task);
|
| | |
|
| | | task.contentLines = lines;
|
| | | if (lines != null && lines.Length > 3)
|
| | | {
|
| | | var length = Mathf.Max(lines.Length - 3, 0);
|
| | | task.capacity = length;
|
| | | task.container = new Dictionary<string, ConfigBase>(length);
|
| | | task.state = TaskState.ReadFileSuccess;
|
| | | SyncParseConfig<T>(task);
|
| | | }
|
| | | else
|
| | | {
|
| | | task.state = TaskState.ReadFileFailure;
|
| | | }
|
| | | }
|
| | |
|
| | | private void SyncParseConfig<T>(ConfigTask _task) where T : ConfigBase, new()
|
| | | {
|
| | | try
|
| | | {
|
| | | for (int i = 3; i < _task.contentLines.Length; i++)
|
| | | {
|
| | | var contents = _task.contentLines[i].Split(new string[] { "\t" }, StringSplitOptions.None);
|
| | | if (contents.Length <= 1)
|
| | | {
|
| | | continue;
|
| | | }
|
| | |
|
| | | var newConfig = new T();
|
| | | newConfig.SetRawContent(contents);
|
| | |
|
| | | newConfig.Parse();
|
| | | newConfig.PostProcess();
|
| | |
|
| | | if (newConfig is IConfigPostProcess)
|
| | | {
|
| | | (newConfig as IConfigPostProcess).OnConfigParseCompleted();
|
| | | }
|
| | |
|
| | | newConfig.parsed = true;
|
| | |
|
| | | _task.container[contents[0]] = newConfig;
|
| | | }
|
| | | }
|
| | | catch (Exception ex)
|
| | | {
|
| | | DesignDebug.Log(ex);
|
| | | }
|
| | | finally
|
| | | {
|
| | | _task.state = TaskState.ParseSuccess;
|
| | | configDictionary[_task.token] = _task.container;
|
| | | }
|
| | |
|
| | | }
|
| | |
|
| | | public T GetTemplate<T>(string _dwTemplateID) where T : ConfigBase, new()
|
| | | {
|
| | | if (string.IsNullOrEmpty(_dwTemplateID))
|
| | | {
|
| | | return null;
|
| | | }
|
| | |
|
| | | var token = typeof(T).MetadataToken;
|
| | | if (configDictionary.ContainsKey(token) == false)
|
| | | {
|
| | | DesignDebug.LogErrorFormat("not find the config:{0}", token);
|
| | | return null;
|
| | | }
|
| | |
|
| | | ConfigBase config = null;
|
| | | var dic = configDictionary[token];
|
| | | if (!dic.ContainsKey(_dwTemplateID))
|
| | | {
|
| | | DesignDebug.LogFormat("not find the config:{0},<color=#ff0000ff>ID:{1}</color>", typeof(T).Name, _dwTemplateID);
|
| | | }
|
| | | else
|
| | | {
|
| | | config = dic[_dwTemplateID];
|
| | | }
|
| | |
|
| | | if (config != null && !config.parsed)
|
| | | {
|
| | | config.Parse();
|
| | | config.PostProcess();
|
| | | config.parsed = true;
|
| | | }
|
| | |
|
| | | return config as T;
|
| | | }
|
| | |
|
| | | public T GetTemplate<T>(int _dwTemplateID) where T : ConfigBase, new()
|
| | | {
|
| | | return GetTemplate<T>(_dwTemplateID.ToString());
|
| | | }
|
| | |
|
| | | public bool ContainKey<T>(int _id)
|
| | | {
|
| | | return ContainKey<T>(_id.ToString());
|
| | | }
|
| | |
|
| | | public bool ContainKey<T>(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<string> GetAllKeys<T>() where T : ConfigBase
|
| | | {
|
| | | var token = typeof(T).MetadataToken;
|
| | | if (!configDictionary.ContainsKey(token))
|
| | | {
|
| | | DesignDebug.LogErrorFormat("not find the dic of config: {0}", typeof(T).Name);
|
| | | return null;
|
| | | }
|
| | |
|
| | | var dicTemplate = configDictionary[token];
|
| | | return new List<string>(dicTemplate.Keys);
|
| | | }
|
| | |
|
| | | public List<T> GetAllValues<T>() where T : ConfigBase, new()
|
| | | {
|
| | | var token = typeof(T).MetadataToken;
|
| | | if (!configDictionary.ContainsKey(token))
|
| | | {
|
| | | DesignDebug.LogErrorFormat("not find the dic of config: {0}", typeof(T).Name);
|
| | | return null;
|
| | | }
|
| | |
|
| | | var configs = new List<T>();
|
| | | var dicTemplate = configDictionary[token];
|
| | | foreach (var value in dicTemplate.Values)
|
| | | {
|
| | | if (value != null && !value.parsed)
|
| | | {
|
| | | value.Parse();
|
| | | value.PostProcess();
|
| | | value.parsed = true;
|
| | | }
|
| | |
|
| | | configs.Add(value as T);
|
| | | }
|
| | |
|
| | | return configs;
|
| | | }
|
| | |
|
| | | class ConfigTask
|
| | | {
|
| | | public readonly Type type;
|
| | | public readonly int token;
|
| | | public readonly string taskName;
|
| | | public readonly AssetPath assetPath;
|
| | | public readonly string filePath;
|
| | |
|
| | | public Action<ConfigTask> launch;
|
| | | public int capacity = 0;
|
| | | public string[] contentLines;
|
| | | public Dictionary<string, ConfigBase> container;
|
| | | public TaskState state = TaskState.None;
|
| | |
|
| | | public ConfigTask(Type _type, AssetPath _assetPath, string _filePath)
|
| | | {
|
| | | type = _type;
|
| | | assetPath = _assetPath;
|
| | | taskName = type.Name;
|
| | | token = type.MetadataToken;
|
| | |
|
| | | filePath = _filePath;
|
| | | }
|
| | | }
|
| | |
|
| | | public enum TaskState
|
| | | {
|
| | | None = 0,
|
| | | Working = 1,
|
| | | ReadFileSuccess = 2,
|
| | | ReadFileFailure = 3,
|
| | | ParseFailure = 4,
|
| | | ParseSuccess = 5,
|
| | | }
|
| | |
|
| | | public enum AssetPath
|
| | | {
|
| | | Resource,
|
| | | ResourceOut,
|
| | | External,
|
| | | }
|
| | |
|
| | | private void OnApplicationOut()
|
| | | {
|
| | | isPlaying = false;
|
| | | }
|
| | |
|
| | | }
|