mlaumcherb/Млаумчерб.Клиент/Игра.cs
2024-11-04 01:45:06 +05:00

142 lines
5.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Linq;
using CliWrap;
using DTLib.Extensions;
using Млаумчерб.Клиент.зримое;
using Млаумчерб.Клиент.классы;
using Млаумчерб.Клиент.сеть;
using Млаумчерб.Клиент.сеть.NetworkTaskFactories;
using static Млаумчерб.Клиент.классы.Пути;
namespace Млаумчерб.Клиент;
public class GameVersion
{
private readonly GameVersionProps _props;
public string Name => _props.Name;
public IOPath WorkingDirectory { get; }
private IOPath JavaExecutableFilePath;
private GameVersionDescriptor descriptor;
private JavaArguments javaArgs;
private GameArguments gameArgs;
private Libraries libraries;
private CancellationTokenSource? gameCts;
private CommandTask<CommandResult>? commandTask;
public static async Task<List<GameVersionProps>> GetAllVersionsAsync()
{
var propsSet = new HashSet<GameVersionProps>();
// local descriptors
foreach (IOPath f in Directory.GetFiles(GetVersionDescriptorsDir()))
{
string name = GetVersionDescriptorName(f);
propsSet.Add(new GameVersionProps(name, null, f));
}
// remote non-duplicating versions
foreach (var removeVersion in await Сеть.GetDownloadableVersions())
{
propsSet.Add(removeVersion);
}
// reverse sort
var propsList = propsSet.ToList();
propsList.Sort((a, b) => b.CompareTo(a));
return propsList;
}
public static async Task<GameVersion> CreateFromPropsAsync(GameVersionProps props)
{
if (!File.Exists(props.LocalDescriptorPath))
{
if (props.RemoteDescriptorUrl is null)
throw new NullReferenceException("can't download game version descriptor '"
+ props.Name + "', because RemoteDescriptorUrl is null");
await Сеть.DownloadFile(props.RemoteDescriptorUrl, props.LocalDescriptorPath);
}
return new GameVersion(props);
}
private GameVersion(GameVersionProps props)
{
_props = props;
string descriptorText = File.ReadAllText(props.LocalDescriptorPath);
descriptor = JsonConvert.DeserializeObject<GameVersionDescriptor>(descriptorText)
?? throw new Exception($"can't parse descriptor file '{props.LocalDescriptorPath}'");
javaArgs = new JavaArguments(descriptor);
gameArgs = new GameArguments(descriptor);
libraries = new Libraries(descriptor);
WorkingDirectory = GetVersionDir(descriptor.id);
JavaExecutableFilePath = GetJavaExecutablePath(descriptor.javaVersion.component);
}
public async Task UpdateFiles(bool checkHashes, Action<NetworkTask> networkTaskCreatedCallback)
{
Приложение.Логгер.LogInfo(nameof(GameVersion), $"started updating version {Name}");
List<INetworkTaskFactory> taskFactories =
[
new AssetsDownloadTaskFactory(descriptor),
new LibrariesDownloadTaskFactory(descriptor, libraries),
new VersionFileDownloadTaskFactory(descriptor),
];
if(Приложение.Настройки.скачиватьабу)
{
taskFactories.Add(new JavaDownloadTaskFactory(descriptor));
}
//TODO: modpack
/*if (modpack != null)
{
taskFactories.Add(new ModpackDownloadTaskFactory(modpack));
}*/
var networkTasks = new List<NetworkTask>();
for (int i = 0; i < taskFactories.Count; i++)
{
var nt = await taskFactories[i].CreateAsync(checkHashes);
if (nt != null)
{
networkTasks.Add(nt);
networkTaskCreatedCallback.Invoke(nt);
}
}
foreach (var nt in networkTasks)
{
await nt.StartAsync();
}
_props.IsDownloaded = true;
Приложение.Логгер.LogInfo(nameof(GameVersion), $"finished updating version {Name}");
}
public async Task Launch()
{
var javaArgsList = javaArgs.FillPlaceholders([]);
var gameArgsList = gameArgs.FillPlaceholders([]);
var command = Cli.Wrap(JavaExecutableFilePath.ToString())
.WithWorkingDirectory(WorkingDirectory.ToString())
.WithArguments(javaArgsList)
.WithArguments(gameArgsList);
Приложение.Логгер.LogInfo(nameof(GameVersion),
$"launching the game" +
"\njava: " + command.TargetFilePath +
"\nworking_dir: " + command.WorkingDirPath +
"\njava_arguments: \n\t" + javaArgsList.MergeToString("\n\t") +
"\ngame_arguments: \n\t" + gameArgsList.MergeToString("\n\t"));
gameCts = new();
commandTask = command.ExecuteAsync(gameCts.Token);
var result = await commandTask;
Приложение.Логгер.LogInfo(nameof(GameVersion), $"game exited with code {result.ExitCode}");
}
public void Close()
{
gameCts?.Cancel();
}
public override string ToString() => Name;
}