Replaced hardcoded SourceType with custom defined ISourceResolver.
This commit is contained in:
committed by
Matthias Mailänder
parent
7188f88ba1
commit
35eb246080
20
OpenRA.Mods.Common/Installer/Availability.cs
Normal file
20
OpenRA.Mods.Common/Installer/Availability.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
|
||||||
|
* 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
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Installer
|
||||||
|
{
|
||||||
|
public enum Availability
|
||||||
|
{
|
||||||
|
Unavailable,
|
||||||
|
GameSource,
|
||||||
|
DigitalInstall
|
||||||
|
}
|
||||||
|
}
|
||||||
19
OpenRA.Mods.Common/Installer/ISourceResolver.cs
Normal file
19
OpenRA.Mods.Common/Installer/ISourceResolver.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
|
||||||
|
* 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
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Installer
|
||||||
|
{
|
||||||
|
public interface ISourceResolver
|
||||||
|
{
|
||||||
|
string FindSourcePath(ModContent.ModSource modSource);
|
||||||
|
Availability GetAvailability();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,10 +43,10 @@ namespace OpenRA.Mods.Common.Installer
|
|||||||
var length = source.Length;
|
var length = source.Length;
|
||||||
|
|
||||||
Action<long> onProgress = null;
|
Action<long> onProgress = null;
|
||||||
if (length < InstallFromDiscLogic.ShowPercentageThreshold)
|
if (length < InstallFromSourceLogic.ShowPercentageThreshold)
|
||||||
updateMessage(modData.Translation.GetString(InstallFromDiscLogic.CopyingFilename, Translation.Arguments("filename", displayFilename)));
|
updateMessage(modData.Translation.GetString(InstallFromSourceLogic.CopyingFilename, Translation.Arguments("filename", displayFilename)));
|
||||||
else
|
else
|
||||||
onProgress = b => updateMessage(modData.Translation.GetString(InstallFromDiscLogic.CopyingFilenameProgress, Translation.Arguments("filename", displayFilename, "progress", 100 * b / length)));
|
onProgress = b => updateMessage(modData.Translation.GetString(InstallFromSourceLogic.CopyingFilenameProgress, Translation.Arguments("filename", displayFilename, "progress", 100 * b / length)));
|
||||||
|
|
||||||
InstallerUtils.CopyStream(source, target, length, onProgress);
|
InstallerUtils.CopyStream(source, target, length, onProgress);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,10 +60,10 @@ namespace OpenRA.Mods.Common.Installer
|
|||||||
var displayFilename = Path.GetFileName(Path.GetFileName(targetPath));
|
var displayFilename = Path.GetFileName(Path.GetFileName(targetPath));
|
||||||
|
|
||||||
Action<long> onProgress = null;
|
Action<long> onProgress = null;
|
||||||
if (length < InstallFromDiscLogic.ShowPercentageThreshold)
|
if (length < InstallFromSourceLogic.ShowPercentageThreshold)
|
||||||
updateMessage(modData.Translation.GetString(InstallFromDiscLogic.Extracing, Translation.Arguments("filename", displayFilename)));
|
updateMessage(modData.Translation.GetString(InstallFromSourceLogic.Extracing, Translation.Arguments("filename", displayFilename)));
|
||||||
else
|
else
|
||||||
onProgress = b => updateMessage(modData.Translation.GetString(InstallFromDiscLogic.ExtracingProgress, Translation.Arguments("filename", displayFilename, "progress", 100 * b / length)));
|
onProgress = b => updateMessage(modData.Translation.GetString(InstallFromSourceLogic.ExtracingProgress, Translation.Arguments("filename", displayFilename, "progress", 100 * b / length)));
|
||||||
|
|
||||||
using (var target = File.OpenWrite(targetPath))
|
using (var target = File.OpenWrite(targetPath))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ namespace OpenRA.Mods.Common.Installer
|
|||||||
{
|
{
|
||||||
Log.Write("install", $"Extracting {sourcePath} -> {targetPath}");
|
Log.Write("install", $"Extracting {sourcePath} -> {targetPath}");
|
||||||
var displayFilename = Path.GetFileName(Path.GetFileName(targetPath));
|
var displayFilename = Path.GetFileName(Path.GetFileName(targetPath));
|
||||||
Action<int> onProgress = percent => updateMessage(modData.Translation.GetString(InstallFromDiscLogic.ExtracingProgress, Translation.Arguments("filename", displayFilename, "progress", percent)));
|
Action<int> onProgress = percent => updateMessage(modData.Translation.GetString(InstallFromSourceLogic.ExtracingProgress, Translation.Arguments("filename", displayFilename, "progress", percent)));
|
||||||
reader.ExtractFile(node.Value.Value, target, onProgress);
|
reader.ExtractFile(node.Value.Value, target, onProgress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ namespace OpenRA.Mods.Common.Installer
|
|||||||
{
|
{
|
||||||
Log.Write("install", $"Extracting {sourcePath} -> {targetPath}");
|
Log.Write("install", $"Extracting {sourcePath} -> {targetPath}");
|
||||||
var displayFilename = Path.GetFileName(Path.GetFileName(targetPath));
|
var displayFilename = Path.GetFileName(Path.GetFileName(targetPath));
|
||||||
Action<int> onProgress = percent => updateMessage(modData.Translation.GetString(InstallFromDiscLogic.ExtracingProgress, Translation.Arguments("filename", displayFilename, "progress", percent)));
|
Action<int> onProgress = percent => updateMessage(modData.Translation.GetString(InstallFromSourceLogic.ExtracingProgress, Translation.Arguments("filename", displayFilename, "progress", percent)));
|
||||||
reader.ExtractFile(node.Value.Value, target, onProgress);
|
reader.ExtractFile(node.Value.Value, target, onProgress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,10 +59,10 @@ namespace OpenRA.Mods.Common.Installer
|
|||||||
var displayFilename = Path.GetFileName(Path.GetFileName(targetPath));
|
var displayFilename = Path.GetFileName(Path.GetFileName(targetPath));
|
||||||
|
|
||||||
Action<long> onProgress = null;
|
Action<long> onProgress = null;
|
||||||
if (length < InstallFromDiscLogic.ShowPercentageThreshold)
|
if (length < InstallFromSourceLogic.ShowPercentageThreshold)
|
||||||
updateMessage(modData.Translation.GetString(InstallFromDiscLogic.Extracing, Translation.Arguments("filename", displayFilename)));
|
updateMessage(modData.Translation.GetString(InstallFromSourceLogic.Extracing, Translation.Arguments("filename", displayFilename)));
|
||||||
else
|
else
|
||||||
onProgress = b => updateMessage(modData.Translation.GetString(InstallFromDiscLogic.ExtracingProgress, Translation.Arguments("filename", displayFilename, "progress", 100 * b / length)));
|
onProgress = b => updateMessage(modData.Translation.GetString(InstallFromSourceLogic.ExtracingProgress, Translation.Arguments("filename", displayFilename, "progress", 100 * b / length)));
|
||||||
|
|
||||||
using (var target = File.OpenWrite(targetPath))
|
using (var target = File.OpenWrite(targetPath))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
|
||||||
|
* 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.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Installer
|
||||||
|
{
|
||||||
|
public class DiscSourceResolver : ISourceResolver
|
||||||
|
{
|
||||||
|
public string FindSourcePath(ModContent.ModSource source)
|
||||||
|
{
|
||||||
|
var volumes = DriveInfo.GetDrives()
|
||||||
|
.Where(d =>
|
||||||
|
{
|
||||||
|
if (d.DriveType == DriveType.CDRom && d.IsReady)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// HACK: the "TFD" DVD is detected as a fixed udf-formatted drive on OSX
|
||||||
|
if (d.DriveType == DriveType.Fixed && d.DriveFormat == "udf")
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
})
|
||||||
|
.Select(v => v.RootDirectory.FullName);
|
||||||
|
|
||||||
|
if (Platform.CurrentPlatform == PlatformType.Linux)
|
||||||
|
{
|
||||||
|
// Outside of Gnome, most mounting tools on Linux don't set DriveType.CDRom
|
||||||
|
// so provide a fallback by allowing users to manually mount images on known paths
|
||||||
|
volumes = volumes.Concat(new[]
|
||||||
|
{
|
||||||
|
"/media/openra",
|
||||||
|
"/media/" + Environment.UserName + "/openra",
|
||||||
|
"/mnt/openra"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var volume in volumes)
|
||||||
|
if (InstallerUtils.IsValidSourcePath(volume, source))
|
||||||
|
return volume;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Availability GetAvailability()
|
||||||
|
{
|
||||||
|
return Availability.GameSource;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
|
||||||
|
* 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.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Installer
|
||||||
|
{
|
||||||
|
public class RegistryDirectoryFromFileSourceResolver : ISourceResolver
|
||||||
|
{
|
||||||
|
public string FindSourcePath(ModContent.ModSource source)
|
||||||
|
{
|
||||||
|
if (source.RegistryKey == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (Platform.CurrentPlatform != PlatformType.Windows)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// We need an extra check for the platform here to silence a warning when the registry is accessed
|
||||||
|
// TODO: Remove this once our platform checks use the same method
|
||||||
|
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
foreach (var prefix in source.RegistryPrefixes)
|
||||||
|
{
|
||||||
|
if (!(Microsoft.Win32.Registry.GetValue(prefix + source.RegistryKey, source.RegistryValue, null) is string path))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
path = Path.GetDirectoryName(path);
|
||||||
|
|
||||||
|
return InstallerUtils.IsValidSourcePath(path, source) ? path : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Availability GetAvailability()
|
||||||
|
{
|
||||||
|
return Platform.CurrentPlatform != PlatformType.Windows ? Availability.DigitalInstall : Availability.Unavailable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#region Copyright & License Information
|
||||||
|
/*
|
||||||
|
* Copyright 2007-2022 The OpenRA Developers (see AUTHORS)
|
||||||
|
* 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.Runtime.InteropServices;
|
||||||
|
|
||||||
|
namespace OpenRA.Mods.Common.Installer
|
||||||
|
{
|
||||||
|
public class RegistryDirectorySourceResolver : ISourceResolver
|
||||||
|
{
|
||||||
|
public string FindSourcePath(ModContent.ModSource source)
|
||||||
|
{
|
||||||
|
if (source.RegistryKey == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
if (Platform.CurrentPlatform != PlatformType.Windows)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// We need an extra check for the platform here to silence a warning when the registry is accessed
|
||||||
|
// TODO: Remove this once our platform checks use the same method
|
||||||
|
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
foreach (var prefix in source.RegistryPrefixes)
|
||||||
|
{
|
||||||
|
if (!(Microsoft.Win32.Registry.GetValue(prefix + source.RegistryKey, source.RegistryValue, null) is string path))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
return InstallerUtils.IsValidSourcePath(path, source) ? path : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Availability GetAvailability()
|
||||||
|
{
|
||||||
|
return Platform.CurrentPlatform != PlatformType.Windows ? Availability.DigitalInstall : Availability.Unavailable;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,6 @@ namespace OpenRA
|
|||||||
{
|
{
|
||||||
public class ModContent : IGlobalModData
|
public class ModContent : IGlobalModData
|
||||||
{
|
{
|
||||||
public enum SourceType { Disc, RegistryDirectory, RegistryDirectoryFromFile }
|
|
||||||
public class ModPackage
|
public class ModPackage
|
||||||
{
|
{
|
||||||
public readonly string Title;
|
public readonly string Title;
|
||||||
@@ -42,7 +41,9 @@ namespace OpenRA
|
|||||||
public class ModSource
|
public class ModSource
|
||||||
{
|
{
|
||||||
public readonly ObjectCreator ObjectCreator;
|
public readonly ObjectCreator ObjectCreator;
|
||||||
public readonly SourceType Type = SourceType.Disc;
|
|
||||||
|
[FieldLoader.Ignore]
|
||||||
|
public readonly MiniYaml Type;
|
||||||
|
|
||||||
// Used to find installation locations for SourceType.Install
|
// Used to find installation locations for SourceType.Install
|
||||||
public readonly string[] RegistryPrefixes = { string.Empty };
|
public readonly string[] RegistryPrefixes = { string.Empty };
|
||||||
@@ -62,6 +63,10 @@ namespace OpenRA
|
|||||||
ObjectCreator = objectCreator;
|
ObjectCreator = objectCreator;
|
||||||
Title = yaml.Value;
|
Title = yaml.Value;
|
||||||
|
|
||||||
|
var type = yaml.Nodes.FirstOrDefault(n => n.Key == "Type");
|
||||||
|
if (type != null)
|
||||||
|
Type = type.Value;
|
||||||
|
|
||||||
var idFiles = yaml.Nodes.FirstOrDefault(n => n.Key == "IDFiles");
|
var idFiles = yaml.Nodes.FirstOrDefault(n => n.Key == "IDFiles");
|
||||||
if (idFiles != null)
|
if (idFiles != null)
|
||||||
IDFiles = idFiles.Value;
|
IDFiles = idFiles.Value;
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ using OpenRA.Widgets;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Common.Widgets.Logic
|
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||||
{
|
{
|
||||||
public class InstallFromDiscLogic : ChromeLogic
|
public class InstallFromSourceLogic : ChromeLogic
|
||||||
{
|
{
|
||||||
// Hide percentage indicators for files smaller than 25 MB
|
// Hide percentage indicators for files smaller than 25 MB
|
||||||
public const int ShowPercentageThreshold = 26214400;
|
public const int ShowPercentageThreshold = 26214400;
|
||||||
@@ -54,19 +54,19 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
Mode visible = Mode.Progress;
|
Mode visible = Mode.Progress;
|
||||||
|
|
||||||
[TranslationReference]
|
[TranslationReference]
|
||||||
static readonly string DetectingDrives = "detecting-drives";
|
static readonly string DetectingSources = "detecting-sources";
|
||||||
|
|
||||||
[TranslationReference]
|
[TranslationReference]
|
||||||
static readonly string CheckingDiscs = "checking-discs";
|
static readonly string CheckingSources = "checking-sources";
|
||||||
|
|
||||||
[TranslationReference("title")]
|
[TranslationReference("title")]
|
||||||
static readonly string SearchingDiscFor = "searching-disc-for";
|
static readonly string SearchingSourceFor = "searching-source-for";
|
||||||
|
|
||||||
[TranslationReference]
|
[TranslationReference]
|
||||||
static readonly string ContentPackageInstallation = "content-package-installation";
|
static readonly string ContentPackageInstallation = "content-package-installation";
|
||||||
|
|
||||||
[TranslationReference]
|
[TranslationReference]
|
||||||
static readonly string GameDiscs = "game-discs";
|
static readonly string GameSources = "game-sources";
|
||||||
|
|
||||||
[TranslationReference]
|
[TranslationReference]
|
||||||
static readonly string DigitalInstalls = "digital-installs";
|
static readonly string DigitalInstalls = "digital-installs";
|
||||||
@@ -111,7 +111,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
static readonly string Back = "back";
|
static readonly string Back = "back";
|
||||||
|
|
||||||
[ObjectCreator.UseCtor]
|
[ObjectCreator.UseCtor]
|
||||||
public InstallFromDiscLogic(Widget widget, ModData modData, ModContent content, Dictionary<string, ModContent.ModSource> sources)
|
public InstallFromSourceLogic(Widget widget, ModData modData, ModContent content, Dictionary<string, ModContent.ModSource> sources)
|
||||||
{
|
{
|
||||||
this.modData = modData;
|
this.modData = modData;
|
||||||
this.content = content;
|
this.content = content;
|
||||||
@@ -119,7 +119,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
Log.AddChannel("install", "install.log");
|
Log.AddChannel("install", "install.log");
|
||||||
|
|
||||||
panel = widget.Get("DISC_INSTALL_PANEL");
|
panel = widget.Get("SOURCE_INSTALL_PANEL");
|
||||||
|
|
||||||
titleLabel = panel.Get<LabelWidget>("TITLE");
|
titleLabel = panel.Get<LabelWidget>("TITLE");
|
||||||
|
|
||||||
@@ -149,65 +149,39 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
|
|
||||||
listLabel = listContainer.Get<LabelWidget>("LIST_MESSAGE");
|
listLabel = listContainer.Get<LabelWidget>("LIST_MESSAGE");
|
||||||
|
|
||||||
DetectContentDisks();
|
DetectContentSources();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsValidDrive(DriveInfo d)
|
void DetectContentSources()
|
||||||
{
|
{
|
||||||
if (d.DriveType == DriveType.CDRom && d.IsReady)
|
var message = modData.Translation.GetString(DetectingSources);
|
||||||
return true;
|
ShowProgressbar(modData.Translation.GetString(CheckingSources), () => message);
|
||||||
|
ShowBackRetry(DetectContentSources);
|
||||||
// HACK: the "TFD" DVD is detected as a fixed udf-formatted drive on OSX
|
|
||||||
if (d.DriveType == DriveType.Fixed && d.DriveFormat == "udf")
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DetectContentDisks()
|
|
||||||
{
|
|
||||||
var message = modData.Translation.GetString(DetectingDrives);
|
|
||||||
ShowProgressbar(modData.Translation.GetString(CheckingDiscs), () => message);
|
|
||||||
ShowBackRetry(DetectContentDisks);
|
|
||||||
|
|
||||||
new Task(() =>
|
new Task(() =>
|
||||||
{
|
{
|
||||||
var volumes = DriveInfo.GetDrives()
|
|
||||||
.Where(IsValidDrive)
|
|
||||||
.Select(v => v.RootDirectory.FullName);
|
|
||||||
|
|
||||||
if (Platform.CurrentPlatform == PlatformType.Linux)
|
|
||||||
{
|
|
||||||
// Outside of Gnome, most mounting tools on Linux don't set DriveType.CDRom
|
|
||||||
// so provide a fallback by allowing users to manually mount images on known paths
|
|
||||||
volumes = volumes.Concat(new[]
|
|
||||||
{
|
|
||||||
"/media/openra",
|
|
||||||
"/media/" + Environment.UserName + "/openra",
|
|
||||||
"/mnt/openra"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var kv in sources)
|
foreach (var kv in sources)
|
||||||
{
|
{
|
||||||
message = modData.Translation.GetString(SearchingDiscFor, Translation.Arguments("title", kv.Value.Title));
|
message = modData.Translation.GetString(SearchingSourceFor, Translation.Arguments("title", kv.Value.Title));
|
||||||
|
|
||||||
var path = FindSourcePath(kv.Value, volumes);
|
var sourceResolver = kv.Value.ObjectCreator.CreateObject<ISourceResolver>($"{kv.Value.Type.Value}SourceResolver");
|
||||||
|
|
||||||
|
var path = sourceResolver.FindSourcePath(kv.Value);
|
||||||
if (path != null)
|
if (path != null)
|
||||||
{
|
{
|
||||||
Log.Write("install", $"Using installer `{kv.Key}: {kv.Value.Title}` of type `{kv.Value.Type}`:");
|
Log.Write("install", $"Using installer `{kv.Key}: {kv.Value.Title}` of type `{kv.Value.Type.Value}`:");
|
||||||
|
|
||||||
var packages = content.Packages.Values
|
var packages = content.Packages.Values
|
||||||
.Where(p => p.Sources.Contains(kv.Key) && !p.IsInstalled())
|
.Where(p => p.Sources.Contains(kv.Key) && !p.IsInstalled())
|
||||||
.Select(p => p.Title);
|
.Select(p => p.Title);
|
||||||
|
|
||||||
// Ignore disc if content is already installed
|
// Ignore source if content is already installed
|
||||||
if (packages.Any())
|
if (packages.Any())
|
||||||
{
|
{
|
||||||
Game.RunAfterTick(() =>
|
Game.RunAfterTick(() =>
|
||||||
{
|
{
|
||||||
ShowList(kv.Value.Title, modData.Translation.GetString(ContentPackageInstallation), packages);
|
ShowList(kv.Value.Title, modData.Translation.GetString(ContentPackageInstallation), packages);
|
||||||
ShowContinueCancel(() => InstallFromDisc(path, kv.Value));
|
ShowContinueCancel(() => InstallFromSource(path, kv.Value));
|
||||||
});
|
});
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@@ -220,35 +194,38 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
.SelectMany(p => p.Sources)
|
.SelectMany(p => p.Sources)
|
||||||
.Select(d => sources[d]);
|
.Select(d => sources[d]);
|
||||||
|
|
||||||
var discs = missingSources
|
var gameSources = new HashSet<string>();
|
||||||
.Where(s => s.Type == ModContent.SourceType.Disc)
|
var digitalInstalls = new HashSet<string>();
|
||||||
.Select(s => s.Title)
|
|
||||||
.Distinct();
|
|
||||||
|
|
||||||
var options = new Dictionary<string, IEnumerable<string>>()
|
foreach (var source in missingSources)
|
||||||
{
|
{
|
||||||
{ modData.Translation.GetString(GameDiscs), discs },
|
var sourceResolver = source.ObjectCreator.CreateObject<ISourceResolver>($"{source.Type.Value}SourceResolver");
|
||||||
};
|
|
||||||
|
|
||||||
if (Platform.CurrentPlatform == PlatformType.Windows)
|
var availability = sourceResolver.GetAvailability();
|
||||||
{
|
|
||||||
var installations = missingSources
|
|
||||||
.Where(s => s.Type == ModContent.SourceType.RegistryDirectory || s.Type == ModContent.SourceType.RegistryDirectoryFromFile)
|
|
||||||
.Select(s => s.Title)
|
|
||||||
.Distinct();
|
|
||||||
|
|
||||||
options.Add(modData.Translation.GetString(DigitalInstalls), installations);
|
if (availability == Availability.GameSource)
|
||||||
|
gameSources.Add(source.Title);
|
||||||
|
else if (availability == Availability.DigitalInstall)
|
||||||
|
digitalInstalls.Add(source.Title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var options = new Dictionary<string, IEnumerable<string>>();
|
||||||
|
|
||||||
|
if (gameSources.Any())
|
||||||
|
options.Add(modData.Translation.GetString(GameSources), gameSources);
|
||||||
|
|
||||||
|
if (digitalInstalls.Any())
|
||||||
|
options.Add(modData.Translation.GetString(DigitalInstalls), digitalInstalls);
|
||||||
|
|
||||||
Game.RunAfterTick(() =>
|
Game.RunAfterTick(() =>
|
||||||
{
|
{
|
||||||
ShowList(modData.Translation.GetString(GameContentNotFound), modData.Translation.GetString(AlternativeContentSources), options);
|
ShowList(modData.Translation.GetString(GameContentNotFound), modData.Translation.GetString(AlternativeContentSources), options);
|
||||||
ShowBackRetry(DetectContentDisks);
|
ShowBackRetry(DetectContentSources);
|
||||||
});
|
});
|
||||||
}).Start();
|
}).Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstallFromDisc(string path, ModContent.ModSource modSource)
|
void InstallFromSource(string path, ModContent.ModSource modSource)
|
||||||
{
|
{
|
||||||
var message = "";
|
var message = "";
|
||||||
ShowProgressbar(modData.Translation.GetString(InstallingContent), () => message);
|
ShowProgressbar(modData.Translation.GetString(InstallingContent), () => message);
|
||||||
@@ -281,7 +258,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
Game.RunAfterTick(() =>
|
Game.RunAfterTick(() =>
|
||||||
{
|
{
|
||||||
ShowMessage(modData.Translation.GetString(InstallationFailed), modData.Translation.GetString(CheckInstallLog));
|
ShowMessage(modData.Translation.GetString(InstallationFailed), modData.Translation.GetString(CheckInstallLog));
|
||||||
ShowBackRetry(() => InstallFromDisc(path, modSource));
|
ShowBackRetry(() => InstallFromSource(path, modSource));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}).Start();
|
}).Start();
|
||||||
@@ -28,7 +28,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
readonly Dictionary<string, ModContent.ModSource> sources = new Dictionary<string, ModContent.ModSource>();
|
readonly Dictionary<string, ModContent.ModSource> sources = new Dictionary<string, ModContent.ModSource>();
|
||||||
readonly Dictionary<string, ModContent.ModDownload> downloads = new Dictionary<string, ModContent.ModDownload>();
|
readonly Dictionary<string, ModContent.ModDownload> downloads = new Dictionary<string, ModContent.ModDownload>();
|
||||||
|
|
||||||
bool discAvailable;
|
bool sourceAvailable;
|
||||||
|
|
||||||
[TranslationReference]
|
[TranslationReference]
|
||||||
static readonly string ManualInstall = "manual-install";
|
static readonly string ManualInstall = "manual-install";
|
||||||
@@ -76,11 +76,11 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
panel.Bounds.Y -= headerHeight / 2;
|
panel.Bounds.Y -= headerHeight / 2;
|
||||||
scrollPanel.Bounds.Y += headerHeight;
|
scrollPanel.Bounds.Y += headerHeight;
|
||||||
|
|
||||||
var discButton = panel.Get<ButtonWidget>("CHECK_DISC_BUTTON");
|
var sourceButton = panel.Get<ButtonWidget>("CHECK_SOURCE_BUTTON");
|
||||||
discButton.Bounds.Y += headerHeight;
|
sourceButton.Bounds.Y += headerHeight;
|
||||||
discButton.IsVisible = () => discAvailable;
|
sourceButton.IsVisible = () => sourceAvailable;
|
||||||
|
|
||||||
discButton.OnClick = () => Ui.OpenWindow("DISC_INSTALL_PANEL", new WidgetArgs
|
sourceButton.OnClick = () => Ui.OpenWindow("SOURCE_INSTALL_PANEL", new WidgetArgs
|
||||||
{
|
{
|
||||||
{ "sources", sources },
|
{ "sources", sources },
|
||||||
{ "content", content }
|
{ "content", content }
|
||||||
@@ -113,7 +113,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
var requiredWidget = container.Get<LabelWidget>("REQUIRED");
|
var requiredWidget = container.Get<LabelWidget>("REQUIRED");
|
||||||
requiredWidget.IsVisible = () => p.Value.Required;
|
requiredWidget.IsVisible = () => p.Value.Required;
|
||||||
|
|
||||||
var sourceWidget = container.Get<ImageWidget>("DISC");
|
var sourceWidget = container.Get<ImageWidget>("SOURCE");
|
||||||
var sourceTitles = p.Value.Sources.Select(s => sources[s].Title).Distinct();
|
var sourceTitles = p.Value.Sources.Select(s => sources[s].Title).Distinct();
|
||||||
var sourceList = sourceTitles.JoinWith("\n");
|
var sourceList = sourceTitles.JoinWith("\n");
|
||||||
var isSourceAvailable = sourceTitles.Any();
|
var isSourceAvailable = sourceTitles.Any();
|
||||||
@@ -139,18 +139,18 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
|||||||
var installedWidget = container.Get<LabelWidget>("INSTALLED");
|
var installedWidget = container.Get<LabelWidget>("INSTALLED");
|
||||||
installedWidget.IsVisible = () => installed;
|
installedWidget.IsVisible = () => installed;
|
||||||
|
|
||||||
var requiresDiscWidget = container.Get<LabelWidget>("REQUIRES_DISC");
|
var requiresSourceWidget = container.Get<LabelWidget>("REQUIRES_SOURCE");
|
||||||
requiresDiscWidget.IsVisible = () => !installed && !downloadEnabled;
|
requiresSourceWidget.IsVisible = () => !installed && !downloadEnabled;
|
||||||
if (!isSourceAvailable)
|
if (!isSourceAvailable)
|
||||||
{
|
{
|
||||||
var manualInstall = modData.Translation.GetString(ManualInstall);
|
var manualInstall = modData.Translation.GetString(ManualInstall);
|
||||||
requiresDiscWidget.GetText = () => manualInstall;
|
requiresSourceWidget.GetText = () => manualInstall;
|
||||||
}
|
}
|
||||||
|
|
||||||
scrollPanel.AddChild(container);
|
scrollPanel.AddChild(container);
|
||||||
}
|
}
|
||||||
|
|
||||||
discAvailable = content.Packages.Values.Any(p => p.Sources.Length > 0 && !p.IsInstalled());
|
sourceAvailable = content.Packages.Values.Any(p => p.Sources.Length > 0 && !p.IsInstalled());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,38 +14,38 @@ using OpenRA.Widgets;
|
|||||||
|
|
||||||
namespace OpenRA.Mods.Common.Widgets.Logic
|
namespace OpenRA.Mods.Common.Widgets.Logic
|
||||||
{
|
{
|
||||||
public class ModContentDiscTooltipLogic : ChromeLogic
|
public class ModContentSourceTooltipLogic : ChromeLogic
|
||||||
{
|
{
|
||||||
[ObjectCreator.UseCtor]
|
[ObjectCreator.UseCtor]
|
||||||
public ModContentDiscTooltipLogic(Widget widget, Func<string> getText)
|
public ModContentSourceTooltipLogic(Widget widget, Func<string> getText)
|
||||||
{
|
{
|
||||||
var discs = widget.Get<ContainerWidget>("DISCS");
|
var sources = widget.Get<ContainerWidget>("SOURCES");
|
||||||
var template = discs.Get<LabelWidget>("DISC_TEMPLATE");
|
var template = sources.Get<LabelWidget>("SOURCE_TEMPLATE");
|
||||||
discs.RemoveChildren();
|
sources.RemoveChildren();
|
||||||
|
|
||||||
var desc = widget.Get<LabelWidget>("DESCRIPTION");
|
var desc = widget.Get<LabelWidget>("DESCRIPTION");
|
||||||
|
|
||||||
var font = Game.Renderer.Fonts[template.Font];
|
var font = Game.Renderer.Fonts[template.Font];
|
||||||
var discTitles = getText().Split('\n');
|
var sourceTitles = getText().Split('\n');
|
||||||
|
|
||||||
var maxWidth = Game.Renderer.Fonts[desc.Font].Measure(desc.Text).X;
|
var maxWidth = Game.Renderer.Fonts[desc.Font].Measure(desc.Text).X;
|
||||||
var sideMargin = desc.Bounds.X;
|
var sideMargin = desc.Bounds.X;
|
||||||
var bottomMargin = discs.Bounds.Height;
|
var bottomMargin = sources.Bounds.Height;
|
||||||
foreach (var disc in discTitles)
|
foreach (var source in sourceTitles)
|
||||||
{
|
{
|
||||||
var label = (LabelWidget)template.Clone();
|
var label = (LabelWidget)template.Clone();
|
||||||
var title = disc;
|
var title = source;
|
||||||
label.GetText = () => title;
|
label.GetText = () => title;
|
||||||
label.Bounds.Y = discs.Bounds.Height;
|
label.Bounds.Y = sources.Bounds.Height;
|
||||||
label.Bounds.Width = font.Measure(disc).X;
|
label.Bounds.Width = font.Measure(source).X;
|
||||||
|
|
||||||
maxWidth = Math.Max(maxWidth, label.Bounds.Width + label.Bounds.X);
|
maxWidth = Math.Max(maxWidth, label.Bounds.Width + label.Bounds.X);
|
||||||
discs.AddChild(label);
|
sources.AddChild(label);
|
||||||
discs.Bounds.Height += label.Bounds.Height;
|
sources.Bounds.Height += label.Bounds.Height;
|
||||||
}
|
}
|
||||||
|
|
||||||
widget.Bounds.Width = 2 * sideMargin + maxWidth;
|
widget.Bounds.Width = 2 * sideMargin + maxWidth;
|
||||||
widget.Bounds.Height = discs.Bounds.Y + bottomMargin + discs.Bounds.Height;
|
widget.Bounds.Height = sources.Bounds.Y + bottomMargin + sources.Bounds.Height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
covertops: Covert Operations Expansion (English)
|
covertops: Covert Operations Expansion (English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
GAME/GAME.DAT: be5a6c4c0a581da09e8f34a3bbf7bd17e525085c
|
GAME/GAME.DAT: be5a6c4c0a581da09e8f34a3bbf7bd17e525085c
|
||||||
CONQUER.MIX: 713b53fa4c188ca9619c6bbeadbfc86513704266
|
CONQUER.MIX: 713b53fa4c188ca9619c6bbeadbfc86513704266
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
tfd: C&C The First Decade (English)
|
tfd: C&C The First Decade (English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
data1.hdr: bef3a08c3fc1b1caf28ca0dbb97c1f900005930e
|
data1.hdr: bef3a08c3fc1b1caf28ca0dbb97c1f900005930e
|
||||||
data1.cab: 12ad6113a6890a1b4d5651a75378c963eaf513b9
|
data1.cab: 12ad6113a6890a1b4d5651a75378c963eaf513b9
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
gdi95: C&C Gold (GDI Disc, English)
|
gdi95: C&C Gold (GDI Disc, English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
DISK.WAV: 8bef9a6687c0fe0afd57c6561df58fa6e64f145d
|
DISK.WAV: 8bef9a6687c0fe0afd57c6561df58fa6e64f145d
|
||||||
CONQUER.MIX: 833e02a09aae694659eb312d3838367f681d1b30
|
CONQUER.MIX: 833e02a09aae694659eb312d3838367f681d1b30
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
nod95: C&C Gold (Nod Disc, English)
|
nod95: C&C Gold (Nod Disc, English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
DISK.WAV: 83a0235525afa5cd6096f2967e3eae032996e38c
|
DISK.WAV: 83a0235525afa5cd6096f2967e3eae032996e38c
|
||||||
CONQUER.MIX: 833e02a09aae694659eb312d3838367f681d1b30
|
CONQUER.MIX: 833e02a09aae694659eb312d3838367f681d1b30
|
||||||
|
|||||||
@@ -247,14 +247,14 @@ archive-validation-failed = Archive validation failed
|
|||||||
extracting = Extracting...
|
extracting = Extracting...
|
||||||
extracting-entry = Extracting { $entry }
|
extracting-entry = Extracting { $entry }
|
||||||
archive-extraction-failed = Archive extraction failed
|
archive-extraction-failed = Archive extraction failed
|
||||||
mirror-selection-failed = Online mirror is not available. Please install from an original disc.
|
mirror-selection-failed = Online mirror is not available. Please install from an original source.
|
||||||
|
|
||||||
## InstallFromDiscLogic
|
## InstallFromSourceLogic
|
||||||
detecting-drives = Detecting drives
|
detecting-sources = Detecting drives
|
||||||
checking-discs = Checking Discs
|
checking-sources = Checking Sources
|
||||||
searching-disc-for = Searching for { $title }
|
searching-source-for = Searching for { $title }
|
||||||
content-package-installation = The following content packages will be installed:
|
content-package-installation = The following content packages will be installed:
|
||||||
game-discs = Game Discs
|
game-sources = Game Sources
|
||||||
digital-installs = Digital Installs
|
digital-installs = Digital Installs
|
||||||
game-content-not-found = Game Content Not Found
|
game-content-not-found = Game Content Not Found
|
||||||
alternative-content-sources = Please insert or install one of the following content sources:
|
alternative-content-sources = Please insert or install one of the following content sources:
|
||||||
@@ -268,10 +268,10 @@ extracting-filename-progress = Extracting { $filename } ({ $progress }%)
|
|||||||
cancel = Cancel
|
cancel = Cancel
|
||||||
retry = Retry
|
retry = Retry
|
||||||
|
|
||||||
## InstallFromDiscLogic, LobbyLogic
|
## InstallFromSourceLogic, LobbyLogic
|
||||||
back = Back
|
back = Back
|
||||||
|
|
||||||
# InstallFromDiscLogic, ModContentPromptLogic
|
# InstallFromSourceLogic, ModContentPromptLogic
|
||||||
continue = Continue
|
continue = Continue
|
||||||
|
|
||||||
## ModContentLogic
|
## ModContentLogic
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
d2k-a: Dune 2000 (English)
|
d2k-a: Dune 2000 (English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
MUSIC/AMBUSH.AUD: bd5926a56a83bc0e49f96037e1f909014ac0772a
|
MUSIC/AMBUSH.AUD: bd5926a56a83bc0e49f96037e1f909014ac0772a
|
||||||
SETUP/SETUP.Z: 937f5ceb1236bf3f3d4e43929305ffe5004078e7
|
SETUP/SETUP.Z: 937f5ceb1236bf3f3d4e43929305ffe5004078e7
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
d2k-b: Dune 2000 (English)
|
d2k-b: Dune 2000 (English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
MUSIC/AMBUSH.AUD: bd5926a56a83bc0e49f96037e1f909014ac0772a
|
MUSIC/AMBUSH.AUD: bd5926a56a83bc0e49f96037e1f909014ac0772a
|
||||||
SETUP/SETUP.Z: 029722e70fb7636f8120028f5c9b6ce81627ff90
|
SETUP/SETUP.Z: 029722e70fb7636f8120028f5c9b6ce81627ff90
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
d2k-c: Dune 2000 (English)
|
d2k-c: Dune 2000 (English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
MUSIC/AMBUSH.AUD: bd5926a56a83bc0e49f96037e1f909014ac0772a
|
MUSIC/AMBUSH.AUD: bd5926a56a83bc0e49f96037e1f909014ac0772a
|
||||||
SETUP/SETUP.Z: d939b39bdbc952b259ce2b45c0bbedefa534b7f2
|
SETUP/SETUP.Z: d939b39bdbc952b259ce2b45c0bbedefa534b7f2
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
d2k-d: Dune 2000 (English)
|
d2k-d: Dune 2000 (English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
MUSIC/AMBUSH.AUD: bd5926a56a83bc0e49f96037e1f909014ac0772a
|
MUSIC/AMBUSH.AUD: bd5926a56a83bc0e49f96037e1f909014ac0772a
|
||||||
SETUP/SETUP.Z: 2411cc5df36954ebd534ceafa3007c8aa9232909
|
SETUP/SETUP.Z: 2411cc5df36954ebd534ceafa3007c8aa9232909
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
d2k-e: Dune 2000 (English)
|
d2k-e: Dune 2000 (English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
MUSIC/AMBUSH.AUD: bd5926a56a83bc0e49f96037e1f909014ac0772a
|
MUSIC/AMBUSH.AUD: bd5926a56a83bc0e49f96037e1f909014ac0772a
|
||||||
SETUP/SETUP.Z: b476661e82eeb05949e97fa1f75fed2343174be5
|
SETUP/SETUP.Z: b476661e82eeb05949e97fa1f75fed2343174be5
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ Background@CONTENT_PANEL:
|
|||||||
Font: Bold
|
Font: Bold
|
||||||
TextColor: CC0000
|
TextColor: CC0000
|
||||||
Text: Required
|
Text: Required
|
||||||
Image@DISC:
|
Image@SOURCE:
|
||||||
X: 275
|
X: 275
|
||||||
Y: 2
|
Y: 2
|
||||||
Width: 20
|
Width: 20
|
||||||
@@ -58,7 +58,7 @@ Background@CONTENT_PANEL:
|
|||||||
ImageCollection: modcontent
|
ImageCollection: modcontent
|
||||||
ImageName: cdicon
|
ImageName: cdicon
|
||||||
TooltipContainer: TOOLTIP_CONTAINER
|
TooltipContainer: TOOLTIP_CONTAINER
|
||||||
TooltipTemplate: DISC_TOOLTIP
|
TooltipTemplate: SOURCE_TOOLTIP
|
||||||
Button@DOWNLOAD:
|
Button@DOWNLOAD:
|
||||||
X: 304
|
X: 304
|
||||||
Y: 0
|
Y: 0
|
||||||
@@ -74,7 +74,7 @@ Background@CONTENT_PANEL:
|
|||||||
Font: Bold
|
Font: Bold
|
||||||
TextColor: 00CC00
|
TextColor: 00CC00
|
||||||
Text: Installed
|
Text: Installed
|
||||||
Label@REQUIRES_DISC:
|
Label@REQUIRES_SOURCE:
|
||||||
X: 304
|
X: 304
|
||||||
Width: 100
|
Width: 100
|
||||||
Height: 23
|
Height: 23
|
||||||
@@ -82,7 +82,7 @@ Background@CONTENT_PANEL:
|
|||||||
Font: Bold
|
Font: Bold
|
||||||
TextColor: DDDDDD
|
TextColor: DDDDDD
|
||||||
Text: Requires Disc
|
Text: Requires Disc
|
||||||
Button@CHECK_DISC_BUTTON:
|
Button@CHECK_SOURCE_BUTTON:
|
||||||
X: 30
|
X: 30
|
||||||
Y: PARENT_BOTTOM - 52
|
Y: PARENT_BOTTOM - 52
|
||||||
Background: button-highlighted
|
Background: button-highlighted
|
||||||
@@ -101,8 +101,8 @@ Background@CONTENT_PANEL:
|
|||||||
Key: escape
|
Key: escape
|
||||||
TooltipContainer@TOOLTIP_CONTAINER:
|
TooltipContainer@TOOLTIP_CONTAINER:
|
||||||
|
|
||||||
Background@DISC_TOOLTIP:
|
Background@SOURCE_TOOLTIP:
|
||||||
Logic: ModContentDiscTooltipLogic
|
Logic: ModContentSourceTooltipLogic
|
||||||
Background: panel-thinborder
|
Background: panel-thinborder
|
||||||
Height: 25
|
Height: 25
|
||||||
Children:
|
Children:
|
||||||
@@ -111,12 +111,12 @@ Background@DISC_TOOLTIP:
|
|||||||
Height: 23
|
Height: 23
|
||||||
Font: Bold
|
Font: Bold
|
||||||
Text: Content available from:
|
Text: Content available from:
|
||||||
Container@DISCS:
|
Container@SOURCES:
|
||||||
Y: 15
|
Y: 15
|
||||||
Width: PARENT_RIGHT - 10
|
Width: PARENT_RIGHT - 10
|
||||||
Height: 7 # used as bottom margin
|
Height: 7 # used as bottom margin
|
||||||
Children:
|
Children:
|
||||||
Label@DISC_TEMPLATE:
|
Label@SOURCE_TEMPLATE:
|
||||||
X: 20
|
X: 20
|
||||||
Height: 14
|
Height: 14
|
||||||
Font: TinyBold
|
Font: TinyBold
|
||||||
@@ -177,8 +177,8 @@ Container@PACKAGE_DOWNLOAD_PANEL:
|
|||||||
Font: Bold
|
Font: Bold
|
||||||
Key: escape
|
Key: escape
|
||||||
|
|
||||||
Background@DISC_INSTALL_PANEL:
|
Background@SOURCE_INSTALL_PANEL:
|
||||||
Logic: InstallFromDiscLogic
|
Logic: InstallFromSourceLogic
|
||||||
X: (WINDOW_RIGHT - WIDTH) / 2
|
X: (WINDOW_RIGHT - WIDTH) / 2
|
||||||
Y: (WINDOW_BOTTOM - HEIGHT) / 2
|
Y: (WINDOW_BOTTOM - HEIGHT) / 2
|
||||||
Width: 500
|
Width: 500
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
aftermath: Aftermath Expansion Disc (English)
|
aftermath: Aftermath Expansion Disc (English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
README.TXT: 9902fb74c019df1b76ff5634e68f0371d790b5e0
|
README.TXT: 9902fb74c019df1b76ff5634e68f0371d790b5e0
|
||||||
SETUP/INSTALL/PATCH.RTP: 5bce93f834f9322ddaa7233242e5b6c7fea0bf17
|
SETUP/INSTALL/PATCH.RTP: 5bce93f834f9322ddaa7233242e5b6c7fea0bf17
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
allied: Red Alert 95 (Allied Disc, English)
|
allied: Red Alert 95 (Allied Disc, English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
MAIN.MIX: 20ebe16f91ff79be2d672f1db5bae9048ff9357c
|
MAIN.MIX: 20ebe16f91ff79be2d672f1db5bae9048ff9357c
|
||||||
Length: 4096
|
Length: 4096
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
cnc95: C&C Gold (GDI or Nod Disc, English)
|
cnc95: C&C Gold (GDI or Nod Disc, English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
CONQUER.MIX: 833e02a09aae694659eb312d3838367f681d1b30
|
CONQUER.MIX: 833e02a09aae694659eb312d3838367f681d1b30
|
||||||
Install:
|
Install:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
counterstrike: Counterstrike Expansion Disc (English)
|
counterstrike: Counterstrike Expansion Disc (English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
README.TXT: 0efe8087383f0b159a9633f891fb5f53c6097cd4
|
README.TXT: 0efe8087383f0b159a9633f891fb5f53c6097cd4
|
||||||
SETUP/INSTALL/CSTRIKE.RTP: fae8ba82db71574f6ecd8fb4ff4026fcb65d2adc
|
SETUP/INSTALL/CSTRIKE.RTP: fae8ba82db71574f6ecd8fb4ff4026fcb65d2adc
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
tfd: C&C The First Decade (English)
|
tfd: C&C The First Decade (English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
data1.hdr: bef3a08c3fc1b1caf28ca0dbb97c1f900005930e
|
data1.hdr: bef3a08c3fc1b1caf28ca0dbb97c1f900005930e
|
||||||
data1.cab: 12ad6113a6890a1b4d5651a75378c963eaf513b9
|
data1.cab: 12ad6113a6890a1b4d5651a75378c963eaf513b9
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
soviet: Red Alert 95 (Soviet Disc, English)
|
soviet: Red Alert 95 (Soviet Disc, English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
MAIN.MIX: 9d108f18560716b684ab8b1da42cc7f3d1b52519
|
MAIN.MIX: 9d108f18560716b684ab8b1da42cc7f3d1b52519
|
||||||
Length: 4096
|
Length: 4096
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
fstorm: Firestorm Expansion Disc (English)
|
fstorm: Firestorm Expansion Disc (English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
Install/README.TXT: f2810b540fce8f3880250213ee08c57780d81c20
|
Install/README.TXT: f2810b540fce8f3880250213ee08c57780d81c20
|
||||||
Install/Language.dll: 4df87c1a2289da57dd14d0a7299546f37357fcca
|
Install/Language.dll: 4df87c1a2289da57dd14d0a7299546f37357fcca
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
tfd: C&C The First Decade (English)
|
tfd: C&C The First Decade (English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
data1.hdr: bef3a08c3fc1b1caf28ca0dbb97c1f900005930e
|
data1.hdr: bef3a08c3fc1b1caf28ca0dbb97c1f900005930e
|
||||||
data1.cab: 12ad6113a6890a1b4d5651a75378c963eaf513b9
|
data1.cab: 12ad6113a6890a1b4d5651a75378c963eaf513b9
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
tibsun: Tiberian Sun (GDI or Nod Disc, English)
|
tibsun: Tiberian Sun (GDI or Nod Disc, English)
|
||||||
|
Type: Disc
|
||||||
IDFiles:
|
IDFiles:
|
||||||
README.TXT: 45745c4a0c888317ec900208a426472779c42bf7
|
README.TXT: 45745c4a0c888317ec900208a426472779c42bf7
|
||||||
AUTOPLAY.WAV: 2dfce5d00f98b641849c29942b651f4e98d30e30
|
AUTOPLAY.WAV: 2dfce5d00f98b641849c29942b651f4e98d30e30
|
||||||
|
|||||||
Reference in New Issue
Block a user