zxl
/
CTT
forked from Cal/CTT
1
0
Fork 0
CTT/Unity/Assets/Model/Game/Entity/Downloader.cs

253 lines
7.6 KiB
C#

//
// Downloader.cs
//
// Author:
// fjy <jiyuan.feng@live.com>
//
// Copyright (c) 2020 fjy
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using ET;
using System;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
namespace libx
{
public class DownloaderUpdateSystem : UpdateSystem<Downloader>
{
public override void Update(Downloader self)
{
self.Update();
}
}
public class Downloader : Entity
{
private const float BYTES_2_MB = 1f / (1024 * 1024);
public int maxDownloads = 3;
private readonly List<Download> _downloads = new List<Download>();
private readonly List<Download> _tostart = new List<Download>();
private readonly List<Download> _progressing = new List<Download>();
public Action<long, long, float> onUpdate;
public Action onFinished;
private int _finishedIndex;
private int _downloadIndex;
private float _startTime;
private float _lastTime;
private long _lastSize;
public long size { get; private set; }
public long position { get; private set; }
public float speed { get; private set; }
public List<Download> downloads { get { return _downloads; } }
private long GetDownloadSize()
{
long len = 0L;
long downloadSize = 0L;
foreach (Download download in _downloads)
{
downloadSize += download.position;
len += download.len;
}
return downloadSize - (len - size);
}
private bool _started;
[SerializeField]private float sampleTime = 0.5f;
public void StartDownload()
{
_tostart.Clear();
_finishedIndex = 0;
_lastSize = 0L;
Restart();
}
public void Restart()
{
_startTime = Time.realtimeSinceStartup;
_lastTime = 0;
_started = true;
_downloadIndex = _finishedIndex;
int max = Math.Min(_downloads.Count, maxDownloads);
for (int i = _finishedIndex; i < max; i++)
{
Download item = _downloads[i];
_tostart.Add(item);
_downloadIndex++;
}
}
public void Stop()
{
_tostart.Clear();
foreach (Download download in _progressing)
{
download.Complete(true);
_downloads[download.id] = download.Clone() as Download;
}
_progressing.Clear();
_started = false;
}
public void Clear()
{
size = 0;
position = 0;
_downloadIndex = 0;
_finishedIndex = 0;
_lastTime = 0f;
_lastSize = 0L;
_startTime = 0;
_started = false;
foreach (Download item in _progressing)
{
item.Complete(true);
}
_progressing.Clear();
_downloads.Clear();
_tostart.Clear();
}
public void AddDownload(string url, string filename, string savePath, string hash, long len)
{
Download download = new Download
{
id = _downloads.Count,
url = url,
name = filename,
hash = hash,
len = len,
savePath = savePath,
completed = OnFinished
};
_downloads.Add(download);
FileInfo info = new FileInfo(download.tempPath);
if (info.Exists)
{
size += len - info.Length;
}
else
{
size += len;
}
}
private void OnFinished(Download download)
{
if (_downloadIndex < _downloads.Count)
{
_tostart.Add(_downloads[_downloadIndex]);
_downloadIndex++;
}
_finishedIndex++;
Debug.Log(string.Format("OnFinished:{0}, {1}", _finishedIndex, _downloads.Count));
if (_finishedIndex != downloads.Count)
return;
if (onFinished != null)
{
onFinished.Invoke();
}
_started = false;
}
public static string GetDisplaySpeed(float downloadSpeed)
{
if (downloadSpeed >= 1024 * 1024)
{
return string.Format("{0:f2}MB/s", downloadSpeed * BYTES_2_MB);
}
if (downloadSpeed >= 1024)
{
return string.Format("{0:f2}KB/s", downloadSpeed / 1024);
}
return string.Format("{0:f2}B/s", downloadSpeed);
}
public static string GetDisplaySize(long downloadSize)
{
if (downloadSize >= 1024 * 1024)
{
return string.Format("{0:f2}MB", downloadSize * BYTES_2_MB);
}
if (downloadSize >= 1024)
{
return string.Format("{0:f2}KB", downloadSize / 1024);
}
return string.Format("{0:f2}B", downloadSize);
}
public void Update()
{
if (!_started)
return;
if (_tostart.Count > 0)
{
for (int i = 0; i < Math.Min(maxDownloads, _tostart.Count); i++)
{
Download item = _tostart[i];
item.Start();
_tostart.RemoveAt(i);
_progressing.Add(item);
i--;
}
}
for (int index = 0; index < _progressing.Count; index++)
{
Download download = _progressing[index];
download.Update();
if (!download.finished)
continue;
_progressing.RemoveAt(index);
index--;
}
position = GetDownloadSize();
float elapsed = Time.realtimeSinceStartup - _startTime;
if (elapsed - _lastTime < sampleTime)
return;
float deltaTime = elapsed - _lastTime;
speed = (position - _lastSize) / deltaTime;
if (onUpdate != null)
{
onUpdate(position, size, speed);
}
_lastTime = elapsed;
_lastSize = position;
}
}
}