game assets downloading

This commit is contained in:
2024-09-24 16:18:06 +05:00
parent 581c4b5498
commit c2e2785a32
20 changed files with 690 additions and 350 deletions

View File

@@ -0,0 +1,31 @@
namespace Млаумчерб.Клиент.классы;
public class ArgumentsWithPlaceholders
{
protected List<string> raw_args = new();
public List<string> FillPlaceholders(Dictionary<string, string> values)
{
List<string> result = new();
foreach (var a in raw_args)
{
var f = a;
int begin = a.IndexOf('$');
if (begin != -1)
{
int keyBegin = begin + 2;
int end = a.IndexOf('}', keyBegin);
if (end != -1)
{
var key = a.Substring(keyBegin, end - keyBegin);
if (!values.TryGetValue(key, out var v))
throw new Exception($"can't find value for placeholder '{key}'");
f = v;
}
}
result.Add(f);
}
return result;
}
}

View File

@@ -0,0 +1,27 @@
using DTLib.Extensions;
namespace Млаумчерб.Клиент.классы;
public class GameArguments : ArgumentsWithPlaceholders
{
private static readonly string[] _enabled_features =
[
"has_custom_resolution"
];
public GameArguments(MinecraftVersionDescriptor d)
{
if (d.minecraftArguments is not null)
{
raw_args.AddRange(d.minecraftArguments.SplitToList(' ', quot: '"'));
}
else if (d.arguments is not null)
{
foreach (var av in d.arguments.game)
{
if(Буржуазия.CheckRules(av.rules, _enabled_features))
raw_args.AddRange(av.value);
}
}
}
}

View File

@@ -0,0 +1,32 @@
namespace Млаумчерб.Клиент.классы;
public class GameVersionProps
{
public string Name { get; }
public IOPath LocalDescriptorPath { get; }
public string? RemoteDescriptorUrl { get; }
private bool _isDownloaded;
public bool IsDownloaded
{
get => _isDownloaded;
set
{
_isDownloaded = value;
DownloadCompleted?.Invoke();
}
}
public event Action? DownloadCompleted;
public GameVersionProps(string name, string? url, IOPath descriptorPath)
{
Name = name;
LocalDescriptorPath = descriptorPath;
RemoteDescriptorUrl = url;
IsDownloaded = File.Exists(Пролетариат.GetVersionJarFilePath(name));
}
public GameVersionProps(string name, string? url) :
this(name, url, Пролетариат.GetVersionDescriptorPath(name)) { }
public override string ToString() => Name;
}

View File

@@ -0,0 +1,27 @@
namespace Млаумчерб.Клиент.классы;
public class JavaArguments : ArgumentsWithPlaceholders
{
private static readonly string[] _initial_arguments =
[
];
private static readonly string[] _enabled_features =
[
];
public JavaArguments(MinecraftVersionDescriptor d)
{
raw_args.AddRange(_initial_arguments);
if (d.arguments is not null)
{
foreach (var av in d.arguments.jvm)
{
if(Буржуазия.CheckRules(av.rules, _enabled_features))
raw_args.AddRange(av.value);
}
}
}
}

View File

@@ -0,0 +1,126 @@
using System.Linq;
// ReSharper disable CollectionNeverUpdated.Global
namespace Млаумчерб.Клиент.классы;
public class MinecraftVersionDescriptor
{
[JsonRequired] public string id { get; set; } = "";
[JsonRequired] public DateTime time { get; set; }
[JsonRequired] public DateTime releaseTime { get; set; }
[JsonRequired] public string type { get; set; } = "";
[JsonRequired] public string mainClass { get; set; } = "";
[JsonRequired] public Downloads downloads { get; set; } = null!;
[JsonRequired] public JavaVersion javaVersion { get; set; } = null!;
[JsonRequired] public List<Library> libraries { get; set; } = null!;
[JsonRequired] public AssetIndexProperties assetIndex { get; set; } = null!;
[JsonRequired] public string assets { get; set; } = "";
public string? minecraftArguments { get; set; }
public ArgumentsNew? arguments { get; set; }
}
public class Artifact
{
[JsonRequired] public string url { get; set; } = "";
[JsonRequired] public string sha1 { get; set; } = "";
[JsonRequired] public int size { get; set; }
}
public class Os
{
public string? name { get; set; }
public string? arch { get; set; }
}
public class Rule
{
[JsonRequired] public string action { get; set; } = "";
public Os? os { get; set; }
public Dictionary<string, bool>? features { get; set; }
}
public class Classifiers
{
[JsonProperty("natives-linux")]
public Artifact? nativeslinux { get; set; }
[JsonProperty("natives-osx")]
public Artifact? nativesosx { get; set; }
[JsonProperty("natives-windows")]
public Artifact? nativeswindows { get; set; }
}
public class LibraryDownloads
{
public Artifact? artifact { get; set; }
public Classifiers? classifiers { get; set; }
}
public class Extract
{
public List<string>? exclude { get; set; }
}
public class Natives
{
public string? linux { get; set; }
public string? osx { get; set; }
public string? windows { get; set; }
}
public class Library
{
[JsonRequired] public string name { get; set; } = "";
public List<Rule>? rules { get; set; }
public Natives? natives { get; set; }
public Extract? extract { get; set; }
[JsonRequired] public LibraryDownloads downloads { get; set; } = null!;
}
public class AssetIndexProperties
{
[JsonRequired] public string id { get; set; } = "";
[JsonRequired] public string url { get; set; } = "";
[JsonRequired] public string sha1 { get; set; } = "";
[JsonRequired] public int size { get; set; }
[JsonRequired] public int totalSize { get; set; }
}
public class Downloads
{
[JsonRequired] public Artifact client { get; set; } = null!;
}
public class JavaVersion
{
[JsonRequired] public string component { get; set; } = "";
[JsonRequired] public int majorVersion { get; set; }
}
public class ArgValue
{
public struct StringOrArray : IEnumerable<string>
{
private string[] ar;
public StringOrArray(ICollection<string> v) => ar = v.ToArray();
public StringOrArray(string v) => ar = [v];
public static implicit operator StringOrArray(string[] v) => new(v);
public static implicit operator StringOrArray(string v) => new(v);
public static implicit operator string[](StringOrArray sar) => sar.ar;
public IEnumerator<string> GetEnumerator() => ar.AsEnumerable().GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => ar.GetEnumerator();
}
public ArgValue() { }
public ArgValue(string arg) => value = arg;
public static implicit operator ArgValue(string arg) => new(arg);
[JsonRequired] public StringOrArray value { get; set; } = [];
public List<Rule> rules { get; set; } = new();
}
public class ArgumentsNew
{
[JsonRequired] public List<ArgValue> jvm { get; set; } = new();
[JsonRequired] public List<ArgValue> game { get; set; } = new();
}

