Exemplo n.º 1
0
        /// <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);
            }
        }