Forráskód Böngészése

Merge remote-tracking branch 'remotes/origin/xiaojie' into GFG

hexiaojie 8 hónapja
szülő
commit
fc301691f6

+ 3 - 0
GameClient/Assets/Game/HotUpdate/Data/PictureData.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 97b7831c03774810a31b64b80de3f7c8
+timeCreated: 1724753001

+ 316 - 0
GameClient/Assets/Game/HotUpdate/Data/PictureData/PictureDataManager.cs

@@ -0,0 +1,316 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using ET;
+using UnityEngine;
+using UnityEngine.Networking;
+
+namespace GFGGame
+{
+    public class PictureDataManager : SingletonBase<PictureDataManager>
+    {
+        //本地地址
+        private const string _loadUrl = "gfgpicture";
+
+        //正在操作的文件队列
+        private Queue<string> _queueOperateFileList = new Queue<string>();
+
+        /// <summary>
+        /// 所有照片的二进制
+        /// </summary>
+        private Dictionary<string, Texture2D> _allPicByteDic = new Dictionary<string, Texture2D>();
+
+        public async ETTask<Texture2D> GetPicNTexture(string tempUrl)
+        {
+            string fileNameKey = GetUrlFileName(tempUrl);
+            if (_allPicByteDic.TryGetValue(fileNameKey, out Texture2D texture2D))
+            {
+                // 可能存在
+                if (texture2D != null &&
+                    texture2D.width > 0 &&
+                    texture2D.height > 0 &&
+                    texture2D.GetPixels().Length > 0)
+                {
+                    // 检查纹理的格式是否支持
+                    if (texture2D.format == TextureFormat.RGBA32 ||
+                        texture2D.format == TextureFormat.RGB24)
+                    {
+                        // 纹理有效,可以正常显示
+                        return texture2D; // 或者转换为 NTexture 对象
+                    }
+                    else
+                    {
+                        Debug.LogError("Texture format is not supported.");
+                        // 处理不支持的纹理格式
+                        return await DownloadOrLoadPic(tempUrl);
+                    }
+                }
+                else
+                {
+                    Debug.LogWarning("Texture is invalid or has no pixels.");
+                    // 处理无效的纹理
+                    return await DownloadOrLoadPic(tempUrl);
+                }
+            }
+
+            //TODO 一定不存在, 需要去进行下载
+            return await DownloadOrLoadPic(tempUrl);
+        }
+
+        //从远端进行下载
+        public async ETTask<Texture2D> DownloadOrLoadPic(string tempUrl)
+        {
+            string fileName = GetUrlFileName(tempUrl);
+            Texture2D texture2D = await DownloadPictureAsync(tempUrl);
+            if (texture2D == null)
+            {
+                return GetDefaultTexture();
+            }
+
+            //不为null, 以协程的方式存储到内存以及, 本地
+
+            _allPicByteDic[fileName] = texture2D;
+            //加入队列
+            _queueOperateFileList.Enqueue(fileName);
+            SavaPicToLoad().Coroutine();
+
+            return texture2D;
+        }
+
+        //存储图片文件到本地,如果存在就进行删除本地或者覆盖,以当前的为最新的进行记录
+        public async ETTask SavaPicToLoad()
+        {
+            var tempList = _queueOperateFileList.ToList();
+
+            for (int i = 0; i < tempList.Count; i++)
+            {
+                if (_queueOperateFileList.Count == 0)
+                {
+                    break;
+                }
+
+                string fileName = _queueOperateFileList.Dequeue();
+                if (string.IsNullOrEmpty(fileName))
+                {
+                    continue;
+                }
+
+                if (!_allPicByteDic.TryGetValue(fileName, out Texture2D texture2D))
+                {
+                    continue;
+                }
+
+                if (texture2D == null)
+                {
+                    continue;
+                }
+
+                // 获取本地存储路径
+                string localPath = Path.Combine(Application.persistentDataPath, fileName);
+
+                // 存储图片文件到本地
+                try
+                {
+                    // 将 Texture2D 转换为字节数组
+                    byte[] imageData = texture2D.EncodeToPNG();
+
+                    // 如果文件已经存在,则覆盖
+                    if (File.Exists(localPath))
+                    {
+                        File.Delete(localPath);
+                    }
+
+                    // 将字节数组写入文件
+                    File.WriteAllBytes(localPath, imageData);
+                }
+                catch (Exception ex)
+                {
+                    Debug.LogError($"Failed to save image to local path: {ex.Message}");
+                }
+            }
+
+            await ETTask.CompletedTask;
+        }
+
+        private async ETTask<Texture2D> DownloadPictureAsync(string tempUrl, int count = 0)
+        {
+            string fileName = GetUrlFileName(tempUrl);
+            
+            if (count >= 3)
+            {
+                PromptController.Instance.ShowFloatTextPrompt("下载失败");
+                ViewManager.Hide<ModalStatusView>();
+                return null;
+            }
+
+            using (UnityWebRequest request = UnityWebRequestTexture.GetTexture(tempUrl))
+            {
+                var asyncOperation = request.SendWebRequest();
+
+                while (!asyncOperation.isDone)
+                {
+                    await TimerComponent.Instance.WaitTillAsync(100); // 等待一段时间后继续检查
+                }
+
+                if (request.result == UnityWebRequest.Result.ProtocolError ||
+                    request.result == UnityWebRequest.Result.ConnectionError)
+                {
+                    count += 1;
+                    return await DownloadPictureAsync(tempUrl, count); // 递归重试
+                }
+                else
+                {
+                    Texture2D texture = (request.downloadHandler as DownloadHandlerTexture).texture;
+                    return texture;
+                }
+            }
+        }
+
+        // 获取存储文件的完整路径
+        public static string GetFilePath(string fileName)
+        {
+            // 获取持久化数据路径
+            string persistentDataPath = Application.persistentDataPath;
+
+            // 创建“zhaoPian”文件夹路径
+            string folderPath = Path.Combine(persistentDataPath, _loadUrl);
+
+            // 确保文件夹存在
+            if (!Directory.Exists(folderPath))
+            {
+                Directory.CreateDirectory(folderPath);
+            }
+
+            // 返回文件的完整路径
+            return Path.Combine(folderPath, fileName);
+        }
+
+        /// <summary>
+        /// 获取下载地址的文件名, 包含后缀 TODO 需要增加容错
+        /// </summary>
+        /// <param name="url"></param>
+        /// <returns></returns>
+        public static string GetUrlFileName(string url)
+        {
+            // 创建一个 Uri 对象
+            Uri uri = new Uri(url);
+
+            // 获取 URL 的路径部分
+            string path = uri.AbsolutePath;
+
+            // 从路径中提取文件名
+            string fileName = System.IO.Path.GetFileName(path);
+
+            // // 获取不包含扩展名的文件名
+            // string fileNameWithoutExtension = System.IO.Path.GetFileNameWithoutExtension(fileName);
+
+            return fileName;
+        }
+
+        //TODO 默认纹理, 让客户端来修改这个代码, 定义一个默认的 Texture2D
+        private Texture2D GetDefaultTexture()
+        {
+            // 创建一个简单的默认图片,比如纯色或空白图片
+            Texture2D defaultTexture = new Texture2D(2, 2);
+            Color[] pixels = defaultTexture.GetPixels();
+            for (int i = 0; i < pixels.Length; i++)
+            {
+                pixels[i] = Color.gray; // 设置为灰色的默认图片
+            }
+
+            defaultTexture.SetPixels(pixels);
+            defaultTexture.Apply();
+
+            return defaultTexture;
+        }
+
+        //初始化的时候根据图片保存时间, 加载最多50条到内存中
+        public void LoadAllImages()
+        {
+            // 获取文件夹路径
+            string folderPath = Path.Combine(Application.persistentDataPath, _loadUrl);
+
+            // 检查文件夹是否存在
+            if (Directory.Exists(folderPath))
+            {
+                // 获取所有图片文件路径(假设图片格式为.jpg和.png)
+                string[] imageFiles = Directory.GetFiles(folderPath, "*.*", SearchOption.TopDirectoryOnly);
+
+                // 过滤出图片文件,并按修改时间排序
+                var imageFileInfos = imageFiles
+                    .Where(filePath => filePath.EndsWith(".jpg") || filePath.EndsWith(".png"))
+                    .Select(filePath => new FileInfo(filePath))
+                    .OrderByDescending(fileInfo => fileInfo.LastWriteTime)
+                    .ToList();
+
+                int loadedCount = 0;
+                const int maxImagesToLoad = 50;
+
+                foreach (var fileInfo in imageFileInfos)
+                {
+                    string filePath = fileInfo.FullName;
+
+                    try
+                    {
+                        // 读取图片数据
+                        byte[] imageData = File.ReadAllBytes(filePath);
+
+                        // 创建纹理并加载数据
+                        Texture2D texture = new Texture2D(2, 2); // 创建一个2x2的空纹理
+                        if (texture.LoadImage(imageData))
+                        {
+                            // 提取文件名作为字典的键
+                            string fileName = Path.GetFileName(filePath);
+
+                            // 将纹理添加到字典
+                            _allPicByteDic[fileName] = texture;
+
+                            Debug.Log($"Loaded {fileName}");
+
+                            loadedCount++;
+
+                            // 如果已经加载了最大数量的图片,停止加载并删除剩余较旧的图片
+                            if (loadedCount >= maxImagesToLoad)
+                            {
+                                DeleteOldImages(imageFileInfos, loadedCount);
+                                return;
+                            }
+                        }
+                        else
+                        {
+                            Debug.LogWarning($"Failed to load image from {filePath}");
+                        }
+                    }
+                    catch
+                    {
+                        Debug.LogWarning($"Error processing file: {filePath}");
+                    }
+                }
+            }
+            else
+            {
+                Debug.LogWarning($"Folder not found: {folderPath}");
+            }
+        }
+
+        // 删除较旧的图片
+        private void DeleteOldImages(List<FileInfo> imageFileInfos, int loadedCount)
+        {
+            // 从已经加载的图片后面开始删除
+            for (int i = loadedCount; i < imageFileInfos.Count; i++)
+            {
+                string filePath = imageFileInfos[i].FullName;
+                try
+                {
+                    File.Delete(filePath);
+                    Debug.Log($"Deleted {filePath}");
+                }
+                catch (Exception ex)
+                {
+                    Debug.LogWarning($"Failed to delete {filePath}: {ex.Message}");
+                }
+            }
+        }
+    }
+}

+ 3 - 0
GameClient/Assets/Game/HotUpdate/Data/PictureData/PictureDataManager.cs.meta

@@ -0,0 +1,3 @@
+fileFormatVersion: 2
+guid: 5abcca2f48ca42e0a71ce2eba52c14a0
+timeCreated: 1724745176