/// <summary> /// Writes this block and all referenced blocks to disk (if they weren't written already). /// </summary> /// <param name="unload"> /// <para><value>true</value>: Unloads this block.</para> /// <para><value>false</value>: Doesn't unload this block.</para> /// <para>Referenced blocks aren't directly affected.</para> /// </param> public void Write(bool unload) { if (!Bound) { GameSave.BindBlock(this); } if (Written) { return; } if (!Loaded) { // This shouldn't happen throw new InvalidOperationException("Tried to write unwritten, unloaded block."); } foreach (BlockStructure block in ReferencedBlocks.Where(block => block.Written == false)) { block.Write(false); // Don't unload referenced blocks. If unload is true, the reference is lost anyway, unless they are used somewhere else. } Stream stream = GameSave.GetBlobFile(_address.Item1); stream.Seek(_address.Item2, SeekOrigin.Begin); #if AssertBlockLength long start = stream.Position; #endif var writer = new BinaryWriter(stream); #if DebugVerboseBlocks Console.WriteLine("Writing {0} from {1} to {2}", GetType(), Address, Address.Item2 + Length); #endif bool isHeader = this is IHeader; if (isHeader) { GameSave.FlushFiles(); } WriteData(writer); #if AssertBlockLength if (stream.Position - start != Length) { throw new Exception("Length mismatch after writing " + GetType() + "!"); } #endif Written = true; UpdateRecursiveUsedSpace(); if (unload) { Unload(); } if (isHeader) { GameSave.MarkFreeSpace(this); } }