public static void SaveExpansionPdb(string strFile, Document[] adoc, string strVersion) { // First save all level docs //annoying //DocManager.SaveAllModified(typeof(LevelDoc)); // Remember active document LevelDoc lvldActive = (LevelDoc)DocManager.GetActiveDocument(typeof(LevelDoc)); // Save documents adoc in an expansion .pdb. Expansion .pdbs need: // - .lvl, .tmap, .trmap, but not .tsets since these come from game .pdbs // - need a version.txt // - need an if demo trigger check "inserted" at save time // - .pdb needs WARI creator, ADD1 type // - data should be compressed for obfuscation purposes PdbPacker pdbp = new PdbPacker(); // Add version.txt byte[] abT = new byte[strVersion.Length + 1]; for (int n = 0; n < strVersion.Length; n++) { abT[n] = (byte)strVersion[n]; } abT[abT.Length - 1] = 0; pdbp.Add(new PdbPacker.File("version.txt", abT)); // Load res.h from embedded resource in prep for pre-process System.Reflection.Assembly ass = typeof(GobImage).Module.Assembly; Stream stmResDotH = ass.GetManifestResourceStream("m.EmbeddedResources." + "res.h"); if (stmResDotH == null) { throw new Exception("Cannot load res.h"); } // Compile levels Random rand = new Random(); ArrayList alsTileSets = new ArrayList(); foreach (LevelDoc lvld in adoc) { // Need to do this unfortunately; some of the "saving" code relies on what the "active" document // is!! DocManager.SetActiveDocument(typeof(LevelDoc), lvld); TemplateDoc tmpd = lvld.GetTemplateDoc(); // Get appropriate TileSet, or make one if this map // uses a new tile collection TileSet tset = null; foreach (TileSet tsetT in alsTileSets) { if (tsetT.TemplateDoc == tmpd) { tset = tsetT; break; } } // Create new tile set if none found if (tset == null) { tset = new TileSet(tmpd, tmpd.GetName() + ".tset"); alsTileSets.Add(tset); } #if false // Generate base file name for this level (this is never user-visible, but it should be // as unique as possible char[] achBase = new char[16]; for (int n = 0; n < achBase.Length; n++) { int nT = rand.Next() % (26 + 10); if (nT < 26) { achBase[n] = (char)(nT + 97); } else { achBase[n] = (char)(nT + 48 - 26); } } if (lvld.MaxPlayers > 1) { achBase[0] = 'm'; achBase[1] = '_'; } string strBase = new String(achBase); #else // This isn't unique which can cause problems due to how packfiles work. // Could change packfile api to accept .pdb parameter. // Note1: set next mission action requires predictable filename // Note2: mission sorting is based on filename, not title // Could put lots of "support" in to fix these problems, or just ship // it like this. // // Hack: filename length 29 // Maximum extension on filename: 7 string strBase = lvld.Title; if (strBase.Length > 29 - 7) { strBase = strBase.Substring(0, 29 - 7); } // If multiplayer, add "m_" to the name by losing the last two characters // so sort order is preserved if (lvld.MaxPlayers > 1) { strBase = "m_" + strBase.Substring(0, strBase.Length - 2); } #endif // Get tile map file for this level MemoryStream stmTmap = new MemoryStream(); TileMap tmap = TileMap.CreateFromImage(tset, lvld.GetMapBitmap(tmpd.TileSize, tmpd, true), tmpd.TileSize); tmap.Save(stmTmap); string strTmap = strBase + ".tmap"; pdbp.Add(new PdbPacker.File(strTmap, stmTmap.ToArray())); stmTmap.Close(); // Get the terrain map file for this level MemoryStream stmTRmap = new MemoryStream(); TerrainMap trmap = new TerrainMap(lvld.GetTerrainMap(tmpd.TileSize, tmpd, false)); trmap.Save(stmTRmap); string strTRmap = strBase + ".trmap"; pdbp.Add(new PdbPacker.File(strTRmap, stmTRmap.ToArray())); stmTRmap.Close(); // Save .ini file for this level doc MemoryStream stmLvld = new MemoryStream(); lvld.SaveIni(stmLvld, -1, strTmap, strTRmap, tmpd.GetName() + ".palbin", true); // Pre-process stmLvld.Seek(0, SeekOrigin.Begin); MemoryStream stmPreprocessed = Misc.PreprocessStream(stmLvld, stmResDotH); stmPreprocessed.Seek(0, SeekOrigin.Begin); Ini iniPreProcessed = new Ini(stmPreprocessed); MemoryStream stmLvldPreProcessedBinary = new MemoryStream(); iniPreProcessed.SaveBinary(stmLvldPreProcessedBinary); stmLvldPreProcessedBinary.Close(); string strLvlName = lvld.OutputFilename; if (strLvlName == null) { strLvlName = strBase + ".lvl"; } pdbp.Add(new PdbPacker.File(strLvlName, stmLvldPreProcessedBinary.ToArray())); stmLvldPreProcessedBinary.Close(); } stmResDotH.Close(); // Restore active document if (lvldActive != null) { DocManager.SetActiveDocument(typeof(LevelDoc), lvldActive); } // Now save out pdb pdbp.Save(strFile, "WARI", "ADD2"); }
static bool PackFiles(string[] args) { // Parse parameters, validate. if (args[1].Length > 4) { Console.WriteLine("Creator id " + args[1] + " must be 4 chars or less."); return(false); } string strCreatorId = args[1]; string strFullPathPdb = Path.GetFullPath(args[2]); string strFilePdb = Path.GetFileName(strFullPathPdb); string strDirPdb = Path.GetDirectoryName(strFullPathPdb); if (strDirPdb == "") { strDirPdb = "."; } if (strFilePdb.Length > 31) { Console.WriteLine("Pdb filename " + strFilePdb + " must be 31 characters or less."); return(false); } string strFileSpec; if (args.Length == 3) { strFileSpec = ".\\*.*"; } else { strFileSpec = args[3]; } // Get list of files to add string strFileFileSpecAdd = Path.GetFileName(strFileSpec); string strDirFileSpecAdd = Path.GetDirectoryName(strFileSpec); if (strDirFileSpecAdd == "") { strDirFileSpecAdd = "."; } string[] astrFilesAdd = Directory.GetFiles(strDirFileSpecAdd, strFileFileSpecAdd); // File types not to compress ArrayList alsStrFilesNoCompress = new ArrayList(); if (args.Length > 4) { if (args[4] == "-nocompress") { for (int i = 5; i < args.Length; i++) { string[] astrFiles = Directory.GetFiles(strDirFileSpecAdd, args[i]); foreach (string str in astrFiles) { alsStrFilesNoCompress.Add(Path.GetFullPath(str)); } } } } // Print status Console.Write("Packing files... "); PdbPacker pdbp = new PdbPacker(); foreach (string strFileAdd in astrFilesAdd) { // Don't add the .pdb we're building string strFullPathAdd = Path.GetFullPath(strFileAdd); if (strFullPathPdb.ToLower() == strFullPathAdd.ToLower()) { continue; } // Get filename only, check length string strFile = Path.GetFileName(strFullPathAdd).ToLower(); if (strFile.Length >= s_cbFilenameMax) { Console.WriteLine("The file " + strFile + " is too long. Must be " + (s_cbFilenameMax - 1) + "chars max."); return(false); } // Compress or not? bool fCompress = true; foreach (string strFileNoCompress in alsStrFilesNoCompress) { if (strFullPathAdd.ToLower() == strFileNoCompress.ToLower()) { fCompress = false; break; } } // Read the file Stream stm = new FileStream(strFullPathAdd, FileMode.Open, FileAccess.Read); BinaryReader brdr = new BinaryReader(stm); PdbPacker.File file = new PdbPacker.File(strFile, brdr.ReadBytes((int)brdr.BaseStream.Length), fCompress); brdr.Close(); pdbp.Add(file); } // Save out pdbp.Save(strFullPathPdb, strCreatorId); return(true); }