using AX.MessageSystem; using AX.NetworkSystem; using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Xml; using UnityEngine; using UnityEngine.SceneManagement; public class UpdateManager : MonoBehaviour { private static UpdateManager instance; public static UpdateManager Instance { get { return instance; } } public DisasterInfo selectedMsg; //被选中的灾情信息 private string serverDirectoryPath;//服务端文件存储文件夹 private string localDirectoryPath;//本地文件存储文件夹 private string tempDirectoryPath; //下载下来的配置文件暂存文件夹//单机版注释掉 private string serverFileXml;//服务端文件版本配置 private string localTempXml; //本地临时配置文件路径 private string localFileXml;//本地文件版本配置 private List fileList = new List(); //需要更新的文件列表 private List delList = new List(); //需要删除的文件列表 private int updateCount; private bool[] completedList; private float[] progressList; public bool isEdit = false; public UpdateState state; private void Awake() { instance = this; selectedMsg = new DisasterInfo(); } /// /// 进入编辑模式 /// public void Edit() { state = UpdateState.Edit; DisasterManager.disaster = selectedMsg; initPath(); downLoadFileVersion();//单机版注释 //versionUpdateOnCompleted();//联机版取消注释 } public void Edit(DisasterInfo info) { selectedMsg = info; DisasterManager.disaster = selectedMsg; state = UpdateState.Edit; initPath(); downLoadFileVersion();//单机版注释 //versionUpdateOnCompleted(); } /// /// 进入查看模式 //单机版注释 /// public void View() { state = UpdateState.View; DisasterManager.disaster = selectedMsg; initPath(); downLoadFileVersion();//单机版注释 //versionUpdateOnCompleted(); } /// /// 进入主场景之前先更新 //单机版注释 /// private void UpdateBeforeContinue() { foreach(string key in delList) { File.Delete(localDirectoryPath + key); } progressList = new float[fileList.Count]; completedList = new bool[fileList.Count]; UpdateResources(); } /// /// 不更新直接进入主场景 /// private void ContinueWithoutUpdate() { if (File.Exists(localTempXml)) { //删除临时配置文件 File.Delete(localTempXml); } DisasterManager.updateFlag = true; switch (state) { case UpdateState.None: break; case UpdateState.Edit: //编辑 DisasterManager.model = PlayModel.editor; break; case UpdateState.View: //查看 DisasterManager.model = PlayModel.view; break; case UpdateState.MainSceneUpdate: break; default: break; } //进入主场景 SceneManager.LoadScene("MainScene_New"); } //单机版注释掉 public void MainSceneUpdateDisaster() { state = UpdateState.MainSceneUpdate; //先更新 initPath(); downLoadFileVersion(); } /// /// 文件路径初始化 /// private void initPath() { fileList = new List(); serverDirectoryPath = selectedMsg.Id.ToString() + "/File/"; //服务器相对路径 localDirectoryPath = Application.dataPath + "/Data/" + selectedMsg.Id.ToString() + "/File/"; //本地路径 tempDirectoryPath = Application.dataPath + "/Temp/" + selectedMsg.Id.ToString() + "/"; //本地临时路径 //单机版注释 //如果本地没有该灾情的文件夹,先创建 if (!Directory.Exists(localDirectoryPath)) { Directory.CreateDirectory(localDirectoryPath); } //如果本地没有临时路径,先创建 //单机版注释 if (!Directory.Exists(tempDirectoryPath)) { Directory.CreateDirectory(tempDirectoryPath); } serverFileXml = selectedMsg.Id.ToString() + "/" + selectedMsg.Id.ToString() + ".xml"; //服务器配置文件 localTempXml = Application.dataPath + "/Temp/" + selectedMsg.Id.ToString() + ".xml"; //本地临时配置文件 localFileXml = Application.dataPath + "/Data/" + selectedMsg.Id.ToString() + "/" + selectedMsg.Id.ToString() + ".xml"; //本地配置文件 } /// /// 下载最新的文件配置文档 //单机版注释 /// private void downLoadFileVersion() { NetworkManager.Default.DownloadFileAsync(localTempXml, serverFileXml , null, OnDownloadProgress, OnFileVersionCompleted); } private void OnDownloadProgress(string arg1, string arg2, float progress) { if (progress < 100) { ResourceLoadWindow.Instance.LoadTextHintWindow("正在更新...", 0.5f); } } //单机版注释掉该方法 private void OnFileVersionCompleted(string localTempXml, string serverFileXml) { if (!File.Exists(localFileXml)) { CreateMD5Tool.Instance.CreateManifestXml(localDirectoryPath, localFileXml); } //获取本地的HashID Dictionary localHashID = getMainFileVersion(localFileXml); //获取最新的HashID Dictionary serverHashID = getMainFileVersion(localTempXml); foreach (string key in serverHashID.Keys) { //1、先判断本地资源列表是否存在,若不存在则属于新资源 if (!localHashID.ContainsKey(key)) { fileList.Add(key); } else { //2、再判断HashID是否相等,若不等则属于新资源 string hash = serverHashID[key]; if (localHashID[key] != serverHashID[key]) { fileList.Add(key); } } } foreach(string key in localHashID.Keys) { //如果本地有但服务端没有,则删除该资源 if (!serverHashID.ContainsKey(key)) { //File.Delete(localDirectoryPath + key); delList.Add(key); } } if (fileList.Count > 0 || delList.Count > 0) { switch (state) { case UpdateState.None: break; case UpdateState.Edit: ResourceLoadWindow.Instance.LoadUpdateTipWindow("本地与服务端内容不一致,是否更新?", UpdateBeforeContinue, ContinueWithoutUpdate); break; case UpdateState.View: ResourceLoadWindow.Instance.LoadUpdateTipWindow("本地与服务端内容不一致,是否更新?", UpdateBeforeContinue, ContinueWithoutUpdate); break; case UpdateState.MainSceneUpdate: UpdateBeforeContinue(); break; default: break; } } else { //将本地临时配置文件替换原有配置文件 FileMove(localTempXml, localFileXml); //更新完成 versionUpdateOnCompleted(); } } /// /// 更新完成 /// private void versionUpdateOnCompleted() { switch (state) { case UpdateState.None: break; case UpdateState.Edit: DisasterManager.model = PlayModel.editor; SceneManager.LoadScene("MainScene_New"); break; case UpdateState.View: DisasterManager.model = PlayModel.view; SceneManager.LoadScene("MainScene_New"); break; case UpdateState.MainSceneUpdate: Debug.Log("灾情更新完成"); MessageDispatcher.SendMessage("DisasterUpdateCompelete"); //单机版注释 break; default: break; } } /// /// 文件下载更新 单机版注释 /// private void UpdateResources() { updateCount = 0; for (int i = 0; i < fileList.Count; i++) { // Debug.Log("#########################第" + i + "个文件开始下载"); var fullPath = tempDirectoryPath + fileList[i]; //本地临时路径 var filePath = serverDirectoryPath + fileList[i]; //服务器相对路径 checkDirectory(fullPath); NetworkManager.Default.DownloadFileAsync(fullPath, filePath, null, OnDownloadProgress, OnCompleted); } } private void checkDirectory(string path) { string directoryName = Path.GetDirectoryName(path); if (!Directory.Exists(directoryName) && directoryName != "") { Directory.CreateDirectory(directoryName); } } //单机版注释 private void OnCompleted(string fullname,string filename) { updateCount++; var fileName = filename.Replace(serverDirectoryPath, string.Empty); var targetFile = localDirectoryPath + fileName; //将临时文件替换原有文件 FileMove(fullname, targetFile); int index = fileList.IndexOf(fileName); completedList[index] = true; Debug.Log("*************************第" + index + "个文件下载完成"); //所有文件更新完成 if (updateCount == fileList.Count) { Directory.Delete(tempDirectoryPath, true); //将本地临时配置文件替换原有配置文件 FileMove(localTempXml, localFileXml); versionUpdateOnCompleted(); } } /// /// 文件移动 /// /// /// private void FileMove(string sourceFile, string targetFile) { if (File.Exists(targetFile)) { File.Delete(targetFile); } else { string directoryName = Path.GetDirectoryName(targetFile); if (!Directory.Exists(directoryName) && directoryName != "") { Directory.CreateDirectory(directoryName); } } try { File.Move(sourceFile, targetFile); } catch (Exception exception) { Debug.LogError(exception.Message); } } private void createLocalFileXml(string path) { XmlDocument document = new XmlDocument(); XmlDeclaration xmldecl = document.CreateXmlDeclaration("1.0", "UTF-8", "yes"); document.AppendChild(xmldecl); XmlElement newChild = document.CreateElement("Files"); document.AppendChild(newChild); document.Save(path); newChild = null; document = null; } /// /// 获取xml文件版本信息 /// /// /// private Dictionary getMainFileVersion(string path) { Dictionary fileHashID = new Dictionary(); XmlDocument document = new XmlDocument(); document.Load(path); XmlNodeList nodeList = document.SelectSingleNode("Files").ChildNodes; foreach (XmlElement fileNode in nodeList) { var fileName = fileNode.GetAttribute("FileName"); var fileHash = fileNode.GetAttribute("Hash"); fileHashID.Add(fileName, fileHash); } document = null; return fileHashID; } } public enum UpdateState { None, /// /// 编辑灾情 /// Edit, /// /// 查看灾情 /// View, /// /// 主场景内更新灾情 /// MainSceneUpdate }