using System.Collections;
|
using System.Collections.Generic;
|
using UnityEngine;
|
using System;
|
using Snxxz.UI;
|
using System.Text.RegularExpressions;
|
|
[XLua.LuaCallCSharp]
|
public class InGameDownLoad : SingletonMonobehaviour<InGameDownLoad>
|
{
|
public const int BYTE_PER_KILOBYTE = 1024;
|
public const int BYTE_PER_MILLIONBYTE = 1048576;
|
|
List<RemoteFile> workingQueue = new List<RemoteFile>();
|
List<AssetVersion> tasks = new List<AssetVersion>();
|
Dictionary<int, List<AssetVersion>> mapTasks = new Dictionary<int, List<AssetVersion>>();
|
|
public bool inGameDownLoadAllow = false;
|
|
public float progress {
|
get {
|
return Mathf.Clamp01((float)showDownLoadedSize / showTotalSize);
|
}
|
}
|
|
public bool isDone { get { return state == State.Completed; } }
|
public long showDownLoadedSize { get { return downLoadedSizeRecord + RemoteFile.TotalDownloadedSize - backGroundDownLoadSizeRecord; } }
|
public long showTotalSize { get { return totalSize - backGroundDownLoadSizeRecord; } }
|
public int showTotalCount { get { return totalCount - downLoadedCountRecord; } }
|
public int showOkCount { get { return okCount - downLoadedCountRecord; } }
|
|
long totalSize = 0;
|
int totalCount = 0;
|
|
int m_OkCount = 0;
|
int okCount {
|
get { return m_OkCount; }
|
set {
|
m_OkCount = value;
|
}
|
}
|
|
long backGroundDownLoadSizeRecord = 0;//后台偷偷已经下载到资源量
|
long downLoadedSizeRecord = 0;//记录上次暂停时记录的下载量
|
int downLoadedCountRecord = 0;//已经下载完成的资源包数量
|
|
public event Action<State> downLoadStateChangeEvent;
|
public event Action<Dominant> dominantDownLoadEvent;
|
|
Action onDownLoadOk;
|
|
Dominant m_DominantState = Dominant.None;
|
public Dominant dominantState {
|
get { return m_DominantState; }
|
private set {
|
if (m_DominantState != value)
|
{
|
m_DominantState = value;
|
if (dominantDownLoadEvent != null)
|
{
|
dominantDownLoadEvent(m_DominantState);
|
}
|
}
|
}
|
}
|
|
State m_State = State.None;
|
public State state {
|
get { return m_State; }
|
set {
|
if (m_State != value)
|
{
|
m_State = value;
|
|
if (downLoadStateChangeEvent != null)
|
{
|
downLoadStateChangeEvent(m_State);
|
}
|
}
|
}
|
}
|
|
int maxWorkingTask = 2;
|
|
TaskModel taskModel { get { return ModelCenter.Instance.GetModel<TaskModel>(); } }
|
|
public List<Reward> rewards = new List<Reward>();
|
public bool hasReward { get; private set; }
|
public string completeDownLoadAccount {
|
get { return LocalSave.GetString("InGameDownLoadCompleteAccount"); }
|
set { LocalSave.SetString("InGameDownLoadCompleteAccount", value); }
|
}
|
|
public Redpoint downLoadRedpoint = new Redpoint(116);
|
|
public void AssignTasks(List<AssetVersion> _tasks, Action _onDownLoadOk)
|
{
|
inGameDownLoadAllow = false;
|
tasks = _tasks;
|
tasks.Sort(AssetDownLoadPriorCompare);
|
onDownLoadOk = _onDownLoadOk;
|
|
totalCount = tasks.Count;
|
okCount = 0;
|
totalSize = 0;
|
|
for (int i = 0; i < tasks.Count; i++)
|
{
|
var task = tasks[i];
|
totalSize += task.size;
|
}
|
|
for (var i = 0; i < tasks.Count; i++)
|
{
|
var assetVersion = tasks[i];
|
var mapId = PriorBundleConfig.GetAssetBelongToMap(assetVersion.GetAssetCategory(), assetVersion.fileName);
|
if (mapId != 0)
|
{
|
if (!mapTasks.ContainsKey(mapId))
|
{
|
mapTasks[mapId] = new List<AssetVersion>();
|
}
|
mapTasks[mapId].Add(assetVersion);
|
}
|
}
|
|
state = State.None;
|
|
TaskModel.Event_MainlineTask -= OnMainTaskChange;
|
TaskModel.Event_MainlineTask += OnMainTaskChange;
|
|
PlayerDatas.Instance.playerDataRefreshEvent -= OnPlayerLevelChange;
|
PlayerDatas.Instance.playerDataRefreshEvent += OnPlayerLevelChange;
|
}
|
|
public void ParseRewardConfig()
|
{
|
var rewardString = FuncConfigConfig.Get("DownReward").Numerical1;
|
var matches = Regex.Matches(rewardString, "(\\d+,\\d+,\\d+)");
|
for (int i = 0; i < matches.Count; i++)
|
{
|
rewards.Add(new Reward(matches[i].Value));
|
}
|
}
|
|
public void UpdateRewardInfo(HA319_tagMCPackDownloadRecord _package)
|
{
|
hasReward = _package.Record == 1;
|
|
if (AssetVersionUtility.unPriorAssetDownLoadDone)
|
{
|
state = !hasReward && completeDownLoadAccount == PlayerDatas.Instance.baseData.AccID ? State.Award : State.Completed;
|
}
|
|
downLoadRedpoint.state = state == State.Award ? RedPointState.Simple : RedPointState.None;
|
}
|
|
public void RequestDownLoadReward(bool _manual)
|
{
|
var send = new CA504_tagCMPlayerGetReward();
|
send.RewardType = 15;
|
send.DataEx = (byte)(_manual ? 0 : 1);
|
GameNetSystem.Instance.SendInfo(send);
|
}
|
|
public float GetMapAssetDownLoadProgress(int mapId)
|
{
|
if (!mapTasks.ContainsKey(mapId))
|
{
|
return 1f;
|
}
|
|
var tasks = mapTasks[mapId];
|
var total = tasks.Count;
|
if (total == 0)
|
{
|
return 1f;
|
}
|
|
var completeCount = 0;
|
foreach (var task in tasks)
|
{
|
if (task.localValid)
|
{
|
completeCount++;
|
}
|
}
|
|
return completeCount / (float)total;
|
}
|
|
int mapId = 0;
|
Action mapAssetDownLoadOk;
|
public void RegisterMapAssetDownLoadOk(int mapId, Action callBack)
|
{
|
var progress = GetMapAssetDownLoadProgress(mapId);
|
if (progress < 0.999f)
|
{
|
this.mapId = mapId;
|
mapAssetDownLoadOk = callBack;
|
}
|
}
|
|
public void UnRegisterMapAssetDownLoadOk()
|
{
|
this.mapId = 0;
|
mapAssetDownLoadOk = null;
|
}
|
|
public void TryDownLoad(Dominant _dominant)
|
{
|
if (!inGameDownLoadAllow)
|
{
|
return;
|
}
|
|
if (tasks == null || tasks.Count == 0 || isDone)
|
{
|
return;
|
}
|
|
if (_dominant < dominantState)
|
{
|
return;
|
}
|
|
switch (_dominant)
|
{
|
case Dominant.None:
|
if (InGameDownTestUtility.enable)
|
{
|
if (InGameDownTestUtility.isWifi)
|
{
|
StartDownLoad();
|
}
|
}
|
else
|
{
|
if (Application.internetReachability == NetworkReachability.ReachableViaLocalAreaNetwork)
|
{
|
StartDownLoad();
|
}
|
}
|
break;
|
case Dominant.Half:
|
if (dominantState == Dominant.None)
|
{
|
backGroundDownLoadSizeRecord = RemoteFile.TotalDownloadedSize;
|
downLoadedCountRecord = okCount;
|
}
|
StartDownLoad();
|
dominantState = Dominant.Half;
|
break;
|
case Dominant.Whole:
|
if (dominantState == Dominant.None)
|
{
|
backGroundDownLoadSizeRecord = RemoteFile.TotalDownloadedSize;
|
downLoadedCountRecord = okCount;
|
Pause();
|
state = State.Prepared;
|
}
|
else if (dominantState == Dominant.Half)
|
{
|
Pause();
|
state = State.Prepared;
|
}
|
|
dominantState = Dominant.Whole;
|
WindowCenter.Instance.Open<InGameDownLoadWin>();
|
break;
|
}
|
|
}
|
|
public void StartDownLoad()
|
{
|
if (state == State.None || state == State.Prepared || state == State.Pause)
|
{
|
state = State.DownLoad;
|
RemoteFile.maxDownLoadTask = 2;
|
RemoteFile.MaxConnectLimit = 12;
|
StartCoroutine("Co_StartDownLoad");
|
}
|
}
|
|
public void Pause()
|
{
|
if (state == State.DownLoad)
|
{
|
StopCoroutine("Co_StartDownLoad");
|
foreach (var remoteFile in workingQueue)
|
{
|
remoteFile.Stop();
|
}
|
workingQueue.Clear();
|
RemoteFile.maxDownLoadTask = 0;
|
RemoteFile.MaxConnectLimit = 0;
|
state = State.Pause;
|
}
|
}
|
|
IEnumerator Co_StartDownLoad()
|
{
|
downLoadedSizeRecord += RemoteFile.TotalDownloadedSize;
|
RemoteFile.Prepare();
|
workingQueue.Clear();
|
okCount = 0;
|
|
var downLoadTasksQueues = new Queue<AssetVersion>();
|
|
for (int i = 0; i < tasks.Count; i++)
|
{
|
var assetVersion = tasks[i];
|
if (!assetVersion.localValid)
|
{
|
downLoadTasksQueues.Enqueue(assetVersion);
|
}
|
else
|
{
|
okCount++;
|
}
|
}
|
|
while (okCount < totalCount)
|
{
|
while (workingQueue.Count < maxWorkingTask && downLoadTasksQueues.Count > 0)
|
{
|
var assetVersion = downLoadTasksQueues.Dequeue();
|
var remoteURL = StringUtility.Contact(VersionUtility.Instance.versionInfo.GetResourcesURL(VersionConfig.Get().branch), "/", assetVersion.relativePath);
|
var localURL = StringUtility.Contact(ResourcesPath.Instance.ExternalStorePath, assetVersion.relativePath);
|
|
var remoteFile = new RemoteFile();
|
workingQueue.Add(remoteFile);
|
remoteFile.Init(remoteURL, localURL, assetVersion, true);
|
remoteFile.Begin(OnFileDownLoadCompleted);
|
}
|
yield return null;
|
}
|
|
TaskModel.Event_MainlineTask -= OnMainTaskChange;
|
PlayerDatas.Instance.playerDataRefreshEvent -= OnPlayerLevelChange;
|
|
WindowCenter.Instance.Close<InGameDownLoadWin>();
|
|
if (!hasReward)
|
{
|
if (dominantState == Dominant.None)
|
{
|
RequestDownLoadReward(false);
|
state = State.Completed;
|
}
|
else
|
{
|
completeDownLoadAccount = PlayerDatas.Instance.baseData.AccID;
|
state = State.Award;
|
}
|
}
|
else
|
{
|
state = State.Completed;
|
}
|
|
downLoadRedpoint.state = state == State.Award ? RedPointState.Simple : RedPointState.None;
|
|
if (onDownLoadOk != null)
|
{
|
onDownLoadOk();
|
onDownLoadOk = null;
|
}
|
}
|
|
private void OnFileDownLoadCompleted(bool _ok, AssetVersion _assetVersion)
|
{
|
foreach (var remote in workingQueue)
|
{
|
if (remote.assetVersion == _assetVersion)
|
{
|
workingQueue.Remove(remote);
|
break;
|
}
|
}
|
|
if (_ok)
|
{
|
okCount++;
|
_assetVersion.localValid = true;
|
}
|
else
|
{
|
var remoteURL = StringUtility.Contact(VersionUtility.Instance.versionInfo.GetResourcesURL(VersionConfig.Get().branch), "/", _assetVersion.relativePath);
|
var localURL = StringUtility.Contact(ResourcesPath.Instance.ExternalStorePath, _assetVersion.relativePath);
|
|
var remoteFile = new RemoteFile();
|
workingQueue.Add(remoteFile);
|
remoteFile.Init(remoteURL, localURL, _assetVersion, true);
|
remoteFile.Begin(OnFileDownLoadCompleted);
|
}
|
}
|
|
Clock netSwitchClock;
|
NetworkReachability m_NetworkReachability = NetworkReachability.NotReachable;
|
NetworkReachability networkReachability {
|
get { return m_NetworkReachability; }
|
set {
|
if (m_NetworkReachability != value)
|
{
|
m_NetworkReachability = value;
|
|
if (dominantState != Dominant.Whole)
|
{
|
switch (m_NetworkReachability)
|
{
|
case NetworkReachability.ReachableViaCarrierDataNetwork:
|
Pause();
|
var endTime = DateTime.Now + new TimeSpan(TimeSpan.TicksPerSecond * 3);
|
if (netSwitchClock != null)
|
{
|
Clock.Stop(netSwitchClock);
|
}
|
|
netSwitchClock = Clock.AlarmAt(endTime, () =>
|
{
|
if (CheckDominantDownLoad())
|
{
|
TryDownLoad(Dominant.Whole);
|
}
|
});
|
break;
|
case NetworkReachability.ReachableViaLocalAreaNetwork:
|
TryDownLoad(Dominant.None);
|
break;
|
default:
|
break;
|
}
|
}
|
}
|
}
|
}
|
|
bool m_SimulateWifi = true;
|
public bool simulateWifi {
|
get { return m_SimulateWifi; }
|
set {
|
if (m_SimulateWifi != value)
|
{
|
m_SimulateWifi = value;
|
|
if (dominantState != Dominant.Whole)
|
{
|
if (m_SimulateWifi)
|
{
|
TryDownLoad(Dominant.None);
|
}
|
else
|
{
|
Pause();
|
var endTime = DateTime.Now + new TimeSpan(TimeSpan.TicksPerSecond * 10);
|
Clock.AlarmAt(endTime, () =>
|
{
|
if (CheckDominantDownLoad())
|
{
|
TryDownLoad(Dominant.Whole);
|
}
|
});
|
}
|
}
|
}
|
|
}
|
}
|
|
float netCheckTimer = 0f;
|
|
private void LateUpdate()
|
{
|
if (state == State.None || state == State.Award || state == State.Completed)
|
{
|
return;
|
}
|
|
netCheckTimer += Time.deltaTime;
|
|
if (InGameDownTestUtility.enable)
|
{
|
simulateWifi = InGameDownTestUtility.isWifi;
|
}
|
else
|
{
|
if (netCheckTimer > 3f)
|
{
|
netCheckTimer = 0f;
|
networkReachability = Application.internetReachability;
|
}
|
}
|
|
if (mapId != 0)
|
{
|
var progress = GetMapAssetDownLoadProgress(mapId);
|
if (progress > 0.9999f)
|
{
|
if (mapAssetDownLoadOk != null)
|
{
|
mapAssetDownLoadOk();
|
mapAssetDownLoadOk = null;
|
mapId = 0;
|
}
|
}
|
}
|
|
}
|
|
public bool CheckDominantDownLoad()
|
{
|
if (tasks == null || tasks.Count == 0 || isDone || dominantState == Dominant.Whole || NewBieCenter.Instance.inGuiding)
|
{
|
return false;
|
}
|
|
if (GeneralDefine.inGameDownLoadLevelCheckPoints == null || GeneralDefine.inGameDownLoadLevelCheckPoints.Count == 0)
|
{
|
return false;
|
}
|
|
if (PlayerDatas.Instance.baseData.LV < GeneralDefine.inGameDownLoadLevelCheckPoints[0])
|
{
|
return false;
|
}
|
|
if (PlayerDatas.Instance.baseData.LV < GeneralDefine.inGameDownLoadHighLevel)
|
{
|
if (InGameDownTestUtility.enable)
|
{
|
if (InGameDownTestUtility.isWifi)
|
{
|
return false;
|
}
|
}
|
else
|
{
|
if (Application.internetReachability != NetworkReachability.ReachableViaCarrierDataNetwork)
|
{
|
return false;
|
}
|
}
|
}
|
|
if (!WindowCenter.Instance.IsOpen("MainInterfaceWin"))
|
{
|
return false;
|
}
|
|
if (WindowCenter.Instance.ExistAnyFullScreenOrMaskWin())
|
{
|
return false;
|
}
|
|
return true;
|
}
|
|
public bool IsHighLevelPlayer()
|
{
|
if (GeneralDefine.inGameDownLoadLevelCheckPoints == null
|
|| GeneralDefine.inGameDownLoadLevelCheckPoints.Count == 0)
|
{
|
return false;
|
}
|
|
var level = PlayerDatas.Instance.baseData.LV;
|
return level > GeneralDefine.inGameDownLoadHighLevel;
|
}
|
|
private void OnPlayerLevelChange(PlayerDataType refreshType)
|
{
|
switch (refreshType)
|
{
|
case PlayerDataType.LV:
|
var level = PlayerDatas.Instance.baseData.LV;
|
var count = GeneralDefine.inGameDownLoadLevelCheckPoints.Count;
|
var lastLevelCheckPoint = GeneralDefine.inGameDownLoadLevelCheckPoints[count - 1];
|
if (GeneralDefine.inGameDownLoadLevelCheckPoints.Contains(level) || IsHighLevelPlayer())
|
{
|
if (CheckDominantDownLoad())
|
{
|
TryDownLoad(Dominant.Whole);
|
}
|
}
|
break;
|
}
|
}
|
|
private void OnMainTaskChange(int _taskId, int _state)
|
{
|
var mainTaskId = taskModel.currentMission;
|
if (GeneralDefine.inGameDownLoadTaskCheckPoints.Contains(mainTaskId)
|
&& taskModel.currentMissionState == 1)
|
{
|
if (CheckDominantDownLoad())
|
{
|
TryDownLoad(Dominant.Whole);
|
}
|
}
|
}
|
|
private int AssetDownLoadPriorCompare(AssetVersion lhs, AssetVersion rhs)
|
{
|
var categoryA = lhs.GetAssetCategory();
|
var categoryB = rhs.GetAssetCategory();
|
var priorA = PriorBundleConfig.GetAssetPrior(categoryA, lhs.fileName);
|
var priorB = PriorBundleConfig.GetAssetPrior(categoryB, rhs.fileName);
|
|
if (priorA != priorB)
|
{
|
return priorA < priorB ? -1 : 1;
|
}
|
else
|
{
|
var isManifestA = lhs.extersion == ".manifest";
|
var isManifestB = rhs.extersion == ".manifest";
|
|
if (!isManifestA && isManifestB)
|
{
|
return -1;
|
}
|
else if (isManifestA && !isManifestB)
|
{
|
return 1;
|
}
|
else
|
{
|
return 0;
|
}
|
}
|
}
|
|
private int GetMaxTask()
|
{
|
switch (Application.platform)
|
{
|
case RuntimePlatform.Android:
|
if (DeviceUtility.cpu >= 4 && DeviceUtility.memory > 3.2f * 1024)
|
{
|
return 2;
|
}
|
else
|
{
|
return 1;
|
}
|
case RuntimePlatform.IPhonePlayer:
|
if (DeviceUtility.cpu > 1 && DeviceUtility.memory > 1.5f * 1024)
|
{
|
return 2;
|
}
|
else
|
{
|
return 1;
|
}
|
case RuntimePlatform.WindowsEditor:
|
return 2;
|
default:
|
return 1;
|
}
|
|
}
|
|
private void Awake()
|
{
|
maxWorkingTask = GetMaxTask();
|
}
|
|
public struct Reward
|
{
|
public int id;
|
public int count;
|
public bool bind;
|
|
public Reward(string _input)
|
{
|
var matches = Regex.Matches(_input, "\\d+");
|
|
if (matches.Count > 0)
|
{
|
int.TryParse(matches[0].Value, out id);
|
}
|
else
|
{
|
id = 0;
|
}
|
|
if (matches.Count > 1)
|
{
|
int.TryParse(matches[1].Value, out count);
|
}
|
else
|
{
|
count = 0;
|
}
|
|
if (matches.Count > 2)
|
{
|
var temp = 0;
|
int.TryParse(matches[2].Value, out temp);
|
bind = temp == 1;
|
}
|
else
|
{
|
bind = false;
|
}
|
}
|
|
}
|
|
public enum State
|
{
|
None,
|
Prepared,
|
DownLoad,
|
Pause,
|
Award,
|
Completed,
|
}
|
|
public enum Dominant
|
{
|
None = 0,
|
Half = 1,
|
Whole = 2,
|
}
|
|
}
|