private Art(string mulFile, IndexFile indexFile, Stream dataStream) { this.mulFile = mulFile; this.indexFile = indexFile; this.dataStream = dataStream; tileObject = new LandscapeData(this); itemsObject = new ItemsData(this); animationsObject = new AnimationsData(this); }
/// <summary> /// Saves object to specified files. /// </summary> /// <param name="idxFile">Index file path.</param> /// <param name="mulFile">Data file path.</param> /// <remarks> /// If mulFile differs from currently loaded file, new file is optimized (data file is sorted and without empty entries). /// Otherwise file must be loaded with write access. /// </remarks> public void Save(string idxFile, string mulFile) { lock (syncRoot) { if (Disposed) throw new ObjectDisposedException("Art"); Stream indexStream = null; try { indexStream = File.Open(idxFile, FileMode.Create, FileAccess.Write, FileShare.None); if (String.Compare(mulFile, this.mulFile, StringComparison.InvariantCultureIgnoreCase) == 0) { // Target data file is same as source file. File will not be optimized. Stream dataStream = this.dataStream; if (!dataStream.CanWrite) throw new InvalidOperationException("Trying to save data to source file, that is not opened for Write access."); foreach (KeyValuePair<int, Bitmap> pair in changeList) { if (pair.Key < 16384) { // Tile, can be saved to same location in data stream IndexData indexData = indexFile.Get(pair.Key, true); if (indexData.IsValid) { dataStream.Seek(indexData.Lookup, SeekOrigin.Begin); IndexData writtenData = Art.WriteTile(dataStream, pair.Value); Debug.Assert(writtenData.Lookup == indexData.Lookup, "writtenData.Lookup == indexData.Lookup"); Debug.Assert(writtenData.Lenght == indexData.Lenght, "writtenData.Lenght == indexData.Lenght"); } else { dataStream.Seek(0, SeekOrigin.End); IndexData writtenData = Art.WriteTile(dataStream, pair.Value); indexFile.Set(pair.Key, writtenData, true); } } else { // Run, will be saved to end of data stream dataStream.Seek(0, SeekOrigin.End); IndexData writtenData = Art.WriteRun(dataStream, pair.Value); indexFile.Set(pair.Key, writtenData, true); } } dataStream.Flush(); Trace.WriteLine(String.Format("Art: File \"{0}\" succesfully updated.", mulFile), "MulLib"); indexFile.Save(indexStream); Trace.WriteLine(String.Format("IndexFile: File \"{0}\" succesfully saved.", idxFile), "MulLib"); changeList.Clear(); } else { // Target data file differs from source file. Optimization will be performed. try { Stream dataStream = File.Open(mulFile, FileMode.Create, FileAccess.Write, FileShare.None); IndexFile newIndexFile = new IndexFile(); for (int i = 0; i < indexFile.Count; i++) { if (changeList.ContainsKey(i)) { IndexData writtenData; if (i < 16384) writtenData = Art.WriteTile(dataStream, changeList[i]); else writtenData = Art.WriteRun(dataStream, changeList[i]); newIndexFile.Set(i, writtenData, true); } else { IndexData indexData = indexFile.Get(i, false); if (indexData.IsValid) { byte[] data = new byte[indexData.Lenght]; this.dataStream.Seek(indexData.Lookup, SeekOrigin.Begin); this.dataStream.Read(data, 0, (int)indexData.Lenght); IndexData writtenData = new IndexData(); writtenData.Lookup = (uint)dataStream.Position; writtenData.Lenght = indexData.Lenght; writtenData.Extra = indexData.Extra; dataStream.Write(data, 0, (int)writtenData.Lenght); } } } dataStream.Flush(); Trace.WriteLine(String.Format("Art: File \"{0}\" succesfully saved.", mulFile), "MulLib"); newIndexFile.Save(indexStream); Trace.WriteLine(String.Format("IndexFile: File \"{0}\" succesfully saved.", idxFile), "MulLib"); } finally { if (dataStream != null) dataStream.Close(); } } } catch (Exception e) { throw new Exception("Error saving Art.", e); } finally { if (indexStream != null) indexStream.Close(); } } }
/// <summary> /// Initializes the new empty Art object. /// </summary> public Art() { mulFile = null; dataStream = Stream.Null; indexFile = new IndexFile(); indexFile.Resize(65536); tileObject = new LandscapeData(this); itemsObject = new ItemsData(this); animationsObject = new AnimationsData(this); }
/// <summary> /// Loads IndexFile object from file. /// </summary> /// <param name="file">File path.</param> public static IndexFile Load(string file) { Stream stream = null; BinaryReader reader = null; try { stream = File.OpenRead(file); reader = new BinaryReader(stream); Trace.WriteLineIf((stream.Length % IndexData.Size) != 0, "IndexFile: File size is not multiple of 12.", "MulLib"); IndexFile indexFile = new IndexFile(); IndexData data = new IndexData(); for (int i = 0; i < stream.Length / IndexData.Size; i++) { data.Lookup = reader.ReadUInt32(); data.Lenght = reader.ReadUInt32(); data.Extra = reader.ReadUInt32(); indexFile.list.Add(data); } Trace.WriteLine(String.Format("IndexFile: File \"{0}\" succesfully loaded.", file), "MulLib"); return indexFile; } catch (Exception e) { throw new Exception("Error loading IndexFile.", e); } finally { if (reader != null) reader.Close(); if (stream != null) stream.Close(); } }