Skip to content

Commit

Permalink
KSP2 support
Browse files Browse the repository at this point in the history
  • Loading branch information
HebaruSan committed Mar 7, 2023
1 parent 2d387d9 commit ee619db
Show file tree
Hide file tree
Showing 33 changed files with 477 additions and 77 deletions.
10 changes: 10 additions & 0 deletions CKAN.schema
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
]
},
Expand Down
6 changes: 5 additions & 1 deletion Core/GameInstanceManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ public class GameInstanceManager : IDisposable
{
private static IGame[] knownGames = new IGame[]
{
new KerbalSpaceProgram()
new KerbalSpaceProgram(),
new KerbalSpaceProgram2(),
};

/// <summary>
Expand Down Expand Up @@ -646,5 +647,8 @@ public IGame DetermineGame(DirectoryInfo path, IUser user)
}
}

public static IGame GameByShortName(string shortName)
=> knownGames.FirstOrDefault(g => g.ShortName == shortName);

}
}
200 changes: 200 additions & 0 deletions Core/Games/KerbalSpaceProgram2.cs
Original file line number Diff line number Diff line change
@@ -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");

/// <summary>
/// Finds the Steam KSP path. Returns null if the folder cannot be located.
/// </summary>
/// <returns>The KSP path.</returns>
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;
}

/// <summary>
/// Get the default non-Steam path to KSP on macOS
/// </summary>
/// <returns>
/// "/Applications/Kerbal Space Program" if it exists and we're on a Mac, else null
/// </returns>
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",
};

/// <summary>
/// Checks the path against a list of reserved game directories
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
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<GameVersion> KnownVersions
=> new List<GameVersion>
{
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<string, string> allowedFolders = new Dictionary<string, string>
{
{ "BepInEx", "BepInEx" },
{ "BepInEx/plugins", "BepInEx/plugins" },
};

/// <summary>
/// Finds the KSP path under a Steam Library. Returns null if the folder cannot be located.
/// </summary>
/// <param name="steamPath">Steam Library Path</param>
/// <returns>The KSP path.</returns>
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));
}
}
2 changes: 1 addition & 1 deletion Dockerfile.netkan
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 3 additions & 1 deletion Netkan/CKAN-netkan.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@
<Compile Include="Sources\Spacedock\SpacedockError.cs" />
<Compile Include="Sources\Spacedock\SpacedockMod.cs" />
<Compile Include="Sources\Spacedock\SpacedockUser.cs" />
<Compile Include="Sources\SpaceWarp\SpaceWarpInfo.cs" />
<Compile Include="Transformers\AvcKrefTransformer.cs" />
<Compile Include="Transformers\AvcTransformer.cs" />
<Compile Include="Transformers\CurseTransformer.cs" />
Expand All @@ -128,6 +129,7 @@
<Compile Include="Transformers\OptimusPrimeTransformer.cs" />
<Compile Include="Transformers\PropertySortTransformer.cs" />
<Compile Include="Transformers\SpacedockTransformer.cs" />
<Compile Include="Transformers\SpaceWarpInfoTransformer.cs" />
<Compile Include="Transformers\StagingTransformer.cs" />
<Compile Include="Transformers\StagingLinksTransformer.cs" />
<Compile Include="Transformers\StripNetkanMetadataTransformer.cs" />
Expand Down Expand Up @@ -180,4 +182,4 @@
<Exec Command="powershell ../build.ps1 Generate-GlobalAssemblyVersionInfo" Condition="!Exists('../_build/meta/GlobalAssemblyVersionInfo.cs') And '$(OS)' == 'Windows_NT'" />
<Exec Command="sh ../build Generate-GlobalAssemblyVersionInfo" Condition="!Exists('../_build/meta/GlobalAssemblyVersionInfo.cs') And '$(OS)' == 'Unix'" />
</Target>
</Project>
</Project>
3 changes: 3 additions & 0 deletions Netkan/CmdLineOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
}
Expand Down
10 changes: 6 additions & 4 deletions Netkan/Processors/Inflator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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<Metadata> Inflate(string filename, Metadata netkan, TransformOptions opts)
Expand Down
6 changes: 4 additions & 2 deletions Netkan/Processors/QueueHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
12 changes: 9 additions & 3 deletions Netkan/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
using CKAN.NetKAN.Processors;
using CKAN.NetKAN.Transformers;
using CKAN.NetKAN.Extensions;
using CKAN.Games;

namespace CKAN.NetKAN
{
Expand Down Expand Up @@ -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)));
Expand All @@ -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(
Expand All @@ -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;
Expand All @@ -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,
Expand Down
Loading

0 comments on commit ee619db

Please sign in to comment.