diff --git a/Sledge.Formats.Configuration.Tests/Resources/Worldcraft/CmdSeq-wc15.wc b/Sledge.Formats.Configuration.Tests/Resources/Worldcraft/CmdSeq-wc15.wc
new file mode 100644
index 0000000..f16f4c9
Binary files /dev/null and b/Sledge.Formats.Configuration.Tests/Resources/Worldcraft/CmdSeq-wc15.wc differ
diff --git a/Sledge.Formats.Configuration.Tests/Resources/Worldcraft/CmdSeq-wc33.wc b/Sledge.Formats.Configuration.Tests/Resources/Worldcraft/CmdSeq-wc33.wc
new file mode 100644
index 0000000..9740c85
Binary files /dev/null and b/Sledge.Formats.Configuration.Tests/Resources/Worldcraft/CmdSeq-wc33.wc differ
diff --git a/Sledge.Formats.Configuration.Tests/Sledge.Formats.Configuration.Tests.csproj b/Sledge.Formats.Configuration.Tests/Sledge.Formats.Configuration.Tests.csproj
index beda79a..9d5a414 100644
--- a/Sledge.Formats.Configuration.Tests/Sledge.Formats.Configuration.Tests.csproj
+++ b/Sledge.Formats.Configuration.Tests/Sledge.Formats.Configuration.Tests.csproj
@@ -9,11 +9,15 @@
+
+
+
+
diff --git a/Sledge.Formats.Configuration.Tests/TestWorldcraftConfiguration.cs b/Sledge.Formats.Configuration.Tests/TestWorldcraftConfiguration.cs
index 575aa71..0156ba0 100644
--- a/Sledge.Formats.Configuration.Tests/TestWorldcraftConfiguration.cs
+++ b/Sledge.Formats.Configuration.Tests/TestWorldcraftConfiguration.cs
@@ -11,14 +11,23 @@ namespace Sledge.Formats.Configuration.Tests;
public sealed class TestWorldcraftConfiguration
{
///
- /// If you don't have worldcraft settings in your registry, this test will fail
+ /// This test is just for information from your local PC, it will not fail.
///
[TestMethod]
public void TestLoadSettingsFromLocalComputer()
{
- var config = WorldcraftConfiguration.LoadFromRegistry(WorldcraftConfigurationLoadSettings.Default);
- Console.WriteLine("Undo levels: " + config.General.UndoLevels);
- Console.WriteLine("Textures: " + string.Join("; ", config.TextureDirectories));
+ try
+ {
+ var config = WorldcraftConfiguration.LoadFromRegistry(WorldcraftConfigurationLoadSettings.Default);
+ Console.WriteLine("Install directory: " + config.General.InstallDirectory);
+ Console.WriteLine("Undo levels: " + config.General.UndoLevels);
+ Console.WriteLine("Textures: " + string.Join("; ", config.TextureDirectories));
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Unable to load config from local computer.");
+ Console.WriteLine(ex.Message);
+ }
}
[TestMethod]
@@ -28,6 +37,7 @@ public void TestLoadSettings()
var config = WorldcraftConfiguration.LoadFromRegistry(new WorldcraftConfigurationLoadSettings
{
LoadGameConfigurations = false,
+ LoadCommandSequences = false,
RegistryLocation = reg.OpenBaseKey(RegistryHive.CurrentUser, RegistryView.Default).OpenSubKey(@"Software\Valve\Worldcraft")
});
@@ -36,6 +46,7 @@ public void TestLoadSettings()
Assert.IsNotNull(config.Views3D);
Assert.IsNotNull(config.TextureDirectories);
Assert.IsNull(config.GameConfigurations);
+ Assert.IsNull(config.CommandSequences);
Assert.AreEqual(@"C:\Users\WDAGUtilityAccount\Desktop\Worldcraft 3.3", config.General.InstallDirectory, StringComparer.InvariantCultureIgnoreCase);
Assert.AreEqual(true, config.General.UseIndependentWindowConfigurations);
@@ -234,6 +245,180 @@ public void TestWriteGameConfigFile33()
Assert.AreEqual(file.Configurations[0].BuildPrograms.BspDirectory, file2.Configurations[0].BuildPrograms.BspDirectory);
}
+ [TestMethod]
+ public void TestReadCommandSequenceFile15()
+ {
+ using var file = typeof(TestWorldcraftConfiguration).Assembly.GetManifestResourceStream("Sledge.Formats.Configuration.Tests.Resources.Worldcraft.CmdSeq-wc15.wc");
+ var sequences = new WorldcraftCommandSequenceFile(file).CommandSequences;
+
+ Assert.AreEqual(2, sequences.Count);
+ var (seq1, seq2) = (sequences[0], sequences[1]);
+
+ Assert.AreEqual("Default", seq1.Name);
+
+ Assert.AreEqual(true, seq1.Steps[0].IsEnabled);
+ Assert.AreEqual("a", seq1.Steps[0].Command);
+ Assert.AreEqual("b", seq1.Steps[0].Arguments);
+ Assert.AreEqual(true, seq1.Steps[0].UseLongFileNames);
+ Assert.AreEqual(true, seq1.Steps[0].EnsureFileExists);
+ Assert.AreEqual("", seq1.Steps[0].FileExistsName);
+ Assert.AreEqual(false, seq1.Steps[0].UseProcessWindow);
+
+ Assert.AreEqual(false, seq1.Steps[1].IsEnabled);
+ Assert.AreEqual("c", seq1.Steps[1].Command);
+ Assert.AreEqual("d", seq1.Steps[1].Arguments);
+ Assert.AreEqual(false, seq1.Steps[1].UseLongFileNames);
+ Assert.AreEqual(false, seq1.Steps[1].EnsureFileExists);
+ Assert.AreEqual("", seq1.Steps[1].FileExistsName);
+ Assert.AreEqual(true, seq1.Steps[1].UseProcessWindow);
+
+ Assert.AreEqual("Test", seq2.Name);
+
+ Assert.AreEqual(false, seq2.Steps[0].IsEnabled);
+ Assert.AreEqual("test1", seq2.Steps[0].Command);
+ Assert.AreEqual("test2", seq2.Steps[0].Arguments);
+ Assert.AreEqual(false, seq2.Steps[0].UseLongFileNames);
+ Assert.AreEqual(true, seq2.Steps[0].EnsureFileExists);
+ Assert.AreEqual("test3", seq2.Steps[0].FileExistsName);
+ Assert.AreEqual(true, seq2.Steps[0].UseProcessWindow);
+ }
+
+ [TestMethod]
+ public void TestReadCommandSequenceFile33()
+ {
+ using var file = typeof(TestWorldcraftConfiguration).Assembly.GetManifestResourceStream("Sledge.Formats.Configuration.Tests.Resources.Worldcraft.CmdSeq-wc33.wc"); var sequences = new WorldcraftCommandSequenceFile(file).CommandSequences;
+
+ Assert.AreEqual(4, sequences.Count);
+ var (seq1, seq2, seq3, seq4) = (sequences[0], sequences[1], sequences[2], sequences[3]);
+
+ Assert.AreEqual("Half-Life (full)", seq1.Name);
+ Assert.AreEqual("Half-Life: Counterstrike (full)", seq2.Name);
+ Assert.AreEqual("Half-Life: Opposing Force (full)", seq3.Name);
+ Assert.AreEqual("Half-Life: Team Fortress (full)", seq4.Name);
+
+ AssertSteps("valve", seq1);
+ AssertSteps("cstrike", seq2);
+ AssertSteps("gearbox", seq3);
+ AssertSteps("tfc", seq4);
+
+ static void AssertSteps(string game, WorldcraftCommandSequence sequence)
+ {
+ Assert.AreEqual(8, sequence.Steps.Count);
+
+ AssertStep(true, "Change Directory", "$exedir", true, false, "", true, sequence.Steps[0]);
+ AssertStep(true, "$csg_exe", @"$path\$file", true, false, "", true, sequence.Steps[1]);
+ AssertStep(true, "$bsp_exe", @"$path\$file", true, false, "", true, sequence.Steps[2]);
+ AssertStep(true, "$vis_exe", @"$path\$file", true, false, "", true, sequence.Steps[3]);
+ AssertStep(true, "$light_exe", @"$path\$file", true, false, "", true, sequence.Steps[4]);
+ AssertStep(true, "Copy File", @"$path\$file.bsp $bspdir\$file.bsp", true, false, "", true, sequence.Steps[5]);
+ AssertStep(true, "Copy File", @"$path\$file.pts $bspdir\$file.pts", true, false, "", true, sequence.Steps[6]);
+ switch (game)
+ {
+ case "valve":
+ AssertStep(true, "$game_exe", "+map $file -dev -console", true, false, "", false, sequence.Steps[7]);
+ break;
+ case "cstrike":
+ AssertStep(true, "$game_exe", "+map $file -game cstrike -dev -console +deathmatch 1", true, false, "", false, sequence.Steps[7]);
+ break;
+ case "gearbox":
+ AssertStep(true, "$game_exe", "+map $file -game gearbox -dev -console", true, false, "", false, sequence.Steps[7]);
+ break;
+ case "tfc":
+ AssertStep(true, "$game_exe", "+map $file -game tfc -dev -console -toconsole +sv_lan 1", true, false, "", false, sequence.Steps[7]);
+ break;
+ }
+ }
+
+ static void AssertStep(bool isEnabled, string command, string args, bool useLongFileNames, bool ensureFileExists, string fileExistsName, bool useProcessWindow, WorldcraftCommandSequenceStep step)
+ {
+ Assert.AreEqual(isEnabled, step.IsEnabled);
+ Assert.AreEqual(command, step.Command);
+ Assert.AreEqual(args, step.Arguments);
+ Assert.AreEqual(useLongFileNames, step.UseLongFileNames);
+ Assert.AreEqual(ensureFileExists, step.EnsureFileExists);
+ Assert.AreEqual(fileExistsName, step.FileExistsName);
+ Assert.AreEqual(useProcessWindow, step.UseProcessWindow);
+ }
+ }
+
+ [DataTestMethod]
+ [DataRow(0.1f)]
+ [DataRow(0.2f)]
+ public void TestWriteCommandSequencesFile(float version)
+ {
+ // The two known versions are identical aside from an unused field, so we can test them together
+ var file = new WorldcraftCommandSequenceFile();
+ file.CommandSequences.Add(new WorldcraftCommandSequence
+ {
+ Name = "Test1",
+ Steps =
+ [
+ new WorldcraftCommandSequenceStep
+ {
+ IsEnabled = true,
+ Command = "test1.step1.command",
+ Arguments = "test1.step1.args",
+ UseLongFileNames = true,
+ EnsureFileExists = false,
+ FileExistsName = "",
+ UseProcessWindow = true
+ },
+ new WorldcraftCommandSequenceStep
+ {
+ IsEnabled = false,
+ Command = "test1.step2.command",
+ Arguments = "test1.step2.args",
+ UseLongFileNames = false,
+ EnsureFileExists = true,
+ FileExistsName = "test1.step2.filename",
+ UseProcessWindow = false
+ },
+ ],
+ });
+ file.CommandSequences.Add(new WorldcraftCommandSequence
+ {
+ Name = "Test2",
+ Steps =
+ [
+ new WorldcraftCommandSequenceStep
+ {
+ IsEnabled = true,
+ Command = "test2.step1.command",
+ Arguments = "test2.step1.args",
+ UseLongFileNames = true,
+ EnsureFileExists = false,
+ FileExistsName = "",
+ UseProcessWindow = true
+ },
+ ],
+ });
+
+ var ms = new MemoryStream();
+ file.Write(ms, version);
+ ms.Position = 0;
+
+ var file2 = new WorldcraftCommandSequenceFile(ms);
+ Assert.AreEqual(file.CommandSequences.Count, file2.CommandSequences.Count);
+ AssertSequence(file.CommandSequences[0], file2.CommandSequences[0]);
+ AssertSequence(file.CommandSequences[1], file2.CommandSequences[1]);
+
+ static void AssertSequence(WorldcraftCommandSequence expected, WorldcraftCommandSequence actual)
+ {
+ Assert.AreEqual(expected.Name, actual.Name);
+ Assert.AreEqual(expected.Steps.Count, actual.Steps.Count);
+ for (var i = 0; i < expected.Steps.Count; i++)
+ {
+ Assert.AreEqual(expected.Steps[i].IsEnabled, actual.Steps[i].IsEnabled);
+ Assert.AreEqual(expected.Steps[i].Command, actual.Steps[i].Command);
+ Assert.AreEqual(expected.Steps[i].Arguments, actual.Steps[i].Arguments);
+ Assert.AreEqual(expected.Steps[i].UseLongFileNames, actual.Steps[i].UseLongFileNames);
+ Assert.AreEqual(expected.Steps[i].EnsureFileExists, actual.Steps[i].EnsureFileExists);
+ Assert.AreEqual(expected.Steps[i].FileExistsName, actual.Steps[i].FileExistsName);
+ Assert.AreEqual(expected.Steps[i].UseProcessWindow, actual.Steps[i].UseProcessWindow);
+ }
+ }
+ }
+
private const string Worldcraft33RegString = """
Windows Registry Editor Version 5.00
diff --git a/Sledge.Formats.Configuration/Worldcraft/CommandType.cs b/Sledge.Formats.Configuration/Worldcraft/CommandType.cs
new file mode 100644
index 0000000..69a975d
--- /dev/null
+++ b/Sledge.Formats.Configuration/Worldcraft/CommandType.cs
@@ -0,0 +1,9 @@
+namespace Sledge.Formats.Configuration.Worldcraft
+{
+ public enum CommandType
+ {
+ RunExecutable = 0,
+ ChangeDirectory = 256,
+ CopyFile = 257,
+ }
+}
\ No newline at end of file
diff --git a/Sledge.Formats.Configuration/Worldcraft/WorldcraftCommandSequence.cs b/Sledge.Formats.Configuration/Worldcraft/WorldcraftCommandSequence.cs
new file mode 100644
index 0000000..904662d
--- /dev/null
+++ b/Sledge.Formats.Configuration/Worldcraft/WorldcraftCommandSequence.cs
@@ -0,0 +1,20 @@
+using System.Collections.Generic;
+
+namespace Sledge.Formats.Configuration.Worldcraft
+{
+ ///
+ /// A sequence of commands to run when compiling a map
+ ///
+ public class WorldcraftCommandSequence
+ {
+ ///
+ /// Command sequence name
+ ///
+ public string Name { get; set; } = "";
+
+ ///
+ /// Command sequence steps
+ ///
+ public List Steps { get; set; } = new List();
+ }
+}
\ No newline at end of file
diff --git a/Sledge.Formats.Configuration/Worldcraft/WorldcraftCommandSequenceFile.cs b/Sledge.Formats.Configuration/Worldcraft/WorldcraftCommandSequenceFile.cs
new file mode 100644
index 0000000..5e51d67
--- /dev/null
+++ b/Sledge.Formats.Configuration/Worldcraft/WorldcraftCommandSequenceFile.cs
@@ -0,0 +1,127 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace Sledge.Formats.Configuration.Worldcraft
+{
+ public class WorldcraftCommandSequenceFile
+ {
+ private const int NameStringLength = 128;
+ private const int CommandStringLength = 260;
+ private static readonly string SequenceFileHeader = "Worldcraft Command Sequences\r\n" + (char)0x1A;
+
+ ///
+ /// Version 0.1 used for Worldcraft 1.1-1.5b
+ ///
+ public const float MinVersion = 0.1f;
+
+ ///
+ /// Version 0.2 used for Worldcraft 1.6a and up
+ ///
+ public const float MaxVersion = 0.2f;
+
+ public List CommandSequences { get; set; }
+
+ public WorldcraftCommandSequenceFile()
+ {
+ CommandSequences = new List();
+ }
+
+ public WorldcraftCommandSequenceFile(Stream stream)
+ {
+ CommandSequences = new List();
+ ReadFromStream(stream);
+ }
+
+ public static WorldcraftGameConfigurationFile FromFile(string file)
+ {
+ using (var stream = File.OpenRead(file))
+ {
+ return new WorldcraftGameConfigurationFile(stream);
+ }
+ }
+
+ private void ReadFromStream(Stream stream)
+ {
+ using (var br = new BinaryReader(stream, Encoding.ASCII, true))
+ {
+ var header = br.ReadFixedLengthString(Encoding.ASCII, SequenceFileHeader.Length);
+ if (header != SequenceFileHeader.TrimEnd('\0')) throw new NotSupportedException($"Incorrect command sequence file header. Expected '{SequenceFileHeader}', got '{header}'.");
+
+ var version = br.ReadSingle();
+ if (version < MinVersion || version > MaxVersion) throw new NotSupportedException($"Unsupported command sequence file version. Expected {MinVersion} or {MaxVersion}, got {version}.");
+
+ var numSequences = br.ReadInt32();
+ for (var i = 0; i < numSequences; i++)
+ {
+ var seq = new WorldcraftCommandSequence
+ {
+ Name = br.ReadFixedLengthString(Encoding.ASCII, NameStringLength)
+ };
+
+ var numSteps = br.ReadInt32();
+ for (var j = 0; j < numSteps; j++)
+ {
+ var step = new WorldcraftCommandSequenceStep
+ {
+ IsEnabled = br.ReadInt32() > 0,
+ Type = (CommandType) br.ReadInt32(), // unknown 1
+ Command = br.ReadFixedLengthString(Encoding.ASCII, CommandStringLength),
+ Arguments = br.ReadFixedLengthString(Encoding.ASCII, CommandStringLength),
+#pragma warning disable CS0612 // Type or member is obsolete
+ UseLongFileNames = br.ReadInt32() > 0,
+#pragma warning restore CS0612
+ EnsureFileExists = br.ReadInt32() > 0,
+ FileExistsName = br.ReadFixedLengthString(Encoding.ASCII, CommandStringLength),
+ UseProcessWindow = br.ReadInt32() > 0
+ };
+ if (Math.Abs(version - 0.2f) < float.Epsilon)
+ {
+ // this looks like a bool, its only set to 1 for $game_exe commands in the default sequences file.
+ // there's no way to control it in the UI, so we'll ignore it.
+ _ = br.ReadInt32();
+ }
+ seq.Steps.Add(step);
+ }
+ CommandSequences.Add(seq);
+ }
+ }
+ }
+
+ public void Write(Stream stream, float version = MaxVersion)
+ {
+ if (version < MinVersion || version > MaxVersion) throw new NotSupportedException($"Unsupported command sequence file version. Expected {MinVersion} or {MaxVersion}, got {version}.");
+
+ using (var bw = new BinaryWriter(stream, Encoding.ASCII, true))
+ {
+ bw.WriteFixedLengthString(Encoding.ASCII, SequenceFileHeader.Length, SequenceFileHeader);
+ bw.Write(version);
+ bw.Write(CommandSequences.Count);
+ foreach (var config in CommandSequences)
+ {
+ // Write sequence name, number of steps, and then each step:
+ bw.WriteFixedLengthString(Encoding.ASCII, NameStringLength, config.Name);
+ bw.Write(config.Steps.Count);
+ foreach (var step in config.Steps)
+ {
+ bw.Write(step.IsEnabled ? 1 : 0);
+ bw.Write(0); // unknown 1
+ bw.WriteFixedLengthString(Encoding.ASCII, CommandStringLength, step.Command);
+ bw.WriteFixedLengthString(Encoding.ASCII, CommandStringLength, step.Arguments);
+#pragma warning disable CS0612 // Type or member is obsolete
+ bw.Write(step.UseLongFileNames ? 1 : 0);
+#pragma warning restore CS0612
+ bw.Write(step.EnsureFileExists ? 1 : 0);
+ bw.WriteFixedLengthString(Encoding.ASCII, CommandStringLength, step.FileExistsName);
+ bw.Write(step.UseProcessWindow ? 1 : 0);
+ if (Math.Abs(version - 0.2f) < float.Epsilon)
+ {
+ bw.Write(0); // unknown 2
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/Sledge.Formats.Configuration/Worldcraft/WorldcraftCommandSequenceStep.cs b/Sledge.Formats.Configuration/Worldcraft/WorldcraftCommandSequenceStep.cs
new file mode 100644
index 0000000..9ede8ec
--- /dev/null
+++ b/Sledge.Formats.Configuration/Worldcraft/WorldcraftCommandSequenceStep.cs
@@ -0,0 +1,50 @@
+using System;
+
+namespace Sledge.Formats.Configuration.Worldcraft
+{
+ ///
+ /// A step in a command sequence representing a single command to run
+ ///
+ public class WorldcraftCommandSequenceStep
+ {
+ ///
+ /// Whether this step is enabled
+ ///
+ public bool IsEnabled { get; set; } = true;
+
+ ///
+ /// The type of command to run
+ ///
+ public CommandType Type { get; set; }
+
+ ///
+ /// The command to run
+ ///
+ public string Command { get; set; } = "";
+
+ ///
+ /// The command arguments
+ ///
+ public string Arguments { get; set; } = "";
+
+ ///
+ /// Doesn't seem to actually do anything, likely from older Windows where 8.3 filenames were common. Only kept since VHE has the option and it's stored in the configuration file.
+ ///
+ [Obsolete] public bool UseLongFileNames { get; set; } = true;
+
+ ///
+ /// Check if a file exists after running the command
+ ///
+ public bool EnsureFileExists { get; set; } = false;
+
+ ///
+ /// The file to check for after running the command
+ ///
+ public string FileExistsName { get; set; } = "";
+
+ ///
+ /// True to display a command window when running
+ ///
+ public bool UseProcessWindow { get; set; } = true;
+ }
+}
\ No newline at end of file
diff --git a/Sledge.Formats.Configuration/Worldcraft/WorldcraftConfiguration.cs b/Sledge.Formats.Configuration/Worldcraft/WorldcraftConfiguration.cs
index e070b5a..fcd0e65 100644
--- a/Sledge.Formats.Configuration/Worldcraft/WorldcraftConfiguration.cs
+++ b/Sledge.Formats.Configuration/Worldcraft/WorldcraftConfiguration.cs
@@ -13,6 +13,7 @@ public class WorldcraftConfiguration
public Worldcraft3DViewsConfiguration Views3D { get; set; }
public List TextureDirectories { get; set; }
public List GameConfigurations { get; set; }
+ public List CommandSequences { get; set; }
public static WorldcraftConfiguration LoadFromRegistry(WorldcraftConfigurationLoadSettings settings = null)
{
@@ -37,15 +38,31 @@ public static WorldcraftConfiguration LoadFromRegistry(WorldcraftConfigurationLo
installDir = config.General.InstallDirectory;
}
- if (settings.LoadGameConfigurations && Directory.Exists(installDir))
+ if (Directory.Exists(installDir))
{
- var configFile = Path.Combine(installDir, "GameCfg.wc");
- if (File.Exists(configFile))
+ if (settings.LoadGameConfigurations)
{
- using (var fs = File.OpenRead(configFile))
+ var configFile = Path.Combine(installDir, "GameCfg.wc");
+ if (File.Exists(configFile))
{
- var cfg = new WorldcraftGameConfigurationFile(fs);
- config.GameConfigurations = cfg.Configurations;
+ using (var fs = File.OpenRead(configFile))
+ {
+ var cfg = new WorldcraftGameConfigurationFile(fs);
+ config.GameConfigurations = cfg.Configurations;
+ }
+ }
+ }
+
+ if (settings.LoadCommandSequences)
+ {
+ var cmdSeqFile = Path.Combine(installDir, "CmdSeq.wc");
+ if (File.Exists(cmdSeqFile))
+ {
+ using (var fs = File.OpenRead(cmdSeqFile))
+ {
+ var cfg = new WorldcraftCommandSequenceFile(fs);
+ config.CommandSequences = cfg.CommandSequences;
+ }
}
}
}
diff --git a/Sledge.Formats.Configuration/Worldcraft/WorldcraftConfigurationLoadSettings.cs b/Sledge.Formats.Configuration/Worldcraft/WorldcraftConfigurationLoadSettings.cs
index e87c5c5..e145cca 100644
--- a/Sledge.Formats.Configuration/Worldcraft/WorldcraftConfigurationLoadSettings.cs
+++ b/Sledge.Formats.Configuration/Worldcraft/WorldcraftConfigurationLoadSettings.cs
@@ -32,6 +32,11 @@ public class WorldcraftConfigurationLoadSettings
///
public bool LoadGameConfigurations { get; set; } = true;
+ ///
+ /// True to attempt to load command sequences from the install directory
+ ///
+ public bool LoadCommandSequences { get; set; } = true;
+
///
/// True to attempt to autodetect the install directory from the registry ([Worldcraft/General/Directory] registry key).
/// All worldcraft versions store the install directory in the registry except for version 1.0.
@@ -51,6 +56,7 @@ public class WorldcraftConfigurationLoadSettings
{
AutodetectRegistryLocation = true,
LoadGameConfigurations = true,
+ LoadCommandSequences = true,
AutodetectInstallDirectory = true,
};
}