Basic packing/extraction of saves. Files only, no directories or registry entries.

This commit is contained in:
Pat Hartl 2023-03-28 23:10:18 -05:00
parent 32d6e109df
commit aa8aba154e

View file

@ -1,4 +1,5 @@
using ICSharpCode.SharpZipLib.Zip;
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;
using LANCommander.PlaynitePlugin.Extensions;
using LANCommander.SDK;
using Playnite.SDK;
@ -6,6 +7,7 @@ using Playnite.SDK.Events;
using Playnite.SDK.Models;
using Playnite.SDK.Plugins;
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
@ -267,9 +269,99 @@ namespace LANCommander.PlaynitePlugin
};
}
public override void OnGameStarting(OnGameStartingEventArgs args)
{
DownloadSave(args.Game);
}
private void DownloadSave(Game game)
{
string tempFile = String.Empty;
if (game != null)
{
PlayniteApi.Dialogs.ActivateGlobalProgress(progress =>
{
progress.ProgressMaxValue = 100;
progress.CurrentProgressValue = 0;
var destination = LANCommander.DownloadLatestSave(Guid.Parse(game.GameId), (changed) =>
{
progress.CurrentProgressValue = changed.ProgressPercentage;
}, (complete) =>
{
progress.CurrentProgressValue = 100;
});
// Lock the thread until download is done
while (progress.CurrentProgressValue != 100)
{
}
tempFile = destination;
},
new GlobalProgressOptions("Downloading latest save...")
{
IsIndeterminate = false,
Cancelable = false
});
// Go into the archive and extract the files to the correct locations
try
{
var tempLocation = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempLocation);
ExtractFilesFromZip(tempFile, tempLocation);
var deserializer = new DeserializerBuilder()
.WithNamingConvention(new PascalCaseNamingConvention())
.Build();
var manifestContents = File.ReadAllText(Path.Combine(tempLocation, "_manifest.yml"));
var manifest = deserializer.Deserialize<GameManifest>(manifestContents);
foreach (var savePath in manifest.SavePaths)
{
var pathTemp = Path.Combine(tempLocation, savePath.Id.ToString(), savePath.Path.Replace('/', '\\').Replace("{InstallDir}\\", ""));
var destination = savePath.Path.Replace('/', '\\').Replace("{InstallDir}", game.InstallDirectory);
if (File.Exists(pathTemp))
{
if (File.Exists(destination))
File.Delete(destination);
File.Move(pathTemp, destination);
}
else if (Directory.Exists(pathTemp))
{
// Better way to handle this? Maybe merge files?
Directory.Delete(destination, true);
Directory.Move(pathTemp, destination);
}
}
// Clean up temp files
Directory.Delete(tempLocation, true);
}
catch (Exception ex)
{
}
}
}
public override void OnGameStopped(OnGameStoppedEventArgs args)
{
var manifestPath = Path.Combine(args.Game.InstallDirectory, "_manifest.yml");
UploadSave(args.Game);
}
private void UploadSave(Game game)
{
var manifestPath = Path.Combine(game.InstallDirectory, "_manifest.yml");
if (File.Exists(manifestPath))
{
@ -286,27 +378,36 @@ namespace LANCommander.PlaynitePlugin
foreach (var savePath in manifest.SavePaths)
{
savePath.Path = savePath.Path.Replace('/', '\\').Replace("{InstallDir}", args.Game.InstallDirectory);
var localPath = savePath.Path.Replace('/', '\\').Replace("{InstallDir}", game.InstallDirectory);
if (Directory.Exists(savePath.Path))
if (Directory.Exists(localPath))
{
AddDirectoryToZip(zipStream, savePath.Path);
AddDirectoryToZip(zipStream, localPath);
}
else if (File.Exists(savePath.Path))
else if (File.Exists(localPath))
{
var entry = new ZipEntry(Path.Combine(savePath.Id.ToString(), Path.GetFileName(savePath.Path)));
var entry = new ZipEntry(Path.Combine(savePath.Id.ToString(), savePath.Path.Replace("{InstallDir}/", "")));
zipStream.PutNextEntry(entry);
byte[] buffer = File.ReadAllBytes(savePath.Path);
byte[] buffer = File.ReadAllBytes(localPath);
zipStream.Write(buffer, 0, buffer.Length);
zipStream.CloseEntry();
}
}
var manifestEntry = new ZipEntry("_manifest.yml");
zipStream.PutNextEntry(manifestEntry);
byte[] manifestBuffer = File.ReadAllBytes(manifestPath);
zipStream.Write(manifestBuffer, 0, manifestBuffer.Length);
zipStream.CloseEntry();
}
var save = LANCommander.UploadSave(args.Game.GameId, File.ReadAllBytes(temp));
var save = LANCommander.UploadSave(game.GameId, File.ReadAllBytes(temp));
File.Delete(temp);
}
@ -338,6 +439,46 @@ namespace LANCommander.PlaynitePlugin
}
}
private void ExtractFilesFromZip(string zipPath, string destination)
{
ZipFile file = null;
try
{
FileStream fs = File.OpenRead(zipPath);
file = new ZipFile(fs);
foreach (ZipEntry entry in file)
{
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);
}
}
}
finally
{
if (file != null)
{
file.IsStreamOwner = true;
file.Close();
}
}
}
public override IEnumerable<TopPanelItem> GetTopPanelItems()
{
yield return new TopPanelItem