/// <summary> /// Performs the conversion of .mon files to .json files. /// </summary> /// <param name="monDirPath">Optional. The path to the directory containing the .mon files. Defaults to the initialization <see cref="options"/> value if not supplied.</param> /// <param name="jsonDirPath">Optional. The path to the directory that will contain the .json files. Defaults to the initialization <see cref="options"/> value if not supplied.</param> /// <param name="overwriteFiles">Optional. A value indicating whether to overwrite files at the destination folder. Defaults to the initialization <see cref="options"/> value if not supplied.</param> public void Convert(string monDirPath = null, string jsonDirPath = null, bool?overwriteFiles = null) { this.options.MonsterFilesDirectory = monDirPath ?? this.options.MonsterFilesDirectory; this.options.OutputDirectory = jsonDirPath ?? this.options.OutputDirectory; this.options.OverwriteFiles = overwriteFiles ?? this.options.OverwriteFiles; DataAnnotationsValidator.ValidateObjectRecursive(this.options); var itemDictionary = this.itemTypesLoader.LoadTypes(); var monDirectoryInfo = new DirectoryInfo(monDirPath); var jsonDirectoryInfo = new DirectoryInfo(jsonDirPath); if (!monDirectoryInfo.Exists) { throw new ArgumentException($"The specified directory for .mon files: [{monDirectoryInfo.FullName}] does not exist."); } if (!jsonDirectoryInfo.Exists) { jsonDirectoryInfo.Create(); if (!jsonDirectoryInfo.Exists) { throw new ArgumentException($"The specified output directory: [{jsonDirectoryInfo.FullName}] does not exist and could not be created."); } } var existingFiles = monDirectoryInfo.GetFiles($"*{MonExtension}"); var modelMap = new Dictionary <string, MonsterModel>(); var raceMap = new Dictionary <uint, string>(); // Now that both directories exist, start processing files serially. foreach (var monFileInfo in existingFiles) { var parsedMonsterModel = CipFileParser.ParseMonsterFile(monFileInfo); if (parsedMonsterModel == null) { continue; } var targetModel = parsedMonsterModel.ToSerializableModel(); var fileNameWithoutExt = monFileInfo.Name.Replace(MonExtension, string.Empty); modelMap.Add(fileNameWithoutExt, targetModel); raceMap.Add(parsedMonsterModel.RaceId, fileNameWithoutExt); } // Ammend item names and summon references foreach (var convertedModel in modelMap.Values) { this.AmmendInventoryItemNames(itemDictionary, convertedModel); this.AmmendSummonReferences(raceMap, convertedModel); } // Output converted models foreach (var(fileNameWithoutExt, convertedModel) in modelMap) { var convertedFilePath = Path.Combine(jsonDirectoryInfo.FullName, Path.GetTempFileName()); var targetFilePath = $"{Path.Combine(jsonDirectoryInfo.FullName, fileNameWithoutExt)}{JsonExtension}"; var tempFileSream = File.Create(convertedFilePath); using (var fw = new StreamWriter(tempFileSream)) { var serializedMonster = JsonConvert.SerializeObject(convertedModel, Formatting.Indented); fw.Write(serializedMonster); fw.Flush(); fw.Close(); } File.Move(convertedFilePath, targetFilePath, overwriteFiles ?? false); } }
/// <summary> /// Reads a <see cref="MonsterTypeEntity"/> out of a monster file. /// </summary> /// <param name="monsterFileInfo">The information about the monster file.</param> /// <returns>The <see cref="MonsterTypeEntity"/> instance.</returns> private static MonsterTypeEntity ReadMonsterFile(FileInfo monsterFileInfo) { monsterFileInfo.ThrowIfNull(nameof(monsterFileInfo)); if (!monsterFileInfo.Exists) { return(null); } var parsedMonster = CipFileParser.ParseMonsterFile(monsterFileInfo); var monsterType = new MonsterTypeEntity() { RaceId = parsedMonster.RaceId.ToString(), Name = parsedMonster.Name, Article = parsedMonster.Article, OriginalOutfit = new Outfit() { Id = parsedMonster.Outfit.Id, Head = parsedMonster.Outfit.Head, Body = parsedMonster.Outfit.Body, Legs = parsedMonster.Outfit.Legs, Feet = parsedMonster.Outfit.Feet, }, Corpse = (ushort)parsedMonster.Corpse, BloodType = parsedMonster.BloodType, BaseExperienceYield = parsedMonster.Experience, SummonCost = parsedMonster.SummonCost, HitpointFleeThreshold = parsedMonster.FleeThreshold, BaseAttack = parsedMonster.Attack, BaseDefense = parsedMonster.Defense, BaseArmorRating = parsedMonster.Armor, LoseTargetDistance = parsedMonster.LoseTarget, Strategy = parsedMonster.Strategy, }; foreach (var flag in parsedMonster.Flags) { if (flag.ToCreatureFlag() is CreatureFlag creatureFlag) { monsterType.SetCreatureFlag(creatureFlag); } } foreach (var(skillType, defaultLevel, currentLevel, maximumLevel, targetCount, countIncreaseFactor, increaserPerLevel) in parsedMonster.Skills) { if (!Enum.TryParse(skillType, ignoreCase: true, out CipMonsterSkillType mSkill)) { continue; } switch (mSkill) { case CipMonsterSkillType.Hitpoints: monsterType.MaxHitpoints = currentLevel < 0 ? ushort.MaxValue : (ushort)defaultLevel; break; case CipMonsterSkillType.GoStrength: monsterType.BaseSpeed = currentLevel < 0 ? ushort.MinValue : (ushort)defaultLevel; break; case CipMonsterSkillType.CarryStrength: monsterType.Capacity = currentLevel < 0 ? ushort.MinValue : (ushort)defaultLevel; break; case CipMonsterSkillType.FistFighting: if (currentLevel > 0) { monsterType.SetSkill(SkillType.NoWeapon, Convert.ToInt32(currentLevel), Convert.ToInt32(defaultLevel), Convert.ToInt32(maximumLevel), targetCount, countIncreaseFactor, increaserPerLevel); } break; } } foreach (var spellRule in parsedMonster.Spells) { // Not implemented yet. } monsterType.SetInventory(parsedMonster.Inventory); monsterType.SetPhrases(parsedMonster.Phrases); return(monsterType); }