public static void WriteImaginaryObject(ImaginaryObject imaginaryObject, BinaryWriter writer,
                                                bool writeImaginaryObjectUniqueIdentifier = true)
        {
            writer.Write(writeImaginaryObjectUniqueIdentifier);

            var imaginaryObjectUniqueIdentifier = 0;

            if (writeImaginaryObjectUniqueIdentifier)
            {
                imaginaryObjectUniqueIdentifier  = totalWrittenImaginaryObjects;
                imaginaryObjectUniqueIdentifier += imaginaryObject.GetHashCode();
                imaginaryObjectUniqueIdentifier += new Random().Next(imaginaryObjectUniqueIdentifier, int.MaxValue);

                writer.Write(imaginaryObjectUniqueIdentifier);
            }

            //try
            //{
            WriteImaginaryObjectType(imaginaryObject.GetType(), writer);

            imaginaryObject.WriteConstructionInfo(writer);
            //}
            //catch (Exception)
            //{
            //	// Revert position to where the writer was before.
            //	WriteImaginaryObject(new CorruptedImaginaryObject(), writer);
            //}

            if (writeImaginaryObjectUniqueIdentifier)
            {
                writer.Write(imaginaryObjectUniqueIdentifier);
            }

            totalWrittenImaginaryObjects++;
        }
        /// <summary>
        ///     Reads an ImaginaryObject from the current position of the reader.
        /// </summary>
        public static ImaginaryObject ReadImaginaryObject(BinaryReader reader, out bool?success)
        {
            var imaginaryObjectUniqueIdentifier = 0;

            var usesImaginaryObjectUniqueIdentifier = reader.ReadBoolean();

            if (usesImaginaryObjectUniqueIdentifier)
            {
                imaginaryObjectUniqueIdentifier = reader.ReadInt32();
            }

            //try
            //{
            ImaginaryObject imaginaryObject = ReadEmptyImaginaryObject(reader);

            imaginaryObject.ReadConstructionInfo(reader);
            //}
            //catch (Exception)
            //{
            //	// Move the position forward to where the ImaginaryObject ends.
            //	return new CorruptedImaginaryObject();
            //}

            if (usesImaginaryObjectUniqueIdentifier)
            {
                success = imaginaryObjectUniqueIdentifier == reader.ReadInt32();
            }
            else
            {
                success = null;
            }

            return(imaginaryObject);
        }
                                                                            GetConstructionParameters()); // TODO: find something faster than Activator to use.

        public object[] GetConstructionParameters()
        {
            object[] imaginaryConstructionParameters = new object[ImaginaryConstructionParameters.Length];

            for (int i = 0; i < ImaginaryConstructionParameters.Length; i++)
            {
                ImaginaryObject imaginaryObject = ImaginaryConstructionParameters[i];
                imaginaryConstructionParameters[i] = imaginaryObject.CreateInstance();
            }

            return(imaginaryConstructionParameters);
        }
        public static void SaveToFile(string path, ImaginaryObject toStore)
        {
            var settings = new XmlWriterSettings {
                Indent = true
            };

            Utilities.CreateEmptyFile(path);

            using (var writerStream = XmlWriter.Create(path, settings))
            {
                new DataContractSerializer(toStore.GetType()).WriteObject(writerStream, toStore);
            }
        }
        // TODO: add TExpected
        public static ImaginaryObject UnpackImaginaryObject(string path)
        {
            Encoding encoding = Encoding.UTF8;

            using (var fileStream = new FileStream(path, FileMode.Open))
#if DEBUG
                // BinaryReader without decompression if the program is being debugged.
                using (var reader = new BinaryReader(fileStream, encoding))
#else
                using (LZ4DecoderStream decompressionStream = LZ4Stream.Decode(fileStream))
                    using (BinaryReader reader = new BinaryReader(decompressionStream, encoding))
#endif
                {
                    // Read the version of CrystalClear that this pack file was created in.
                    var fileCreatedInVersion = new Version(reader.ReadString());

                    // Is the pack file from an older version of CrystalClear?
                    if (fileCreatedInVersion < CrystalClearInformation.CrystalClearVersion)
                    {
                        // The version that this file was created in is older than the current version.
                        Output.ErrorLog(
                            $"This file was created in an older version of the CrystalClear Engine. {fileCreatedInVersion} (file) < {CrystalClearInformation.CrystalClearVersion} (current)");
                    }

                    // Is the pack file from a newer version of CrystalClear?
                    else if (fileCreatedInVersion > CrystalClearInformation.CrystalClearVersion)
                    {
                        // The version that this file was created in is newer than the current version.
                        Output.ErrorLog(
                            $"This file was created in a newer version of the CrystalClear Engine. {fileCreatedInVersion} (file) > {CrystalClearInformation.CrystalClearVersion} (current)");
                    }

                    ImaginaryObject unpacked;

                    unpacked = ImaginaryObject.ReadImaginaryObject(reader, out _);

                    return(unpacked);
                }
        }
        public static void PackImaginaryObjectToFile(string path, ImaginaryObject toStore)
        {
            Encoding encoding = Encoding.UTF8;

            Utilities.CreateEmptyFile(path);

            using (var fileStream = new FileStream(path, FileMode.Create))
#if DEBUG
                using (var writer = new BinaryWriter(fileStream, encoding))
#else
                using (LZ4EncoderStream compressionStream = LZ4Stream.Encode(fileStream))
                    using (BinaryWriter writer = new BinaryWriter(compressionStream, encoding))
#endif
                {
                    // Write the current CrystalClear version to the file.
                    writer.Write(CrystalClearInformation.CrystalClearVersion.ToString());

                    // Write the constructor data.
                    toStore.WriteThis(writer);

                    // Save the file.
                    writer.Flush();
                }
        }
 protected override void ReadConstructionInfo(BinaryReader reader)
 {
     ImaginaryObjectBase = ReadImaginaryObject(reader, out _);
 }
 public ImaginaryScript(ImaginaryObject imaginaryObjectBase)
 {
     ImaginaryObjectBase = imaginaryObjectBase;
 }
 // TODO: rewrite, probably.
 public ImaginaryHierarchyObject(ImaginaryHierarchyObject parent, ImaginaryObject imaginaryObjectBase)
 {
     Parent = parent;
     ImaginaryObjectBase = imaginaryObjectBase;
 }