private static void RunApplication(ProgramArgs args) { // Simple convention for files: // - Source data is stored in <build path>/src/<package name> // - Output data will always be in the same folder var configPath = args.BuildConfigPath; if (!File.Exists(configPath)) { throw new Exception($"Could not find build config file. Looking for: {configPath}"); } var buildConfig = Serialization.Deserialize <BuildConfig>(File.ReadAllText(configPath)); foreach (var buildConfigPackage in buildConfig.Packages) { BuildPackage(args, buildConfigPackage); } if (buildConfig.GenerateIndex) { var buildIndex = new BuildIndex(); buildIndex.BuiltAt = DateTime.Now; buildIndex.Entries = new List <BuildIndexEntry>(); foreach (var buildConfigPackage in buildConfig.Packages) { var outPath = Path.Combine(args.OutPath, buildConfigPackage.DistributionName + ".mods"); var checksum = CryptUtil.SHA1File(outPath); buildIndex.Entries.Add(new BuildIndexEntry { Checksum = checksum, Name = buildConfigPackage.DistributionName + ".mods" }); } File.WriteAllText(Path.Combine(args.OutPath, "index.json"), Serialization.Serialize(buildIndex)); } }
private static void BuildPackage(ProgramArgs args, BuildConfigPackage buildConfigPackage) { var packageBasePath = Path.Combine(Path.GetDirectoryName(args.BuildConfigPath) ?? "", "src", buildConfigPackage.SourceName); var packageConfigPath = Path.Combine(packageBasePath, "config.json"); if (!File.Exists(packageConfigPath)) { throw new Exception($"Could not find config file for package {buildConfigPackage.SourceName} ({buildConfigPackage.DistributionName}): looking for {packageConfigPath}"); } var packageConfig = Serialization.Deserialize <PackageConfig>(File.ReadAllText(packageConfigPath)); var masterKey = new byte[0]; Console.WriteLine($"Building: {buildConfigPackage.SourceName} ({buildConfigPackage.DistributionName})"); var outPath = Path.Combine(args.OutPath, buildConfigPackage.DistributionName + ".mods"); using var fs = File.Open(outPath, FileMode.Create, FileAccess.Write); using var ms = new MemoryStream(); var packageHeader = new PackageHeader { Magic = 0x4459495A, CompilationTimestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), EncryptionEnabled = packageConfig.EncryptFiles }; if (packageConfig.EncryptFiles) { packageHeader.KeyLength = KeyLength; masterKey = CryptUtil.GenerateKey(KeyLength); } BinaryUtils.MarshalStruct(ms, packageHeader); if (packageConfig.EncryptFiles) { byte[] xorTable = { 0x94, 0xce, 0xc3, 0xae, 0x73, 0xf9, 0xf1, 0xb9 }; for (var i = 0; i < masterKey.Length; i++) { ms.WriteByte((byte)(masterKey[i] ^ xorTable[i % xorTable.Length])); } } using (var zipFile = new ZipFile()) { if (packageConfig.EncryptFiles) { zipFile.Encryption = EncryptionAlgorithm.WinZipAes256; zipFile.Password = Encoding.ASCII.GetString(masterKey); } foreach (var packageConfigEntry in packageConfig.Entries) { ProcessPackageEntry(args, packageConfigEntry, buildConfigPackage, zipFile); } Console.WriteLine($"Saving: {buildConfigPackage.SourceName} ({buildConfigPackage.DistributionName})"); zipFile.Save(ms); } Console.WriteLine($"Flushing: {buildConfigPackage.SourceName} ({buildConfigPackage.DistributionName}) -> {outPath}"); ms.Position = 0; ms.CopyTo(fs); }