LANCommander/LANCommander.Playnite.Exten.../InstallController.cs

204 lines
6.7 KiB
C#
Raw Normal View History

2023-01-07 04:12:03 +00:00
using Playnite.SDK;
using Playnite.SDK.Models;
using Playnite.SDK.Plugins;
using LANCommander.SDK.Enums;
2023-01-07 04:12:03 +00:00
using LANCommander.SDK.Extensions;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Core;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
using LANCommander.SDK.Models;
using System.Collections.ObjectModel;
2023-01-07 04:12:03 +00:00
namespace LANCommander.PlaynitePlugin
2023-01-07 04:12:03 +00:00
{
public class LANCommanderInstallController : InstallController
{
private LANCommanderLibraryPlugin Plugin;
2023-01-15 07:10:36 +00:00
private PowerShellRuntime PowerShellRuntime;
private Playnite.SDK.Models.Game PlayniteGame;
2023-01-07 04:12:03 +00:00
public LANCommanderInstallController(LANCommanderLibraryPlugin plugin, Playnite.SDK.Models.Game game) : base(game)
2023-01-07 04:12:03 +00:00
{
Name = "Install using LANCommander";
Plugin = plugin;
2023-01-15 07:10:36 +00:00
PlayniteGame = game;
PowerShellRuntime = new PowerShellRuntime();
2023-01-07 04:12:03 +00:00
}
public override void Install(InstallActionArgs args)
{
var gameId = Guid.Parse(Game.GameId);
var game = Plugin.LANCommander.GetGame(gameId);
var manifest = Plugin.LANCommander.GetGameManifest(gameId);
2023-01-07 04:12:03 +00:00
var tempFile = Download(game);
var installDirectory = Extract(game, tempFile);
2023-01-15 07:10:36 +00:00
var installInfo = new GameInstallationData()
{
InstallDirectory = installDirectory
};
2023-01-15 07:10:36 +00:00
PlayniteGame.InstallDirectory = installDirectory;
WriteManifest(manifest, installDirectory);
SaveScript(game, installDirectory, ScriptType.Install);
SaveScript(game, installDirectory, ScriptType.Uninstall);
SaveScript(game, installDirectory, ScriptType.NameChange);
SaveScript(game, installDirectory, ScriptType.KeyChange);
try
{
PowerShellRuntime.RunScript(PlayniteGame, ScriptType.Install);
PowerShellRuntime.RunScript(PlayniteGame, ScriptType.NameChange, Plugin.Settings.PlayerName);
2023-01-28 23:18:41 +00:00
var key = Plugin.LANCommander.GetAllocatedKey(game.Id);
PowerShellRuntime.RunScript(PlayniteGame, ScriptType.KeyChange, $"\"{key}\"");
}
catch { }
2023-01-15 07:10:36 +00:00
Plugin.UpdateGame(manifest, gameId);
InvokeOnInstalled(new GameInstalledEventArgs(installInfo));
2023-01-07 04:12:03 +00:00
}
private string Download(LANCommander.SDK.Models.Game game)
{
string tempFile = String.Empty;
if (game != null)
2023-01-07 04:12:03 +00:00
{
Plugin.PlayniteApi.Dialogs.ActivateGlobalProgress(progress =>
2023-01-07 04:12:03 +00:00
{
progress.ProgressMaxValue = 100;
progress.CurrentProgressValue = 0;
var destination = Plugin.LANCommander.DownloadGame(game.Id, (changed) =>
2023-01-07 04:12:03 +00:00
{
progress.CurrentProgressValue = changed.ProgressPercentage;
}, (complete) =>
{
progress.CurrentProgressValue = 100;
});
// Lock the thread until download is done
2023-01-07 04:12:03 +00:00
while (progress.CurrentProgressValue != 100)
{
}
tempFile = destination;
},
new GlobalProgressOptions($"Downloading {game.Title}...")
2023-01-07 04:12:03 +00:00
{
IsIndeterminate = false,
Cancelable = false,
});
return tempFile;
}
else
throw new Exception("Game failed to download!");
2023-01-07 04:12:03 +00:00
}
private string Extract(LANCommander.SDK.Models.Game game, string archivePath)
2023-01-07 04:12:03 +00:00
{
var destination = Path.Combine(Plugin.Settings.InstallDirectory, game.Title.SanitizeFilename());
2023-01-07 04:12:03 +00:00
Plugin.PlayniteApi.Dialogs.ActivateGlobalProgress(progress =>
2023-01-07 04:12:03 +00:00
{
ZipFile file = null;
2023-01-07 04:12:03 +00:00
try
2023-01-07 04:12:03 +00:00
{
FileStream fs = File.OpenRead(archivePath);
2023-01-07 04:12:03 +00:00
file = new ZipFile(fs);
2023-01-07 04:12:03 +00:00
progress.ProgressMaxValue = file.Count;
2023-01-07 04:12:03 +00:00
foreach (ZipEntry entry in file)
2023-01-07 04:12:03 +00:00
{
if (!entry.IsFile)
continue;
byte[] buffer = new byte[4096];
var zipStream = file.GetInputStream(entry);
var entryDestination = Path.Combine(destination, entry.Name);
var entryDirectory = Path.GetDirectoryName(entryDestination);
if (!String.IsNullOrWhiteSpace(entryDirectory))
Directory.CreateDirectory(entryDirectory);
using (FileStream streamWriter = File.Create(entryDestination))
{
StreamUtils.Copy(zipStream, streamWriter, buffer);
}
progress.CurrentProgressValue = entry.ZipFileIndex;
2023-01-07 04:12:03 +00:00
}
}
finally
2023-01-07 04:12:03 +00:00
{
if (file != null)
{
file.IsStreamOwner = true;
file.Close();
}
File.Delete(archivePath);
2023-01-07 04:12:03 +00:00
}
},
new GlobalProgressOptions($"Extracting {game.Title}...")
{
IsIndeterminate = false,
Cancelable = false,
});
2023-01-07 04:12:03 +00:00
return destination;
2023-01-07 04:12:03 +00:00
}
private void WriteManifest(SDK.GameManifest manifest, string installDirectory)
{
var serializer = new SerializerBuilder()
.WithNamingConvention(PascalCaseNamingConvention.Instance)
.Build();
var yaml = serializer.Serialize(manifest);
File.WriteAllText(Path.Combine(installDirectory, "_manifest.yml"), yaml);
}
private void SaveScript(LANCommander.SDK.Models.Game game, string installationDirectory, ScriptType type)
{
var script = game.Scripts.FirstOrDefault(s => s.Type == type);
if (script == null)
return;
if (script.RequiresAdmin)
script.Contents = "# Requires Admin" + "\r\n\r\n" + script.Contents;
var filename = PowerShellRuntime.GetScriptFilePath(PlayniteGame, type);
if (File.Exists(filename))
File.Delete(filename);
File.WriteAllText(filename, script.Contents);
}
2023-01-07 04:12:03 +00:00
}
}