RAGECOOP-V/Client/DownloadManager.cs

186 lines
6.0 KiB
C#
Raw Normal View History

2022-04-02 18:11:30 +02:00
using System.IO;
using System.Linq;
using System.Collections.Generic;
2022-04-02 16:40:24 +02:00
namespace CoopClient
{
internal static class DownloadManager
2022-04-02 16:40:24 +02:00
{
private static readonly List<DownloadFile> _downloadFiles = new List<DownloadFile>();
private static readonly Dictionary<byte, FileStream> _streams = new Dictionary<byte, FileStream>();
private static readonly List<byte> _filesFinished = new List<byte>();
public static bool DownloadComplete = false;
2022-04-02 16:40:24 +02:00
2022-04-12 07:51:35 +02:00
public static void AddFile(byte id, string name, long length)
2022-04-02 16:40:24 +02:00
{
2022-04-03 02:27:30 +02:00
string downloadFolder = $"scripts\\resources\\{Main.MainSettings.LastServerAddress.Replace(":", ".")}";
2022-04-02 18:11:30 +02:00
if (!Directory.Exists(downloadFolder))
{
Directory.CreateDirectory(downloadFolder);
}
if (FileAlreadyExists(downloadFolder, name, length))
{
// Send the server we are already done
Main.MainNetworking.SendDownloadFinish(id);
2022-04-11 15:10:27 +02:00
Cancel(id);
return;
}
2022-04-11 13:37:38 +02:00
if (!new string[] { ".js", ".xml" }.Any(x => x == Path.GetExtension(name)))
{
2022-04-11 15:10:27 +02:00
Cancel(id);
GTA.UI.Notification.Show($"The download of a file from the server was blocked! [{name}]", true);
Logger.Write($"The download of a file from the server was blocked! [{name}]", Logger.LogLevel.Server);
return;
}
lock (_downloadFiles)
{
_downloadFiles.Add(new DownloadFile()
{
FileID = id,
FileName = name,
FileLength = length
});
2022-04-02 18:11:30 +02:00
}
lock (_streams)
{
2022-04-06 08:44:17 +02:00
_streams.Add(id, new FileStream($"{downloadFolder}\\{name}", FileMode.CreateNew, FileAccess.Write, FileShare.ReadWrite));
}
2022-04-02 16:40:24 +02:00
}
2022-04-02 18:11:30 +02:00
/// <summary>
/// Check if the file already exists and if the size correct otherwise delete this file
/// </summary>
/// <param name="folder"></param>
/// <param name="name"></param>
/// <param name="length"></param>
/// <returns></returns>
private static bool FileAlreadyExists(string folder, string name, long length)
2022-04-02 16:40:24 +02:00
{
string filePath = $"{folder}\\{name}";
2022-04-02 18:11:30 +02:00
if (File.Exists(filePath))
{
if (new FileInfo(filePath).Length == length)
2022-04-02 18:11:30 +02:00
{
return true;
}
// Delete the file because the length is wrong (maybe the file was updated)
File.Delete(filePath);
}
return false;
}
2022-04-19 07:41:39 +02:00
public static void RenderProgress()
2022-04-11 15:10:27 +02:00
{
if (_downloadFiles.Count == 0)
{
return;
}
lock (_downloadFiles) lock (_filesFinished)
{
new LemonUI.Elements.ScaledText(new System.Drawing.PointF(System.Windows.Forms.Screen.PrimaryScreen.Bounds.Width / 2, System.Windows.Forms.Screen.PrimaryScreen.Bounds.Height - 60), $"Downloading files {_filesFinished.Count()} / {_downloadFiles.Count() + _filesFinished.Count()}", 0.5f) { Alignment = GTA.UI.Alignment.Center }.Draw();
}
}
public static void Write(byte id, byte[] chunk)
{
lock (_filesFinished)
{
if (_filesFinished.Contains(id))
2022-04-02 18:11:30 +02:00
{
return;
2022-04-02 18:11:30 +02:00
}
}
2022-04-02 16:40:24 +02:00
lock (_streams)
{
2022-04-06 08:44:17 +02:00
FileStream fs = _streams.FirstOrDefault(x => x.Key == id).Value;
if (fs == null)
{
2022-04-06 08:44:17 +02:00
Logger.Write($"Stream for file {id} not found!", Logger.LogLevel.Server);
return;
}
fs.Write(chunk, 0, chunk.Length);
lock (_downloadFiles)
{
DownloadFile file = _downloadFiles.FirstOrDefault(x => x.FileID == id);
if (file == null)
{
2022-04-06 08:44:17 +02:00
Logger.Write($"File {id} couldn't be found in the list!", Logger.LogLevel.Server);
return;
}
file.FileWritten += chunk.Length;
2022-04-06 06:52:02 +02:00
if (file.FileWritten >= file.FileLength)
{
Cancel(id);
}
}
}
}
public static void Cancel(byte id)
{
2022-04-11 15:10:27 +02:00
lock (_streams) lock (_downloadFiles) lock (_filesFinished)
{
FileStream fs = _streams.ContainsKey(id) ? _streams[id] : null;
if (fs != null)
{
fs.Close();
fs.Dispose();
_streams.Remove(id);
}
if (_downloadFiles.Any(x => x.FileID == id))
{
_downloadFiles.Remove(_downloadFiles.First(x => x.FileID == id));
}
2022-04-11 15:10:27 +02:00
_filesFinished.Add(id);
}
2022-04-02 18:11:30 +02:00
}
2022-04-06 08:44:17 +02:00
public static void Cleanup(bool everything)
2022-04-02 18:11:30 +02:00
{
lock (_streams) lock (_downloadFiles) lock (_filesFinished)
2022-04-02 18:11:30 +02:00
{
2022-04-06 08:44:17 +02:00
foreach (KeyValuePair<byte, FileStream> stream in _streams)
{
stream.Value.Close();
stream.Value.Dispose();
}
_streams.Clear();
_downloadFiles.Clear();
_filesFinished.Clear();
2022-04-02 18:11:30 +02:00
}
2022-04-06 08:44:17 +02:00
if (everything)
{
DownloadComplete = false;
}
2022-04-02 16:40:24 +02:00
}
}
internal class DownloadFile
{
public byte FileID { get; set; } = 0;
public string FileName { get; set; } = string.Empty;
public long FileLength { get; set; } = 0;
2022-04-06 06:52:02 +02:00
public long FileWritten { get; set; } = 0;
}
2022-04-02 16:40:24 +02:00
}