View File

@@ -0,0 +1,27 @@
namespace Млаумчерб.Клиент.классы;
public class VersionCatalog
{
[JsonRequired] public List<RemoteVersionDescriptorProps> versions { get; set; } = null!;
}
public class AssetProperties
{
[JsonRequired] public string hash { get; set; } = "";
[JsonRequired] public int size { get; set; }
}
public class AssetIndex
{
[JsonRequired] public Dictionary<string, AssetProperties> objects { get; set; } = new();
}
public class RemoteVersionDescriptorProps
{
[JsonRequired] public string id { get; set; } = "";
[JsonRequired] public string type { get; set; } = "";
[JsonRequired] public string url { get; set; } = "";
[JsonRequired] public string sha1 { get; set; } = "";
[JsonRequired] public DateTime time { get; set; }
[JsonRequired] public DateTime releaseTime { get; set; }
}

View File

@@ -1,129 +1,28 @@
using Newtonsoft.Json;
using System.Runtime.InteropServices;
// ReSharper disable CollectionNeverUpdated.Global
namespace Млаумчерб.Клиент.классы;
public class Artifact
{
[JsonRequired] public string url { get; set; } = "";
[JsonRequired] public string sha1 { get; set; } = "";
[JsonRequired] public int size { get; set; }
}
public class Os
{
[JsonRequired] public string name { get; set; } = "";
}
public class Rule
{
[JsonRequired] public string action { get; set; } = "";
public Os? os { get; set; }
public Dictionary<string, bool>? features { get; set; }
}
public class Classifiers
{
[JsonProperty("natives-linux")]
public Artifact? nativeslinux { get; set; }
[JsonProperty("natives-osx")]
public Artifact? nativesosx { get; set; }
[JsonProperty("natives-windows")]
public Artifact? nativeswindows { get; set; }
}
public class LibraryDownloads
{
public Artifact? artifact { get; set; }
public Classifiers? classifiers { get; set; }
}
public class Extract
{
public List<string>? exclude { get; set; }
}
public class Natives
{
public string? linux { get; set; }
public string? osx { get; set; }
public string? windows { get; set; }
}
public class Library
{
[JsonRequired] public string name { get; set; } = "";
public List<Rule>? rules { get; set; }
public Natives? natives { get; set; }
public Extract? extract { get; set; }
[JsonRequired] public LibraryDownloads downloads { get; set; } = null!;
}
public class AssetIndex
{
[JsonRequired] public string id { get; set; } = "";
[JsonRequired] public int totalSize { get; set; }
[JsonRequired] public bool known { get; set; }
[JsonRequired] public string url { get; set; } = "";
[JsonRequired] public string sha1 { get; set; } = "";
[JsonRequired] public int size { get; set; }
}
public class Downloads
{
[JsonRequired] public Artifact client { get; set; } = null!;
}
public class JavaVersion
{
[JsonRequired] public string component { get; set; } = "";
[JsonRequired] public int majorVersion { get; set; }
}
public class ArgValue
{
[JsonRequired] public string value { get; set; } = "";
public List<Rule> rules { get; set; } = new();
}
public class ArgumentsNew
{
[JsonRequired] public List<ArgValue> jvm { get; set; } = new();
[JsonRequired] public List<ArgValue> game { get; set; } = new();
}
public class MinecraftVersionDescriptor
{
[JsonRequired] public string id { get; set; } = "";
[JsonRequired] public string jar { get; set; } = "";
[JsonRequired] public string family { get; set; } = "";
[JsonRequired] public DateTime time { get; set; }
[JsonRequired] public DateTime releaseTime { get; set; }
[JsonRequired] public string type { get; set; } = "";
[JsonRequired] public string mainClass { get; set; } = "";
[JsonRequired] public Downloads downloads { get; set; } = null!;
[JsonRequired] public JavaVersion javaVersion { get; set; } = null!;
[JsonRequired] public List<Library> libraries { get; set; } = null!;
[JsonRequired] public AssetIndex assetIndex { get; set; } = null!;
[JsonRequired] public string assets { get; set; } = "";
public string? minecraftArguments { get; set; }
public ArgumentsNew? arguments { get; set; }
}
public static class Буржуазия
{
public static bool CheckOs(Os os)
{
return os.name switch
public static bool CheckOs(Os os) =>
os.name switch
{
null => true,
"osx" => OperatingSystem.IsWindows(),
"linux" => OperatingSystem.IsLinux(),
"windows" => OperatingSystem.IsWindows(),
_ => throw new ArgumentOutOfRangeException(os.name)
}
&& os.arch switch
{
null => true,
"x86" => RuntimeInformation.OSArchitecture == Architecture.X86,
"x64" => RuntimeInformation.OSArchitecture == Architecture.X64,
"arm64" => RuntimeInformation.OSArchitecture == Architecture.Arm64,
_ => false
};
}
public static bool CheckRules(ICollection<Rule> rules, ICollection<string> enabled_features)
{
bool allowed = false;
@@ -139,9 +38,8 @@ public static class Буржуазия
{
if (is_enabled)
{
if (r.action == "allow")
allowed = true;
else return false;
if (r.action != "allow")
return false;
}
}
}
@@ -155,4 +53,4 @@ public static class Буржуазия
return allowed;
}
}
}

