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); }
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); }