diff --git a/LANCommander.Playnite.Extension/InstallController.cs b/LANCommander.Playnite.Extension/InstallController.cs index 44c3923..d9f4f87 100644 --- a/LANCommander.Playnite.Extension/InstallController.cs +++ b/LANCommander.Playnite.Extension/InstallController.cs @@ -1,23 +1,17 @@ -using Playnite.SDK; -using Playnite.SDK.Models; -using Playnite.SDK.Plugins; +using LANCommander.PlaynitePlugin.Helpers; using LANCommander.SDK.Enums; using LANCommander.SDK.Extensions; +using LANCommander.SDK.Models; +using Playnite.SDK; +using Playnite.SDK.Models; +using Playnite.SDK.Plugins; +using SharpCompress.Common; +using SharpCompress.Readers; 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; -using System.Web.Caching; -using LANCommander.PlaynitePlugin.Helpers; namespace LANCommander.PlaynitePlugin { @@ -45,19 +39,9 @@ namespace LANCommander.PlaynitePlugin var gameId = Guid.Parse(Game.GameId); var game = Plugin.LANCommander.GetGame(gameId); - string tempDownloadLocation; - - if (Plugin.DownloadCache.ContainsKey(gameId)) - tempDownloadLocation = Plugin.DownloadCache[gameId]; - else - { - tempDownloadLocation = Download(game); - Plugin.DownloadCache[gameId] = tempDownloadLocation; - } - var installDirectory = RetryHelper.RetryOnException(10, TimeSpan.FromMilliseconds(500), "", () => { - return Extract(game, tempDownloadLocation); + return DownloadAndExtract(game); }); if (installDirectory == "") @@ -103,11 +87,61 @@ namespace LANCommander.PlaynitePlugin Plugin.UpdateGame(manifest, gameId); Plugin.DownloadCache.Remove(gameId); - File.Delete(tempDownloadLocation); InvokeOnInstalled(new GameInstalledEventArgs(installInfo)); } + private string DownloadAndExtract(LANCommander.SDK.Models.Game game) + { + if (game == null) + { + throw new Exception("Game failed to download!"); + } + + var destination = Path.Combine(Plugin.Settings.InstallDirectory, game.Title.SanitizeFilename()); + + Plugin.PlayniteApi.Dialogs.ActivateGlobalProgress(progress => + { + try + { + Directory.CreateDirectory(destination); + progress.ProgressMaxValue = 100; + progress.CurrentProgressValue = 0; + + using (var gameStream = Plugin.LANCommander.StreamGame(game.Id)) + using (var reader = ReaderFactory.Open(gameStream)) + { + progress.ProgressMaxValue = gameStream.Length; + + gameStream.OnProgress += (pos, len) => + { + progress.CurrentProgressValue = pos; + }; + + reader.WriteAllToDirectory(destination, new ExtractionOptions() + { + ExtractFullPath = true, + Overwrite = true + }); + } + } + catch (Exception ex) + { + if (Directory.Exists(destination)) + { + Directory.Delete(destination, true); + } + } + }, + new GlobalProgressOptions($"Downloading {game.Title}...") + { + IsIndeterminate = false, + Cancelable = false, + }); + + return destination; + } + private string Download(LANCommander.SDK.Models.Game game) { string tempFile = String.Empty; @@ -153,45 +187,23 @@ namespace LANCommander.PlaynitePlugin Plugin.PlayniteApi.Dialogs.ActivateGlobalProgress(progress => { - ZipFile file = null; + Directory.CreateDirectory(destination); - try + using (var fs = File.OpenRead(archivePath)) + using (var ts = new TrackableStream(fs)) + using (var reader = ReaderFactory.Open(ts)) { - FileStream fs = File.OpenRead(archivePath); - - file = new ZipFile(fs); - - progress.ProgressMaxValue = file.Count; - - foreach (ZipEntry entry in file) + progress.ProgressMaxValue = ts.Length; + ts.OnProgress += (pos, len) => { - if (!entry.IsFile) - continue; + progress.CurrentProgressValue = pos; + }; - 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; - } - } - finally - { - if (file != null) + reader.WriteAllToDirectory(destination, new ExtractionOptions() { - file.IsStreamOwner = true; - file.Close(); - } + ExtractFullPath = true, + Overwrite = true + }); } }, new GlobalProgressOptions($"Extracting {game.Title}...") diff --git a/LANCommander.Playnite.Extension/LANCommander.PlaynitePlugin.csproj b/LANCommander.Playnite.Extension/LANCommander.PlaynitePlugin.csproj index 9f42d54..bc92634 100644 --- a/LANCommander.Playnite.Extension/LANCommander.PlaynitePlugin.csproj +++ b/LANCommander.Playnite.Extension/LANCommander.PlaynitePlugin.csproj @@ -34,9 +34,6 @@ ..\packages\rix0rrr.BeaconLib.1.0.2\lib\net40\BeaconLib.dll - - ..\packages\SharpZipLib.1.4.2\lib\netstandard2.0\ICSharpCode.SharpZipLib.dll - ..\packages\Microsoft.Bcl.AsyncInterfaces.5.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll @@ -48,6 +45,9 @@ ..\packages\RestSharp.106.15.0\lib\net452\RestSharp.dll + + ..\packages\SharpCompress.0.33.0\lib\net462\SharpCompress.dll + ..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll @@ -64,8 +64,11 @@ ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll - - ..\packages\System.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll + + ..\packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll + + + ..\packages\System.Text.Encoding.CodePages.7.0.0\lib\net462\System.Text.Encoding.CodePages.dll ..\packages\System.Text.Encodings.Web.5.0.0\lib\net461\System.Text.Encodings.Web.dll @@ -93,6 +96,7 @@ + diff --git a/LANCommander.Playnite.Extension/LANCommanderClient.cs b/LANCommander.Playnite.Extension/LANCommanderClient.cs index 787148e..990e825 100644 --- a/LANCommander.Playnite.Extension/LANCommanderClient.cs +++ b/LANCommander.Playnite.Extension/LANCommanderClient.cs @@ -1,7 +1,6 @@ using LANCommander.SDK; using LANCommander.SDK.Models; using RestSharp; -using RestSharp.Extensions; using System; using System.Collections.Generic; using System.ComponentModel; @@ -9,10 +8,7 @@ using System.IO; using System.Linq; using System.Net; using System.Net.NetworkInformation; -using System.Text; using System.Threading.Tasks; -using System.Windows.Media.Converters; -using YamlDotNet.Core; namespace LANCommander.PlaynitePlugin { @@ -64,6 +60,20 @@ namespace LANCommander.PlaynitePlugin return tempFile; } + private TrackableStream StreamRequest(string route) + { + route = route.TrimStart('/'); + + var client = new WebClient(); + var tempFile = Path.GetTempFileName(); + + client.Headers.Add("Authorization", $"Bearer {Token.AccessToken}"); + + var ws = client.OpenRead(new Uri($"{Client.BaseUrl}{route}")); + + return new TrackableStream(ws, true, Convert.ToInt64(client.ResponseHeaders["Content-Length"])); + } + public async Task AuthenticateAsync(string username, string password) { var response = await Client.ExecuteAsync(new RestRequest("/api/Auth", Method.POST).AddJsonBody(new AuthRequest() @@ -166,6 +176,11 @@ namespace LANCommander.PlaynitePlugin return DownloadRequest($"/api/Games/{id}/Download", progressHandler, completeHandler); } + public TrackableStream StreamGame(Guid id) + { + return StreamRequest($"/api/Games/{id}/Download"); + } + public string DownloadArchive(Guid id, Action progressHandler, Action completeHandler) { return DownloadRequest($"/api/Archives/Download/{id}", progressHandler, completeHandler); diff --git a/LANCommander.Playnite.Extension/LANCommanderLibraryPlugin.cs b/LANCommander.Playnite.Extension/LANCommanderLibraryPlugin.cs index 8d0c32e..9530dd6 100644 --- a/LANCommander.Playnite.Extension/LANCommanderLibraryPlugin.cs +++ b/LANCommander.Playnite.Extension/LANCommanderLibraryPlugin.cs @@ -1,28 +1,17 @@ -using ICSharpCode.SharpZipLib.Core; -using ICSharpCode.SharpZipLib.Zip; -using LANCommander.PlaynitePlugin.Extensions; +using LANCommander.PlaynitePlugin.Extensions; using LANCommander.PlaynitePlugin.Services; -using LANCommander.SDK; using Playnite.SDK; 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; using System.IO; using System.Linq; -using System.Net.NetworkInformation; -using System.Text; -using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; -using System.Windows.Data; using System.Windows.Media; -using YamlDotNet.Serialization; -using YamlDotNet.Serialization.NamingConventions; using PN = Playnite; namespace LANCommander.PlaynitePlugin @@ -294,9 +283,10 @@ namespace LANCommander.PlaynitePlugin FontSize = 16, FontFamily = ResourceProvider.GetResource("FontIcoFont") as FontFamily, Padding = new Thickness(10, 0, 10, 0), - + }, - Activated = () => { + Activated = () => + { ShowNameChangeWindow(); } }; diff --git a/LANCommander.Playnite.Extension/Services/GameSaveService.cs b/LANCommander.Playnite.Extension/Services/GameSaveService.cs index 0a9dba7..bf9cbe5 100644 --- a/LANCommander.Playnite.Extension/Services/GameSaveService.cs +++ b/LANCommander.Playnite.Extension/Services/GameSaveService.cs @@ -1,16 +1,17 @@ -using ICSharpCode.SharpZipLib.Zip; -using LANCommander.SDK; +using LANCommander.SDK; +using Playnite.SDK; using Playnite.SDK.Models; +using SharpCompress.Archives; +using SharpCompress.Archives.Zip; +using SharpCompress.Common; +using SharpCompress.Readers; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; -using System.Threading.Tasks; -using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization; -using ICSharpCode.SharpZipLib.Core; -using Playnite.SDK; +using YamlDotNet.Serialization.NamingConventions; namespace LANCommander.PlaynitePlugin.Services { @@ -20,7 +21,8 @@ namespace LANCommander.PlaynitePlugin.Services private readonly IPlayniteAPI PlayniteApi; private readonly PowerShellRuntime PowerShellRuntime; - internal GameSaveService(LANCommanderClient lanCommander, IPlayniteAPI playniteApi, PowerShellRuntime powerShellRuntime) { + internal GameSaveService(LANCommanderClient lanCommander, IPlayniteAPI playniteApi, PowerShellRuntime powerShellRuntime) + { LANCommander = lanCommander; PlayniteApi = playniteApi; PowerShellRuntime = powerShellRuntime; @@ -166,9 +168,9 @@ namespace LANCommander.PlaynitePlugin.Services var manifest = deserializer.Deserialize(File.ReadAllText(manifestPath)); var temp = Path.GetTempFileName(); - using (ZipOutputStream zipStream = new ZipOutputStream(File.Create(temp))) + using (var archive = ZipArchive.Create()) { - zipStream.SetLevel(5); + archive.DeflateCompressionLevel = SharpCompress.Compressors.Deflate.CompressionLevel.BestCompression; #region Add files from defined paths foreach (var savePath in manifest.SavePaths.Where(sp => sp.Type == "File")) @@ -177,18 +179,27 @@ namespace LANCommander.PlaynitePlugin.Services if (Directory.Exists(localPath)) { - AddDirectoryToZip(zipStream, localPath, localPath, savePath.Id); + AddDirectoryToZip(archive, localPath, localPath, savePath.Id); } else if (File.Exists(localPath)) { - var entry = new ZipEntry(Path.Combine(savePath.Id.ToString(), savePath.Path.Replace("{InstallDir}/", ""))); + archive.AddEntry(Path.Combine(savePath.Id.ToString(), savePath.Path.Replace("{InstallDir}/", "")), localPath); + } + } + #endregion - zipStream.PutNextEntry(entry); + #region Add files from defined paths + foreach (var savePath in manifest.SavePaths.Where(sp => sp.Type == "File")) + { + var localPath = Environment.ExpandEnvironmentVariables(savePath.Path.Replace('/', '\\').Replace("{InstallDir}", game.InstallDirectory)); - byte[] buffer = File.ReadAllBytes(localPath); - - zipStream.Write(buffer, 0, buffer.Length); - zipStream.CloseEntry(); + if (Directory.Exists(localPath)) + { + AddDirectoryToZip(archive, localPath, localPath, savePath.Id); + } + else if (File.Exists(localPath)) + { + archive.AddEntry(Path.Combine(savePath.Id.ToString(), savePath.Path.Replace("{InstallDir}/", "")), localPath); } } #endregion @@ -218,47 +229,32 @@ namespace LANCommander.PlaynitePlugin.Services File.Delete(tempRegFile); } - zipStream.PutNextEntry(new ZipEntry("_registry.reg")); - - byte[] regBuffer = Encoding.UTF8.GetBytes(exportFile.ToString()); - - zipStream.Write(regBuffer, 0, regBuffer.Length); - zipStream.CloseEntry(); + archive.AddEntry("_registry.reg", new MemoryStream(Encoding.UTF8.GetBytes(exportFile.ToString())), true); } #endregion - var manifestEntry = new ZipEntry("_manifest.yml"); + archive.AddEntry("_manifest.yml", manifestPath); - zipStream.PutNextEntry(manifestEntry); + using (var ms = new MemoryStream()) + { + archive.SaveTo(ms); - byte[] manifestBuffer = File.ReadAllBytes(manifestPath); + ms.Seek(0, SeekOrigin.Begin); - zipStream.Write(manifestBuffer, 0, manifestBuffer.Length); - zipStream.CloseEntry(); + var save = LANCommander.UploadSave(game.GameId, ms.ToArray()); + } } - - var save = LANCommander.UploadSave(game.GameId, File.ReadAllBytes(temp)); - - File.Delete(temp); } } - private void AddDirectoryToZip(ZipOutputStream zipStream, string path, string workingDirectory, Guid pathId) + private void AddDirectoryToZip(ZipArchive zipArchive, string path, string workingDirectory, Guid pathId) { foreach (var file in Directory.GetFiles(path)) { // Oh man is this a hack. We should be removing only the working directory from the start, // but we're making the assumption that the working dir put in actually prefixes the path. // Also wtf, that Path.Combine is stripping the pathId out? - var entry = new ZipEntry(Path.Combine(pathId.ToString(), path.Substring(workingDirectory.Length), Path.GetFileName(file))); - - zipStream.PutNextEntry(entry); - - byte[] buffer = File.ReadAllBytes(file); - - zipStream.Write(buffer, 0, buffer.Length); - - zipStream.CloseEntry(); + zipArchive.AddEntry(Path.Combine(pathId.ToString(), path.Substring(workingDirectory.Length), Path.GetFileName(file)), file); } foreach (var child in Directory.GetDirectories(path)) @@ -269,47 +265,21 @@ namespace LANCommander.PlaynitePlugin.Services //zipStream.PutNextEntry(entry); //zipStream.CloseEntry(); - AddDirectoryToZip(zipStream, child, workingDirectory, pathId); + AddDirectoryToZip(zipArchive, child, workingDirectory, pathId); } } private void ExtractFilesFromZip(string zipPath, string destination) { - ZipFile file = null; - - try + using (var fs = File.OpenRead(zipPath)) + using (var ts = new TrackableStream(fs)) + using (var reader = ReaderFactory.Open(ts)) { - FileStream fs = File.OpenRead(zipPath); - - file = new ZipFile(fs); - - foreach (ZipEntry entry in file) + reader.WriteAllToDirectory(destination, new ExtractionOptions() { - 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(); - } + ExtractFullPath = true, + Overwrite = true + }); } } } diff --git a/LANCommander.Playnite.Extension/TrackableStream.cs b/LANCommander.Playnite.Extension/TrackableStream.cs new file mode 100644 index 0000000..cff27f8 --- /dev/null +++ b/LANCommander.Playnite.Extension/TrackableStream.cs @@ -0,0 +1,340 @@ +using System; +using System.IO; + +namespace LANCommander.PlaynitePlugin +{ + internal class TrackableStream : MemoryStream, IDisposable + { + public delegate void OnProgressDelegate(long Position, long Length); + public event OnProgressDelegate OnProgress = delegate { }; + private long internalStreamProgress = 0; + private Stream internalStream; + private bool disposeStream = false; + private long? streamLength; + + // + // Summary: + // Initializes a new instance of the TrackableStream class with an expandable + // capacity initialized to zero. + public TrackableStream() : base() { } + + // + // Summary: + // Initializes a new instance of the TrackableStream class with the contents of stream. + // capacity initialized to zero. + public TrackableStream(Stream stream, bool disposeStream = false, long? streamLength = null) : base() + { + internalStream = stream; + this.disposeStream = disposeStream; + this.streamLength = streamLength; + } + + // + // Summary: + // Initializes a new instance of the TrackableStream class with an expandable + // capacity initialized as specified. + // + // Parameters: + // capacity: + // The initial size of the internal array in bytes. + // + // Exceptions: + // T:System.ArgumentOutOfRangeException: + // capacity is negative. + public TrackableStream(int capacity) : base(capacity) { } + + // + // Summary: + // Initializes a new non-resizable instance of the TrackableStream class + // based on the specified byte array. + // + // Parameters: + // buffer: + // The array of unsigned bytes from which to create the current stream. + // + // Exceptions: + // T:System.ArgumentNullException: + // buffer is null. + public TrackableStream(byte[] buffer) : base(buffer) { } + + // + // Summary: + // Initializes a new non-resizable instance of the TrackableStream class + // based on the specified byte array with the TrackableStream.CanWrite property + // set as specified. + // + // Parameters: + // buffer: + // The array of unsigned bytes from which to create this stream. + // + // writable: + // The setting of the TrackableStream.CanWrite property, which determines + // whether the stream supports writing. + // + // Exceptions: + // T:System.ArgumentNullException: + // buffer is null. + public TrackableStream(byte[] buffer, bool writable) : base(buffer, writable) { } + + // + // Summary: + // Initializes a new non-resizable instance of the TrackableStream class + // based on the specified region (index) of a byte array. + // + // Parameters: + // buffer: + // The array of unsigned bytes from which to create this stream. + // + // index: + // The index into buffer at which the stream begins. + // + // count: + // The length of the stream in bytes. + // + // Exceptions: + // T:System.ArgumentNullException: + // buffer is null. + // + // T:System.ArgumentOutOfRangeException: + // index or count is less than zero. + // + // T:System.ArgumentException: + // The buffer length minus index is less than count. + public TrackableStream(byte[] buffer, int index, int count) : base(buffer, index, count) { } + + // + // Summary: + // Initializes a new non-resizable instance of the TrackableStream class + // based on the specified region of a byte array, with the TrackableStream.CanWrite + // property set as specified. + // + // Parameters: + // buffer: + // The array of unsigned bytes from which to create this stream. + // + // index: + // The index in buffer at which the stream begins. + // + // count: + // The length of the stream in bytes. + // + // writable: + // The setting of the TrackableStream.CanWrite property, which determines + // whether the stream supports writing. + // + // Exceptions: + // T:System.ArgumentNullException: + // buffer is null. + // + // T:System.ArgumentOutOfRangeException: + // index or count are negative. + // + // T:System.ArgumentException: + // The buffer length minus index is less than count. + public TrackableStream(byte[] buffer, int index, int count, bool writable) : base(buffer, index, count, writable) { } + + // + // Summary: + // Initializes a new instance of the TrackableStream class based on the specified + // region of a byte array, with the TrackableStream.CanWrite property set + // as specified, and the ability to call TrackableStream.GetBuffer set as + // specified. + // + // Parameters: + // buffer: + // The array of unsigned bytes from which to create this stream. + // + // index: + // The index into buffer at which the stream begins. + // + // count: + // The length of the stream in bytes. + // + // writable: + // The setting of the TrackableStream.CanWrite property, which determines + // whether the stream supports writing. + // + // publiclyVisible: + // true to enable TrackableStream.GetBuffer, which returns the unsigned byte + // array from which the stream was created; otherwise, false. + // + // Exceptions: + // T:System.ArgumentNullException: + // buffer is null. + // + // T:System.ArgumentOutOfRangeException: + // index or count is negative. + // + // T:System.ArgumentException: + // The buffer length minus index is less than count. + public TrackableStream(byte[] buffer, int index, int count, bool writable, bool publiclyVisible) : base(buffer, index, count, writable, publiclyVisible) { } + + // + // Summary: + // Writes a block of bytes to the current stream using data read from a buffer. + // + // Parameters: + // buffer: + // The buffer to write data from. + // + // offset: + // The zero-based byte offset in buffer at which to begin copying bytes to the current + // stream. + // + // count: + // The maximum number of bytes to write. + // + // Exceptions: + // T:System.ArgumentNullException: + // buffer is null. + // + // T:System.NotSupportedException: + // The stream does not support writing. For additional information see System.IO.Stream.CanWrite.-or- + // The current position is closer than count bytes to the end of the stream, and + // the capacity cannot be modified. + // + // T:System.ArgumentException: + // offset subtracted from the buffer length is less than count. + // + // T:System.ArgumentOutOfRangeException: + // offset or count are negative. + // + // T:System.IO.IOException: + // An I/O error occurs. + // + // T:System.ObjectDisposedException: + // The current stream instance is closed. + public override void Write(byte[] array, int offset, int count) + { + if (internalStream is Stream) + { + internalStream.Write(array, offset, count); + OnProgress(internalStream.Position, internalStream.Length); + } + else + { + base.Write(array, offset, count); + OnProgress(this.Position, this.Length); + } + } + + // + // Summary: + // Writes a byte to the current stream at the current position. + // + // Parameters: + // value: + // The byte to write. + // + // Exceptions: + // T:System.NotSupportedException: + // The stream does not support writing. For additional information see System.IO.Stream.CanWrite.-or- + // The current position is at the end of the stream, and the capacity cannot be + // modified. + // + // T:System.ObjectDisposedException: + // The current stream is closed. + public override void WriteByte(byte value) + { + if (internalStream is Stream) + { + internalStream.WriteByte(value); + OnProgress(internalStream.Position, internalStream.Length); + } + else + { + base.WriteByte(value); + OnProgress(this.Position, this.Length); + } + } + + // + // Summary: + // Reads a block of bytes from the current stream and writes the data to a buffer. + // + // Parameters: + // buffer: + // When this method returns, contains the specified byte array with the values between + // offset and (offset + count - 1) replaced by the characters read from the current + // stream. + // + // offset: + // The zero-based byte offset in buffer at which to begin storing data from the + // current stream. + // + // count: + // The maximum number of bytes to read. + // + // Returns: + // The total number of bytes written into the buffer. This can be less than the + // number of bytes requested if that number of bytes are not currently available, + // or zero if the end of the stream is reached before any bytes are read. + // + // Exceptions: + // T:System.ArgumentNullException: + // buffer is null. + // + // T:System.ArgumentOutOfRangeException: + // offset or count is negative. + // + // T:System.ArgumentException: + // offset subtracted from the buffer length is less than count. + // + // T:System.ObjectDisposedException: + // The current stream instance is closed. + public override int Read(byte[] array, int offset, int count) + { + int r; + if (internalStream is Stream) + { + r = internalStream.Read(array, offset, count); + internalStreamProgress += r; + OnProgress(internalStreamProgress, this.Length); + } + else + { + r = base.Read(array, offset, count); + OnProgress(this.Position, this.Length); + } + + return r; + } + + // + // Summary: + // Reads a byte from the current stream. + // + // Returns: + // The byte cast to a System.Int32, or -1 if the end of the stream has been reached. + // + // Exceptions: + // T:System.ObjectDisposedException: + // The current stream instance is closed. + public override int ReadByte() + { + int r; + if (internalStream is Stream) + { + r = internalStream.ReadByte(); + internalStreamProgress += r; + OnProgress(internalStreamProgress, this.Length); + } + else + { + r = base.ReadByte(); + OnProgress(this.Position, this.Length); + } + return r; + } + + public void Dispose() + { + if (disposeStream) + { + internalStream.Dispose(); + } + } + + public long Length => streamLength ?? internalStream.Length; + } +} diff --git a/LANCommander.Playnite.Extension/UninstallController.cs b/LANCommander.Playnite.Extension/UninstallController.cs index 158e111..0bb28e8 100644 --- a/LANCommander.Playnite.Extension/UninstallController.cs +++ b/LANCommander.Playnite.Extension/UninstallController.cs @@ -1,17 +1,8 @@ -using Playnite.SDK; +using LANCommander.SDK.Enums; using Playnite.SDK.Models; using Playnite.SDK.Plugins; -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 LANCommander.SDK.Enums; namespace LANCommander.PlaynitePlugin { diff --git a/LANCommander.Playnite.Extension/app.config b/LANCommander.Playnite.Extension/app.config index 6314000..8adb46d 100644 --- a/LANCommander.Playnite.Extension/app.config +++ b/LANCommander.Playnite.Extension/app.config @@ -4,7 +4,7 @@ - + diff --git a/LANCommander.Playnite.Extension/packages.config b/LANCommander.Playnite.Extension/packages.config index fe9fb0b..aa5952d 100644 --- a/LANCommander.Playnite.Extension/packages.config +++ b/LANCommander.Playnite.Extension/packages.config @@ -6,11 +6,12 @@ - + - + +