public static void findBspPakDependencies(BSP bsp, string tempdir) { // Search the temp folder to find dependencies of files extracted from the pak file if (Directory.Exists(tempdir)) foreach (String file in Directory.EnumerateFiles(tempdir, "*.vmt", SearchOption.AllDirectories)) foreach (string material in AssetUtils.findVmtMaterials(new FileInfo(file).FullName)) bsp.TextureList.Add(material); }
public static void findBspUtilityFiles(BSP bsp, List <string> sourceDirectories, bool renamenav, bool genparticlemanifest) { // Utility files are other files that are not assets and are sometimes not referenced in the bsp // those are manifests, soundscapes, nav, radar and detail files // Soundscape file string internalPath = "scripts/soundscapes_" + bsp.file.Name.Replace(".bsp", ".txt"); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.soundscape = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // Soundscript file internalPath = "maps/" + bsp.file.Name.Replace(".bsp", "") + "_level_sounds.txt"; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.soundscript = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // Nav file (.nav) internalPath = "maps/" + bsp.file.Name.Replace(".bsp", ".nav"); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { if (renamenav) { internalPath = "maps/embed.nav"; } bsp.nav = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // detail file (.vbsp) Dictionary <string, string> worldspawn = bsp.entityList.First(item => item["classname"] == "worldspawn"); if (worldspawn.ContainsKey("detailvbsp")) { internalPath = worldspawn["detailvbsp"]; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.detail = new KeyValuePair <string, string>(internalPath, externalPath); break; } } } // Vehicle scripts List <KeyValuePair <string, string> > vehicleScripts = new List <KeyValuePair <string, string> >(); foreach (Dictionary <string, string> ent in bsp.entityList) { if (ent.ContainsKey("vehiclescript")) { foreach (string source in sourceDirectories) { string externalPath = source + "/" + ent["vehiclescript"]; if (File.Exists(externalPath)) { internalPath = ent["vehiclescript"]; vehicleScripts.Add(new KeyValuePair <string, string>(ent["vehiclescript"], externalPath)); } } } } bsp.VehicleScriptList = vehicleScripts; // Effect Scripts List <KeyValuePair <string, string> > effectScripts = new List <KeyValuePair <string, string> >(); foreach (Dictionary <string, string> ent in bsp.entityList) { if (ent.ContainsKey("scriptfile")) { foreach (string source in sourceDirectories) { string externalPath = source + "/" + ent["scriptfile"]; if (File.Exists(externalPath)) { internalPath = ent["scriptfile"]; effectScripts.Add(new KeyValuePair <string, string>(ent["scriptfile"], externalPath)); } } } } bsp.EffectScriptList = effectScripts; // Res file (for tf2's pd gamemode) Dictionary <string, string> pd_ent = bsp.entityList.FirstOrDefault(item => item["classname"] == "tf_logic_player_destruction"); if (pd_ent != null && pd_ent.ContainsKey("res_file")) { foreach (string source in sourceDirectories) { string externalPath = source + "/" + pd_ent["res_file"]; if (File.Exists(externalPath)) { bsp.res = new KeyValuePair <string, string>(pd_ent["res_file"], externalPath); break; } } } // Radar file internalPath = "resource/overviews/" + bsp.file.Name.Replace(".bsp", ".txt"); List <KeyValuePair <string, string> > ddsfiles = new List <KeyValuePair <string, string> >(); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.radartxt = new KeyValuePair <string, string>(internalPath, externalPath); bsp.TextureList.AddRange(findVmtMaterials(externalPath)); List <string> ddsInternalPaths = findRadarDdsFiles(externalPath); //find out if they exists or not foreach (string ddsInternalPath in ddsInternalPaths) { foreach (string source2 in sourceDirectories) { string ddsExternalPath = source2 + "/" + ddsInternalPath; if (File.Exists(ddsExternalPath)) { ddsfiles.Add(new KeyValuePair <string, string>(ddsInternalPath, ddsExternalPath)); break; } } } break; } } bsp.radardds = ddsfiles; // csgo kv file (.kv) internalPath = "maps/" + bsp.file.Name.Replace(".bsp", ".kv"); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.kv = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // csgo loading screen text file (.txt) internalPath = "maps/" + bsp.file.Name.Replace(".bsp", ".txt"); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.txt = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // csgo loading screen image (.jpg) internalPath = "maps/" + bsp.file.Name.Replace(".bsp", ""); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; foreach (string extension in new String[] { ".jpg", ".jpeg" }) { if (File.Exists(externalPath + extension)) { bsp.jpg = new KeyValuePair <string, string>(internalPath + ".jpg", externalPath + extension); } } } // language files, particle manifests and soundscript file // (these language files are localized text files for tf2 mission briefings) string internalDir = "maps/"; string name = bsp.file.Name.Replace(".bsp", ""); string searchPattern = name + "*.txt"; List <KeyValuePair <string, string> > langfiles = new List <KeyValuePair <string, string> >(); foreach (string source in sourceDirectories) { string externalDir = source + "/" + internalDir; DirectoryInfo dir = new DirectoryInfo(externalDir); if (dir.Exists) { foreach (FileInfo f in dir.GetFiles(searchPattern)) { // particle files if particle manifest is not being generated if (!genparticlemanifest) { if (f.Name.StartsWith(name + "_particles") || f.Name.StartsWith(name + "_manifest")) { bsp.particleManifest = new KeyValuePair <string, string>(internalDir + f.Name, externalDir + f.Name); } } // soundscript if (f.Name.StartsWith(name + "_level_sounds")) { bsp.soundscript = new KeyValuePair <string, string>(internalDir + f.Name, externalDir + f.Name); } // presumably language files else { langfiles.Add(new KeyValuePair <string, string>(internalDir + f.Name, externalDir + f.Name)); } } } } bsp.languages = langfiles; // ASW/Source2009 branch VScripts List <string> vscripts = new List <string>(); foreach (Dictionary <string, string> entity in bsp.entityList) { foreach (KeyValuePair <string, string> kvp in entity) { if (kvp.Key.ToLower() == "vscripts") { string[] scripts = kvp.Value.Split(' '); foreach (string script in scripts) { vscripts.Add("scripts/vscripts/" + script); } } } } bsp.vscriptList = vscripts; }
// onFailure is for utility files such as nav, radar, etc which get excluded. if they are excluded, the Delegate is run. This is used for removing the files from the BSP class, so they dont appear in the summary at the end private bool AddFile(KeyValuePair <string, string> paths, Action <BSP> onExcluded = null, BSP bsp = null) { var externalPath = paths.Value; // exclude files that are excluded if (externalPath != "" && File.Exists(externalPath) && !excludedFiles.Contains(externalPath.ToLower().Replace('/', '\\')) && !excludedDirs.Any(externalPath.ToLower().Replace('/', '\\').StartsWith)) { Files.Add(paths); return(true); } if (onExcluded != null && bsp != null) { onExcluded(bsp); } return(false); }
public override void Run(CompileContext context) { CompileErrors = new List <Error>(); verbose = GetParameterString().Contains("-verbose"); dryrun = GetParameterString().Contains("-dryrun"); renamenav = GetParameterString().Contains("-renamenav"); include = Regex.IsMatch(GetParameterString(), @"-include\b"); // ensures it doesnt match -includedir includeDir = GetParameterString().Contains("-includedir"); exclude = Regex.IsMatch(GetParameterString(), @"-exclude\b"); // ensures it doesnt match -excludedir excludeDir = GetParameterString().Contains("-excludedir"); excludevpk = GetParameterString().Contains("-excludevpk"); packvpk = GetParameterString().Contains("-vpk"); includefilelist = GetParameterString().Contains("-includefilelist"); usefilelist = GetParameterString().Contains("-usefilelist"); char[] paramChars = GetParameterString().ToCharArray(); List <string> parameters = ParseParameters(paramChars); List <string> includeFiles = new List <string>(); List <string> excludeFiles = new List <string>(); List <string> excludeDirs = new List <string>(); List <string> excludedVpkFiles = new List <string>(); try { CompilePalLogger.LogLine("\nCompilePal - Automated Packaging"); bspZip = context.Configuration.BSPZip; vpk = context.Configuration.VPK; gameFolder = context.Configuration.GameFolder; bspPath = context.CopyLocation; if (!File.Exists(bspPath)) { throw new FileNotFoundException(); } // manually passing in a file list if (usefilelist) { var fileListParam = parameters.First(p => p.StartsWith("usefilelist")).Split(new[] { " " }, 2, StringSplitOptions.None); if (fileListParam.Length > 1 && !string.IsNullOrWhiteSpace(fileListParam[1])) { outputFile = fileListParam[1]; if (!File.Exists(outputFile)) { CompilePalLogger.LogCompileError($"Could not find file list {outputFile}, exiting pack step\n", new Error($"Could not find file list {outputFile}, exiting pack step\n", ErrorSeverity.Error)); return; } CompilePalLogger.LogLine($"Using file list {outputFile}"); PackFileList(context, outputFile); return; } CompilePalLogger.LogCompileError("No file list set, exiting pack step\n", new Error("No file list set, exiting pack step", ErrorSeverity.Error)); return; } outputFile = "BSPZipFiles\\files.txt"; Keys.vmtTextureKeyWords = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "texturekeys.txt")).ToList(); Keys.vmtMaterialKeyWords = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "materialkeys.txt")).ToList(); Keys.vmfSoundKeys = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "vmfsoundkeys.txt")).ToList(); Keys.vmfMaterialKeys = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "vmfmaterialkeys.txt")).ToList(); Keys.vmfModelKeys = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "vmfmodelkeys.txt")).ToList(); // get manually included files if (include) { //Get included files from parameter list foreach (string parameter in parameters) { if (parameter.Contains("include")) { var filePath = parameter.Replace("\"", "").Replace("include ", "").TrimEnd(' '); //Test that file exists if (File.Exists(filePath)) { includeFiles.Add(filePath); } else { CompilePalLogger.LogCompileError($"Could not find file: {filePath}\n", new Error($"Could not find file: {filePath}", $"Could not find file: {filePath}", ErrorSeverity.Caution)); } } } } // get manually included files in directories if (includeDir) { //Get included files from parameter list foreach (string parameter in parameters) { if (parameter.Contains("includedir")) { var folderPath = parameter.Replace("\"", "").Replace("includedir ", "").TrimEnd(' '); //Test that folder exists if (Directory.Exists(folderPath)) { var files = Directory.GetFiles(folderPath, "*", SearchOption.AllDirectories); foreach (var file in files) { includeFiles.Add(file); } } else { CompilePalLogger.LogCompileError($"Could not find folder: {folderPath}\n", new Error($"Could not find folder: {folderPath}", ErrorSeverity.Caution)); } } } } if (exclude) { //Get excluded files from parameter list foreach (string parameter in parameters) { if (Regex.IsMatch(parameter, @"^exclude\b")) { var filePath = parameter.Replace("\"", "") .Replace("exclude ", "") .Replace('/', '\\') .ToLower().TrimEnd(' '); //Test that file exists if (File.Exists(filePath)) { excludeFiles.Add(filePath); } else { CompilePalLogger.LogCompileError($"Could not find file: {filePath}\n", new Error($"Could not find file: {filePath}", ErrorSeverity.Caution)); } } } } if (excludeDir) { //Get excluded directories from parameter list foreach (string parameter in parameters) { if (Regex.IsMatch(parameter, @"^excludedir\b")) { var path = parameter.Replace("\"", "") .Replace("excludedir ", "") .Replace('/', '\\') .ToLower().TrimEnd(' '); //Test that dir exists if (Directory.Exists(path)) { excludeDirs.Add(path); } else { CompilePalLogger.LogCompileError($"Could not find folder: {path}\n", new Error($"Could not find folder: {path}", ErrorSeverity.Caution)); } } } } // exclude files that are in the specified vpk. if (excludevpk) { foreach (string parameter in parameters) { if (parameter.Contains("excludevpk")) { var vpkPath = parameter.Replace("\"", "").Replace("excludevpk ", "").TrimEnd(' '); string[] vpkFileList = GetVPKFileList(vpkPath); foreach (string file in vpkFileList) { excludedVpkFiles.Add(file.ToLower()); } } } } CompilePalLogger.LogLine("Finding sources of game content..."); sourceDirectories = GetSourceDirectories(gameFolder); if (verbose) { CompilePalLogger.LogLine("Source directories:"); foreach (var sourceDirectory in sourceDirectories) { CompilePalLogger.LogLine(sourceDirectory); } } CompilePalLogger.LogLine("Reading BSP..."); BSP map = new BSP(new FileInfo(bspPath)); AssetUtils.findBspUtilityFiles(map, sourceDirectories, renamenav, genParticleManifest); // give files unique names based on map so they dont get overwritten if (dryrun) { outputFile = $"BSPZipFiles\\{Path.GetFileNameWithoutExtension(map.file.FullName)}_files.txt"; } //Set map particle manifest if (genParticleManifest) { map.particleManifest = particleManifest; } string unpackDir = System.IO.Path.GetTempPath() + Guid.NewGuid(); UnpackBSP(unpackDir); AssetUtils.findBspPakDependencies(map, unpackDir); CompilePalLogger.LogLine("Initializing pak file..."); PakFile pakfile = new PakFile(map, sourceDirectories, includeFiles, excludeFiles, excludeDirs, excludedVpkFiles, outputFile); if (includefilelist) { var fileListParams = parameters.Where(p => p.StartsWith("includefilelist")).Select(f => f.Split(new[] { " " }, 2, StringSplitOptions.None)); foreach (var fileListParam in fileListParams) { if (fileListParam.Length <= 1 || string.IsNullOrWhiteSpace(fileListParam[1])) { CompilePalLogger.LogCompileError("No file list parameter set\n", new Error("No file list parameter set", ErrorSeverity.Error)); continue; } var inputFile = fileListParam[1]; if (!File.Exists(inputFile)) { CompilePalLogger.LogCompileError($"Could not find file list {inputFile}\n", new Error($"Could not find file list {inputFile}\n", ErrorSeverity.Error)); continue; } CompilePalLogger.LogDebug($"Adding files from file list {inputFile}"); var filelist = File.ReadAllLines(inputFile); // file list format is internal path, newline, external path for (int i = 0; i < filelist.Length - 1; i += 2) { var internalPath = filelist[i]; var externalPath = filelist[i + 1]; if (!pakfile.AddInternalFile(internalPath, externalPath)) { CompilePalLogger.LogCompileError($"Failed to pack ${externalPath}\n", new Error($"Failed to pack ${externalPath}\n", ErrorSeverity.Error)); } } CompilePalLogger.LogLine($"Added {filelist.Length / 2} files from ${inputFile}"); } } if (packvpk) { string vpkName = context.BSPFile.Replace(".bsp", ".vpk"); if (File.Exists(vpkName)) { File.Delete(vpkName); } var responseFile = pakfile.GetResponseFile(); if (File.Exists(bspPath)) { // Add bsp to the vpk responseFile.Add(bspPath.Replace(gameFolder + "\\", ""), gameFolder); } if (GetParameterString().Contains("-ainfo")) { foreach (string parameter in parameters) { if (parameter.Contains("ainfo")) { var @filePath = parameter.Replace("\"", "").Replace("ainfo ", "").TrimEnd(' '); //Test that file exists if (File.Exists(filePath)) { File.Copy(filePath, Path.Combine(gameFolder, "addoninfo.txt"), true); responseFile.Add("addoninfo.txt", gameFolder); } } } } CompilePalLogger.LogLine("Running VPK..."); foreach (var path in sourceDirectories) { var testedFiles = ""; foreach (var entry in responseFile) { if (entry.Value.Contains(path) || path.Contains(entry.Value)) { testedFiles += entry.Key + "\n"; } } var combinedPath = Path.Combine(path, "_tempResponseFile.txt"); File.WriteAllText(combinedPath, testedFiles); PackVPK(vpkName, combinedPath, path); File.Delete(combinedPath); } File.Delete("_tempResponseFile.txt"); if (GetParameterString().Contains("-ainfo")) { File.Delete(Path.Combine(gameFolder, "addoninfo.txt")); } } else { CompilePalLogger.LogLine("Writing file list..."); pakfile.OutputToFile(); if (dryrun) { CompilePalLogger.LogLine("File list saved as " + Environment.CurrentDirectory + outputFile); } else { PackFileList(context, outputFile); } } CompilePalLogger.LogLine("Finished!"); CompilePalLogger.LogLine("---------------------"); CompilePalLogger.LogLine(pakfile.vmtcount + " materials found"); CompilePalLogger.LogLine(pakfile.mdlcount + " models found"); CompilePalLogger.LogLine(pakfile.pcfcount + " particle files found"); CompilePalLogger.LogLine(pakfile.sndcount + " sounds found"); if (pakfile.vehiclescriptcount != 0) { CompilePalLogger.LogLine(pakfile.vehiclescriptcount + " vehicle scripts found"); } if (pakfile.effectscriptcount != 0) { CompilePalLogger.LogLine(pakfile.effectscriptcount + " effect scripts found"); } if (pakfile.vscriptcount != 0) { CompilePalLogger.LogLine(pakfile.vscriptcount + " vscripts found"); } if (pakfile.panoramaMapIconCount != 0) { CompilePalLogger.LogLine(pakfile.panoramaMapIconCount + " panorama map icons found"); } string additionalFiles = (map.nav.Key != default(string) ? "\n-nav file" : "") + (map.soundscape.Key != default(string) ? "\n-soundscape" : "") + (map.soundscript.Key != default(string) ? "\n-soundscript" : "") + (map.detail.Key != default(string) ? "\n-detail file" : "") + (map.particleManifest.Key != default(string) ? "\n-particle manifest" : "") + (map.radartxt.Key != default(string) ? "\n-radar files" : "") + (map.txt.Key != default(string) ? "\n-loading screen text" : "") + (map.jpg.Key != default(string) ? "\n-loading screen image" : "") + (map.kv.Key != default(string) ? "\n-kv file" : "") + (map.res.Key != default(string) ? "\n-res file" : ""); if (additionalFiles != "") { CompilePalLogger.LogLine("additional files: " + additionalFiles); } CompilePalLogger.LogLine("---------------------"); } catch (FileNotFoundException) { CompilePalLogger.LogCompileError($"Could not find {bspPath}\n", new Error($"Could not find {bspPath}", ErrorSeverity.Error)); } catch (Exception exception) { CompilePalLogger.LogLine("Something broke:"); CompilePalLogger.LogCompileError($"{exception}\n", new Error(exception.ToString(), "CompilePal Internal Error", ErrorSeverity.FatalError)); } }
public override void Run(CompileContext context) { verbose = GetParameterString().Contains("-verbose"); dryrun = GetParameterString().Contains("-dryrun"); renamenav = GetParameterString().Contains("-renamenav"); include = GetParameterString().Contains("-include"); exclude = GetParameterString().Contains("-exclude"); packvpk = GetParameterString().Contains("-vpk"); char[] paramChars = GetParameterString().ToCharArray(); List <string> parameters = ParseParameters(paramChars); List <string> includeFiles = new List <string>(); List <string> excludeFiles = new List <string>(); try { CompilePalLogger.LogLine("\nCompilePal - Automated Packaging"); bspZip = context.Configuration.BSPZip; vpk = context.Configuration.VPK; gameFolder = context.Configuration.GameFolder; bspPath = context.CopyLocation; if (!File.Exists(bspPath)) { throw new FileNotFoundException(); } Keys.vmtTextureKeyWords = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "texturekeys.txt")).ToList(); Keys.vmtMaterialKeyWords = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "materialkeys.txt")).ToList(); Keys.vmfSoundKeys = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "vmfsoundkeys.txt")).ToList(); Keys.vmfMaterialKeys = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "vmfmaterialkeys.txt")).ToList(); Keys.vmfModelKeys = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "vmfmodelkeys.txt")).ToList(); // get manually included files if (include) { //Get included files from parameter list foreach (string parameter in parameters) { if (parameter.Contains("include")) { var @filePath = parameter.Replace("\"", "").Replace("include ", "").TrimEnd(' '); //Test that file exists if (File.Exists(filePath)) { includeFiles.Add(filePath); } else { CompilePalLogger.LogLineColor($"Could not find file: {filePath}", Error.GetSeverityBrush(2)); } } } } if (exclude) { //Get excluded files from parameter list foreach (string parameter in parameters) { if (parameter.Contains("exclude")) { var @filePath = parameter.Replace("\"", "").Replace("exclude ", "").Replace('/', '\\').ToLower().TrimEnd(' '); //Test that file exists if (File.Exists(filePath)) { excludeFiles.Add(filePath); } else { CompilePalLogger.LogLineColor($"Could not find file: {filePath}", Error.GetSeverityBrush(2)); } } } } CompilePalLogger.LogLine("Finding sources of game content..."); sourceDirectories = GetSourceDirectories(gameFolder); CompilePalLogger.LogLine("Reading BSP..."); BSP map = new BSP(new FileInfo(bspPath)); AssetUtils.findBspUtilityFiles(map, sourceDirectories, renamenav, genParticleManifest); //Set map particle manifest if (genParticleManifest) { map.particleManifest = particleManifest; } string unpackDir = System.IO.Path.GetTempPath() + Guid.NewGuid(); UnpackBSP(unpackDir); AssetUtils.findBspPakDependencies(map, unpackDir); CompilePalLogger.LogLine("Initializing pak file..."); PakFile pakfile = new PakFile(map, sourceDirectories, includeFiles, excludeFiles); if (packvpk) { string vpkName = context.BSPFile.Replace(".bsp", ".vpk"); if (File.Exists(vpkName)) { File.Delete(vpkName); } var responseFile = pakfile.GetResponseFile(); if (File.Exists(bspPath)) { // Add bsp to the vpk responseFile.Add(bspPath.Replace(gameFolder + "\\", ""), gameFolder); } if (GetParameterString().Contains("-ainfo")) { foreach (string parameter in parameters) { if (parameter.Contains("ainfo")) { var @filePath = parameter.Replace("\"", "").Replace("ainfo ", "").TrimEnd(' '); //Test that file exists if (File.Exists(filePath)) { File.Copy(filePath, Path.Combine(gameFolder, "addoninfo.txt"), true); responseFile.Add("addoninfo.txt", gameFolder); } } } } CompilePalLogger.LogLine("Running VPK..."); foreach (var path in sourceDirectories) { var testedFiles = ""; foreach (var entry in responseFile) { if (entry.Value.Contains(path) || path.Contains(entry.Value)) { testedFiles += entry.Key + "\n"; } } var combinedPath = Path.Combine(path, "_tempResponseFile.txt"); File.WriteAllText(combinedPath, testedFiles); PackVPK(vpkName, combinedPath, path); File.Delete(combinedPath); } File.Delete("_tempResponseFile.txt"); if (GetParameterString().Contains("-ainfo")) { File.Delete(Path.Combine(gameFolder, "addoninfo.txt")); } } else { CompilePalLogger.LogLine("Writing file list..."); pakfile.OutputToFile(); if (dryrun) { CompilePalLogger.LogLine("File list saved as " + Environment.CurrentDirectory + "\\files.txt"); } else { CompilePalLogger.LogLine("Running bspzip..."); PackBSP(); } CompilePalLogger.LogLine("Copying packed bsp to vmf folder..."); if (File.Exists(context.BSPFile)) { if (File.Exists(context.BSPFile + ".unpacked")) { File.Delete(context.BSPFile + ".unpacked"); } File.Move(context.BSPFile, context.BSPFile + ".unpacked"); } File.Copy(bspPath, context.BSPFile); } CompilePalLogger.LogLine("Finished!"); CompilePalLogger.LogLine("---------------------"); CompilePalLogger.LogLine(pakfile.vmtcount + " materials found"); CompilePalLogger.LogLine(pakfile.mdlcount + " models found"); CompilePalLogger.LogLine(pakfile.pcfcount + " particle files found"); CompilePalLogger.LogLine(pakfile.sndcount + " sounds found"); if (pakfile.vehiclescriptcount != 0) { CompilePalLogger.LogLine(pakfile.vehiclescriptcount + " vehicle scripts found"); } if (pakfile.effectscriptcount != 0) { CompilePalLogger.LogLine(pakfile.effectscriptcount + " effect scripts found"); } if (pakfile.vscriptcount != 0) { CompilePalLogger.LogLine(pakfile.vscriptcount + " vscripts found"); } string additionalFiles = (map.nav.Key != default(string) ? "\n-nav file" : "") + (map.soundscape.Key != default(string) ? "\n-soundscape" : "") + (map.soundscript.Key != default(string) ? "\n-soundscript" : "") + (map.detail.Key != default(string) ? "\n-detail file" : "") + (map.particleManifest.Key != default(string) ? "\n-particle manifest" : "") + (map.radartxt.Key != default(string) ? "\n-radar files" : "") + (map.txt.Key != default(string) ? "\n-loading screen text" : "") + (map.jpg.Key != default(string) ? "\n-loading screen image" : "") + (map.kv.Key != default(string) ? "\n-kv file" : "") + (map.res.Key != default(string) ? "\n-res file" : ""); if (additionalFiles != "") { CompilePalLogger.LogLine("additional files: " + additionalFiles); } CompilePalLogger.LogLine("---------------------"); } catch (FileNotFoundException) { CompilePalLogger.LogLine("FAILED - Could not find " + bspPath); } catch (Exception exception) { CompilePalLogger.LogLine("Something broke:"); CompilePalLogger.LogLine(exception.ToString()); } }
public PakFile(BSP bsp, List <string> sourceDirectories, List <string> includeFiles, List <string> excludedFiles) { mdlcount = vmtcount = pcfcount = sndcount = vehiclescriptcount = 0; sourceDirs = sourceDirectories; this.excludedFiles = excludedFiles; Files = new Dictionary <string, string>(); if (bsp.nav.Key != default(string)) { Files.Add(bsp.nav); } if (bsp.detail.Key != default(string)) { Files.Add(bsp.detail); } if (bsp.kv.Key != default(string)) { Files.Add(bsp.kv); } if (bsp.txt.Key != default(string)) { Files.Add(bsp.txt); } if (bsp.jpg.Key != default(string)) { Files.Add(bsp.jpg); } if (bsp.radartxt.Key != default(string)) { Files.Add(bsp.radartxt); } if (bsp.res.Key != default(string)) { Files.Add(bsp.res); foreach (string material in AssetUtils.findResMaterials(bsp.res.Value)) { AddTexture(material); } } if (bsp.particleManifest.Key != default(string)) { Files.Add(bsp.particleManifest); foreach (string particle in AssetUtils.findManifestPcfs(bsp.particleManifest.Value)) { AddParticle(particle); } } if (bsp.soundscape.Key != default(string)) { Files.Add(bsp.soundscape); foreach (string sound in AssetUtils.findSoundscapeSounds(bsp.soundscape.Value)) { if (AddFile(sound, FindExternalFile(sound))) { sndcount++; } } } if (bsp.soundscript.Key != default(string)) { Files.Add(bsp.soundscript); foreach (string sound in AssetUtils.findSoundscapeSounds(bsp.soundscript.Value)) { if (AddFile(sound, FindExternalFile(sound))) { sndcount++; } } } // find color correction files foreach (Dictionary <string, string> cc in bsp.entityList.Where(item => item["classname"] == "color_correction")) { if (cc.ContainsKey("filename")) { AddFile(cc["filename"], FindExternalFile(cc["filename"])); } } foreach (KeyValuePair <string, string> vehicleScript in bsp.VehicleScriptList) { if (AddFile(vehicleScript.Key, vehicleScript.Value)) { vehiclescriptcount++; } } foreach (KeyValuePair <string, string> dds in bsp.radardds) { AddFile(dds.Key, dds.Value); } foreach (KeyValuePair <string, string> lang in bsp.languages) { AddFile(lang.Key, lang.Value); } foreach (string model in bsp.EntModelList) { AddModel(model); } for (int i = 0; i < bsp.ModelList.Count; i++) { AddModel(bsp.ModelList[i], bsp.modelSkinList[i]); } foreach (string vmt in bsp.TextureList) { AddTexture(vmt); } foreach (string vmt in bsp.EntTextureList) { AddTexture(vmt); } foreach (string sound in bsp.EntSoundList) { if (AddFile(sound, FindExternalFile(sound))) { sndcount++; } } // add all manually included files // TODO right now the manually included files search for files it depends on. Not sure if this should be default behavior foreach (var file in includeFiles) { // try to get the source directory the file is located in FileInfo fileInfo = new FileInfo(file); // default base directory is the game folder string baseDir = GameConfigurationManager.GameConfiguration.GameFolder; var potentialSubDir = sourceDirs; potentialSubDir.Remove(baseDir); foreach (var folder in potentialSubDir) { if (fileInfo.Directory != null && fileInfo.Directory.FullName.Contains(folder)) { baseDir = folder; break; } } string internalPath = file.Replace(baseDir + "\\", ""); // try to determine file type by extension switch (file.Split('.').Last()) { case "vmt": AddTexture(internalPath); break; case "pcf": AddParticle(internalPath); break; case "mdl": AddModel(internalPath); break; case "wav": case "mp3": AddFile(internalPath, file); sndcount++; break; default: AddFile(internalPath, file); break; } } }
public PakFile(BSP bsp, List <string> sourceDirectories) { mdlcount = vmtcount = pcfcount = sndcount = 0; sourceDirs = sourceDirectories; Files = new Dictionary <string, string>(); if (bsp.nav.Key != default(string)) { Files.Add(bsp.nav); } if (bsp.detail.Key != default(string)) { Files.Add(bsp.detail); } if (bsp.particleManifest.Key != default(string)) { Files.Add(bsp.particleManifest); foreach (string particle in AssetUtils.findManifestPcfs(bsp.particleManifest.Value)) { AddParticle(particle); } } if (bsp.soundscape.Key != default(string)) { Files.Add(bsp.soundscape); foreach (string sound in AssetUtils.findSoundscapeSounds(bsp.soundscape.Value)) { if (AddFile(sound, FindExternalFile(sound))) { sndcount++; } } } if (bsp.soundscript.Key != default(string)) { Files.Add(bsp.soundscript); foreach (string sound in AssetUtils.findSoundscapeSounds(bsp.soundscript.Value)) { if (AddFile(sound, FindExternalFile(sound))) { sndcount++; } } } // find color correction files foreach (Dictionary <string, string> cc in bsp.entityList.Where(item => item["classname"] == "color_correction")) { AddFile(cc["filename"], FindExternalFile(cc["filename"])); } foreach (KeyValuePair <string, string> lang in bsp.languages) { AddFile(lang.Key, lang.Value); } foreach (string model in bsp.EntModelList) { AddModel(model); } for (int i = 0; i < bsp.ModelList.Count; i++) { AddModel(bsp.ModelList[i], bsp.modelSkinList[i]); } foreach (string vmt in bsp.TextureList) { AddTexture(vmt); } foreach (string vmt in bsp.EntTextureList) { AddTexture(vmt); } foreach (string sound in bsp.EntSoundList) { if (AddFile(sound, FindExternalFile(sound))) { sndcount++; } } }
public override void Run(CompileContext context) { verbose = GetParameterString().Contains("-verbose"); dryrun = GetParameterString().Contains("-dryrun"); renamenav = GetParameterString().Contains("-renamenav"); try { CompilePalLogger.LogLine("\nCompilePal - Automated Packaging"); bspZip = context.Configuration.BSPZip; gameFolder = context.Configuration.GameFolder; bspPath = context.CopyLocation; if (!File.Exists(bspPath)) { throw new FileNotFoundException(); } Keys.vmtTextureKeyWords = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "texturekeys.txt")).ToList(); Keys.vmtMaterialKeyWords = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "materialkeys.txt")).ToList(); Keys.vmfSoundKeys = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "vmfsoundkeys.txt")).ToList(); Keys.vmfMaterialKeys = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "vmfmaterialkeys.txt")).ToList(); Keys.vmfModelKeys = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "vmfmodelkeys.txt")).ToList(); CompilePalLogger.LogLine("Finding sources of game content..."); sourceDirectories = GetSourceDirectories(gameFolder); CompilePalLogger.LogLine("Reading BSP..."); BSP map = new BSP(new FileInfo(bspPath)); AssetUtils.findBspUtilityFiles(map, sourceDirectories, renamenav); string unpackDir = System.IO.Path.GetTempPath() + Guid.NewGuid(); UnpackBSP(unpackDir); AssetUtils.findBspPakDependencies(map, unpackDir); CompilePalLogger.LogLine("Initializing pak file..."); PakFile pakfile = new PakFile(map, sourceDirectories); CompilePalLogger.LogLine("Writing file list..."); pakfile.OutputToFile(); if (dryrun) { CompilePalLogger.LogLine("File list saved as " + Environment.CurrentDirectory + "\\files.txt"); } else { CompilePalLogger.LogLine("Running bspzip..."); PackBSP(); } CompilePalLogger.LogLine("Finished!"); CompilePalLogger.LogLine("---------------------"); CompilePalLogger.LogLine(pakfile.vmtcount + " materials found"); CompilePalLogger.LogLine(pakfile.mdlcount + " models found"); CompilePalLogger.LogLine(pakfile.pcfcount + " particle files found"); CompilePalLogger.LogLine(pakfile.sndcount + " sounds found"); string additionalFiles = (map.nav.Key != default(string) ? "\n-nav file" : "") + (map.soundscape.Key != default(string) ? "\n-soundscape" : "") + (map.soundscript.Key != default(string) ? "\n-soundscript" : "") + (map.detail.Key != default(string) ? "\n-detail file" : "") + (map.particleManifest.Key != default(string) ? "\n-particle manifest" : "") + (map.radartxt.Key != default(string) ? "\n-radar files" : "") + (map.txt.Key != default(string) ? "\n-loading screen text" : "") + (map.jpg.Key != default(string) ? "\n-loading screen image" : "") + (map.kv.Key != default(string) ? "\n-kv file" : "") + (map.res.Key != default(string) ? "\n-res file" : ""); CompilePalLogger.LogLine(additionalFiles != default(string) ? "additional files: " + additionalFiles : "none"); CompilePalLogger.LogLine("---------------------"); } catch (FileNotFoundException) { CompilePalLogger.LogLine("FAILED - Could not find " + bspPath); } catch (Exception exception) { CompilePalLogger.LogLine("Something broke:"); CompilePalLogger.LogLine(exception.ToString()); } }
public static void findBspUtilityFiles(BSP bsp, List <string> sourceDirectories, bool renamenav, bool genparticlemanifest) { // Utility files are other files that are not assets and are sometimes not referenced in the bsp // those are manifests, soundscapes, nav, radar and detail files var bspName = bsp.file.Name.Replace(".bsp", string.Empty); // Soundscape file string internalPath = "scripts/soundscapes_" + bspName + ".txt"; // Soundscapes can have either .txt or .vsc extensions string internalPathVsc = "scripts/soundscapes_" + bspName + ".vsc"; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; string externalVscPath = source + "/" + internalPathVsc; if (File.Exists(externalPath)) { bsp.soundscape = new KeyValuePair <string, string>(internalPath, externalPath); break; } if (File.Exists(externalVscPath)) { bsp.soundscape = new KeyValuePair <string, string>(internalPathVsc, externalVscPath); break; } } // Soundscript file internalPath = "maps/" + bspName + "_level_sounds.txt"; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.soundscript = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // Nav file (.nav) internalPath = "maps/" + bspName + ".nav"; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { if (renamenav) { internalPath = "maps/embed.nav"; } bsp.nav = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // detail file (.vbsp) Dictionary <string, string> worldspawn = bsp.entityList.First(item => item["classname"] == "worldspawn"); if (worldspawn.ContainsKey("detailvbsp")) { internalPath = worldspawn["detailvbsp"]; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.detail = new KeyValuePair <string, string>(internalPath, externalPath); break; } } } // Vehicle scripts List <KeyValuePair <string, string> > vehicleScripts = new List <KeyValuePair <string, string> >(); foreach (Dictionary <string, string> ent in bsp.entityList) { if (ent.ContainsKey("vehiclescript")) { foreach (string source in sourceDirectories) { string externalPath = source + "/" + ent["vehiclescript"]; if (File.Exists(externalPath)) { internalPath = ent["vehiclescript"]; vehicleScripts.Add(new KeyValuePair <string, string>(ent["vehiclescript"], externalPath)); } } } } bsp.VehicleScriptList = vehicleScripts; // Effect Scripts List <KeyValuePair <string, string> > effectScripts = new List <KeyValuePair <string, string> >(); foreach (Dictionary <string, string> ent in bsp.entityList) { if (ent.ContainsKey("scriptfile")) { foreach (string source in sourceDirectories) { string externalPath = source + "/" + ent["scriptfile"]; if (File.Exists(externalPath)) { internalPath = ent["scriptfile"]; effectScripts.Add(new KeyValuePair <string, string>(ent["scriptfile"], externalPath)); } } } } bsp.EffectScriptList = effectScripts; // Res file (for tf2's pd gamemode) Dictionary <string, string> pd_ent = bsp.entityList.FirstOrDefault(item => item["classname"] == "tf_logic_player_destruction"); if (pd_ent != null && pd_ent.ContainsKey("res_file")) { foreach (string source in sourceDirectories) { string externalPath = source + "/" + pd_ent["res_file"]; if (File.Exists(externalPath)) { bsp.res = new KeyValuePair <string, string>(pd_ent["res_file"], externalPath); break; } } } // Radar file internalPath = "resource/overviews/" + bspName + ".txt"; List <KeyValuePair <string, string> > ddsfiles = new List <KeyValuePair <string, string> >(); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.radartxt = new KeyValuePair <string, string>(internalPath, externalPath); bsp.TextureList.AddRange(findVmtMaterials(externalPath)); List <string> ddsInternalPaths = findRadarDdsFiles(externalPath); //find out if they exists or not foreach (string ddsInternalPath in ddsInternalPaths) { foreach (string source2 in sourceDirectories) { string ddsExternalPath = source2 + "/" + ddsInternalPath; if (File.Exists(ddsExternalPath)) { ddsfiles.Add(new KeyValuePair <string, string>(ddsInternalPath, ddsExternalPath)); break; } } } break; } } bsp.radardds = ddsfiles; // csgo kv file (.kv) internalPath = "maps/" + bspName + ".kv"; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.kv = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // csgo loading screen text file (.txt) internalPath = "maps/" + bspName + ".txt"; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.txt = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // csgo loading screen image (.jpg) internalPath = "maps/" + bspName; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; foreach (string extension in new String[] { ".jpg", ".jpeg" }) { if (File.Exists(externalPath + extension)) { bsp.jpg = new KeyValuePair <string, string>(internalPath + ".jpg", externalPath + extension); } } } // csgo story file (.txt) internalPath = "maps/" + bspName + "_story.txt"; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.story = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // csgo cameras file (.txt) internalPath = "maps/" + bspName + "_cameras.txt"; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.cameras = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // csgo retake file (.txt) internalPath = "maps/" + bspName + "_retake.txt"; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.retake = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // csgo panorama map icons (.png) internalPath = "materials/panorama/images/map_icons/screenshots/"; var panoramaMapIcons = new List <KeyValuePair <string, string> >(); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; foreach (string resolution in new[] { "360p", "1080p" }) { if (File.Exists($"{externalPath}{resolution}/{bspName}.png")) { panoramaMapIcons.Add(new KeyValuePair <string, string>($"{internalPath}{resolution}/{bspName}.png", $"{externalPath}{resolution}/{bspName}.png")); } } } bsp.PanoramaMapIcons = panoramaMapIcons; // csgo spawnmask file (.png) internalPath = "maps/" + bspName + "_spawnmask.png"; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.spawnmaskPng = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // csgo tablet file local (.vtf) var tabletBaseFolderpath = "materials/models/weapons/v_models/tablet/"; internalPath = tabletBaseFolderpath + "tablet_radar_" + bspName + ".vtf"; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; try { if (File.Exists(externalPath)) { bsp.tabletVtfLocal = new KeyValuePair <string, string>(internalPath, externalPath); break; } } catch (DirectoryNotFoundException e) { } } // csgo tablet file workshop (.vtf) var keepSearching = true; foreach (string source in sourceDirectories) { string externalFolderPath = source + "/" + tabletBaseFolderpath + "/tablet_radar_workshop/"; try { foreach (var folderName in Directory.GetDirectories(externalFolderPath).Select(Path.GetFileName).ToArray()) { if (ulong.TryParse(folderName, out ulong num)) { internalPath = tabletBaseFolderpath + $"tablet_radar_workshop/{num}/" + bspName + ".vtf"; string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.workshopId = num; bsp.tabletVtfWorkshop = new KeyValuePair <string, string>(internalPath, externalPath); keepSearching = false; break; } } } } catch (DirectoryNotFoundException e) { } if (!keepSearching) { break; } } // csgo spawn select file local (.png) var spawnSelectBaseFolderpath = "materials/panorama/images/survival/spawnselect/"; internalPath = spawnSelectBaseFolderpath + "map_" + bspName + ".png"; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; try { if (File.Exists(externalPath)) { bsp.spawnSelectPngLocal = new KeyValuePair <string, string>(internalPath, externalPath); break; } } catch (DirectoryNotFoundException e) { } } // csgo spawn select file workshop (.png) keepSearching = true; foreach (string source in sourceDirectories) { string externalFolderPath = source + "/" + spawnSelectBaseFolderpath + "/map_workshop/"; try { foreach (var folderName in Directory.GetDirectories(externalFolderPath).Select(Path.GetFileName).ToArray()) { if (ulong.TryParse(folderName, out ulong num)) { internalPath = spawnSelectBaseFolderpath + $"map_workshop/{num}/" + bspName + ".png"; string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.workshopId = num; bsp.spawnSelectPngWorkshop = new KeyValuePair <string, string>(internalPath, externalPath); keepSearching = false; break; } } } } catch (DirectoryNotFoundException e) { } if (!keepSearching) { break; } } // Duplicate the workshop tablet file to the local tablet file location if it does not exist if (bsp.tabletVtfLocal.Equals(default(KeyValuePair <string, string>)) && !bsp.tabletVtfWorkshop.Equals(default(KeyValuePair <string, string>))) { internalPath = tabletBaseFolderpath + "tablet_radar_" + bspName + ".vtf"; string source = bsp.tabletVtfWorkshop.Value.Split(new string[] { "materials/" }, StringSplitOptions.None).FirstOrDefault(); string externalPath = source + "/" + internalPath; bsp.tabletVtfLocal = new KeyValuePair <string, string>(internalPath, bsp.tabletVtfWorkshop.Value); } else if (bsp.workshopId > 0 && !bsp.tabletVtfLocal.Equals(default(KeyValuePair <string, string>)) && bsp.tabletVtfWorkshop.Equals(default(KeyValuePair <string, string>))) // Can only be done if the workshop id is known { internalPath = tabletBaseFolderpath + $"tablet_radar_workshop/{bsp.workshopId}/" + bspName + ".vtf"; string source = bsp.tabletVtfLocal.Value.Split(new string[] { "materials/" }, StringSplitOptions.None).FirstOrDefault(); string externalPath = source + "/" + internalPath; bsp.tabletVtfWorkshop = new KeyValuePair <string, string>(internalPath, bsp.tabletVtfLocal.Value); } // Duplicate the workshop spawn select file to the local spawn select file location if it does not exist if (bsp.spawnSelectPngLocal.Equals(default(KeyValuePair <string, string>)) && !bsp.spawnSelectPngWorkshop.Equals(default(KeyValuePair <string, string>))) { internalPath = spawnSelectBaseFolderpath + "map_" + bspName + ".png"; string source = bsp.spawnSelectPngWorkshop.Value.Split(new string[] { "materials/" }, StringSplitOptions.None).FirstOrDefault(); string externalPath = source + "/" + internalPath; bsp.spawnSelectPngLocal = new KeyValuePair <string, string>(internalPath, bsp.spawnSelectPngWorkshop.Value); } else if (bsp.workshopId > 0 && !bsp.spawnSelectPngLocal.Equals(default(KeyValuePair <string, string>)) && bsp.spawnSelectPngWorkshop.Equals(default(KeyValuePair <string, string>))) // Can only be done if the workshop id is known { internalPath = spawnSelectBaseFolderpath + $"map_workshop/{bsp.workshopId}/" + bspName + ".png"; string source = bsp.spawnSelectPngLocal.Value.Split(new string[] { "materials/" }, StringSplitOptions.None).FirstOrDefault(); string externalPath = source + "/" + internalPath; bsp.spawnSelectPngWorkshop = new KeyValuePair <string, string>(internalPath, bsp.spawnSelectPngLocal.Value); } // language files, particle manifests and soundscript file // (these language files are localized text files for tf2 mission briefings) string internalDir = "maps/"; string searchPattern = bspName + "*.txt"; List <KeyValuePair <string, string> > langfiles = new List <KeyValuePair <string, string> >(); foreach (string source in sourceDirectories) { string externalDir = source + "/" + internalDir; DirectoryInfo dir = new DirectoryInfo(externalDir); if (dir.Exists) { foreach (FileInfo f in dir.GetFiles(searchPattern)) { // particle files if particle manifest is not being generated if (!genparticlemanifest) { if (f.Name.StartsWith(bspName + "_particles") || f.Name.StartsWith(bspName + "_manifest")) { bsp.particleManifest = new KeyValuePair <string, string>(internalDir + f.Name, externalDir + f.Name); } } // soundscript if (f.Name.StartsWith(bspName + "_level_sounds")) { bsp.soundscript = new KeyValuePair <string, string>(internalDir + f.Name, externalDir + f.Name); } // presumably language files else { langfiles.Add(new KeyValuePair <string, string>(internalDir + f.Name, externalDir + f.Name)); } } } } bsp.languages = langfiles; // ASW/Source2009 branch VScripts List <string> vscripts = new List <string>(); foreach (Dictionary <string, string> entity in bsp.entityList) { foreach (KeyValuePair <string, string> kvp in entity) { if (kvp.Key.ToLower() == "vscripts") { string[] scripts = kvp.Value.Split(' '); foreach (string script in scripts) { vscripts.Add("scripts/vscripts/" + script); } } } } // look for scripts referenced in other scripts using IncludeScript or DoIncludeScript // will not work if multiple IncludeScript or DoIncludeScript are done on the same line var vscriptsParsing = new List <string>(); vscriptsParsing.AddRange(vscripts); while (vscriptsParsing.Count() > 0) { Regex lineComments = new Regex(@"//(.*?)\r?\n"); //////// TODO: currently does not remove single line comments ?? Regex blockComments = new Regex(@"/\*(.*?)\*/"); var vscriptsFound = new List <string>(); foreach (var vscript in vscriptsParsing) { var filepath = PakFile.FindExternalFile(vscript, sourceDirectories); if (string.IsNullOrWhiteSpace(filepath)) { continue; } var lines = File.ReadAllLines(filepath); foreach (var line in lines) { // remove comments string regexedLine = lineComments.Replace(line, ""); //////// TODO: currently does not remove single line comments ?? regexedLine = blockComments.Replace(regexedLine, ""); // continue if whitespace if (string.IsNullOrWhiteSpace(regexedLine)) { continue; } // split the line to see if it includes a script var splits = regexedLine.Split(new string[] { "DoIncludeScript(\"", "IncludeScript(\"" }, StringSplitOptions.None).ToList(); if (splits.Count() > 1) { if (!splits[0].Contains("//")) { var correctSplit = splits[1]; var path = correctSplit.Split('\"').FirstOrDefault(); vscriptsFound.Add(("scripts/vscripts/" + path).Replace("//", "/")); } } } } vscriptsParsing = vscriptsFound; vscripts.AddRange(vscriptsFound); } bsp.vscriptList = vscripts; }
public PakFile(BSP bsp, List<string> sourceDirectories) { mdlcount = vmtcount = pcfcount = sndcount = 0; sourceDirs = sourceDirectories; Files = new Dictionary<string, string>(); if (bsp.nav.Key != default(string)) Files.Add(bsp.nav); if (bsp.detail.Key != default(string)) Files.Add(bsp.detail); if (bsp.kv.Key != default(string)) Files.Add(bsp.kv); if (bsp.txt.Key != default(string)) Files.Add(bsp.txt); if (bsp.jpg.Key != default(string)) Files.Add(bsp.jpg); if (bsp.radartxt.Key != default(string)) Files.Add(bsp.radartxt); if (bsp.res.Key != default(string)) { Files.Add(bsp.res); foreach (string material in AssetUtils.findResMaterials(bsp.res.Value)) AddTexture(material); } if (bsp.particleManifest.Key != default(string)) { Files.Add(bsp.particleManifest); foreach (string particle in AssetUtils.findManifestPcfs(bsp.particleManifest.Value)) AddParticle(particle); } if (bsp.soundscape.Key != default(string)) { Files.Add(bsp.soundscape); foreach (string sound in AssetUtils.findSoundscapeSounds(bsp.soundscape.Value)) if (AddFile(sound, FindExternalFile(sound))) sndcount++; } if (bsp.soundscript.Key != default(string)) { Files.Add(bsp.soundscript); foreach (string sound in AssetUtils.findSoundscapeSounds(bsp.soundscript.Value)) if (AddFile(sound, FindExternalFile(sound))) sndcount++; } // find color correction files foreach (Dictionary<string, string> cc in bsp.entityList.Where(item => item["classname"] == "color_correction")) AddFile(cc["filename"], FindExternalFile(cc["filename"])); foreach (KeyValuePair<string, string> dds in bsp.radardds) AddFile(dds.Key, dds.Value); foreach (KeyValuePair<string, string> lang in bsp.languages) AddFile(lang.Key, lang.Value); foreach (string model in bsp.EntModelList) AddModel(model); for (int i = 0; i < bsp.ModelList.Count; i++) AddModel(bsp.ModelList[i], bsp.modelSkinList[i]); foreach (string vmt in bsp.TextureList) AddTexture(vmt); foreach (string vmt in bsp.EntTextureList) AddTexture(vmt); foreach (string sound in bsp.EntSoundList) if (AddFile(sound, FindExternalFile(sound))) sndcount++; }
public override void Run(CompileContext context) { try { bspZip = context.Configuration.BSPZip; gameFolder = context.Configuration.GameFolder; bspPath = context.BSPFile; Keys.vmtTextureKeyWords = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "texturekeys.txt")).ToList(); Keys.vmtMaterialKeyWords = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "materialkeys.txt")).ToList(); Keys.vmfSoundKeys = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "vmfsoundkeys.txt")).ToList(); Keys.vmfMaterialKeys = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "vmfmaterialkeys.txt")).ToList(); Keys.vmfModelKeys = File.ReadAllLines(System.IO.Path.Combine(keysFolder, "vmfmodelkeys.txt")).ToList(); CompilePalLogger.LogLine("Finding sources of game content..."); GetSourceDirectories(gameFolder); CompilePalLogger.LogLine("Reading BSP..."); BSP map = new BSP(new FileInfo(bspPath)); AssetUtils.findBspUtilityFiles(map, sourceDirectories); string unpackDir = System.IO.Path.GetTempPath() + Guid.NewGuid(); UnpackBSP(unpackDir); AssetUtils.findBspPakDependencies(map, unpackDir); CompilePalLogger.LogLine("Initializing pak file..."); PakFile pakfile = new PakFile(map, sourceDirectories); CompilePalLogger.LogLine("Writing file list..."); pakfile.OutputToFile(); CompilePalLogger.LogLine("Running bspzip..."); PackBSP(); CompilePalLogger.LogLine("Finished packing!"); CompilePalLogger.LogLine("---------------------"); CompilePalLogger.LogLine(pakfile.vmtcount + " materials added"); CompilePalLogger.LogLine(pakfile.mdlcount + " models added"); CompilePalLogger.LogLine(pakfile.pcfcount + " particle files added"); CompilePalLogger.LogLine(pakfile.sndcount + " sounds added"); string additionalFiles = (map.nav.Key != default(string) ? "\n-nav file" : "") + (map.soundscape.Key != default(string) ? "\n-soundscape" : "") + (map.soundscript.Key != default(string) ? "\n-soundscript" : "") + (map.detail.Key != default(string) ? "\n-detail file" : "") + (map.particleManifest.Key != default(string) ? "\n-particle manifest" : "") + (map.radartxt.Key != default(string) ? "\n-radar files" : "") + (map.txt.Key != default(string) ? "\n-loading screen text" : "") + (map.jpg.Key != default(string) ? "\n-loading screen image" : "") + (map.kv.Key != default(string) ? "\n-kv file" : ""); CompilePalLogger.LogLine(additionalFiles != default(string) ? "additional files: " + additionalFiles : "none"); CompilePalLogger.LogLine("---------------------"); } catch (Exception exception) { CompilePalLogger.LogLine("Something broke:"); CompilePalLogger.LogLine(exception.ToString()); } }
public static void findBspUtilityFiles(BSP bsp, List <string> sourceDirectories) { // Utility files are other files that are not assets and are sometimes not referenced in the bsp // those are manifests, soundscapes, nav, radar and detail files // Soundscape file string internalPath = "scripts/soundscapes_" + bsp.file.Name.Replace(".bsp", ".txt"); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.soundscape = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // Soundscript file internalPath = "maps/" + bsp.file.Name.Replace(".bsp", "") + "_level_sounds.txt"; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.soundscript = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // Nav file (.nav) internalPath = "maps/" + bsp.file.Name.Replace(".bsp", ".nav"); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.nav = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // detail file (.vbsp) Dictionary <string, string> worldspawn = bsp.entityList.First(item => item["classname"] == "worldspawn"); if (worldspawn.ContainsKey("detailvbsp")) { internalPath = worldspawn["detailvbsp"]; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.detail = new KeyValuePair <string, string>(internalPath, externalPath); break; } } } // Radar file internalPath = "resource/overviews/" + bsp.file.Name.Replace(".bsp", ".txt"); List <KeyValuePair <string, string> > ddsfiles = new List <KeyValuePair <string, string> >(); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.radartxt = new KeyValuePair <string, string>(internalPath, externalPath); bsp.TextureList.AddRange(findVmtMaterials(externalPath)); List <string> ddsInternalPaths = findRadarDdsFiles(externalPath); //find out if they exists or not foreach (string ddsInternalPath in ddsInternalPaths) { foreach (string source2 in sourceDirectories) { string ddsExternalPath = source2 + "/" + ddsInternalPath; if (File.Exists(ddsExternalPath)) { ddsfiles.Add(new KeyValuePair <string, string>(ddsInternalPath, ddsExternalPath)); break; } } } break; } } bsp.radardds = ddsfiles; // csgo kv file (.kv) internalPath = "maps/" + bsp.file.Name.Replace(".bsp", ".kv"); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.kv = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // csgo loading screen text file (.txt) internalPath = "maps/" + bsp.file.Name.Replace(".bsp", ".txt"); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.txt = new KeyValuePair <string, string>(internalPath, externalPath); break; } } // csgo loading screen image (.jpg) internalPath = "maps/" + bsp.file.Name.Replace(".bsp", ""); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; foreach (string extension in new String[] { ".jpg", ".jpeg" }) { if (File.Exists(externalPath + extension)) { bsp.jpg = new KeyValuePair <string, string>(internalPath + ".jpg", externalPath + extension); } } } // language files, particle manifests and soundscript file // (these language files are localized text files for tf2 mission briefings) string internalDir = "maps/"; string name = bsp.file.Name.Replace(".bsp", ""); string searchPattern = name + "*.txt"; List <KeyValuePair <string, string> > langfiles = new List <KeyValuePair <string, string> >(); foreach (string source in sourceDirectories) { string externalDir = source + "/" + internalDir; DirectoryInfo dir = new DirectoryInfo(externalDir); if (dir.Exists) { foreach (FileInfo f in dir.GetFiles(searchPattern)) { // particle files if (f.Name.StartsWith(name + "_particles") || f.Name.StartsWith(name + "_manifest")) { bsp.particleManifest = new KeyValuePair <string, string>(internalDir + f.Name, externalDir + f.Name); } // soundscript else if (f.Name.StartsWith(name + "_level_sounds")) { bsp.soundscript = new KeyValuePair <string, string>(internalDir + f.Name, externalDir + f.Name); } // presumably language files else { langfiles.Add(new KeyValuePair <string, string>(internalDir + f.Name, externalDir + f.Name)); } } } } bsp.languages = langfiles; }
public static void findBspUtilityFiles(BSP bsp, List<string> sourceDirectories, bool renamenav) { // Utility files are other files that are not assets and are sometimes not referenced in the bsp // those are manifests, soundscapes, nav, radar and detail files // Soundscape file string internalPath = "scripts/soundscapes_" + bsp.file.Name.Replace(".bsp", ".txt"); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.soundscape = new KeyValuePair<string, string>(internalPath, externalPath); break; } } // Soundscript file internalPath = "maps/" + bsp.file.Name.Replace(".bsp", "") + "_level_sounds.txt"; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.soundscript = new KeyValuePair<string, string>(internalPath, externalPath); break; } } // Nav file (.nav) internalPath = "maps/" + bsp.file.Name.Replace(".bsp", ".nav"); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { if (renamenav) internalPath = "maps/embed.nav"; bsp.nav = new KeyValuePair<string, string>(internalPath, externalPath); break; } } // detail file (.vbsp) Dictionary<string, string> worldspawn = bsp.entityList.First(item => item["classname"] == "worldspawn"); if (worldspawn.ContainsKey("detailvbsp")) { internalPath = worldspawn["detailvbsp"]; foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.detail = new KeyValuePair<string, string>(internalPath, externalPath); break; } } } // Res file (for tf2's pd gamemode) Dictionary<string, string> pd_ent = bsp.entityList.FirstOrDefault(item => item["classname"] == "tf_logic_player_destruction"); if (pd_ent != null && pd_ent.ContainsKey("res_file")) { foreach (string source in sourceDirectories) { string externalPath = source + "/" + pd_ent["res_file"]; if (File.Exists(externalPath)) { bsp.res = new KeyValuePair<string, string>(pd_ent["res_file"], externalPath); break; } } } // Radar file internalPath = "resource/overviews/" + bsp.file.Name.Replace(".bsp", ".txt"); List<KeyValuePair<string, string>> ddsfiles = new List<KeyValuePair<string, string>>(); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.radartxt = new KeyValuePair<string, string>(internalPath, externalPath); bsp.TextureList.AddRange(findVmtMaterials(externalPath)); List<string> ddsInternalPaths = findRadarDdsFiles(externalPath); //find out if they exists or not foreach (string ddsInternalPath in ddsInternalPaths) { foreach (string source2 in sourceDirectories) { string ddsExternalPath = source2 + "/" + ddsInternalPath; if (File.Exists(ddsExternalPath)) { ddsfiles.Add(new KeyValuePair<string, string>(ddsInternalPath, ddsExternalPath)); break; } } } break; } } bsp.radardds = ddsfiles; // csgo kv file (.kv) internalPath = "maps/" + bsp.file.Name.Replace(".bsp", ".kv"); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.kv = new KeyValuePair<string, string>(internalPath, externalPath); break; } } // csgo loading screen text file (.txt) internalPath = "maps/" + bsp.file.Name.Replace(".bsp", ".txt"); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; if (File.Exists(externalPath)) { bsp.txt = new KeyValuePair<string, string>(internalPath, externalPath); break; } } // csgo loading screen image (.jpg) internalPath = "maps/" + bsp.file.Name.Replace(".bsp", ""); foreach (string source in sourceDirectories) { string externalPath = source + "/" + internalPath; foreach (string extension in new String[] {".jpg", ".jpeg"}) if (File.Exists(externalPath + extension)) bsp.jpg = new KeyValuePair<string, string>(internalPath + ".jpg", externalPath + extension); } // language files, particle manifests and soundscript file // (these language files are localized text files for tf2 mission briefings) string internalDir = "maps/"; string name = bsp.file.Name.Replace(".bsp", ""); string searchPattern = name + "*.txt"; List<KeyValuePair<string, string>> langfiles = new List<KeyValuePair<string, string>>(); foreach (string source in sourceDirectories) { string externalDir = source + "/" + internalDir; DirectoryInfo dir = new DirectoryInfo(externalDir); if (dir.Exists) foreach (FileInfo f in dir.GetFiles(searchPattern)) // particle files if (f.Name.StartsWith(name + "_particles") || f.Name.StartsWith(name + "_manifest")) bsp.particleManifest = new KeyValuePair<string, string>(internalDir + f.Name, externalDir + f.Name); // soundscript else if (f.Name.StartsWith(name + "_level_sounds")) bsp.soundscript = new KeyValuePair<string, string>(internalDir + f.Name, externalDir + f.Name); // presumably language files else langfiles.Add(new KeyValuePair<string, string>(internalDir + f.Name, externalDir + f.Name)); } bsp.languages = langfiles; }