87 lines
2.9 KiB
C#
87 lines
2.9 KiB
C#
#region Copyright & License Information
|
|
/*
|
|
* Copyright (c) The OpenRA Developers and Contributors
|
|
* This file is part of OpenRA, which is free software. It is made
|
|
* available to you under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation, either version 3 of
|
|
* the License, or (at your option) any later version. For more
|
|
* information, see COPYING.
|
|
*/
|
|
#endregion
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using OpenRA.Mods.Common.FileFormats;
|
|
using OpenRA.Mods.Common.Widgets.Logic;
|
|
using FS = OpenRA.FileSystem.FileSystem;
|
|
|
|
namespace OpenRA.Mods.Common.Installer
|
|
{
|
|
public class ExtractBlastSourceAction : ISourceAction
|
|
{
|
|
public void RunActionOnSource(MiniYaml actionYaml, string path, ModData modData, List<string> extracted, Action<string> updateMessage)
|
|
{
|
|
// Yaml path may be specified relative to a named directory (e.g. ^SupportDir) or the detected source path
|
|
var sourcePath = actionYaml.Value.StartsWith('^') ? Platform.ResolvePath(actionYaml.Value) : FS.ResolveCaseInsensitivePath(Path.Combine(path, actionYaml.Value));
|
|
|
|
using (var source = File.OpenRead(sourcePath))
|
|
{
|
|
source.Position = 12;
|
|
var numFiles = source.ReadUInt16();
|
|
source.Position = 51;
|
|
source.Position = source.ReadUInt32();
|
|
|
|
var entries = new Dictionary<string, (uint Length, uint Offset)>();
|
|
|
|
for (var i = 0; i < numFiles; i++)
|
|
{
|
|
source.Position += 7;
|
|
var entry = (source.ReadUInt32(), source.ReadUInt32());
|
|
source.Position += 14;
|
|
var key = source.ReadASCII(source.ReadByte());
|
|
source.Position += 13;
|
|
|
|
// This does not apply on game relevant data.
|
|
entries.TryAdd(key, entry);
|
|
}
|
|
|
|
foreach (var node in actionYaml.Nodes)
|
|
{
|
|
var targetPath = Platform.ResolvePath(node.Key);
|
|
|
|
if (File.Exists(targetPath))
|
|
{
|
|
Log.Write("install", "Skipping installed file " + targetPath);
|
|
continue;
|
|
}
|
|
|
|
var (length, offset) = entries[node.Value.Value];
|
|
|
|
source.Position = offset;
|
|
|
|
extracted.Add(targetPath);
|
|
Directory.CreateDirectory(Path.GetDirectoryName(targetPath));
|
|
var displayFilename = Path.GetFileName(Path.GetFileName(targetPath));
|
|
|
|
Action<long> onProgress = null;
|
|
if (length < InstallFromSourceLogic.ShowPercentageThreshold)
|
|
updateMessage(TranslationProvider.GetString(
|
|
InstallFromSourceLogic.Extracing,
|
|
Translation.Arguments("filename", displayFilename)));
|
|
else
|
|
onProgress = b => updateMessage(TranslationProvider.GetString(
|
|
InstallFromSourceLogic.ExtractingProgress,
|
|
Translation.Arguments("filename", displayFilename, "progress", 100 * b / length)));
|
|
|
|
using (var target = File.OpenWrite(targetPath))
|
|
{
|
|
Log.Write("install", $"Extracting {sourcePath} -> {targetPath}");
|
|
Blast.Decompress(source, target, (read, _) => onProgress?.Invoke(read));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|