예제 #1
0
        private bool InternalLoad(string path, Core.Version version, ClientFeatures features)
        {
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException(nameof(path));
            }

            if (version == null)
            {
                throw new ArgumentNullException(nameof(version));
            }

            if (!File.Exists(path))
            {
                throw new FileNotFoundException($"File not found: {path}", path);
            }

            if (this.Loaded)
            {
                return(true);
            }

            if (features == ClientFeatures.None || features == ClientFeatures.Transparency)
            {
                features |= version.Value >= (ushort)DatFormat.Format_755 ? ClientFeatures.PatternZ : features;
                features |= version.Value >= (ushort)DatFormat.Format_960 ? ClientFeatures.Extended : features;
                features |= version.Value >= (ushort)DatFormat.Format_1050 ? ClientFeatures.FrameDurations : features;
                features |= version.Value >= (ushort)DatFormat.Format_1057 ? ClientFeatures.FrameGroups : features;
            }

            using (FileStream stream = new FileStream(path, FileMode.Open))
            {
                BinaryReader reader = new BinaryReader(stream);

                uint signature = reader.ReadUInt32();
                if (signature != version.DatSignature)
                {
                    string message = "Invalid DAT signature. Expected signature is {0:X} and loaded signature is {1:X}.";
                    throw new Exception(string.Format(message, version.DatSignature, signature));
                }

                this.ItemCount    = reader.ReadUInt16();
                this.OutfitCount  = reader.ReadUInt16();
                this.EffectCount  = reader.ReadUInt16();
                this.MissileCount = reader.ReadUInt16();

                int total  = this.ItemCount + this.OutfitCount + this.EffectCount + this.MissileCount;
                int loaded = 0;

                // load item list.
                for (ushort id = 100; id <= this.ItemCount; id++)
                {
                    ThingType item = new ThingType(id, ThingCategory.Item);
                    if (!ThingTypeSerializer.ReadProperties(item, version.Format, reader) ||
                        !ThingTypeSerializer.ReadTexturePatterns(item, features, reader))
                    {
                        throw new Exception("Items list cannot be loaded.");
                    }

                    this.Items.Add(id, item);
                }

                // update progress.
                if (this.ProgressChanged != null)
                {
                    loaded += this.ItemCount;
                    this.ProgressChanged(this, (loaded * 100) / total);
                }

                // load outfit list.
                for (ushort id = 1; id <= this.OutfitCount; id++)
                {
                    ThingType outfit = new ThingType(id, ThingCategory.Outfit);
                    if (!ThingTypeSerializer.ReadProperties(outfit, version.Format, reader) ||
                        !ThingTypeSerializer.ReadTexturePatterns(outfit, features, reader))
                    {
                        throw new Exception("Outfits list cannot be loaded.");
                    }

                    this.Outfits.Add(id, outfit);
                }

                // update progress.
                if (this.ProgressChanged != null)
                {
                    loaded += this.OutfitCount;
                    this.ProgressChanged(this, (loaded * 100) / total);
                }

                // load effect list.
                for (ushort id = 1; id <= this.EffectCount; id++)
                {
                    ThingType effect = new ThingType(id, ThingCategory.Effect);
                    if (!ThingTypeSerializer.ReadProperties(effect, version.Format, reader) ||
                        !ThingTypeSerializer.ReadTexturePatterns(effect, features, reader))
                    {
                        throw new Exception("Effects list cannot be loaded.");
                    }

                    this.Effects.Add(id, effect);
                }

                // update progress.
                if (this.ProgressChanged != null)
                {
                    loaded += this.EffectCount;
                    this.ProgressChanged(this, (loaded * 100) / total);
                }

                // load missile list.
                for (ushort id = 1; id <= this.MissileCount; id++)
                {
                    ThingType missile = new ThingType(id, ThingCategory.Missile);
                    if (!ThingTypeSerializer.ReadProperties(missile, version.Format, reader) ||
                        !ThingTypeSerializer.ReadTexturePatterns(missile, features, reader))
                    {
                        throw new Exception("Missiles list cannot be loaded.");
                    }

                    this.Missiles.Add(id, missile);
                }

                // update progress.
                if (this.ProgressChanged != null)
                {
                    loaded += this.MissileCount;
                    this.ProgressChanged(this, (loaded * 100) / total);
                }
            }

            this.FilePath       = path;
            this.Version        = version;
            this.ClientFeatures = features;
            this.Changed        = false;
            this.Loaded         = true;
            this.Disposed       = false;
            return(true);
        }
