mirror of
https://github.com/Alex-Rachel/TEngine.git
synced 2025-08-14 16:51:28 +00:00
Loader
Loader
This commit is contained in:
@@ -22,5 +22,40 @@ namespace TEngine
|
||||
|
||||
public class LoadData
|
||||
{
|
||||
public UpdateType Type; //是否底包更新
|
||||
public UpdateStyle Style; //是否强制更新
|
||||
public UpdateNotice Notice;//是否提示
|
||||
public List<LoadResource> List;
|
||||
public List<LoadResource> All;
|
||||
}
|
||||
|
||||
public enum UpdateType
|
||||
{
|
||||
None = 0,
|
||||
PackageUpdate = 1, //底包更新
|
||||
ResourceUpdate = 2,//资源更新
|
||||
}
|
||||
|
||||
public enum UpdateStyle
|
||||
{
|
||||
None = 0,
|
||||
Froce = 1, //强制
|
||||
Optional = 2,//非强制
|
||||
}
|
||||
|
||||
public enum UpdateNotice
|
||||
{
|
||||
None = 0,
|
||||
Notice = 1, //提示
|
||||
NoNotice = 2,//非提示
|
||||
}
|
||||
|
||||
public enum VersionRequestErrorCode
|
||||
{
|
||||
Ok = 1,
|
||||
Error = 2,
|
||||
Invalid_Param = 3,
|
||||
Update_Process = 4,
|
||||
Patch_Not_Exist = 5
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
@@ -35,6 +37,9 @@ namespace TEngine
|
||||
private const int MaxTryCount = 3;
|
||||
private bool _connectBack;
|
||||
private bool _needUpdate = false;
|
||||
private LoadData _currentData;
|
||||
private UpdateType _currentType = UpdateType.None;
|
||||
private readonly string _downloadFilePath = FileSystem.ResourceRoot + "/";
|
||||
|
||||
public LoadMgr()
|
||||
{
|
||||
@@ -93,6 +98,244 @@ namespace TEngine
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var onlineParamStr = LoaderUtilities.HttpGet(OnlineParamUrl);
|
||||
var onlineParam = (Dictionary<string, object>)MiniJSON.Json.Deserialize(onlineParamStr);
|
||||
string onlineResVersion = onlineParam["resVersion"].ToString();
|
||||
TLogger.LogInfo($"onlineResVersion:{onlineResVersion}");
|
||||
LatestResId = onlineResVersion;
|
||||
var resListStr = LoaderUtilities.HttpGet(GetOnlineResListUrl(LatestResId) + "Md5CheckList.json");
|
||||
var resDic = (Dictionary<string, object>)MiniJSON.Json.Deserialize(resListStr);
|
||||
List<object> resList = (List<object>)resDic["target"];
|
||||
_connectBack = true;
|
||||
|
||||
OnHttpResponse(CreateLoadData(onlineParam, resList));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
StartGame();
|
||||
#else
|
||||
LoaderUtilities.DelayFun(RequestVersion, new WaitForSeconds(1f));
|
||||
#endif
|
||||
TLogger.LogError(e.Message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
internal void OnHttpResponse(LoadData formatData)
|
||||
{
|
||||
if (formatData == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//检测一下是不是本地存在该版本,如果存在就本地做回退,不需要走下载流程
|
||||
_currentData = formatData;
|
||||
var exitLocalVersion = _CheckLocalVersion(_currentData.List);
|
||||
if (exitLocalVersion)
|
||||
{
|
||||
_needUpdate = LatestResId != GameConfig.Instance.ResId;
|
||||
StartGame();
|
||||
return;
|
||||
}
|
||||
//检测一下本地是否存在资源,如果存在了就直接解压就行了,如果不存在还需要下载
|
||||
_currentData.List = _CheckLocalExitResource(_currentData.List);
|
||||
_currentType = _currentData.Type;
|
||||
|
||||
//TODO
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 本地检测,过滤掉本地存在了的资源
|
||||
/// </summary>
|
||||
/// <param name="res"></param>
|
||||
/// <returns></returns>
|
||||
private List<LoadResource> _CheckLocalExitResource(List<LoadResource> res)
|
||||
{
|
||||
var list = new List<LoadResource>();
|
||||
foreach (var item in res)
|
||||
{
|
||||
string resPath = _downloadFilePath + item.Url;
|
||||
if (File.Exists(resPath))
|
||||
{
|
||||
if (string.CompareOrdinal(LoaderUtilities.GetMd5Hash(resPath), item.Md5) == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
list.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
list.Add(item);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检测是否是版本回退了
|
||||
/// </summary>
|
||||
/// <param name="res"></param>
|
||||
/// <returns></returns>
|
||||
private bool _CheckLocalVersion(List<LoadResource> res)
|
||||
{
|
||||
foreach (var item in res)
|
||||
{
|
||||
string tempVersion = item.Url.Split('_')[1];
|
||||
if (!GameConfig.Instance.CheckLocalVersion(tempVersion))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void StartGame()
|
||||
{
|
||||
if (_startGameEvent != null)
|
||||
{
|
||||
_startGameEvent();
|
||||
}
|
||||
}
|
||||
|
||||
internal LoadData CreateLoadData(Dictionary<string, object> onlineParam, List<object> resList = null)
|
||||
{
|
||||
if (onlineParam == null)
|
||||
{
|
||||
|
||||
return null;
|
||||
}
|
||||
var data = new LoadData();
|
||||
var result = int.Parse("1");
|
||||
var versionStr = LoaderUtilities.HttpGet(GetOnlineResListUrl(LatestResId) + "version.json");
|
||||
var versionDic = (Dictionary<string, object>)MiniJSON.Json.Deserialize(versionStr);
|
||||
string version = versionDic["AppVersion"].ToString();
|
||||
switch (result)
|
||||
{
|
||||
case (int)VersionRequestErrorCode.Ok:
|
||||
{
|
||||
data.Type = UpdateType.ResourceUpdate;
|
||||
data.Style = UpdateStyle.Optional;
|
||||
data.Notice = UpdateNotice.Notice;
|
||||
|
||||
data.Type = (UpdateType)int.Parse(onlineParam["UpdateType"].ToString());
|
||||
|
||||
if (GameConfig.Instance.ResId == LatestResId)
|
||||
{
|
||||
TLogger.LogInfo("GameConfig.Instance.ResId 匹配,无需更新");
|
||||
data.Type = UpdateType.None;
|
||||
}
|
||||
if (data.Type != UpdateType.PackageUpdate)
|
||||
{
|
||||
data.Style = (UpdateStyle)int.Parse(onlineParam["UpdateStyle"].ToString());
|
||||
data.Notice = (UpdateNotice)int.Parse(onlineParam["UpdateNotice"].ToString());
|
||||
}
|
||||
data.List = new List<LoadResource>();
|
||||
data.All = new List<LoadResource>();
|
||||
|
||||
if (resList != null)
|
||||
{
|
||||
for (int i = 0; i < resList.Count; i++)
|
||||
{
|
||||
var item = (Dictionary<string, object>)resList[i];
|
||||
string fileName = item["fileName"].ToString();
|
||||
var itemTemp = new LoadResource
|
||||
{
|
||||
RemoteUrl = _onlineResListUrl + fileName,
|
||||
Md5 = item["md5"].ToString(),
|
||||
Size = (long)item["fileSize"],
|
||||
Url = fileName + "_" + LatestResId,
|
||||
};
|
||||
data.List.Add(itemTemp);
|
||||
data.All.Add(itemTemp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case (int)VersionRequestErrorCode.Patch_Not_Exist:
|
||||
LatestResId = string.Empty;
|
||||
#if UNITY_EDITOR_WIN || _DEVELOPMENT_BUILD_
|
||||
StartGame();
|
||||
#else
|
||||
//TODO
|
||||
#endif
|
||||
return null;
|
||||
default:
|
||||
|
||||
return null;
|
||||
}
|
||||
if (GameConfig.Instance.ResId == LatestResId)
|
||||
{
|
||||
TLogger.LogInfo($"GameConfig.Instance.ResId{GameConfig.Instance.ResId} == onlineResVersion{LatestResId}");
|
||||
}
|
||||
else
|
||||
{
|
||||
TLogger.LogInfo($"GameConfig.Instance.ResId{GameConfig.Instance.ResId} != onlineResVersion{LatestResId}");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
private string _resListUrl = string.Empty;
|
||||
private string _onlineParamUrl = string.Empty;
|
||||
internal const string Url = "http://1.12.241.46:8081/TXYXGame/";
|
||||
|
||||
internal string ResListUrl
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_resListUrl))
|
||||
{
|
||||
#if UNITY_EDITOR || UNITY_ANDROID
|
||||
_resListUrl = Url + "AssetBundles/Android/ver_" + GameConfig.Instance.ResId + "/";
|
||||
#elif UNITY_IOS || UNITY_IPHONE
|
||||
_resListUrl = Url + "AssetBundles/IOS/ver_" + GameConfig.Instance.ResId + "/";
|
||||
#elif UNITY_STANDALONE_WIN
|
||||
_resListUrl = Url + "AssetBundles/WIN/ver_" + GameConfig.Instance.ResId + "/";
|
||||
#endif
|
||||
}
|
||||
return _resListUrl;
|
||||
}
|
||||
}
|
||||
|
||||
private string _onlineResListUrl = string.Empty;
|
||||
internal string GetOnlineResListUrl(string onlineResId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(_onlineResListUrl))
|
||||
{
|
||||
#if UNITY_EDITOR || UNITY_ANDROID
|
||||
_onlineResListUrl = Url + "AssetBundles/Android/ver_" + onlineResId + "/";
|
||||
#elif UNITY_IOS || UNITY_IPHONE
|
||||
_onlineResListUrl = Url + "AssetBundles/IOS/ver_" + onlineResId + "/";
|
||||
#elif UNITY_STANDALONE_WIN
|
||||
_onlineResListUrl = Url + "AssetBundles/WIN/ver_" + onlineResId + "/";
|
||||
#endif
|
||||
}
|
||||
TLogger.LogInfo(_onlineResListUrl);
|
||||
return _onlineResListUrl;
|
||||
}
|
||||
|
||||
internal string OnlineParamUrl
|
||||
{
|
||||
get
|
||||
{
|
||||
if (string.IsNullOrEmpty(_onlineParamUrl))
|
||||
{
|
||||
#if UNITY_EDITOR || UNITY_ANDROID
|
||||
_onlineParamUrl = Url + "androidVer.json";
|
||||
#elif UNITY_IOS || UNITY_IPHONE
|
||||
_onlineParamUrl = Url + "iosVer.json";
|
||||
#elif UNITY_STANDALONE_WIN
|
||||
_onlineParamUrl = Url + "winVer.json";
|
||||
#endif
|
||||
}
|
||||
return _onlineParamUrl;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,10 +1,14 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TEngine
|
||||
{
|
||||
@@ -63,5 +67,327 @@ namespace TEngine
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
#region WebRequest
|
||||
|
||||
public class NetContent
|
||||
{
|
||||
public bool Statue;
|
||||
public bool Result;
|
||||
public string MsgContent;
|
||||
public byte[] data;
|
||||
public Action<bool, string> SuccessCallback;
|
||||
public Action<bool, string> ErrorCallback;
|
||||
|
||||
public void SetResult(bool result, string content)
|
||||
{
|
||||
Statue = true;
|
||||
Result = result;
|
||||
MsgContent = content;
|
||||
}
|
||||
|
||||
public void SetParam(byte[] param)
|
||||
{
|
||||
data = param;
|
||||
}
|
||||
|
||||
public void SetAction(Action<bool, string> success, Action<bool, string> faile)
|
||||
{
|
||||
SuccessCallback = success;
|
||||
ErrorCallback = faile;
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Statue = false;
|
||||
Result = false;
|
||||
MsgContent = "";
|
||||
}
|
||||
}
|
||||
|
||||
private static NetContent _msgContent = new NetContent();
|
||||
private static Coroutine _coroutine;
|
||||
private static HttpWebRequest webReq;
|
||||
|
||||
/// <summary>
|
||||
/// 网络请求
|
||||
/// </summary>
|
||||
/// <param name="postUrl"></param>
|
||||
/// <param name="paramData"></param>
|
||||
/// <param name="dataEncode"></param>
|
||||
/// <param name="msgId"></param>
|
||||
/// <param name="appid"></param>
|
||||
/// <param name="appSecret"></param>
|
||||
/// <param name="successCallback"></param>
|
||||
/// <param name="errorCallback"></param>
|
||||
public static void PostWebRequest(
|
||||
string postUrl,
|
||||
string paramData,
|
||||
Action<bool, string> successCallback = null,
|
||||
Action<bool, string> errorCallback = null
|
||||
)
|
||||
{
|
||||
TLogger.LogInfo($"TEngine.LoaderUtilities.PostWebRequest url:{postUrl},paramData:{paramData}");
|
||||
_msgContent.Clear();
|
||||
|
||||
byte[] byteArray = Encoding.UTF8.GetBytes(paramData);
|
||||
|
||||
if (webReq != null)
|
||||
{
|
||||
webReq.Abort();
|
||||
webReq = null;
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
webReq = (HttpWebRequest)WebRequest.Create(new Uri(postUrl));
|
||||
|
||||
webReq.Method = "POST";
|
||||
webReq.ContentType = "application/json";
|
||||
webReq.ContentLength = byteArray.Length;
|
||||
_msgContent.SetParam(byteArray);
|
||||
_msgContent.SetAction(successCallback, errorCallback);
|
||||
|
||||
var result = webReq.BeginGetRequestStream(RequestComplete, webReq);
|
||||
ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, TimeoutCallback, result, 2000, true);
|
||||
|
||||
if (_coroutine != null)
|
||||
{
|
||||
MonoManager.Instance.StopCoroutine(_coroutine);
|
||||
}
|
||||
_coroutine = MonoManager.Instance.StartCoroutine(_Response(_msgContent));
|
||||
}
|
||||
|
||||
private static IEnumerator _Response(NetContent content)
|
||||
{
|
||||
while (content.Statue == false)
|
||||
{
|
||||
yield return null;
|
||||
}
|
||||
|
||||
if (content.Result)
|
||||
{
|
||||
_msgContent.SuccessCallback?.Invoke(content.Result, content.MsgContent);
|
||||
}
|
||||
else
|
||||
{
|
||||
_msgContent.ErrorCallback?.Invoke(content.Result, "");
|
||||
}
|
||||
|
||||
if (_coroutine != null)
|
||||
{
|
||||
MonoManager.Instance.StopCoroutine(_coroutine);
|
||||
_coroutine = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void RequestComplete(IAsyncResult result)
|
||||
{
|
||||
if (result != null && result.IsCompleted)
|
||||
{
|
||||
var request = result.AsyncState as HttpWebRequest;
|
||||
try
|
||||
{
|
||||
Stream stream = request.EndGetRequestStream(result);
|
||||
stream.Write(_msgContent.data, 0, _msgContent.data.Length);
|
||||
stream.Close();
|
||||
stream.Dispose();
|
||||
var rspResult = webReq.BeginGetResponse(ResponseComplete, webReq);
|
||||
ThreadPool.RegisterWaitForSingleObject(rspResult.AsyncWaitHandle, TimeoutCallback, result, 2000, true);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_msgContent.SetResult(false, e.ToString());
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void ResponseComplete(IAsyncResult asyncResult)
|
||||
{
|
||||
HttpWebRequest request;
|
||||
HttpWebResponse response;
|
||||
StreamReader reader;
|
||||
Stream recive;
|
||||
|
||||
request = (asyncResult.AsyncState as HttpWebRequest);
|
||||
var res = request.EndGetResponse(asyncResult);
|
||||
response = res as HttpWebResponse;
|
||||
if (response != null && response.StatusCode == HttpStatusCode.OK)
|
||||
{
|
||||
recive = response.GetResponseStream();
|
||||
reader = new StreamReader(recive);
|
||||
try
|
||||
{
|
||||
string result = reader.ReadToEnd();
|
||||
_msgContent.SetResult(true, result);
|
||||
reader.Close();
|
||||
reader.Dispose();
|
||||
recive.Close();
|
||||
recive.Dispose();
|
||||
response.Close();
|
||||
request.Abort();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_msgContent.SetResult(false, e.ToString());
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (reader != null)
|
||||
{
|
||||
reader.Close();
|
||||
reader.Dispose();
|
||||
}
|
||||
|
||||
if (request != null)
|
||||
{
|
||||
reader.Dispose();
|
||||
}
|
||||
|
||||
if (response != null)
|
||||
{
|
||||
response.Close();
|
||||
}
|
||||
|
||||
if (request != null)
|
||||
{
|
||||
request.Abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (response == null)
|
||||
{
|
||||
_msgContent.SetResult(false, "HttpResponse:response is null");
|
||||
}
|
||||
else
|
||||
{
|
||||
_msgContent.SetResult(false, "HttpResponse:" + response.StatusCode.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void TimeoutCallback(object state, bool timedOut)
|
||||
{
|
||||
if (!timedOut) return;
|
||||
_msgContent.SetResult(false, "timeout");
|
||||
IAsyncResult result = state as IAsyncResult;
|
||||
if (result != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
Stream stream = webReq.EndGetRequestStream(result);
|
||||
stream.Close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
throw;
|
||||
}
|
||||
webReq.Abort();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 延迟执行
|
||||
/// </summary>
|
||||
/// <param name="callback"></param>
|
||||
/// <param name="time"></param>
|
||||
public static Coroutine DelayFun(Action callback, YieldInstruction time)
|
||||
{
|
||||
return MonoManager.Instance.StartCoroutine(DelayFunIEnumerator(callback, time));
|
||||
}
|
||||
|
||||
public static IEnumerator DelayFunIEnumerator(Action callback, YieldInstruction time)
|
||||
{
|
||||
yield return time;
|
||||
callback();
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 数据格式转换
|
||||
/// </summary>
|
||||
/// <param name="data">数据</param>
|
||||
/// <returns></returns>
|
||||
public static string FormatData(long data)
|
||||
{
|
||||
string result = "";
|
||||
if (data < 0)
|
||||
data = 0;
|
||||
|
||||
if (data > 1024 * 1024)
|
||||
{
|
||||
result = ((int)(data / (1024 * 1024))).ToString() + "MB";
|
||||
}
|
||||
else if (data > 1024)
|
||||
{
|
||||
result = ((int)(data / 1024)).ToString() + "KB";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = data + "B";
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取文件大小
|
||||
/// </summary>
|
||||
/// <param name="path">文件路径</param>
|
||||
/// <returns></returns>
|
||||
public static long GetFileSize(string path)
|
||||
{
|
||||
using (FileStream file = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
{
|
||||
return file.Length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GET请求与获取结果
|
||||
/// </summary>
|
||||
public static string HttpGet(string url, string postDataStr = "")
|
||||
{
|
||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url + (postDataStr == "" ? "" : "?") + postDataStr);
|
||||
request.Method = "GET";
|
||||
request.ContentType = "text/html;charset=UTF-8";
|
||||
|
||||
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||||
Stream myResponseStream = response.GetResponseStream();
|
||||
StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.UTF8);
|
||||
string retString = myStreamReader.ReadToEnd();
|
||||
myStreamReader.Close();
|
||||
myResponseStream.Close();
|
||||
|
||||
return retString;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// POST请求与获取结果
|
||||
/// </summary>
|
||||
public static string HttpPost(string url, string postDataStr)
|
||||
{
|
||||
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
|
||||
request.Method = "POST";
|
||||
request.ContentType = "application/x-www-form-urlencoded";
|
||||
request.ContentLength = postDataStr.Length;
|
||||
StreamWriter writer = new StreamWriter(request.GetRequestStream(), Encoding.ASCII);
|
||||
writer.Write(postDataStr);
|
||||
writer.Flush();
|
||||
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
|
||||
string encoding = response.ContentEncoding;
|
||||
if (encoding == null || encoding.Length < 1)
|
||||
{
|
||||
encoding = "UTF-8"; //默认编码
|
||||
}
|
||||
StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.GetEncoding(encoding));
|
||||
string retString = reader.ReadToEnd();
|
||||
return retString;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user