View File

@@ -1,89 +1,25 @@
using DTLib.Extensions;
namespace Млаумчерб.Клиент.классы;
namespace Млаумчерб.Клиент.классы;
public class Пролетариат
public static class Пролетариат
{
public static IOPath GetAssetIndexFilePath(string id) =>
Path.Concat(Приложение.Настройки.путь_к_кубачу, $"assets/indexes/{id}.json");
}
public class ArgumentsWithPlaceholders
{
protected List<string> raw_args = new();
public List<string> FillPlaceholders(Dictionary<string, string> values)
{
List<string> result = new();
foreach (var a in raw_args)
{
var f = a;
int begin = a.IndexOf('$');
if (begin != -1)
{
int keyBegin = begin + 2;
int end = a.IndexOf('}', keyBegin);
if (end != -1)
{
var key = a.Substring(keyBegin, end - keyBegin);
if (!values.TryGetValue(key, out var v))
throw new Exception($"can't find value for placeholder '{key}'");
f = v;
}
}
result.Add(f);
}
return result;
}
}
public class JavaArguments : ArgumentsWithPlaceholders
{
private static readonly string[] _initial_arguments =
[
];
private static readonly string[] _enabled_features =
[
];
public JavaArguments(MinecraftVersionDescriptor d)
{
raw_args.AddRange(_initial_arguments);
if (d.arguments is not null)
{
foreach (var av in d.arguments.jvm)
{
if(Буржуазия.CheckRules(av.rules, _enabled_features))
raw_args.Add(av.value);
}
}
}
}
public class GameArguments : ArgumentsWithPlaceholders
{
private static readonly string[] _enabled_features =
[
"has_custom_resolution"
];
public static IOPath GetVersionDescriptorDir() =>
Path.Concat(Приложение.Настройки.путь_к_кубачу, "version_descriptors");
public GameArguments(MinecraftVersionDescriptor d)
{
if (d.minecraftArguments is not null)
{
raw_args.AddRange(d.minecraftArguments.SplitToList(' ', quot: '"'));
}
else if (d.arguments is not null)
{
foreach (var av in d.arguments.game)
{
if(Буржуазия.CheckRules(av.rules, _enabled_features))
raw_args.Add(av.value);
}
}
}
}
public static string GetVersionDescriptorName(IOPath path) =>
path.LastName().RemoveExtension().ToString();
public static IOPath GetVersionDescriptorPath(string name) =>
Path.Concat(GetVersionDescriptorDir(), Path.ReplaceRestrictedChars(name) + ".json");
public static IOPath GetVersionDir() =>
Path.Concat(Приложение.Настройки.путь_к_кубачу, "versions");
public static IOPath GetVersionJarFilePath(string name) =>
Path.Concat(GetVersionDir(), name + ".jar");
public static IOPath GetLibrariesDir() =>
Path.Concat(Приложение.Настройки.путь_к_кубачу, "libraries");
}