예제 #2
0
        public bool Save(string path, Core.Version version, ClientFeatures features)
        {
            if (path == null)
            {
                throw new ArgumentNullException(nameof(path));
            }

            if (version == null)
            {
                throw new ArgumentNullException(nameof(version));
            }

            if (this.Disposed)
            {
                throw new ObjectDisposedException(this.GetType().Name);
            }

            if (!this.Loaded)
            {
                return(false);
            }

            if (features == ClientFeatures.None || features == ClientFeatures.Transparency)
            {
                features |= version.Value >= (ushort)DatFormat.Format_755 ? ClientFeatures.PatternZ : features;
                features |= version.Value >= (ushort)DatFormat.Format_960 ? ClientFeatures.Extended : features;
                features |= version.Value >= (ushort)DatFormat.Format_1050 ? ClientFeatures.FrameDurations : features;
                features |= version.Value >= (ushort)DatFormat.Format_1057 ? ClientFeatures.FrameGroups : features;
            }

            string directory = Path.GetDirectoryName(path);

            if (!Directory.Exists(directory))
            {
                Directory.CreateDirectory(directory);
            }

            if (!this.Changed && this.Version.Equals(version) && this.ClientFeatures == features &&
                this.FilePath != null && !this.FilePath.Equals(path))
            {
                // just copy the content if nothing has changed.
                File.Copy(this.FilePath, path, true);

                if (this.ProgressChanged != null)
                {
                    this.ProgressChanged(this, 100);
                }
            }
            else
            {
                string tmpPath = Path.Combine(directory, Path.GetFileNameWithoutExtension(path) + ".tmp");

                using (FlagsBinaryWriter writer = new FlagsBinaryWriter(new FileStream(tmpPath, FileMode.Create)))
                {
                    // write the signature.
                    writer.Write(version.DatSignature);

                    // write item, outfit, effect and missile count.
                    writer.Write(this.ItemCount);
                    writer.Write(this.OutfitCount);
                    writer.Write(this.EffectCount);
                    writer.Write(this.MissileCount);

                    int total    = this.ItemCount + this.OutfitCount + this.EffectCount + this.MissileCount;
                    int compiled = 0;

                    // write item list.
                    for (ushort id = 100; id <= this.ItemCount; id++)
                    {
                        ThingType item = this.Items[id];
                        if (!ThingTypeSerializer.WriteProperties(item, version.Format, writer) ||
                            !ThingTypeSerializer.WriteTexturePatterns(item, features, writer))
                        {
                            throw new Exception("Items list cannot be compiled.");
                        }
                    }

                    // update progress.
                    if (this.ProgressChanged != null)
                    {
                        compiled += this.ItemCount;
                        this.ProgressChanged(this, (compiled * 100) / total);
                    }

                    bool onlyOneGroup = ((this.ClientFeatures & ClientFeatures.FrameGroups) == ClientFeatures.FrameGroups) &&
                                        ((features & ClientFeatures.FrameGroups) != ClientFeatures.FrameGroups);

                    // write outfit list.
                    for (ushort id = 1; id <= this.OutfitCount; id++)
                    {
                        ThingType outfit = onlyOneGroup ? ThingType.ToSingleFrameGroup(this.Outfits[id]) : this.Outfits[id];
                        if (!ThingTypeSerializer.WriteProperties(outfit, version.Format, writer) ||
                            !ThingTypeSerializer.WriteTexturePatterns(outfit, features, writer))
                        {
                            throw new Exception("Outfits list cannot be compiled.");
                        }
                    }

                    // update progress.
                    if (this.ProgressChanged != null)
                    {
                        compiled += this.OutfitCount;
                        this.ProgressChanged(this, (compiled * 100) / total);
                    }

                    // write effect list.
                    for (ushort id = 1; id <= this.EffectCount; id++)
                    {
                        ThingType effect = this.Effects[id];
                        if (!ThingTypeSerializer.WriteProperties(effect, version.Format, writer) ||
                            !ThingTypeSerializer.WriteTexturePatterns(effect, features, writer))
                        {
                            throw new Exception("Effects list cannot be compiled.");
                        }
                    }

                    // update progress.
                    if (this.ProgressChanged != null)
                    {
                        compiled += this.EffectCount;
                        this.ProgressChanged(this, (compiled * 100) / total);
                    }

                    // write missile list.
                    for (ushort id = 1; id <= this.MissileCount; id++)
                    {
                        ThingType missile = this.Missiles[id];
                        if (!ThingTypeSerializer.WriteProperties(missile, version.Format, writer) ||
                            !ThingTypeSerializer.WriteTexturePatterns(missile, features, writer))
                        {
                            throw new Exception("Missiles list cannot be compiled.");
                        }
                    }

                    // update progress.
                    if (this.ProgressChanged != null)
                    {
                        compiled += this.MissileCount;
                        this.ProgressChanged(this, (compiled * 100) / total);
                    }
                }

                if (File.Exists(path))
                {
                    File.Delete(path);
                }

                File.Move(tmpPath, path);
            }

            this.FilePath       = path;
            this.Version        = version;
            this.ClientFeatures = features;
            this.Changed        = false;

            if (this.StorageCompiled != null)
            {
                this.StorageCompiled(this);
            }

            return(true);
        }