401 lines
16 KiB
C#
401 lines
16 KiB
C#
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.Net;
|
|
using System.Reflection;
|
|
using GraphicsManager;
|
|
using GraphicsManager.Enums;
|
|
using GraphicsManager.Objects;
|
|
using GraphicsManager.Objects.Core;
|
|
using OpenTK.Mathematics;
|
|
using OpenTK.Windowing.Desktop;
|
|
|
|
namespace Updater;
|
|
|
|
public class NewUpdater : FPSWindow
|
|
{
|
|
private readonly ConfigFile cf;
|
|
private ProgressBar<ulong> TotalProgress;
|
|
private Argumets Argumets;
|
|
private List<Tuple<ProgressBar<ulong>, Label, int>> ProgressThreads = new();
|
|
private readonly BackgroundWorker Download = new();
|
|
private Label? Total_Downloaded, Transfer_Speed;
|
|
private readonly System.Timers.Timer Speed;
|
|
private List<double> speeds = new();
|
|
|
|
public NewUpdater(NativeWindowSettings nws, GameWindowSettings gws, Argumets args)
|
|
:base(nws, gws)
|
|
{
|
|
ShowMissingChar = false;
|
|
LogFrames = false;
|
|
Speed = new()
|
|
{
|
|
Interval = 500
|
|
};
|
|
Speed.Elapsed += Speed_Elapsed;
|
|
CanControleUpdate = false;
|
|
//small = (uint)Math.Round(0.0656167979002625 * StartGUI.Height, 0);
|
|
//RenderObjects.Add(Total_Downloaded = new RenderText("Download Amount", "OpenSans-Regular", small, -0.9381188f, 0.149797574f, 1.0f, new Vector2(1f, 0f), new Vector4(cf.Colors.Text.R, cf.Colors.Text.G, cf.Colors.Text.B, cf.Colors.Text.A)));
|
|
//small = (uint)Math.Round(0.078740157480315 * StartGUI.Height, 0);
|
|
//RenderObjects.Add(Transfer_Speed = new RenderText("Download Speed", "OpenSans-Regular", small, -0.9381188f, -0.05263158f, 1.2f, new Vector2(1f, 0f), new Vector4(cf.Colors.Text.R, cf.Colors.Text.G, cf.Colors.Text.B, cf.Colors.Text.A)));
|
|
|
|
FontFamily r = FontFamily.LoadFontFamily(Tools.GetResourceStream(Assembly.GetExecutingAssembly(), "Updater.Resource.OpenSans.zip"), "OpenSans");
|
|
FontInteraction fi = FontInteraction.Load(r);
|
|
cf = Config.GetConfig();
|
|
|
|
Size = new(cf.Scale(Size.X), cf.Scale(Size.Y));
|
|
Argumets = args;
|
|
int WallDistance = cf.Scale(15);
|
|
BackgroundColor = cf.Colors.Background.ToColor4();
|
|
|
|
Texture ProgressbarTexture = TextureManager.AddTexture(File.OpenRead("/home/jacob/Pictures/Progress.png"));
|
|
Controls.Add(TotalProgress = new(ProgressbarTexture)
|
|
{
|
|
Location = new(WallDistance, cf.Scale(70)),
|
|
Size = new(Size.X - WallDistance - WallDistance, cf.Scale(20)),
|
|
BackgroundColor = cf.Colors.Progress_bars.Backcolor.ToColor4(),
|
|
ProgressColor = cf.Colors.Progress_bars.Fillcolor.ToColor4(),
|
|
ProgressValue = 5,
|
|
ProgressGap = new(cf.Scale(3)),
|
|
Shader = Rectangle.DefaultAlphaShader[Context],
|
|
TextureDisplay = TextureDisplay.ProgressHorizontalCenter,
|
|
UpdateOnDraw = true,
|
|
InnerShader = Rectangle.DefaultAlphaShader[Context]
|
|
});
|
|
|
|
fi.PixelHeight = (uint)WallDistance;
|
|
TotalProgress.Controls.Add(Total_Downloaded = new(fi)
|
|
{
|
|
Color = Color4.Black,
|
|
Text = "Downloading ...."
|
|
});
|
|
Total_Downloaded.Location = new(cf.Scale(5), (TotalProgress.Size.Y - Total_Downloaded.Size.Y) / 2);
|
|
Controls.Add(Transfer_Speed = new(fi)
|
|
{
|
|
Text = "abcdefghijklmnopqrstuvwxyz",
|
|
Location = new(WallDistance + Total_Downloaded.Location.X, cf.Scale(5))
|
|
});
|
|
|
|
int gap = cf.Scale(10);
|
|
for (int i = 0; i < cf.Format.DownloadThreads; i++)
|
|
{
|
|
ProgressBar<ulong> temp;
|
|
Size = new(Size.X, Size.Y + gap + TotalProgress.Size.Y);
|
|
Label l = new(fi)
|
|
{
|
|
Color = Color4.Black,
|
|
Text = "Downloading ...."
|
|
};
|
|
l.Location = new(Total_Downloaded.Location.X, (TotalProgress.Size.Y - l.Size.Y) / 2);
|
|
Controls.Add(temp = new(ProgressbarTexture)
|
|
{
|
|
Location = new(WallDistance, cf.Scale(70) + (TotalProgress.Size.Y * (i + 1)) + (gap * (i + 1))),
|
|
Size = TotalProgress.Size,
|
|
BackgroundColor = TotalProgress.BackgroundColor,
|
|
ProgressColor = TotalProgress.ProgressColor,
|
|
ProgressValue = 100,
|
|
ProgressGap = TotalProgress.ProgressGap,
|
|
Shader = TotalProgress.Shader,
|
|
TextureDisplay = TotalProgress.TextureDisplay,
|
|
UpdateOnDraw = true,
|
|
InnerShader = TotalProgress.InnerShader
|
|
});
|
|
temp.Controls.Add(l);
|
|
ProgressThreads.Add(new(temp,l, i));
|
|
}
|
|
|
|
Download.DoWork += Download_DoWork;
|
|
Download.RunWorkerCompleted += Download_RunWorkerCompleted;
|
|
Download.WorkerReportsProgress = true;
|
|
Invoke(Download.RunWorkerAsync);
|
|
Speed.Start();
|
|
}
|
|
|
|
private ulong last;
|
|
private string end = "";
|
|
|
|
private void Speed_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
|
|
{
|
|
ulong BytesPertenthSec;
|
|
if (last > TotalProgress.ProgressValue) BytesPertenthSec= 0;
|
|
else BytesPertenthSec= (TotalProgress.ProgressValue) - last;
|
|
last = TotalProgress.ProgressValue;
|
|
speeds.Add(BytesPertenthSec * 2);
|
|
if (speeds.Count > 25) speeds.RemoveAt(0);
|
|
if (Transfer_Speed is not null && speeds.Average() != 0)
|
|
{
|
|
Transfer_Speed.Text = Download_Speed_Neat(speeds.Average());
|
|
Set_Downloaded_Amount_Neat();
|
|
}
|
|
}
|
|
|
|
private void Download_DoWork(object? sender, DoWorkEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
void TryDeleteDir(string? dir)
|
|
{
|
|
if (string.IsNullOrEmpty(dir) || string.IsNullOrWhiteSpace(dir)) return;
|
|
try
|
|
{
|
|
if (Directory.Exists(dir)) Directory.Delete(dir, true);
|
|
}
|
|
catch
|
|
{
|
|
DirectoryInfo dirInfo = new(dir);
|
|
foreach (var file in dirInfo.GetFiles())
|
|
{
|
|
try
|
|
{
|
|
file.Delete();
|
|
}
|
|
catch
|
|
{
|
|
// ignored
|
|
}
|
|
}
|
|
foreach (var subdir in dirInfo.GetDirectories())
|
|
{
|
|
TryDeleteDir(subdir.FullName);
|
|
}
|
|
}
|
|
}
|
|
TryDeleteDir(Argumets.LocalDirectory);
|
|
Directory.CreateDirectory(Argumets.LocalDirectory);
|
|
|
|
try
|
|
{
|
|
HttpClient client = new();
|
|
|
|
Task<string> files_pre = client.GetStringAsync($"https://{Handler.Domain}/Updater/Files?directory={Argumets.RemoteDirectory}{Argumets.UriBranch}{Argumets.UriSeflContaind}{Argumets.UriPlatform}{Argumets.UriVersion}");
|
|
Task<string> max_pre = client.GetStringAsync(
|
|
$"https://{Handler.Domain}/Updater/GetSize?directory={Argumets.RemoteDirectory}{Argumets.UriBranch}{Argumets.UriSeflContaind}{Argumets.UriPlatform}{Argumets.UriVersion}");
|
|
max_pre.Wait();
|
|
TotalProgress.MaxProgressValue = ulong.Parse(max_pre.Result);
|
|
end = Downloaded_Amount_Neat(TotalProgress.MaxProgressValue);
|
|
files_pre.Wait();
|
|
string[] files = files_pre.Result.Split('\n');
|
|
Queue<int> IndexesWaiting = new();
|
|
for (int i = 0; i < cf.Format.DownloadThreads; i++)
|
|
{
|
|
IndexesWaiting.Enqueue(i);
|
|
}
|
|
_ = Parallel.ForEach(files, new ParallelOptions() { MaxDegreeOfParallelism = cf.Format.DownloadThreads },
|
|
file =>
|
|
{
|
|
try
|
|
{
|
|
int v;
|
|
lock (IndexesWaiting)
|
|
{
|
|
v = IndexesWaiting.Dequeue();
|
|
}
|
|
Tuple<ProgressBar<ulong>, Label, int> pb = ProgressThreads[v];
|
|
StartDownloadForFile(file, pb.Item1, pb.Item2).Wait();
|
|
IndexesWaiting.Enqueue(v);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Console.WriteLine(exception);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
StackTrace st = new(ex, true);
|
|
StackFrame? frame = st.GetFrame(0);
|
|
if (frame is null) return;
|
|
int line = frame.GetFileLineNumber();
|
|
string msg = $"Error in Updater.exe in function Download_DoWork on line '{line}' through error '{ex.Message}'\nERROR:\n'{ex}' FRAM:\n '{frame}'";
|
|
MessageBox.Show(ex.ToString());
|
|
_ = new HttpClient().PostAsync($"https://{Handler.Domain}/Updater/Error/updater", new StringContent(msg));
|
|
}
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Console.WriteLine(exception);
|
|
throw;
|
|
}
|
|
}
|
|
|
|
private async Task StartDownloadForFile(string file, ProgressBar<ulong> pb, Label pbLabel)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(file)) return;
|
|
string[] temp = file.Split('/');
|
|
if (file.Contains('/'))
|
|
{
|
|
string cur = "";
|
|
for (int i = 0; i < temp.Length - 1; i++)
|
|
{
|
|
cur = Path.Join(cur, temp[i]);
|
|
if (!Directory.Exists(Path.Join(Argumets.LocalDirectory, cur)))
|
|
Directory.CreateDirectory(Path.Join(Argumets.LocalDirectory, cur));
|
|
}
|
|
}
|
|
using HttpClient client = new();
|
|
string max = await client.GetStringAsync($"https://{Handler.Domain}/Updater/GetFileSize?directory={Argumets.RemoteDirectory}{Argumets.UriBranch}{Argumets.UriVersion}{Argumets.UriSeflContaind}{Argumets.UriPlatform}&file={file}");
|
|
Invoke(() =>
|
|
{
|
|
pb.ProgressValue = 0;
|
|
pb.MaxProgressValue = ulong.Parse(max);
|
|
string s = $"Downloading {temp[^1]}";
|
|
try
|
|
{
|
|
pbLabel.Text = s;
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Console.WriteLine(e);
|
|
}
|
|
});
|
|
await DownloadFileAsync(pb,
|
|
$"https://{Handler.Domain}/Updater/GetFile?directory={Argumets.RemoteDirectory}{Argumets.UriBranch}{Argumets.UriVersion}{Argumets.UriSeflContaind}{Argumets.UriPlatform}&file={file}",
|
|
file.Replace("/", Handler.Slash));
|
|
}
|
|
|
|
private async Task DownloadFileAsync(ProgressBar<ulong> progressBar, string url, string destinationPath)
|
|
{
|
|
using (HttpClient client = new HttpClient())
|
|
using (HttpResponseMessage response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead))
|
|
{
|
|
response.EnsureSuccessStatusCode();
|
|
|
|
|
|
using (var contentStream = await response.Content.ReadAsStreamAsync())
|
|
using (var fileStream = new FileStream(Path.Join(Argumets.LocalDirectory, destinationPath), FileMode.Create, FileAccess.Write, FileShare.None, 8192, true))
|
|
{
|
|
var buffer = new byte[8192];
|
|
long totalRead = 0;
|
|
int bytesRead;
|
|
|
|
while ((bytesRead = await contentStream.ReadAsync(buffer, 0, buffer.Length)) > 0)
|
|
{
|
|
await fileStream.WriteAsync(buffer, 0, bytesRead);
|
|
totalRead += bytesRead;
|
|
TotalProgress.ProgressValue += (ulong)bytesRead;
|
|
progressBar.ProgressValue = (ulong)totalRead;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Download_RunWorkerCompleted(object? sender, RunWorkerCompletedEventArgs e)
|
|
{
|
|
try
|
|
{
|
|
Invoke(Close);
|
|
}
|
|
catch (Exception exception)
|
|
{
|
|
Console.WriteLine(exception);
|
|
}
|
|
}
|
|
|
|
#region Neat
|
|
private string Download_Speed_Neat(double Number)
|
|
{
|
|
ConfigFileSize cfs = cf.Format.DownloadSpeed;
|
|
string Size = SizeName(Number, cfs);
|
|
int bytes = 1024;
|
|
if (cfs == ConfigFileSize.MebiBit || cfs == ConfigFileSize.MebiByte) bytes = 1000;
|
|
int Exponet;
|
|
if (Number / bytes >= 1)
|
|
if (Number / Math.Pow(bytes, 2) >= 1)
|
|
if (Number / Math.Pow(bytes, 3) >= 1) Exponet = 3;
|
|
else Exponet = 2;
|
|
else Exponet = 1;
|
|
else Exponet = 0;
|
|
if (cfs == ConfigFileSize.MebiBit || cfs == ConfigFileSize.MegaBit) Number *= 8;
|
|
Number = Math.Round(Number / Math.Pow(bytes, Exponet), 2, MidpointRounding.ToEven);
|
|
if (!Number.ToString().Contains('.'))
|
|
{
|
|
return $"{Number}.00{Size}/s";
|
|
}
|
|
else
|
|
{
|
|
if (Number.ToString().Remove(0, Number.ToString().IndexOf('.')).Length == 1)
|
|
{
|
|
return $"{Number}0{Size}/s";
|
|
}
|
|
else
|
|
{
|
|
return $"{Number}{Size}/s";
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Set_Downloaded_Amount_Neat()
|
|
{
|
|
Total_Downloaded!.Text = $"Downloaded {Downloaded_Amount_Neat(TotalProgress.ProgressValue)} of {end}";
|
|
}
|
|
|
|
private string Downloaded_Amount_Neat(double Number)
|
|
{
|
|
int Exponet = 0;
|
|
ConfigFileSize cfs = cf.Format.DownloadAmount;
|
|
int bytes = 1024;
|
|
if (cfs == ConfigFileSize.MebiBit || cfs == ConfigFileSize.MebiByte) bytes = 1000;
|
|
string Size = SizeName(Number, cfs);
|
|
if (Size.ToLower().StartsWith('g')) Exponet = 3;
|
|
else if (Size.ToLower().StartsWith('m')) Exponet = 2;
|
|
else if (Size.ToLower().StartsWith('k')) Exponet = 1;
|
|
Number = Math.Round(Number / Math.Pow(bytes, Exponet), 2, MidpointRounding.ToEven);
|
|
if (cfs == ConfigFileSize.MebiBit || cfs == ConfigFileSize.MegaBit) Number *= 8;
|
|
string text = "";
|
|
if (!Number.ToString().Contains('.'))
|
|
{
|
|
text = $"{Number}.00{Size}{text}";
|
|
}
|
|
else
|
|
{
|
|
text = Number.ToString().Remove(0, Number.ToString().IndexOf('.')).Length != 1 ? $"{Number}{Size}{text}" : $"{Number}0{Size}{text}";
|
|
}
|
|
|
|
return text;
|
|
}
|
|
|
|
private static string SizeName(double Number, ConfigFileSize format)
|
|
{
|
|
string Size;
|
|
switch (format)
|
|
{
|
|
default:
|
|
case ConfigFileSize.MegaByte:
|
|
if (Number / 1000 >= 1)
|
|
if (Number / Math.Pow(1000, 2) >= 1)
|
|
if (Number / Math.Pow(1000, 3) >= 1) Size = "GB";
|
|
else Size = "MB";
|
|
else Size = "KB";
|
|
else Size = "B";
|
|
break;
|
|
case ConfigFileSize.MebiByte:
|
|
if (Number / 1024 >= 1)
|
|
if (Number / Math.Pow(1024, 2) >= 1)
|
|
if (Number / Math.Pow(1024, 3) >= 1) Size = "GiB";
|
|
else Size = "MiB";
|
|
else Size = "KiB";
|
|
else Size = "B";
|
|
break;
|
|
case ConfigFileSize.MegaBit:
|
|
Number *= 8;
|
|
if (Number / 1000 >= 1)
|
|
if (Number / Math.Pow(1000, 2) >= 1)
|
|
if (Number / Math.Pow(1000, 3) >= 1) Size = "Gb";
|
|
else Size = "Mb";
|
|
else Size = "Kb";
|
|
else Size = "b";
|
|
break;
|
|
case ConfigFileSize.MebiBit:
|
|
Number *= 8;
|
|
if (Number / 1024 >= 1)
|
|
if (Number / Math.Pow(1024, 2) >= 1)
|
|
if (Number / Math.Pow(1024, 3) >= 1) Size = "Gib";
|
|
else Size = "Mib";
|
|
else Size = "Kib";
|
|
else Size = "b";
|
|
break;
|
|
}
|
|
return Size;
|
|
}
|
|
#endregion
|
|
} |