/// <summary> /// Saves the ERF file under the specified name. /// </summary> /// <param name="fileName">The name of the file.</param> public void SaveAs(string fileName) { NWNLogger.Log(0, "module.SaveAs entering [{0}]", fileName); // The ERF must be decompressed first unless it is a new ERF. if (keys.Length > 0 && string.Empty == decompressedPath) throw new NWNException("ERF must be decompressed to recreate"); // Copy all of the modified files into the temp directory StringCollection replacedFiles = ReplacedFiles; NWNLogger.Log(0, "module.SaveAs copying {0} modified files into temp directory", replacedFiles.Count); foreach (string file in replacedFiles) File.Copy(file, Path.Combine(decompressedPath, Path.GetFileName(file)), true); // Figure out the new number of files in the ERF and create new // key/resource arrays of the proper size. int fileCount = keys.Length + addedFileHash.Count - removedFiles.Count; NWNLogger.Log(0, "module.SaveAs {0} total files, allocating key/resource arrays", fileCount); ErfKey[] newKeys = new ErfKey[fileCount]; ErfResource[] newResources = new ErfResource[fileCount]; // Create a buffer to store the data. NWNLogger.Log(0, "module.SaveAs creating memory stream"); MemoryStream buffer = new MemoryStream(); // Copy all of the existing not-removed files into the new key/resource // arrays. int index = 0; for (int i = 0; i < keys.Length; i++) { string file = keys[i].FileName; if (string.Empty == file || removedFiles.Contains(file)) continue; // Copy the key/resource pair over. NWNLogger.Log(1, "module.SaveAs copying file[{0}] '{1}'", i, file); newKeys[index] = keys[i]; newResources[index] = resources[i]; // Read the file into the buffer. ReadFileIntoStream(Path.Combine(decompressedPath, file), ref newResources[index], buffer); index++; } // Add all of the new files to the key/resource arrays. StringCollection addedFiles = AddedFiles; foreach (string file in addedFiles) { NWNLogger.Log(1, "module.SaveAs adding new file '{0}'", file); // SBH - depends on mode (NWN1 uses 1.0, 2 uses 1.1) if (NWNInfo.ModeNWN1) newKeys[index] = new ErfKey(file, 1.0); else newKeys[index] = new ErfKey(file, 1.1); newResources[index] = new ErfResource(); // Read the file into the buffer. ReadFileIntoStream(file, ref newResources[index], buffer); index++; } // Figure out how big our descriptions are going to be. NWNLogger.Log(0, "module.SaveAs calcing description size"); int descriptionsCount = 0; for (int i = 0; i < descriptions.Length; i++) descriptionsCount += descriptions[i].SizeInStream; // Create a new resource header and calculate the new offsets. NWNLogger.Log(0, "module.SaveAs creating header"); ErfHeader newHeader = header; newHeader.OffsetToLocalizedString = Marshal.SizeOf(typeof(ErfHeader)); newHeader.OffsetToKeyList = newHeader.OffsetToLocalizedString + descriptionsCount; newHeader.EntryCount = fileCount; //SBH - depends on mode if (NWNInfo.ModeNWN1) newHeader.OffsetToResourceList = newHeader.OffsetToKeyList + (fileCount * ErfKey.SizeOf(1.0)); else newHeader.OffsetToResourceList = newHeader.OffsetToKeyList + (fileCount * ErfKey.SizeOf(1.1)); // Calculate the offset to the beginning of the resource data and adjust // the offsets in the resource array to take this into account. NWNLogger.Log(0, "module.SaveAs calcing offsets"); int offsetToData = newHeader.OffsetToResourceList + (fileCount * Marshal.SizeOf(typeof(ErfResource))); for (int i = 0; i < newResources.Length; i++) newResources[i].OffsetToResource += offsetToData; // Create the new file and write the data to it. NWNLogger.Log(0, "module.SaveAs creating output file"); string newName = fileName + ".New"; using (FileStream writer = new FileStream(newName, FileMode.Create, FileAccess.Write, FileShare.Write)) { NWNLogger.Log(0, "module.SaveAs writing header"); newHeader.Serialize(writer); NWNLogger.Log(0, "module.SaveAs writing strings"); ErfString.Serialize(writer, descriptions); NWNLogger.Log(0, "module.SaveAs writing keys"); ErfKey.Serlialize(writer, newKeys); NWNLogger.Log(0, "module.SaveAs writing resources"); ErfResource.Serlialize(writer, newResources); NWNLogger.Log(0, "module.SaveAs writing raw data"); writer.Write(buffer.GetBuffer(), 0, (int) buffer.Length); NWNLogger.Log(0, "module.SaveAs flushing and closing"); writer.Flush(); writer.Close(); } // Delete the old file and rename the new file to the proper name. NWNLogger.Log(0, "module.SaveAs copying over current file"); File.Copy(newName, fileName, true); NWNLogger.Log(0, "module.SaveAs deleting"); File.Delete(newName); // Update the ERF's field's with the new values. NWNLogger.Log(0, "module.SaveAs updating object definition"); header = newHeader; keys = newKeys; resources = newResources; // Clear our string collections. replacedFileHash.Clear(); addedFileHash.Clear(); removedFiles.Clear(); fileInfo = new FileInfo(fileName); }
public static ErfKey[] Deserialize(Stream s, int count, double version) { // Create an array of ErfKeys from the stream. ErfKey[] keys = new ErfKey[count]; for (int i = 0; i < count; i++) keys[i] = new ErfKey(s, version); return keys; }
public static void Serlialize(Stream s, ErfKey[] keys) { foreach(ErfKey key in keys) { key.Serlialize(s); } }
/// <summary> /// Serializes an ErfKey array to the stream. /// </summary> /// <param name="s">The stream</param> /// <param name="keys">The array to serialize</param> public static void Serlialize(Stream s, ErfKey[] keys) { // Loop through the keys, assigning them a resource ID // (it's just the array index) and then serializing them. for (int i = 0; i < keys.Length; i++) { keys[i].resourceID = i; keys[i].Serialize(s); } }