//
// NostaleDataParser.cs
//
// Copyright (c) František Boháček. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using Microsoft.Extensions.Options;
using NosSmooth.Data.Abstractions;
using NosSmooth.Data.Abstractions.Language;
using NosSmooth.Data.NOSFiles.Files;
using NosSmooth.Data.NOSFiles.Options;
using NosSmooth.Data.NOSFiles.Parsers;
using NosSmooth.Data.NOSFiles.Readers;
using Remora.Results;
namespace NosSmooth.Data.NOSFiles;
///
/// Parser of NosTale .NOS files.
///
public class NostaleDataParser
{
private readonly FileReader _fileReader;
private readonly NostaleDataOptions _options;
private readonly LanguageServiceOptions _languageOptions;
private NostaleData? _parsed;
///
/// Initializes a new instance of the class.
///
/// The file reader.
/// The options.
/// The language options.
public NostaleDataParser
(
FileReader fileReader,
IOptions options,
IOptions languageOptions
)
{
_fileReader = fileReader;
_options = options.Value;
_languageOptions = languageOptions.Value;
}
///
/// Extract NosTale files from archives.
///
/// The path to the nostale data files.
/// The languages to include.
/// The nostale files.
public Result GetFiles(string? path = null, params Language[] languages)
{
string datFilesPath = Path.Combine(path ?? _options.NostaleDataPath, _options.InfosFileName);
string mapGridsFilesPath = Path.Combine(path ?? _options.NostaleDataPath, _options.MapGridsFileName);
string languageFilesPath = Path.Combine(path ?? _options.NostaleDataPath, _options.LanguageFileName);
var datFile = _fileReader.ReadFileSystemFile(datFilesPath);
if (!datFile.IsSuccess)
{
return Result.FromError(datFile);
}
var mapGridsFile = _fileReader.ReadFileSystemFile(mapGridsFilesPath);
if (!mapGridsFile.IsSuccess)
{
return Result.FromError(mapGridsFile);
}
var languageFiles = new Dictionary();
foreach (var language in languages.Concat(_options.SupportedLanguages).Distinct())
{
var langString = language.ToString().ToUpper();
var langPath = languageFilesPath.Replace("%lang%", langString);
var languageFile = _fileReader.ReadFileSystemFile(langPath);
if (!languageFile.IsSuccess)
{
return Result.FromError(languageFile);
}
languageFiles.Add(language, languageFile.Entity.Content);
}
return new NostaleFiles(languageFiles, datFile.Entity.Content, mapGridsFile.Entity.Content);
}
///
/// Parse the nostale files.
///
/// The path to the files.
/// The languages to parse.
/// Parsed data or an error.
public Result ParseFiles(string? path = null, params Language[] languages)
{
try
{
if (_parsed is not null)
{
return _parsed;
}
var filesResult = GetFiles(path, languages);
if (!filesResult.IsSuccess)
{
return Result.FromError(filesResult);
}
var files = filesResult.Entity;
var skillParser = new SkillParser();
var skillsResult = skillParser.Parse(files);
if (!skillsResult.IsSuccess)
{
return Result.FromError(skillsResult);
}
var mapParser = new MapParser();
var mapsResult = mapParser.Parse(files);
if (!mapsResult.IsSuccess)
{
return Result.FromError(mapsResult);
}
var itemParser = new ItemParser();
var itemsResult = itemParser.Parse(files);
if (!itemsResult.IsSuccess)
{
return Result.FromError(itemsResult);
}
var monsterParser = new MonsterParser();
var monstersResult = monsterParser.Parse(files);
if (!monstersResult.IsSuccess)
{
return Result.FromError(monstersResult);
}
var langParser = new LangParser();
var translations
= new Dictionary>>();
foreach (var language in files.LanguageFiles.Keys)
{
var languageParseResult = langParser.Parse(files, language);
if (!languageParseResult.IsSuccess)
{
return Result.FromError(languageParseResult);
}
translations.Add(language, languageParseResult.Entity);
}
return _parsed = new NostaleData
(
translations,
itemsResult.Entity,
monstersResult.Entity,
skillsResult.Entity,
mapsResult.Entity
);
}
catch (Exception e)
{
return e;
}
}
///
/// Create a language service from parsed files.
///
/// A language service or an error.
public Result CreateLanguageService()
{
var parsed = ParseFiles();
if (!parsed.IsSuccess)
{
return Result.FromError(parsed);
}
return new LanguageService(parsed.Entity.Translations, _languageOptions);
}
///
/// Create an info service from parsed files.
///
/// An info service or an error.
public Result CreateInfoService()
{
var parsed = ParseFiles();
if (!parsed.IsSuccess)
{
return Result.FromError(parsed);
}
return new InfoService(parsed.Entity);
}
}