diff --git a/CKAN.schema b/CKAN.schema
index defe003f0f..ee02809e0d 100644
--- a/CKAN.schema
+++ b/CKAN.schema
@@ -439,6 +439,16 @@
"description" : "Spec v1.25 Missions path",
"type" : "string",
"pattern" : "^Missions"
+ },
+ {
+ "description" : "KSP2 BepInEx plugins folder",
+ "type" : "string",
+ "pattern" : "BepInEx/plugins"
+ },
+ {
+ "description" : "KSP2 SpaceWarp plugins folder",
+ "type" : "string",
+ "pattern" : "SpaceWarp/Mods"
}
]
},
diff --git a/Core/GameInstanceManager.cs b/Core/GameInstanceManager.cs
index 44dd27decc..7f775ce3be 100644
--- a/Core/GameInstanceManager.cs
+++ b/Core/GameInstanceManager.cs
@@ -22,7 +22,8 @@ public class GameInstanceManager : IDisposable
{
private static IGame[] knownGames = new IGame[]
{
- new KerbalSpaceProgram()
+ new KerbalSpaceProgram(),
+ new KerbalSpaceProgram2(),
};
///
@@ -646,5 +647,8 @@ public IGame DetermineGame(DirectoryInfo path, IUser user)
}
}
+ public static IGame GameByShortName(string shortName)
+ => knownGames.FirstOrDefault(g => g.ShortName == shortName);
+
}
}
diff --git a/Core/Games/KerbalSpaceProgram2.cs b/Core/Games/KerbalSpaceProgram2.cs
new file mode 100644
index 0000000000..93b3342706
--- /dev/null
+++ b/Core/Games/KerbalSpaceProgram2.cs
@@ -0,0 +1,200 @@
+using System;
+using System.Diagnostics;
+using System.Linq;
+using System.IO;
+using System.Collections.Generic;
+
+using Autofac;
+using log4net;
+
+using CKAN.Versioning;
+
+namespace CKAN.Games
+{
+ public class KerbalSpaceProgram2 : IGame
+ {
+ public string ShortName => "KSP2";
+
+ public bool GameInFolder(DirectoryInfo where)
+ => where.EnumerateFiles().Any(f => f.Name == "KSP2_x64.exe")
+ && where.EnumerateDirectories().Any(d => d.Name == "KSP2_x64_Data");
+
+ ///
+ /// Finds the Steam KSP path. Returns null if the folder cannot be located.
+ ///
+ /// The KSP path.
+ public string SteamPath()
+ {
+ // Attempt to get the Steam path.
+ string steamPath = CKANPathUtils.SteamPath();
+
+ if (steamPath == null)
+ {
+ return null;
+ }
+
+ // Default steam library
+ string installPath = GameDirectory(steamPath);
+ if (installPath != null)
+ {
+ return installPath;
+ }
+
+ // Attempt to find through config file
+ string configPath = Path.Combine(steamPath, "config", "config.vdf");
+ if (File.Exists(configPath))
+ {
+ log.InfoFormat("Found Steam config file at {0}", configPath);
+ StreamReader reader = new StreamReader(configPath);
+ string line;
+ while ((line = reader.ReadLine()) != null)
+ {
+ // Found Steam library
+ if (line.Contains("BaseInstallFolder"))
+ {
+ // This assumes config file is valid, we just skip it if it looks funny.
+ string[] split_line = line.Split('"');
+
+ if (split_line.Length > 3)
+ {
+ log.DebugFormat("Found a Steam Libary Location at {0}", split_line[3]);
+
+ installPath = GameDirectory(split_line[3]);
+ if (installPath != null)
+ {
+ log.InfoFormat("Found a KSP install at {0}", installPath);
+ return installPath;
+ }
+ }
+ }
+ }
+ }
+
+ // Could not locate the folder.
+ return null;
+ }
+
+ ///
+ /// Get the default non-Steam path to KSP on macOS
+ ///
+ ///
+ /// "/Applications/Kerbal Space Program" if it exists and we're on a Mac, else null
+ ///
+ public string MacPath()
+ {
+ if (Platform.IsMac)
+ {
+ string installPath = Path.Combine(
+ // This is "/Applications" in Mono on Mac
+ Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles),
+ "Kerbal Space Program 2"
+ );
+ return Directory.Exists(installPath) ? installPath : null;
+ }
+ return null;
+ }
+
+ public string PrimaryModDirectoryRelative => "BepInEx/plugins";
+
+ public string PrimaryModDirectory(GameInstance inst)
+ => CKANPathUtils.NormalizePath(
+ Path.Combine(inst.GameDir(), PrimaryModDirectoryRelative));
+
+ public string[] StockFolders => new string[]
+ {
+ "KSP2_x64_Data",
+ "MonoBleedingEdge",
+ "PDLauncher",
+ };
+
+ public string[] ReservedPaths => new string[]
+ {
+ };
+
+ public string[] CreateableDirs => new string[]
+ {
+ "BepInEx",
+ "BepInEx/plugins",
+ };
+
+ ///
+ /// Checks the path against a list of reserved game directories
+ ///
+ ///
+ ///
+ public bool IsReservedDirectory(GameInstance inst, string path)
+ => path == inst.GameDir() || path == inst.CkanDir()
+ || path == PrimaryModDirectory(inst);
+
+ public bool AllowInstallationIn(string name, out string path)
+ => allowedFolders.TryGetValue(name, out path);
+
+ public void RebuildSubdirectories(GameInstance inst)
+ {
+ }
+
+ public string DefaultCommandLine =>
+ Platform.IsUnix ? "./KSP2.x86_64 -single-instance"
+ : Platform.IsMac ? "./KSP2.app/Contents/MacOS/KSP"
+ : "KSP2_x64.exe -single-instance";
+
+ public string[] AdjustCommandLine(string[] args, GameVersion installedVersion)
+ => args;
+
+ public List KnownVersions
+ => new List
+ {
+ new GameVersion(0, 1, 0, 0),
+ };
+
+ public GameVersion DetectVersion(DirectoryInfo where)
+ => GameVersion.Parse(
+ FileVersionInfo.GetVersionInfo(
+ Path.Combine(where.FullName, "KSP2_x64.exe")).ProductVersion);
+
+ public string CompatibleVersionsFile => "compatible_game_versions.json";
+
+ public string[] BuildIDFiles => new string[]
+ {
+ "KSP2_x64.exe",
+ };
+
+ public Uri DefaultRepositoryURL => new Uri("https://github.com/KSP-CKAN/KSP2-CKAN-meta/archive/master.tar.gz");
+
+ public Uri RepositoryListURL => new Uri("https://raw.githubusercontent.com/KSP-CKAN/KSP2-CKAN-meta/master/repositories.json");
+
+ private readonly Dictionary allowedFolders = new Dictionary
+ {
+ { "BepInEx", "BepInEx" },
+ { "BepInEx/plugins", "BepInEx/plugins" },
+ };
+
+ ///
+ /// Finds the KSP path under a Steam Library. Returns null if the folder cannot be located.
+ ///
+ /// Steam Library Path
+ /// The KSP path.
+ private static string GameDirectory(string steamPath)
+ {
+ // There are several possibilities for the path under Linux.
+ // Try with the uppercase version.
+ string installPath = Path.Combine(steamPath, "SteamApps", "common", "Kerbal Space Program 2");
+
+ if (Directory.Exists(installPath))
+ {
+ return installPath;
+ }
+
+ // Try with the lowercase version.
+ installPath = Path.Combine(steamPath, "steamapps", "common", "Kerbal Space Program 2");
+
+ if (Directory.Exists(installPath))
+ {
+ return installPath;
+ }
+ return null;
+ }
+
+ private static readonly ILog log = LogManager.GetLogger(typeof(KerbalSpaceProgram2));
+ }
+}
diff --git a/Dockerfile.netkan b/Dockerfile.netkan
index f2715ce594..259298be75 100644
--- a/Dockerfile.netkan
+++ b/Dockerfile.netkan
@@ -5,6 +5,6 @@ RUN useradd -ms /bin/bash netkan
USER netkan
WORKDIR /home/netkan
ADD netkan.exe .
-ENTRYPOINT /usr/bin/mono netkan.exe --queues $QUEUES \
+ENTRYPOINT /usr/bin/mono netkan.exe --game $GAME --queues $QUEUES \
--net-useragent 'Mozilla/5.0 (compatible; Netkanbot/1.0; CKAN; +https://github.com/KSP-CKAN/NetKAN-Infra)' \
--github-token $GH_Token --gitlab-token "$GL_Token" --cachedir ckan_cache -v
diff --git a/Netkan/CKAN-netkan.csproj b/Netkan/CKAN-netkan.csproj
index 7d65873867..b0e8c02e48 100644
--- a/Netkan/CKAN-netkan.csproj
+++ b/Netkan/CKAN-netkan.csproj
@@ -108,6 +108,7 @@
+
@@ -128,6 +129,7 @@
+
@@ -180,4 +182,4 @@
-
\ No newline at end of file
+
diff --git a/Netkan/CmdLineOptions.cs b/Netkan/CmdLineOptions.cs
index 8c6eeafd1b..e412274dda 100644
--- a/Netkan/CmdLineOptions.cs
+++ b/Netkan/CmdLineOptions.cs
@@ -55,6 +55,9 @@ internal class CmdLineOptions
[Option("version", HelpText = "Display the netkan version number and exit")]
public bool Version { get; set; }
+ [Option("game", DefaultValue = "KSP", HelpText = "Short name of the game for which to inflate mods")]
+ public string Game { get; set; }
+
[ValueOption(0)]
public string File { get; set; }
}
diff --git a/Netkan/Processors/Inflator.cs b/Netkan/Processors/Inflator.cs
index 3d0baf3bb6..64254f61a0 100644
--- a/Netkan/Processors/Inflator.cs
+++ b/Netkan/Processors/Inflator.cs
@@ -4,18 +4,20 @@
using System.Linq;
using Autofac;
using log4net;
+
using CKAN.Configuration;
using CKAN.Versioning;
using CKAN.NetKAN.Model;
using CKAN.NetKAN.Services;
using CKAN.NetKAN.Transformers;
using CKAN.NetKAN.Validators;
+using CKAN.Games;
namespace CKAN.NetKAN.Processors
{
public class Inflator
{
- public Inflator(string cacheDir, bool overwriteCache, string githubToken, string gitlabToken, bool prerelease)
+ public Inflator(string cacheDir, bool overwriteCache, string githubToken, string gitlabToken, bool prerelease, IGame game)
{
log.Debug("Initializing inflator");
cache = FindCache(
@@ -24,11 +26,11 @@ public Inflator(string cacheDir, bool overwriteCache, string githubToken, string
cacheDir
);
- IModuleService moduleService = new ModuleService();
+ IModuleService moduleService = new ModuleService(game);
IFileService fileService = new FileService(cache);
http = new CachingHttpService(cache, overwriteCache);
- ckanValidator = new CkanValidator(http, moduleService);
- transformer = new NetkanTransformer(http, fileService, moduleService, githubToken, gitlabToken, prerelease, netkanValidator);
+ ckanValidator = new CkanValidator(http, moduleService, game);
+ transformer = new NetkanTransformer(http, fileService, moduleService, githubToken, gitlabToken, prerelease, game, netkanValidator);
}
internal IEnumerable Inflate(string filename, Metadata netkan, TransformOptions opts)
diff --git a/Netkan/Processors/QueueHandler.cs b/Netkan/Processors/QueueHandler.cs
index ee8c842528..e25fab8a92 100644
--- a/Netkan/Processors/QueueHandler.cs
+++ b/Netkan/Processors/QueueHandler.cs
@@ -13,22 +13,24 @@
using log4net.Repository.Hierarchy;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
+
using CKAN.Versioning;
using CKAN.NetKAN.Transformers;
using CKAN.NetKAN.Model;
using CKAN.NetKAN.Extensions;
+using CKAN.Games;
namespace CKAN.NetKAN.Processors
{
public class QueueHandler
{
- public QueueHandler(string inputQueueName, string outputQueueName, string cacheDir, bool overwriteCache, string githubToken, string gitlabToken, bool prerelease)
+ public QueueHandler(string inputQueueName, string outputQueueName, string cacheDir, bool overwriteCache, string githubToken, string gitlabToken, bool prerelease, IGame game)
{
warningAppender = GetQueueLogAppender();
(LogManager.GetRepository() as Hierarchy)?.Root.AddAppender(warningAppender);
log.Debug("Initializing SQS queue handler");
- inflator = new Inflator(cacheDir, overwriteCache, githubToken, gitlabToken, prerelease);
+ inflator = new Inflator(cacheDir, overwriteCache, githubToken, gitlabToken, prerelease, game);
inputQueueURL = getQueueUrl(inputQueueName);
outputQueueURL = getQueueUrl(outputQueueName);
diff --git a/Netkan/Program.cs b/Netkan/Program.cs
index 84378fcb4d..124bdd77c5 100644
--- a/Netkan/Program.cs
+++ b/Netkan/Program.cs
@@ -16,6 +16,7 @@
using CKAN.NetKAN.Processors;
using CKAN.NetKAN.Transformers;
using CKAN.NetKAN.Extensions;
+using CKAN.Games;
namespace CKAN.NetKAN
{
@@ -47,6 +48,8 @@ public static int Main(string[] args)
return ExitOk;
}
+ var game = GameInstanceManager.GameByShortName(Options.Game);
+
if (!string.IsNullOrEmpty(Options.ValidateCkan))
{
var ckan = new Metadata(JObject.Parse(File.ReadAllText(Options.ValidateCkan)));
@@ -55,7 +58,8 @@ public static int Main(string[] args)
Options.OverwriteCache,
Options.GitHubToken,
Options.GitLabToken,
- Options.PreRelease
+ Options.PreRelease,
+ game
);
inf.ValidateCkan(ckan);
Console.WriteLine(QueueHandler.serializeCkan(
@@ -74,7 +78,8 @@ public static int Main(string[] args)
Options.OverwriteCache,
Options.GitHubToken,
Options.GitLabToken,
- Options.PreRelease
+ Options.PreRelease,
+ game
);
qh.Process();
return ExitOk;
@@ -92,7 +97,8 @@ public static int Main(string[] args)
Options.OverwriteCache,
Options.GitHubToken,
Options.GitLabToken,
- Options.PreRelease
+ Options.PreRelease,
+ game
);
var ckans = inf.Inflate(
Options.File,
diff --git a/Netkan/Services/IModuleService.cs b/Netkan/Services/IModuleService.cs
index ed3ce3000b..0793649cbb 100644
--- a/Netkan/Services/IModuleService.cs
+++ b/Netkan/Services/IModuleService.cs
@@ -5,6 +5,7 @@
using Newtonsoft.Json.Linq;
using CKAN.NetKAN.Sources.Avc;
+using CKAN.NetKAN.Sources.SpaceWarp;
namespace CKAN.NetKAN.Services
{
@@ -19,6 +20,8 @@ internal interface IModuleService
IEnumerable GetPlugins(CkanModule module, ZipFile zip, GameInstance inst);
IEnumerable GetCrafts(CkanModule module, ZipFile zip, GameInstance inst);
+ SpaceWarpInfo GetSpaceWarpInfo(CkanModule module, ZipFile zip, GameInstance inst);
+
IEnumerable FileSources(CkanModule module, ZipFile zip, GameInstance inst);
IEnumerable FileDestinations(CkanModule module, string filePath);
}
diff --git a/Netkan/Services/ModuleService.cs b/Netkan/Services/ModuleService.cs
index 4e091c2e08..857055d32c 100644
--- a/Netkan/Services/ModuleService.cs
+++ b/Netkan/Services/ModuleService.cs
@@ -12,12 +12,20 @@
using CKAN.Versioning;
using CKAN.Extensions;
using CKAN.NetKAN.Sources.Avc;
+using CKAN.NetKAN.Sources.SpaceWarp;
using CKAN.Games;
namespace CKAN.NetKAN.Services
{
internal sealed class ModuleService : IModuleService
{
+ public ModuleService(IGame game)
+ {
+ this.game = game;
+ }
+
+ private IGame game;
+
private static readonly ILog Log = LogManager.GetLogger(typeof(ModuleService));
public AvcVersion GetInternalAvc(CkanModule module, string zipFilePath, string internalFilePath = null)
@@ -66,7 +74,7 @@ public bool HasInstallableFiles(CkanModule module, string filePath)
try
{
ModuleInstaller.FindInstallableFiles(module, filePath,
- new GameInstance(new KerbalSpaceProgram(), "/", "dummy", new NullUser()));
+ new GameInstance(game, "/", "dummy", new NullUser()));
}
catch (BadMetadataKraken)
{
@@ -97,7 +105,7 @@ public IEnumerable FileSources(CkanModule module, ZipFile zip, GameIns
public IEnumerable FileDestinations(CkanModule module, string filePath)
{
- var inst = new GameInstance(new KerbalSpaceProgram(), "/", "dummy", null, false);
+ var inst = new GameInstance(game, "/", "dummy", null, false);
return ModuleInstaller
.FindInstallableFiles(module, filePath, inst)
.Where(f => !f.source.IsDirectory)
@@ -230,7 +238,7 @@ public Tuple FindInternalAvc(CkanModule module, ZipFile zipfile,
const string versionExt = ".version";
// Get all our version files
- var ksp = new GameInstance(new KerbalSpaceProgram(), "/", "dummy", new NullUser());
+ var ksp = new GameInstance(game, "/", "dummy", new NullUser());
var files = ModuleInstaller.FindInstallableFiles(module, zipfile, ksp)
.Select(x => x.source)
.Where(source => source.Name.EndsWith(versionExt,
@@ -315,5 +323,15 @@ public static AvcVersion GetInternalAvc(ZipFile zipfile, ZipEntry avcEntry)
}
}
}
+
+ private const string SpaceWarpInfoFilename = "swinfo.json";
+
+ public SpaceWarpInfo GetSpaceWarpInfo(CkanModule module, ZipFile zip, GameInstance inst)
+ => GetFilesBySuffix(module, zip, SpaceWarpInfoFilename, inst)
+ .Select(instF => instF.source)
+ .Select(entry =>
+ JsonConvert.DeserializeObject(
+ new StreamReader(zip.GetInputStream(entry)).ReadToEnd()))
+ .FirstOrDefault();
}
}
diff --git a/Netkan/Sources/SpaceWarp/SpaceWarpInfo.cs b/Netkan/Sources/SpaceWarp/SpaceWarpInfo.cs
new file mode 100644
index 0000000000..7e76913063
--- /dev/null
+++ b/Netkan/Sources/SpaceWarp/SpaceWarpInfo.cs
@@ -0,0 +1,50 @@
+using System;
+
+using Newtonsoft.Json;
+
+// https://github.com/SpaceWarpDev/SpaceWarp/blob/main/example_mod_info.json
+
+namespace CKAN.NetKAN.Sources.SpaceWarp
+{
+ public class SpaceWarpInfo
+ {
+ public string mod_id;
+ public string name;
+ public string author;
+ public string description;
+ public string source;
+ public string version;
+ public Dependency[] dependencies;
+ public VersionMinMax ksp2_version;
+ }
+
+ public class Dependency
+ {
+ public string id;
+ public VersionMinMax version;
+ }
+
+ public class VersionMinMax
+ {
+ [JsonConverter(typeof(SpaceWarpGameVersionConverter))]
+ public string min;
+ [JsonConverter(typeof(SpaceWarpGameVersionConverter))]
+ public string max;
+ }
+
+ public class SpaceWarpGameVersionConverter : JsonConverter
+ {
+ public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
+ => (reader.Value as string)?.Replace("*", "any");
+
+ public override bool CanConvert(Type objectType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/Netkan/Transformers/InstallSizeTransformer.cs b/Netkan/Transformers/InstallSizeTransformer.cs
index 2bec4cb65e..ea2bcfceb6 100644
--- a/Netkan/Transformers/InstallSizeTransformer.cs
+++ b/Netkan/Transformers/InstallSizeTransformer.cs
@@ -13,10 +13,11 @@ internal sealed class InstallSizeTransformer : ITransformer
{
public string Name { get { return "install_size"; } }
- public InstallSizeTransformer(IHttpService http, IModuleService moduleService)
+ public InstallSizeTransformer(IHttpService http, IModuleService moduleService, IGame game)
{
_http = http;
_moduleService = moduleService;
+ _game = game;
}
public IEnumerable Transform(Metadata metadata, TransformOptions opts)
@@ -26,7 +27,7 @@ public IEnumerable Transform(Metadata metadata, TransformOptions opts)
var json = metadata.Json();
CkanModule mod = CkanModule.FromJson(json.ToString());
ZipFile zip = new ZipFile(_http.DownloadModule(metadata));
- GameInstance inst = new GameInstance(new KerbalSpaceProgram(), "/", "dummy", new NullUser());
+ GameInstance inst = new GameInstance(_game, "/", "dummy", new NullUser());
json["install_size"] = _moduleService.FileSources(mod, zip, inst)
.Select(ze => ze.Size)
.Sum();
@@ -40,5 +41,6 @@ public IEnumerable Transform(Metadata metadata, TransformOptions opts)
private readonly IHttpService _http;
private readonly IModuleService _moduleService;
+ private readonly IGame _game;
}
}
diff --git a/Netkan/Transformers/InternalCkanTransformer.cs b/Netkan/Transformers/InternalCkanTransformer.cs
index c66c479874..5d30d06054 100644
--- a/Netkan/Transformers/InternalCkanTransformer.cs
+++ b/Netkan/Transformers/InternalCkanTransformer.cs
@@ -19,13 +19,15 @@ internal sealed class InternalCkanTransformer : ITransformer
private readonly IHttpService _http;
private readonly IModuleService _moduleService;
+ private readonly IGame _game;
public string Name { get { return "internal_ckan"; } }
- public InternalCkanTransformer(IHttpService http, IModuleService moduleService)
+ public InternalCkanTransformer(IHttpService http, IModuleService moduleService, IGame game)
{
_http = http;
_moduleService = moduleService;
+ _game = game;
}
public IEnumerable Transform(Metadata metadata, TransformOptions opts)
@@ -39,7 +41,7 @@ public IEnumerable Transform(Metadata metadata, TransformOptions opts)
var moduleJson = metadata.Json();
moduleJson.SafeAdd("version", "1");
CkanModule mod = CkanModule.FromJson(moduleJson.ToString());
- GameInstance inst = new GameInstance(new KerbalSpaceProgram(), "/", "dummy", new NullUser());
+ GameInstance inst = new GameInstance(_game, "/", "dummy", new NullUser());
var internalJson = _moduleService.GetInternalCkan(mod, _http.DownloadModule(metadata), inst);
diff --git a/Netkan/Transformers/LocalizationsTransformer.cs b/Netkan/Transformers/LocalizationsTransformer.cs
index 731d897dee..88b87089f0 100644
--- a/Netkan/Transformers/LocalizationsTransformer.cs
+++ b/Netkan/Transformers/LocalizationsTransformer.cs
@@ -21,10 +21,11 @@ internal sealed class LocalizationsTransformer : ITransformer
///
/// HTTP service
/// Module service
- public LocalizationsTransformer(IHttpService http, IModuleService moduleService)
+ public LocalizationsTransformer(IHttpService http, IModuleService moduleService, IGame game)
{
_http = http;
_moduleService = moduleService;
+ _game = game;
}
///
@@ -52,7 +53,7 @@ public IEnumerable Transform(Metadata metadata, TransformOptions opts)
{
CkanModule mod = CkanModule.FromJson(json.ToString());
ZipFile zip = new ZipFile(_http.DownloadModule(metadata));
- GameInstance inst = new GameInstance(new KerbalSpaceProgram(), "/", "dummy", new NullUser());
+ GameInstance inst = new GameInstance(_game, "/", "dummy", new NullUser());
log.Debug("Extracting locales");
// Extract the locale names from the ZIP's cfg files
@@ -86,6 +87,7 @@ public IEnumerable Transform(Metadata metadata, TransformOptions opts)
private readonly IHttpService _http;
private readonly IModuleService _moduleService;
+ private readonly IGame _game;
private static readonly ILog log = LogManager.GetLogger(typeof(LocalizationsTransformer));
diff --git a/Netkan/Transformers/NetkanTransformer.cs b/Netkan/Transformers/NetkanTransformer.cs
index bc81d8f081..1c64100e95 100644
--- a/Netkan/Transformers/NetkanTransformer.cs
+++ b/Netkan/Transformers/NetkanTransformer.cs
@@ -9,6 +9,7 @@
using CKAN.NetKAN.Sources.Gitlab;
using CKAN.NetKAN.Sources.Jenkins;
using CKAN.NetKAN.Sources.Spacedock;
+using CKAN.Games;
namespace CKAN.NetKAN.Transformers
{
@@ -29,6 +30,7 @@ public NetkanTransformer(
string githubToken,
string gitlabToken,
bool prerelease,
+ IGame game,
IValidator validator
)
{
@@ -37,7 +39,7 @@ IValidator validator
var glApi = new GitlabApi(http, gitlabToken);
_transformers = InjectVersionedOverrideTransformers(new List
{
- new StagingTransformer(),
+ new StagingTransformer(game),
new MetaNetkanTransformer(http, ghApi),
new SpacedockTransformer(new SpacedockApi(http), ghApi),
new CurseTransformer(new CurseApi(http)),
@@ -46,9 +48,10 @@ IValidator validator
new HttpTransformer(),
new JenkinsTransformer(new JenkinsApi(http)),
new AvcKrefTransformer(http, ghApi),
- new InternalCkanTransformer(http, moduleService),
+ new InternalCkanTransformer(http, moduleService, game),
+ new SpaceWarpInfoTransformer(http, moduleService, game),
new AvcTransformer(http, moduleService, ghApi),
- new LocalizationsTransformer(http, moduleService),
+ new LocalizationsTransformer(http, moduleService, game),
new VersionEditTransformer(),
new ForcedVTransformer(),
new EpochTransformer(),
@@ -57,7 +60,7 @@ IValidator validator
// specify a before or after property.
new VersionedOverrideTransformer(before: new string[] { null }, after: new string[] { null }),
new DownloadAttributeTransformer(http, fileService),
- new InstallSizeTransformer(http, moduleService),
+ new InstallSizeTransformer(http, moduleService, game),
new GeneratedByTransformer(),
new OptimusPrimeTransformer(),
new StripNetkanMetadataTransformer(),
diff --git a/Netkan/Transformers/SpaceWarpInfoTransformer.cs b/Netkan/Transformers/SpaceWarpInfoTransformer.cs
new file mode 100644
index 0000000000..ae284e87a3
--- /dev/null
+++ b/Netkan/Transformers/SpaceWarpInfoTransformer.cs
@@ -0,0 +1,63 @@
+using System.Collections.Generic;
+
+using ICSharpCode.SharpZipLib.Zip;
+using log4net;
+
+using CKAN.NetKAN.Model;
+using CKAN.NetKAN.Sources.SpaceWarp;
+using CKAN.NetKAN.Services;
+using CKAN.NetKAN.Extensions;
+using CKAN.Versioning;
+using CKAN.Games;
+
+namespace CKAN.NetKAN.Transformers
+{
+ internal sealed class SpaceWarpInfoTransformer : ITransformer
+ {
+ public SpaceWarpInfoTransformer(IHttpService httpSvc, IModuleService modSvc, IGame game)
+ {
+ this.httpSvc = httpSvc;
+ this.modSvc = modSvc;
+ this.game = game;
+ }
+
+ public string Name => "space_warp_info";
+
+ public IEnumerable Transform(Metadata metadata, TransformOptions opts)
+ {
+ if (metadata.Download != null)
+ {
+ var moduleJson = metadata.Json();
+ moduleJson.SafeAdd("version", "1");
+ CkanModule mod = CkanModule.FromJson(moduleJson.ToString());
+ GameInstance inst = new GameInstance(game, "/", "dummy", new NullUser());
+ ZipFile zip = new ZipFile(httpSvc.DownloadModule(metadata));
+ SpaceWarpInfo modinfo = modSvc.GetSpaceWarpInfo(mod, zip, inst);
+ if (modinfo != null)
+ {
+ var json = metadata.Json();
+ json.SafeAdd("name", modinfo.name);
+ json.SafeAdd("author", modinfo.author);
+ json.SafeAdd("abstract", modinfo.description);
+ json.SafeAdd("version", modinfo.version);
+ if (GameVersion.TryParse(modinfo.ksp2_version.min, out GameVersion _))
+ {
+ json.SafeAdd("ksp_version_min", modinfo.ksp2_version.min);
+ }
+ if (GameVersion.TryParse(modinfo.ksp2_version.max, out GameVersion _))
+ {
+ json.SafeAdd("ksp_version_max", modinfo.ksp2_version.max);
+ }
+ yield return new Metadata(json);
+ }
+ }
+ yield return metadata;
+ }
+
+ private readonly IHttpService httpSvc;
+ private readonly IModuleService modSvc;
+ private readonly IGame game;
+
+ private static readonly ILog log = LogManager.GetLogger(typeof(SpaceWarpInfoTransformer));
+ }
+}
diff --git a/Netkan/Transformers/SpacedockTransformer.cs b/Netkan/Transformers/SpacedockTransformer.cs
index d863770925..1ee9bcd387 100644
--- a/Netkan/Transformers/SpacedockTransformer.cs
+++ b/Netkan/Transformers/SpacedockTransformer.cs
@@ -76,7 +76,7 @@ private Metadata TransformOne(Metadata metadata, JObject json, SpacedockMod sdMo
if (json["ksp_version_min"] == null && json["ksp_version_max"] == null && json["ksp_version"] == null)
{
Log.DebugFormat("Writing ksp_version from SpaceDock: {0}", latestVersion.KSP_version);
- json["ksp_version"] = latestVersion.KSP_version.ToString();
+ json["ksp_version"] = latestVersion.KSP_version.WithoutBuild.ToString();
}
json.SafeAdd("name", sdMod.name);
diff --git a/Netkan/Transformers/StagingTransformer.cs b/Netkan/Transformers/StagingTransformer.cs
index be4835fef2..ec17214216 100644
--- a/Netkan/Transformers/StagingTransformer.cs
+++ b/Netkan/Transformers/StagingTransformer.cs
@@ -13,9 +13,10 @@ namespace CKAN.NetKAN.Transformers
{
internal sealed class StagingTransformer : ITransformer
{
- public StagingTransformer()
+ public StagingTransformer(IGame game)
{
- currentRelease = new KerbalSpaceProgram().KnownVersions.Max().ToVersionRange();
+ this.game = game;
+ currentRelease = game.KnownVersions.Max().ToVersionRange();
}
public string Name { get { return "staging"; } }
@@ -41,7 +42,6 @@ private bool VersionsNeedManualReview(Metadata metadata, out string reason)
var maxVer = maxStr == null ? GameVersion.Any : GameVersion.Parse((string)maxStr);
if (currentRelease.IntersectWith(new GameVersionRange(minVer, maxVer)) == null)
{
- var game = new KerbalSpaceProgram();
reason = $"Hard-coded game versions not compatible with current release: {GameVersionRange.VersionSpan(game, minVer, maxVer)}\r\nPlease check that they match the forum thread.";
return true;
}
@@ -53,7 +53,9 @@ private bool VersionsNeedManualReview(Metadata metadata, out string reason)
}
}
- private static GameVersionRange currentRelease;
+ private readonly GameVersionRange currentRelease;
+ private readonly IGame game;
+
private static readonly ILog Log = LogManager.GetLogger(typeof(StagingTransformer));
}
}
diff --git a/Netkan/Validators/CkanValidator.cs b/Netkan/Validators/CkanValidator.cs
index 53018e8f2e..9b6fb9e19a 100644
--- a/Netkan/Validators/CkanValidator.cs
+++ b/Netkan/Validators/CkanValidator.cs
@@ -1,6 +1,8 @@
using System.Collections.Generic;
+
using CKAN.NetKAN.Model;
using CKAN.NetKAN.Services;
+using CKAN.Games;
namespace CKAN.NetKAN.Validators
{
@@ -8,7 +10,7 @@ internal sealed class CkanValidator : IValidator
{
private readonly List _validators;
- public CkanValidator(IHttpService downloader, IModuleService moduleService)
+ public CkanValidator(IHttpService downloader, IModuleService moduleService, IGame game)
{
this.downloader = downloader;
this.moduleService = moduleService;
@@ -16,14 +18,14 @@ public CkanValidator(IHttpService downloader, IModuleService moduleService)
{
new IsCkanModuleValidator(),
new TagsValidator(),
- new InstallsFilesValidator(downloader, moduleService),
- new MatchesKnownGameVersionsValidator(),
+ new InstallsFilesValidator(downloader, moduleService, game),
+ new MatchesKnownGameVersionsValidator(game),
new ObeysCKANSchemaValidator(),
new KindValidator(),
- new HarmonyValidator(downloader, moduleService),
- new ModuleManagerDependsValidator(downloader, moduleService),
- new PluginsValidator(downloader, moduleService),
- new CraftsInShipsValidator(downloader, moduleService),
+ new HarmonyValidator(downloader, moduleService, game),
+ new ModuleManagerDependsValidator(downloader, moduleService, game),
+ new PluginsValidator(downloader, moduleService, game),
+ new CraftsInShipsValidator(downloader, moduleService, game),
};
}
diff --git a/Netkan/Validators/CraftsInShipsValidator.cs b/Netkan/Validators/CraftsInShipsValidator.cs
index 7f3fd9ebe2..28ad5b6aec 100644
--- a/Netkan/Validators/CraftsInShipsValidator.cs
+++ b/Netkan/Validators/CraftsInShipsValidator.cs
@@ -4,6 +4,7 @@
using Newtonsoft.Json.Linq;
using ICSharpCode.SharpZipLib.Zip;
using log4net;
+
using CKAN.NetKAN.Services;
using CKAN.NetKAN.Model;
using CKAN.Games;
@@ -12,10 +13,11 @@ namespace CKAN.NetKAN.Validators
{
internal sealed class CraftsInShipsValidator : IValidator
{
- public CraftsInShipsValidator(IHttpService http, IModuleService moduleService)
+ public CraftsInShipsValidator(IHttpService http, IModuleService moduleService, IGame game)
{
_http = http;
_moduleService = moduleService;
+ _game = game;
}
public void Validate(Metadata metadata)
@@ -30,7 +32,7 @@ public void Validate(Metadata metadata)
if (!string.IsNullOrEmpty(package))
{
var zip = new ZipFile(package);
- var inst = new GameInstance(new KerbalSpaceProgram(), "/", "dummy", null, false);
+ var inst = new GameInstance(_game, "/", "dummy", null, false);
var badCrafts = _moduleService.GetCrafts(mod, zip, inst)
.Where(f => !AllowedCraftPath(inst.ToRelativeGameDir(f.destination)))
.ToList();
@@ -55,6 +57,7 @@ private bool AllowedCraftPath(string path)
private readonly IHttpService _http;
private readonly IModuleService _moduleService;
+ private readonly IGame _game;
private static readonly ILog Log = LogManager.GetLogger(typeof(CraftsInShipsValidator));
}
diff --git a/Netkan/Validators/HarmonyValidator.cs b/Netkan/Validators/HarmonyValidator.cs
index 1eb5950cfe..13cfa89fc0 100644
--- a/Netkan/Validators/HarmonyValidator.cs
+++ b/Netkan/Validators/HarmonyValidator.cs
@@ -13,10 +13,11 @@ namespace CKAN.NetKAN.Validators
{
internal sealed class HarmonyValidator : IValidator
{
- public HarmonyValidator(IHttpService http, IModuleService moduleService)
+ public HarmonyValidator(IHttpService http, IModuleService moduleService, IGame game)
{
_http = http;
_moduleService = moduleService;
+ _game = game;
}
public void Validate(Metadata metadata)
@@ -25,14 +26,14 @@ public void Validate(Metadata metadata)
CkanModule mod = CkanModule.FromJson(json.ToString());
// The Harmony2 module is allowed to install a Harmony DLL;
// anybody else must have "provides":["Harmony1"] to do so
- if (!mod.IsDLC && mod.identifier != "Harmony2")
+ if (_game.ShortName == "KSP" && !mod.IsDLC && mod.identifier != "Harmony2")
{
// Need to peek at the mod's files
var package = _http.DownloadModule(metadata);
if (!string.IsNullOrEmpty(package))
{
ZipFile zip = new ZipFile(package);
- GameInstance inst = new GameInstance(new KerbalSpaceProgram(), "/", "dummy", new NullUser());
+ GameInstance inst = new GameInstance(_game, "/", "dummy", new NullUser());
var harmonyDLLs = _moduleService.GetPlugins(mod, zip, inst)
.Select(instF => instF.source.Name)
@@ -55,6 +56,7 @@ public void Validate(Metadata metadata)
private readonly IHttpService _http;
private readonly IModuleService _moduleService;
+ private readonly IGame _game;
private static readonly ILog Log = LogManager.GetLogger(typeof(HarmonyValidator));
}
diff --git a/Netkan/Validators/InstallsFilesValidator.cs b/Netkan/Validators/InstallsFilesValidator.cs
index bb86fef45f..68448b4070 100644
--- a/Netkan/Validators/InstallsFilesValidator.cs
+++ b/Netkan/Validators/InstallsFilesValidator.cs
@@ -12,11 +12,13 @@ internal sealed class InstallsFilesValidator : IValidator
{
private readonly IHttpService _http;
private readonly IModuleService _moduleService;
+ private readonly IGame _game;
- public InstallsFilesValidator(IHttpService http, IModuleService moduleService)
+ public InstallsFilesValidator(IHttpService http, IModuleService moduleService, IGame game)
{
_http = http;
_moduleService = moduleService;
+ _game = game;
}
public void Validate(Metadata metadata)
@@ -31,7 +33,7 @@ public void Validate(Metadata metadata)
{
throw new Kraken(string.Format(
"Module contains no files matching: {0}",
- mod.DescribeInstallStanzas(new KerbalSpaceProgram())
+ mod.DescribeInstallStanzas(_game)
));
}
diff --git a/Netkan/Validators/MatchesKnownGameVersionsValidator.cs b/Netkan/Validators/MatchesKnownGameVersionsValidator.cs
index cc309198d4..44d419dc44 100644
--- a/Netkan/Validators/MatchesKnownGameVersionsValidator.cs
+++ b/Netkan/Validators/MatchesKnownGameVersionsValidator.cs
@@ -1,17 +1,19 @@
using System.Collections.Generic;
using Autofac;
+
using CKAN.GameVersionProviders;
using CKAN.Versioning;
-using CKAN.Games;
using CKAN.NetKAN.Model;
+using CKAN.Games;
namespace CKAN.NetKAN.Validators
{
internal sealed class MatchesKnownGameVersionsValidator : IValidator
{
- public MatchesKnownGameVersionsValidator()
+ public MatchesKnownGameVersionsValidator(IGame game)
{
- knownVersions = new KerbalSpaceProgram().KnownVersions;
+ this.game = game;
+ knownVersions = game.KnownVersions;
}
public void Validate(Metadata metadata)
@@ -21,11 +23,11 @@ public void Validate(Metadata metadata)
{
GameVersion minKsp = null, maxKsp = null;
Registry.GetMinMaxVersions(new List() {mod}, out _, out _, out minKsp, out maxKsp);
- var game = new KerbalSpaceProgram();
throw new Kraken($"{metadata.Identifier} doesn't match any valid game version: {GameVersionRange.VersionSpan(game, minKsp, maxKsp)}");
}
}
private List knownVersions;
+ private IGame game;
}
}
diff --git a/Netkan/Validators/ModuleManagerDependsValidator.cs b/Netkan/Validators/ModuleManagerDependsValidator.cs
index 58d1e9cbda..bbd495e9af 100644
--- a/Netkan/Validators/ModuleManagerDependsValidator.cs
+++ b/Netkan/Validators/ModuleManagerDependsValidator.cs
@@ -4,6 +4,7 @@
using Newtonsoft.Json.Linq;
using ICSharpCode.SharpZipLib.Zip;
using log4net;
+
using CKAN.NetKAN.Services;
using CKAN.NetKAN.Model;
using CKAN.Extensions;
@@ -13,10 +14,11 @@ namespace CKAN.NetKAN.Validators
{
internal sealed class ModuleManagerDependsValidator : IValidator
{
- public ModuleManagerDependsValidator(IHttpService http, IModuleService moduleService)
+ public ModuleManagerDependsValidator(IHttpService http, IModuleService moduleService, IGame game)
{
_http = http;
_moduleService = moduleService;
+ _game = game;
}
public void Validate(Metadata metadata)
@@ -31,7 +33,7 @@ public void Validate(Metadata metadata)
if (!string.IsNullOrEmpty(package))
{
ZipFile zip = new ZipFile(package);
- GameInstance inst = new GameInstance(new KerbalSpaceProgram(), "/", "dummy", new NullUser());
+ GameInstance inst = new GameInstance(_game, "/", "dummy", new NullUser());
var mmConfigs = _moduleService.GetConfigFiles(mod, zip, inst)
.Where(cfg => moduleManagerRegex.IsMatch(
new StreamReader(zip.GetInputStream(cfg.source)).ReadToEnd()))
@@ -63,6 +65,7 @@ public void Validate(Metadata metadata)
private readonly IHttpService _http;
private readonly IModuleService _moduleService;
+ private readonly IGame _game;
private static readonly ILog Log = LogManager.GetLogger(typeof(ModuleManagerDependsValidator));
}
diff --git a/Netkan/Validators/PluginsValidator.cs b/Netkan/Validators/PluginsValidator.cs
index c4e25f3dc1..1fcc5c4a61 100644
--- a/Netkan/Validators/PluginsValidator.cs
+++ b/Netkan/Validators/PluginsValidator.cs
@@ -4,6 +4,7 @@
using Newtonsoft.Json.Linq;
using ICSharpCode.SharpZipLib.Zip;
using log4net;
+
using CKAN.Extensions;
using CKAN.NetKAN.Services;
using CKAN.NetKAN.Model;
@@ -13,10 +14,11 @@ namespace CKAN.NetKAN.Validators
{
internal sealed class PluginsValidator : IValidator
{
- public PluginsValidator(IHttpService http, IModuleService moduleService)
+ public PluginsValidator(IHttpService http, IModuleService moduleService, IGame game)
{
_http = http;
_moduleService = moduleService;
+ _game = game;
}
public void Validate(Metadata metadata)
@@ -31,7 +33,7 @@ public void Validate(Metadata metadata)
if (!string.IsNullOrEmpty(package))
{
ZipFile zip = new ZipFile(package);
- GameInstance inst = new GameInstance(new KerbalSpaceProgram(), "/", "dummy", new NullUser());
+ GameInstance inst = new GameInstance(_game, "/", "dummy", new NullUser());
var plugins = _moduleService.GetPlugins(mod, zip, inst).ToList();
bool hasPlugin = plugins.Any();
@@ -76,6 +78,7 @@ public void Validate(Metadata metadata)
private readonly IHttpService _http;
private readonly IModuleService _moduleService;
+ private readonly IGame _game;
private static readonly ILog Log = LogManager.GetLogger(typeof(PluginsValidator));
}
diff --git a/Spec.md b/Spec.md
index 4e15854afc..04f2c4ec5a 100644
--- a/Spec.md
+++ b/Spec.md
@@ -293,8 +293,9 @@ three source directives:
In addition a destination directive *must* be provided:
- `install_to`: The target location where the matched file or directory should be installed.
- - Valid values for this entry are `GameData`, `Missions`(**v1.25**), `Ships`, `Ships/SPH`(**v1.12**), `Ships/VAB`(**v1.12**), `Ships/@thumbs/VAB`(**v1.16**), `Ships/@thumbs/SPH`(**v1.16**), `Ships/Script`(**v1.29**), `Tutorial`, `Scenarios` (**v1.14**)
+ - Valid values for this entry for KSP1 mods are `GameData`, `Missions`(**v1.25**), `Ships`, `Ships/SPH`(**v1.12**), `Ships/VAB`(**v1.12**), `Ships/@thumbs/VAB`(**v1.16**), `Ships/@thumbs/SPH`(**v1.16**), `Ships/Script`(**v1.29**), `Tutorial`, `Scenarios` (**v1.14**),
and `GameRoot` (which should be used sparingly, if at all).
+ - Valid values for this entry for KSP2 mods are `GameRoot`, `BepInEx/plugins` (**v1.32**), and `SpaceWarp/Mods` (**v1.32**)
- A path to a given subfolder location can be specified *only* under `GameData` (**v1.2**);
for example: `GameData/MyMod/Plugins`. The client *must* check this path and abort the install
if any attempts to traverse up directories are found (eg: `GameData/../Example`).
diff --git a/Tests/NetKAN/Services/ModuleServiceTests.cs b/Tests/NetKAN/Services/ModuleServiceTests.cs
index 0264b49f35..fbea93058e 100644
--- a/Tests/NetKAN/Services/ModuleServiceTests.cs
+++ b/Tests/NetKAN/Services/ModuleServiceTests.cs
@@ -21,7 +21,7 @@ public void HasInstallableFilesReturnsFalseWhenNoInstallableFiles()
var json = JObject.Parse(TestData.DogeCoinFlag_101());
json["install"][0]["file"] = "DOES_NOT_EXIST";
- var sut = new ModuleService();
+ var sut = new ModuleService(new KerbalSpaceProgram());
// Act
var result = sut.HasInstallableFiles(CkanModule.FromJson(json.ToString()), zip);
@@ -39,7 +39,7 @@ public void HasInstallableFilesReturnsTrueWhenInstallableFiles()
var zip = TestData.DogeCoinFlagZip();
var json = JObject.Parse(TestData.DogeCoinFlag_101());
- var sut = new ModuleService();
+ var sut = new ModuleService(new KerbalSpaceProgram());
// Act
var result = sut.HasInstallableFiles(CkanModule.FromJson(json.ToString()), zip);
@@ -54,7 +54,7 @@ public void HasInstallableFilesReturnsTrueWhenInstallableFiles()
public void GetsInternalCkanCorrectly()
{
// Arrange
- var sut = new ModuleService();
+ var sut = new ModuleService(new KerbalSpaceProgram());
CkanModule mod = CkanModule.FromJson(TestData.DogeCoinFlag_101());
GameInstance inst = new GameInstance(new KerbalSpaceProgram(), "/", "dummy", new NullUser());
@@ -80,7 +80,7 @@ public void GetsInternalAvcCorrectly()
json["version"] = "1.0.0";
json["download"] = "https://awesomemod.example/AwesomeMod.zip";
- var sut = new ModuleService();
+ var sut = new ModuleService(new KerbalSpaceProgram());
// Act
var result = sut.GetInternalAvc(CkanModule.FromJson(json.ToString()), TestData.DogeCoinFlagAvcZip());
diff --git a/Tests/NetKAN/Transformers/InstallSizeTransformerTests.cs b/Tests/NetKAN/Transformers/InstallSizeTransformerTests.cs
index 8896b322aa..a41fe4d686 100644
--- a/Tests/NetKAN/Transformers/InstallSizeTransformerTests.cs
+++ b/Tests/NetKAN/Transformers/InstallSizeTransformerTests.cs
@@ -7,6 +7,7 @@
using CKAN.NetKAN.Model;
using CKAN.NetKAN.Services;
using CKAN.NetKAN.Transformers;
+using CKAN.Games;
using Tests.Data;
namespace Tests.NetKAN.Transformers
@@ -24,9 +25,9 @@ public void Transform_NormalModule_CorrectInstallSize()
mHttp.Setup(i => i.DownloadModule(It.IsAny()))
.Returns(TestData.DogeCoinFlagZip());
- var modSvc = new ModuleService();
+ var modSvc = new ModuleService(new KerbalSpaceProgram());
- ITransformer sut = new InstallSizeTransformer(mHttp.Object, modSvc);
+ ITransformer sut = new InstallSizeTransformer(mHttp.Object, modSvc, new KerbalSpaceProgram());
// Act
var result = sut.Transform(new Metadata(json), opts).First();
diff --git a/Tests/NetKAN/Transformers/InternalCkanTransformerTests.cs b/Tests/NetKAN/Transformers/InternalCkanTransformerTests.cs
index b0b68d283a..ce117bdb67 100644
--- a/Tests/NetKAN/Transformers/InternalCkanTransformerTests.cs
+++ b/Tests/NetKAN/Transformers/InternalCkanTransformerTests.cs
@@ -10,6 +10,7 @@
using CKAN.NetKAN.Model;
using CKAN.NetKAN.Services;
using CKAN.NetKAN.Transformers;
+using CKAN.Games;
namespace Tests.NetKAN.Transformers
{
@@ -39,7 +40,7 @@ public void AddsMissingProperties()
It.IsAny()))
.Returns(internalCkan);
- var sut = new InternalCkanTransformer(mHttp.Object, mModuleService.Object);
+ var sut = new InternalCkanTransformer(mHttp.Object, mModuleService.Object, new KerbalSpaceProgram());
var json = new JObject();
json["spec_version"] = 1;
@@ -78,7 +79,7 @@ public void DoesNotOverrideExistingProperties()
It.IsAny()))
.Returns(internalCkan);
- var sut = new InternalCkanTransformer(mHttp.Object, mModuleService.Object);
+ var sut = new InternalCkanTransformer(mHttp.Object, mModuleService.Object, new KerbalSpaceProgram());
var json = new JObject();
json["spec_version"] = 1;
@@ -120,7 +121,7 @@ public void HigherOfTwoSpecVersionsIsChosen(
It.IsAny()))
.Returns(internalCkan);
- var sut = new InternalCkanTransformer(mHttp.Object, mModuleService.Object);
+ var sut = new InternalCkanTransformer(mHttp.Object, mModuleService.Object, new KerbalSpaceProgram());
var json = new JObject();
json["spec_version"] = specVersion;
diff --git a/Tests/NetKAN/Validators/CkanValidatorTests.cs b/Tests/NetKAN/Validators/CkanValidatorTests.cs
index 5a27a64565..2c1ef3aadb 100644
--- a/Tests/NetKAN/Validators/CkanValidatorTests.cs
+++ b/Tests/NetKAN/Validators/CkanValidatorTests.cs
@@ -1,10 +1,12 @@
-using CKAN;
+using Moq;
+using Newtonsoft.Json.Linq;
+using NUnit.Framework;
+
+using CKAN;
using CKAN.NetKAN.Model;
using CKAN.NetKAN.Services;
using CKAN.NetKAN.Validators;
-using Moq;
-using Newtonsoft.Json.Linq;
-using NUnit.Framework;
+using CKAN.Games;
namespace Tests.NetKAN.Validators
{
@@ -37,7 +39,7 @@ public void DoesNotThrowOnValidCkan()
mModuleService.Setup(i => i.HasInstallableFiles(It.IsAny(), It.IsAny()))
.Returns(true);
- var sut = new CkanValidator(mHttp.Object, mModuleService.Object);
+ var sut = new CkanValidator(mHttp.Object, mModuleService.Object, new KerbalSpaceProgram());
var json = (JObject)ValidCkan.DeepClone();
// Act
@@ -62,7 +64,7 @@ public void DoesThrowWhenMissingProperty(string propertyName)
mModuleService.Setup(i => i.HasInstallableFiles(It.IsAny(), It.IsAny()))
.Returns(true);
- var sut = new CkanValidator(mHttp.Object, mModuleService.Object);
+ var sut = new CkanValidator(mHttp.Object, mModuleService.Object, new KerbalSpaceProgram());
var json = (JObject)ValidCkan.DeepClone();
json.Remove(propertyName);
@@ -85,7 +87,7 @@ public void DoesThrowWhenIdentifiersDoNotMatch()
mModuleService.Setup(i => i.HasInstallableFiles(It.IsAny(), It.IsAny()))
.Returns(true);
- var sut = new CkanValidator(mHttp.Object, mModuleService.Object);
+ var sut = new CkanValidator(mHttp.Object, mModuleService.Object, new KerbalSpaceProgram());
var json = new JObject();
json["spec_version"] = 1;
json["identifier"] = "AmazingMod";
@@ -113,7 +115,7 @@ public void DoesThrowWhenNoInstallableFiles()
netkan["spec_version"] = 1;
netkan["identifier"] = "AwesomeMod";
- var sut = new CkanValidator(mHttp.Object, mModuleService.Object);
+ var sut = new CkanValidator(mHttp.Object, mModuleService.Object, new KerbalSpaceProgram());
var json = (JObject)ValidCkan.DeepClone();
// Act
diff --git a/Tests/NetKAN/Validators/InstallsFilesValidatorTests.cs b/Tests/NetKAN/Validators/InstallsFilesValidatorTests.cs
index 320f190d79..93a4680400 100644
--- a/Tests/NetKAN/Validators/InstallsFilesValidatorTests.cs
+++ b/Tests/NetKAN/Validators/InstallsFilesValidatorTests.cs
@@ -1,10 +1,12 @@
-using CKAN;
+using Moq;
+using Newtonsoft.Json.Linq;
+using NUnit.Framework;
+
+using CKAN;
using CKAN.NetKAN.Model;
using CKAN.NetKAN.Services;
using CKAN.NetKAN.Validators;
-using Moq;
-using Newtonsoft.Json.Linq;
-using NUnit.Framework;
+using CKAN.Games;
namespace Tests.NetKAN.Validators
{
@@ -27,7 +29,7 @@ public void DoesNotThrowWhenInstallableFiles()
json["version"] = "1.0.0";
json["download"] = "https://www.awesome-mod.example/AwesomeMod.zip";
- var sut = new InstallsFilesValidator(mHttp.Object, mModuleService.Object);
+ var sut = new InstallsFilesValidator(mHttp.Object, mModuleService.Object, new KerbalSpaceProgram());
// Act
TestDelegate act = () => sut.Validate(new Metadata(json));
@@ -54,7 +56,7 @@ public void DoesThrowWhenNoInstallableFiles()
json["version"] = "1.0.0";
json["download"] = "https://www.awesome-mod.example/AwesomeMod.zip";
- var sut = new InstallsFilesValidator(mHttp.Object, mModuleService.Object);
+ var sut = new InstallsFilesValidator(mHttp.Object, mModuleService.Object, new KerbalSpaceProgram());
// Act
TestDelegate act = () => sut.Validate(new Metadata(json));
diff --git a/Tests/NetKAN/Validators/MatchesKnownGameVersionsValidatorTests.cs b/Tests/NetKAN/Validators/MatchesKnownGameVersionsValidatorTests.cs
index fecd7f4c5c..8dac393ceb 100644
--- a/Tests/NetKAN/Validators/MatchesKnownGameVersionsValidatorTests.cs
+++ b/Tests/NetKAN/Validators/MatchesKnownGameVersionsValidatorTests.cs
@@ -1,7 +1,9 @@
using Newtonsoft.Json.Linq;
using NUnit.Framework;
+
using CKAN.NetKAN.Model;
using CKAN.NetKAN.Validators;
+using CKAN.Games;
namespace Tests.NetKAN.Validators
{
@@ -55,7 +57,7 @@ private void TryVersion(string ksp_version, string ksp_version_min, string ksp_v
}
// Act
- var val = new MatchesKnownGameVersionsValidator();
+ var val = new MatchesKnownGameVersionsValidator(new KerbalSpaceProgram());
val.Validate(new Metadata(json));
}
}